diff --git a/.depend b/.depend index 0ec0736d8..c7bff499c 100644 --- a/.depend +++ b/.depend @@ -1,171 +1,183 @@ -# DO NOT DELETE +# Automatically generated by makedepend. +# Run "make depend" to rebuild. -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 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 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 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 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 +# DO NOT DELETE +addr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 addr.h +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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 addr.h match.h log.h ./ssherr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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: authfile.h monitor_wrap.h compat.h channels.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h sshbuf.h misc.h servconf.h openbsd-compat/sys-queue.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h canohost.h uidswap.h packet.h dispatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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: canohost.h monitor_wrap.h pathnames.h match.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 kex.h mac.h crypto_api.h sshbuf.h log.h ./ssherr.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h misc.h servconf.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h misc.h servconf.h compat.h ssh2.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 kex.h mac.h crypto_api.h sshbuf.h log.h ./ssherr.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h +auth2-pubkey.o: pathnames.h uidswap.h auth-options.h canohost.h monitor_wrap.h authfile.h match.h channels.h session.h sk-api.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 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 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 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 compat.h log.h match.h kex.h mac.h crypto_api.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 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 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 -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 ssherr.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 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 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 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 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 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 ssh.h -packet.o: 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 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 +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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h sshbuf.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h pathnames.h monitor_wrap.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h atomicio.h misc.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h authfile.h misc.h atomicio.h sshkey.h sshbuf.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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-libcrypto.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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-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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h sshbuf.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h misc.h readconf.h clientloop.h sshconnect.h authfd.h atomicio.h sshpty.h match.h msg.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h match.h kex.h mac.h crypto_api.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h dispatch.h packet.h openbsd-compat/sys-queue.h compat.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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: 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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 +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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h misc.h pathnames.h digest.h hmac.h sshbuf.h +kex.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h +kex.o: match.h misc.h monitor.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 +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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h packet.h openbsd-compat/sys-queue.h dispatch.h ssh2.h sshbuf.h digest.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 +kexsntrup761x25519.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 +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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 utf8.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h match.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h atomicio.h packet.h openbsd-compat/sys-queue.h dispatch.h canohost.h auth.h auth-pam.h audit.h sshbuf.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h ssh.h sshbuf.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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: 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 ./ssherr.h misc.h servconf.h monitor.h monitor_wrap.h monitor_fdpass.h compat.h ssh2.h authfd.h match.h sk-api.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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_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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 +monitor_wrap.o: loginrec.h auth-options.h packet.h dispatch.h log.h ./ssherr.h monitor.h monitor_wrap.h atomicio.h monitor_fdpass.h misc.h channels.h session.h servconf.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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 +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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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: channels.h ssh.h packet.h dispatch.h sshbuf.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 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 ./ssherr.h canohost.h misc.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h misc.h servconf.h openbsd-compat/sys-queue.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 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 +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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 openbsd-compat/sys-queue.h xmalloc.h ssh.h log.h ./ssherr.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 +servconf.o: sshkey.h kex.h mac.h crypto_api.h match.h channels.h groupaccess.h canohost.h packet.h dispatch.h hostfile.h auth.h auth-pam.h audit.h loginrec.h myproposal.h digest.h +serverloop.o: cipher-aesctr.h 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 +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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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 +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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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-realpath.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 -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 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 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 sshsig.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 log.h sshkey.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 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 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 +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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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-realpath.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 +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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h pathnames.h misc.h utf8.h sftp.h sshbuf.h sftp-common.h sftp-client.h openbsd-compat/glob.h +sk-usbhid.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 +sntrup761.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 +srclimit.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 addr.h canohost.h log.h ./ssherr.h misc.h srclimit.h xmalloc.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 log.h ./ssherr.h sshkey.h sshbuf.h authfd.h authfile.h pathnames.h misc.h digest.h ssh-sk.h sk-api.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 sshkey.h authfd.h compat.h log.h ./ssherr.h misc.h digest.h match.h msg.h pathnames.h ssh-pkcs11.h sk-api.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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-sk.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 sshbuf.h ./ssherr.h digest.h sshkey.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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-sk.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h sshbuf.h sshkey.h ssh.h digest.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h sshbuf.h sshkey.h ssh.h +ssh-keygen.o: cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 sshbuf.h pathnames.h log.h ./ssherr.h misc.h match.h hostfile.h dns.h ssh.h ssh2.h ssh-pkcs11.h atomicio.h krl.h digest.h utf8.h authfd.h sshsig.h ssh-sk.h sk-api.h cipher.h +ssh-keyscan.o: ./ssherr.h atomicio.h misc.h hostfile.h ssh_api.h ssh2.h dns.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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-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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h sshkey.h ssh.h ssh2.h misc.h sshbuf.h authfile.h msg.h canohost.h pathnames.h readconf.h uidswap.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h misc.h sshkey.h authfd.h ssh-pkcs11.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h sshkey.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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-sk-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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h sshbuf.h sshkey.h msg.h digest.h pathnames.h ssh-sk.h misc.h +ssh-sk-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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h sshkey.h authfd.h misc.h sshbuf.h msg.h uidswap.h ssh-sk.h +ssh-sk.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 packet.h dispatch.h sshbuf.h channels.h +ssh.o: sshkey.h authfd.h authfile.h pathnames.h clientloop.h log.h ./ssherr.h misc.h readconf.h sshconnect.h kex.h mac.h crypto_api.h sshpty.h match.h msg.h version.h myproposal.h utf8.h +ssh_api.o: authfile.h misc.h version.h myproposal.h sshbuf.h openbsd-compat/openssl-compat.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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-io.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 atomicio.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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: 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 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 match.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 -sshsig.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 authfd.h authfile.h log.h misc.h sshbuf.h sshsig.h ssherr.h sshkey.h match.h digest.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 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 -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 +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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h misc.h readconf.h atomicio.h dns.h monitor_fdpass.h ssh2.h version.h authfile.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 +sshconnect2.o: myproposal.h sshconnect.h authfile.h dh.h authfd.h log.h ./ssherr.h misc.h readconf.h match.h canohost.h msg.h pathnames.h uidswap.h hostfile.h utf8.h ssh-sk.h sk-api.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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 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 sk-api.h srclimit.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 match.h ssh-sk.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 openbsd-compat/sys-queue.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h misc.h +sshsig.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 authfd.h authfile.h log.h ./ssherr.h misc.h sshbuf.h sshsig.h sshkey.h match.h digest.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.h compat.h sshbuf.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 +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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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 ./ssherr.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.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/.github/configs b/.github/configs new file mode 100755 index 000000000..1c06e00d1 --- /dev/null +++ b/.github/configs @@ -0,0 +1,110 @@ +#!/bin/sh +# +# usage: configs vmname test_config (or '' for default) +# +# Sets the following variables: +# CONFIGFLAGS options to ./configure +# SSHD_CONFOPTS sshd_config options +# TEST_TARGET make target used when testing. defaults to "tests". +# LTESTS + +config=$1 + +TEST_TARGET="tests" +LTESTS="" +SKIP_LTESTS="" +SUDO=sudo # run with sudo by default +TEST_SSH_UNSAFE_PERMISSIONS=1 + +CONFIGFLAGS="" +LIBCRYPTOFLAGS="" + +case "$config" in + default|sol64) + ;; + kitchensink) + CONFIGFLAGS="--with-kerberos5 --with-libedit --with-pam" + CONFIGFLAGS="${CONFIGFLAGS} --with-security-key-builtin --with-selinux" + CONFIGFLAGS="${CONFIGFLAGS} --with-cflags=-DSK_DEBUG" + ;; + hardenedmalloc) + CONFIGFLAGS="--with-ldflags=-lhardened_malloc" + ;; + kerberos5) + CONFIGFLAGS="--with-kerberos5" + ;; + libedit) + CONFIGFLAGS="--with-libedit" + ;; + *pam) + CONFIGFLAGS="--with-pam" + SSHD_CONFOPTS="UsePam yes" + ;; + libressl-head) + LIBCRYPTOFLAGS="--with-ssl-dir=/opt/libressl/head --with-rpath=-Wl,-rpath," + ;; + openssl-head) + LIBCRYPTOFLAGS="--with-ssl-dir=/opt/openssl/head --with-rpath=-Wl,-rpath," + ;; + selinux) + CONFIGFLAGS="--with-selinux" + ;; + sk) + CONFIGFLAGS="--with-security-key-builtin" + ;; + without-openssl) + LIBCRYPTOFLAGS="--without-openssl" + TEST_TARGET=t-exec + ;; + valgrind-1) + # rlimit sandbox and FORTIFY_SOURCE confuse Valgrind. + CONFIGFLAGS="--without-sandbox --without-hardening" + CONFIGFLAGS="$CONFIGFLAGS --with-cppflags=-D_FORTIFY_SOURCE=0" + # Valgrind slows things down enough that the agent timeout test + # won't reliably pass, and the unit tests run longer than allowed + # by github. + TEST_TARGET="t-exec USE_VALGRIND=1" + SKIP_LTESTS="agent-timeout rekey try-ciphers cert-userkey integrity" + ;; + valgrind-2) + CONFIGFLAGS="--without-sandbox --without-hardening" + CONFIGFLAGS="$CONFIGFLAGS --with-cppflags=-D_FORTIFY_SOURCE=0" + # The rekey test takes >30 min so run separately. + TEST_TARGET="t-exec USE_VALGRIND=1" + LTESTS="rekey try-ciphers cert-userkey integrity" + ;; + *) + echo "Unknown configuration $config" + exit 1 + ;; +esac + +# The Solaris 64bit targets are special since they need a non-flag arg. +case "$config" in + sol64*) + CONFIGFLAGS="x86_64 --with-cflags=-m64 --with-ldflags=-m64 ${CONFIGFLAGS}" + LIBCRYPTOFLAGS="--with-ssl-dir=/usr/local/ssl64" + ;; +esac + +case "${TARGET_HOST}" in + sol10|sol11) + # sol10 VM is 32bit and the unit tests are slow. + # sol11 has 4 test configs so skip unit tests to speed up. + TEST_TARGET="tests SKIP_UNIT=1" + ;; +esac + +# If we have a local openssl/libressl, use that. +if [ -z "${LIBCRYPTOFLAGS}" ]; then + # last-match + for i in /usr/local /usr/local/ssl /usr/local/opt/openssl; do + if [ -x ${i}/bin/openssl ]; then + LIBCRYPTOFLAGS="--with-ssl-dir=${i}" + fi + done +fi + +CONFIGFLAGS="${CONFIGFLAGS} ${LIBCRYPTOFLAGS}" + +export LTESTS SUDO TEST_TARGET TEST_SSH_UNSAFE_PERMISSIONS diff --git a/.github/configure.sh b/.github/configure.sh new file mode 100755 index 000000000..e098730f0 --- /dev/null +++ b/.github/configure.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +. .github/configs $1 + +set -x +./configure ${CONFIGFLAGS} diff --git a/.github/run_test.sh b/.github/run_test.sh new file mode 100755 index 000000000..66fd52603 --- /dev/null +++ b/.github/run_test.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +. .github/configs $1 $2 + +[ -z "${SUDO}" ] || ${SUDO} mkdir -p /var/empty + +set -ex + +if [ -z "${LTESTS}" ]; then + make ${TEST_TARGET} SKIP_LTESTS="${SKIP_LTESTS}" + result=$? +else + make ${TEST_TARGET} SKIP_LTESTS="${SKIP_LTESTS}" LTESTS="${LTESTS}" + result=$? +fi + +if [ ! -z "${SSHD_CONFOPTS}" ]; then + echo "rerunning tests with TEST_SSH_SSHD_CONFOPTS='${SSHD_CONFOPTS}'" + make t-exec TEST_SSH_SSHD_CONFOPTS="${SSHD_CONFOPTS}" + result2=$? + if [ "${result2}" -ne 0 ]; then + result="${result2}" + fi +fi + +if [ "$result" -ne "0" ]; then + for i in regress/failed*; do + echo ------------------------------------------------------------------------- + echo LOGFILE $i + cat $i + echo ------------------------------------------------------------------------- + done +fi diff --git a/.github/setup_ci.sh b/.github/setup_ci.sh new file mode 100755 index 000000000..e53a351c5 --- /dev/null +++ b/.github/setup_ci.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash + +case $(./config.guess) in +*-darwin*) + brew install automake + exit 0 + ;; +esac + +TARGETS=$@ + +PACKAGES="" +INSTALL_FIDO_PPA="no" + +#echo "Setting up for '$TARGETS'" + +set -ex + +lsb_release -a + +if [ "${TARGETS}" = "kitchensink" ]; then + TARGETS="kerberos5 libedit pam sk selinux" +fi + +for TARGET in $TARGETS; do + case $TARGET in + default|without-openssl|without-zlib) + # nothing to do + ;; + kerberos5) + PACKAGES="$PACKAGES heimdal-dev" + #PACKAGES="$PACKAGES libkrb5-dev" + ;; + libedit) + PACKAGES="$PACKAGES libedit-dev" + ;; + *pam) + PACKAGES="$PACKAGES libpam0g-dev" + ;; + sk) + INSTALL_FIDO_PPA="yes" + PACKAGES="$PACKAGES libfido2-dev libu2f-host-dev" + ;; + selinux) + PACKAGES="$PACKAGES libselinux1-dev selinux-policy-dev" + ;; + hardenedmalloc) + INSTALL_HARDENED_MALLOC=yes + ;; + openssl-head) + INSTALL_OPENSSL_HEAD=yes + ;; + libressl-head) + INSTALL_LIBRESSL_HEAD=yes + ;; + valgrind*) + PACKAGES="$PACKAGES valgrind" + ;; + *) echo "Invalid option '${TARGET}'" + exit 1 + ;; + esac +done + +if [ "yes" == "$INSTALL_FIDO_PPA" ]; then + sudo apt update -qq + sudo apt install software-properties-common + sudo apt-add-repository ppa:yubico/stable +fi + +if [ "x" != "x$PACKAGES" ]; then + sudo apt update -qq + sudo apt install -qy $PACKAGES +fi + +if [ "${INSTALL_HARDENED_MALLOC}" = "yes" ]; then + (cd ${HOME} && + git clone https://github.com/GrapheneOS/hardened_malloc.git && + cd ${HOME}/hardened_malloc && + make -j2 && sudo cp libhardened_malloc.so /usr/lib/) +fi + +if [ "${INSTALL_OPENSSL_HEAD}" = "yes" ];then + (cd ${HOME} && + git clone https://github.com/openssl/openssl.git && + cd ${HOME}/openssl && + ./config no-threads no-engine no-fips no-shared --prefix=/opt/openssl/head && + make -j2 && sudo make install_sw) +fi + +if [ "${INSTALL_LIBRESSL_HEAD}" = "yes" ];then + (mkdir -p ${HOME}/libressl && cd ${HOME}/libressl && + git clone https://github.com/libressl-portable/portable.git && + cd ${HOME}/libressl/portable && sh update.sh && sh autogen.sh && + ./configure --prefix=/opt/libressl/head && + make -j2 && sudo make install_sw) +fi diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml new file mode 100644 index 000000000..c2e9c5327 --- /dev/null +++ b/.github/workflows/c-cpp.yml @@ -0,0 +1,63 @@ +name: C/C++ CI + +on: + push: + branches: [ master, ci ] + pull_request: + branches: [ master ] + +jobs: + ci: + if: github.repository != 'openssh/openssh-portable-selfhosted' + strategy: + fail-fast: false + matrix: + # First we test all OSes in the default configuration. + os: [ubuntu-20.04, ubuntu-18.04, ubuntu-16.04, macos-10.15] + configs: [default] + # Then we include any extra configs we want to test for specific VMs. + # Valgrind slows things down quite a bit, so start them first. + include: + - { os: ubuntu-20.04, configs: valgrind-1 } + - { os: ubuntu-20.04, configs: valgrind-2 } + - { os: ubuntu-20.04, configs: pam } + - { os: ubuntu-20.04, configs: kitchensink } + - { os: ubuntu-20.04, configs: hardenedmalloc } + - { os: ubuntu-20.04, configs: libressl-head } + - { os: ubuntu-20.04, configs: openssl-head } + - { os: ubuntu-18.04, configs: pam } + - { os: ubuntu-18.04, configs: kerberos5 } + - { os: ubuntu-18.04, configs: libedit } + - { os: ubuntu-18.04, configs: sk } + - { os: ubuntu-18.04, configs: selinux } + - { os: ubuntu-18.04, configs: kitchensink } + - { os: ubuntu-18.04, configs: without-openssl } + - { os: ubuntu-16.04, configs: pam } + - { os: ubuntu-16.04, configs: kitchensink } + - { os: macos-10.15, configs: pam } + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - name: setup CI system + run: ./.github/setup_ci.sh ${{ matrix.configs }} + - name: autoreconf + run: autoreconf + - name: configure + run: ./.github/configure.sh ${{ matrix.configs }} + - name: make + run: make -j2 + - name: install moduli + run: sudo sh -c "mkdir -p /usr/local/etc/; cp moduli /usr/local/etc/" + - name: make tests + run: ./.github/run_test.sh ${{ matrix.configs }} + env: + SUDO: sudo + TEST_SSH_UNSAFE_PERMISSIONS: 1 + - name: save regress logs + if: failure() + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.os }}-${{ matrix.configs }}-regress-logs + path: | + regress/*.log + regress/valgrind-out/ diff --git a/.github/workflows/selfhosted.yml b/.github/workflows/selfhosted.yml new file mode 100644 index 000000000..aadcb42b4 --- /dev/null +++ b/.github/workflows/selfhosted.yml @@ -0,0 +1,68 @@ +name: C/C++ CI self-hosted + +on: + push: + branches: [ master, ci ] + +jobs: + selfhosted: + if: github.repository == 'openssh/openssh-portable-selfhosted' + runs-on: ${{ matrix.os }} + env: + TARGET_HOST: ${{ matrix.os }} + SUDO: sudo + strategy: + fail-fast: false + # We use a matrix in two parts: firstly all of the VMs are tested with the + # default config. "vm" corresponds to a label associated with the worker. + matrix: + os: [bbone, dfly30, dfly48, dfly58, fbsd6, fbsd7, fbsd12, sol10, sol11] + configs: + - default + # Then we include any extra configs we want to test for specific VMs. + include: + - { os: dfly30, configs: without-openssl} + - { os: dfly48, configs: pam } + - { os: dfly58, configs: pam } + - { os: fbsd6, configs: pam } + - { os: fbsd7, configs: pam } + - { os: fbsd12, configs: pam } + - { os: sol10, configs: pam } + - { os: sol11, configs: pam } + - { os: sol11, configs: sol64 } + # - { os: sol11, configs: sol64-pam } + steps: + - uses: actions/checkout@v2 + - name: autoreconf + run: autoreconf + - name: shutdown VM if running + run: vmshutdown + - name: startup VM + run: vmstartup + - name: configure + run: vmrun ./.github/configure.sh ${{ matrix.configs }} + - name: save config files + if: failure() + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.os }}-${{ matrix.configs }}-config-files + path: | + config.h + config.log + - name: make + run: vmrun make + - name: install moduli + run: vmrun "sudo mkdir -p /usr/local/etc/; sudo cp moduli /usr/local/etc/" + - name: make tests + run: vmrun ./.github/run_test.sh ${{ matrix.configs }} + - name: save regress logs + if: failure() + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.os }}-${{ matrix.configs }}-regress-logs + path: | + regress/*.log + regress/valgrind-out/ + - name: shutdown VM + if: always() + run: vmshutdown diff --git a/.gitignore b/.gitignore index d0e89fb7c..0e0efe998 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,11 @@ Makefile buildpkg.sh config.h config.h.in +config.h.in~ +config.log config.status configure +aclocal.m4 openbsd-compat/Makefile openbsd-compat/regress/Makefile openssh.xml @@ -12,6 +15,8 @@ opensshd.init survey.sh **/*.0 **/*.o +**/*.lo +**/*.so **/*.out **/*.a autom4te.cache/ @@ -25,8 +30,10 @@ ssh-keygen ssh-keyscan ssh-keysign ssh-pkcs11-helper +ssh-sk-helper sshd !regress/misc/fuzz-harness/Makefile +!regress/unittests/sshsig/Makefile tags # Ignores in Windows fork diff --git a/.skipped-commit-ids b/.skipped-commit-ids index dd573532f..495dbf1d1 100644 --- a/.skipped-commit-ids +++ b/.skipped-commit-ids @@ -11,6 +11,17 @@ db6375fc302e3bdf07d96430c63c991b2c2bd3ff moduli update 99dd10e72c04e93849981d43d64c946619efa474 include sshbuf-misc.c 9e1c23476bb845f3cf3d15d9032da3ed0cb2fcf5 sshbuf-misc.c in regress 569f08445c27124ec7c7f6c0268d844ec56ac061 Makefile tweaks for !openssl +58ec755be4e51978ecfee73539090eb68652a987 moduli update +4bd5551b306df55379afe17d841207990eb773bf Makefile.inc +14806a59353152f843eb349e618abbf6f4dd3ada Makefile.inc +8ea4455a2d9364a0a04f9e4a2cbfa4c9fcefe77e Makefile.inc +d9b910e412d139141b072a905e66714870c38ac0 Makefile.inc +7b7b619c1452a459310b0cf4391c5757c6bdbc0f moduli update +5010ff08f7ad92082e87dde098b20f5c24921a8f moduli regen script update +3bcae7a754db3fc5ad3cab63dd46774edb35b8ae moduli regen script update +52ff0e3205036147b2499889353ac082e505ea54 moduli update +07b5031e9f49f2b69ac5e85b8da4fc9e393992a0 Makefile.inc +cc12a9029833d222043aecd252d654965c351a69 moduli-gen Makefile Old upstream tree: diff --git a/INSTALL b/INSTALL index 814768791..d97946fe0 100644 --- a/INSTALL +++ b/INSTALL @@ -7,29 +7,36 @@ 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 from either of: - - LibreSSL (https://www.libressl.org/) - - OpenSSL (https://www.openssl.org) with any of the following versions: - - 1.0.x >= 1.0.1 or 1.1.0 >= 1.1.0g or any 1.1.1 - -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 due to a bug in EVP_CipherInit -OpenSSL 1.1 versions prior to 1.1.0g can't be used. - To support Privilege Separation (which is now required) you will need to create the user, group and directory used by sshd for privilege separation. See README.privsep for details. + The remaining items are optional. +A working installation of zlib: +Zlib 1.1.4 or 1.2.1.2 or greater (earlier 1.2.x versions have problems): +http://www.gzip.org/zlib/ + +libcrypto from either of LibreSSL or OpenSSL. Building without libcrypto +is supported but severely restricts the available ciphers and algorithms. + - LibreSSL (https://www.libressl.org/) + - OpenSSL (https://www.openssl.org) with any of the following versions: + - 1.0.x >= 1.0.1 or 1.1.0 >= 1.1.0g or any 1.1.1 + +Note that due to a bug in EVP_CipherInit OpenSSL 1.1 versions prior to +1.1.0g can't be used. + +LibreSSL/OpenSSL should be compiled as a position-independent library +(i.e. -fPIC, eg by configuring OpenSSL as "./config [options] -fPIC" +or LibreSSL as "CFLAGS=-fPIC ./configure") 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. + +If you build either from source, running the OpenSSL self-test ("make +tests") or the LibreSSL equivalent ("make check") and ensuring that all +tests pass is strongly recommended. + 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. @@ -44,7 +51,7 @@ http://prngd.sourceforge.net/ EGD: -The Entropy Gathering Daemon (EGD) suppports the same interface as prngd. +The Entropy Gathering Daemon (EGD) supports the same interface as prngd. It also supported only if libcrypto is configured to support it. http://egd.sourceforge.net/ @@ -53,7 +60,7 @@ 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. +HP-UX 11, AIX >= 5.2, FreeBSD, NetBSD and Mac OS X. Information about the various PAM implementations are available: @@ -90,11 +97,12 @@ 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. +the code out of git yourself) then you will need autoconf-2.69 and +automake-1.16.1 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/ +http://www.gnu.org/software/automake/ Basic Security Module (BSM): @@ -110,6 +118,16 @@ 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. +libfido2: + +libfido2 allows the use of hardware security keys over USB. libfido2 +in turn depends on libcbor. libfido2 >= 1.5.0 is strongly recommended. +Limited functionality is possible with earlier libfido2 versions. + +https://github.com/Yubico/libfido2 +https://github.com/pjk/libcbor + + 2. Building / Installation -------------------------- @@ -205,6 +223,11 @@ libraries are installed. --with-ssl-engine enables Libre/OpenSSL's (hardware) ENGINE support +--without-openssl builds without using OpenSSL. Only a subset of ciphers +and algorithms are supported in this configuration. + +--without-zlib builds without zlib. This disables the Compression option. + --with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to real (AF_INET) IPv4 addresses. Works around some quirks on Linux. @@ -236,7 +259,7 @@ 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) +configuration). If you have configured OpenSSH with EGD support, ensure that EGD is running and has collected some Entropy. @@ -261,6 +284,6 @@ 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 +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/LICENCE b/LICENCE index a2278a05d..5999c5e9d 100644 --- a/LICENCE +++ b/LICENCE @@ -314,6 +314,68 @@ OpenSSH contains no GPL code. * authorization. * ****************************************************************************/ + The Blowfish cipher implementation is licensed by Niels Provis under + a 4-clause BSD license: + + * Blowfish - a fast block cipher designed by Bruce Schneier + * + * Copyright 1997 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Niels Provos. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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. + + Some replacement code is licensed by the NetBSD foundation under a + 2-clause BSD license: + + * Copyright (c) 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Todd Vierling. + * + * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. ------ $OpenBSD: LICENCE,v 1.20 2017/04/30 23:26:16 djm Exp $ diff --git a/Makefile.in b/Makefile.in index adb1977e2..e3cd296ca 100644 --- a/Makefile.in +++ b/Makefile.in @@ -24,6 +24,7 @@ ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass SFTP_SERVER=$(libexecdir)/sftp-server SSH_KEYSIGN=$(libexecdir)/ssh-keysign SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper +SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper PRIVSEP_PATH=@PRIVSEP_PATH@ SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ STRIP_OPT=@STRIP_OPT@ @@ -35,32 +36,37 @@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \ -D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \ -D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \ -D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \ + -D_PATH_SSH_SK_HELPER=\"$(SSH_SK_HELPER)\" \ -D_PATH_SSH_PIDDIR=\"$(piddir)\" \ -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" CC=@CC@ LD=@LD@ CFLAGS=@CFLAGS@ +CFLAGS_NOPIE=@CFLAGS_NOPIE@ CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ +PICFLAG=@PICFLAG@ LIBS=@LIBS@ K5LIBS=@K5LIBS@ GSSLIBS=@GSSLIBS@ -SSHLIBS=@SSHLIBS@ SSHDLIBS=@SSHDLIBS@ LIBEDIT=@LIBEDIT@ +LIBFIDO2=@LIBFIDO2@ AR=@AR@ AWK=@AWK@ RANLIB=@RANLIB@ INSTALL=@INSTALL@ SED=@SED@ -ENT=@ENT@ XAUTH_PATH=@XAUTH_PATH@ LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@ +LDFLAGS_NOPIE=-L. -Lopenbsd-compat/ @LDFLAGS_NOPIE@ 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) +.SUFFIXES: .lo + +TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) XMSS_OBJS=\ ssh-xmss.o \ @@ -89,22 +95,25 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ cipher-ctr.o cleanup.o \ compat.o fatal.o hostfile.o \ log.o match.o moduli.o nchan.o packet.o \ - readpass.o ttymodes.o xmalloc.o addrmatch.o \ + readpass.o ttymodes.o xmalloc.o addr.o addrmatch.o \ atomicio.o dispatch.o mac.o misc.o utf8.o \ - monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ + monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-ecdsa-sk.o \ + ssh-ed25519-sk.o ssh-rsa.o dh.o \ msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ ssh-pkcs11.o smult_curve25519_ref.o \ - 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 \ + poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \ + ssh-ed25519.o digest-openssl.o digest-libc.o \ + hmac.o sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ kexgexc.o kexgexs.o \ - sntrup4591761.o kexsntrup4591761x25519.o kexgen.o \ - platform-pledge.o platform-tracing.o platform-misc.o + kexsntrup761x25519.o sntrup761.o kexgen.o \ + sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ + sshbuf-io.o +SKOBJS= ssh-sk-client.o SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ - sshconnect.o sshconnect2.o mux.o + sshconnect.o sshconnect2.o mux.o $(SKOBJS) SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ audit.o audit-bsm.o audit-linux.o platform.o \ @@ -116,13 +125,33 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.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 sftp-realpath.o \ + srclimit.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 + sandbox-solaris.o uidswap.o $(SKOBJS) -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 +SCP_OBJS= scp.o progressmeter.o + +SSHADD_OBJS= ssh-add.o $(SKOBJS) + +SSHAGENT_OBJS= ssh-agent.o ssh-pkcs11-client.o $(SKOBJS) + +SSHKEYGEN_OBJS= ssh-keygen.o sshsig.o $(SKOBJS) + +SSHKEYSIGN_OBJS=ssh-keysign.o readconf.o uidswap.o $(SKOBJS) + +P11HELPER_OBJS= ssh-pkcs11-helper.o ssh-pkcs11.o $(SKOBJS) + +SKHELPER_OBJS= ssh-sk-helper.o ssh-sk.o sk-usbhid.o + +SSHKEYSCAN_OBJS=ssh-keyscan.o $(SKOBJS) + +SFTPSERVER_OBJS=sftp-common.o sftp-server.o sftp-server-main.o + +SFTP_OBJS= sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o + +MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-sk-helper.8.out sshd_config.5.out ssh_config.5.out +MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-sk-helper.8 sshd_config.5 ssh_config.5 MANTYPE = @MANTYPE@ CONFIGFILES=sshd_config.out ssh_config.out moduli.out @@ -158,7 +187,7 @@ $(SSHOBJS): Makefile.in config.h $(SSHDOBJS): Makefile.in config.h configure-check: $(srcdir)/configure -$(srcdir)/configure: configure.ac aclocal.m4 +$(srcdir)/configure: configure.ac $(srcdir)/m4/*.m4 @echo "ERROR: configure is out of date; please run ${AUTORECONF} (and configure)" 1>&2 @exit 1 @@ -175,37 +204,40 @@ libssh.a: $(LIBSSH_OBJS) $(RANLIB) $@ ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) - $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) $(GSSLIBS) + $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(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) +scp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SCP_OBJS) + $(LD) -o $@ $(SCP_OBJS) $(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-add$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHADD_OBJS) + $(LD) -o $@ $(SSHADD_OBJS) $(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-agent$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHAGENT_OBJS) + $(LD) -o $@ $(SSHAGENT_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o sshsig.o - $(LD) -o $@ ssh-keygen.o sshsig.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) +ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYGEN_OBJS) + $(LD) -o $@ $(SSHKEYGEN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -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-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSIGN_OBJS) + $(LD) -o $@ $(SSHKEYSIGN_OBJS) $(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-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(P11HELPER_OBJS) + $(LD) -o $@ $(P11HELPER_OBJS) $(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) +ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(SKHELPER_OBJS) + $(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) -sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-realpath.o sftp-server-main.o - $(LD) -o $@ sftp-server.o sftp-common.o sftp-realpath.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) +ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) + $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(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) +sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTPSERVER_OBJS) + $(LD) -o $@ $(SFTPSERVER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + +sftp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTP_OBJS) + $(LD) -o $@ $(SFTP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT) # test driver for the loginrec code - not built by default logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o @@ -233,7 +265,7 @@ moduli: echo clean: regressclean - rm -f *.o *.a $(TARGETS) logintest config.cache config.log + rm -f *.o *.lo *.a $(TARGETS) logintest config.cache config.log rm -f *.out core survey rm -f regress/check-perm$(EXEEXT) rm -f regress/mkdtemp$(EXEEXT) @@ -243,6 +275,8 @@ clean: regressclean 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/sshsig/*.o + rm -f regress/unittests/sshsig/test_sshsig$(EXEEXT) rm -f regress/unittests/bitmap/*.o rm -f regress/unittests/bitmap/test_bitmap$(EXEEXT) rm -f regress/unittests/conversion/*.o @@ -255,8 +289,9 @@ clean: regressclean rm -f regress/unittests/match/test_match$(EXEEXT) rm -f regress/unittests/utf8/*.o rm -f regress/unittests/utf8/test_utf8$(EXEEXT) - rm -f regress/misc/kexfuzz/*.o - rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT) + rm -f regress/misc/sk-dummy/*.o + rm -f regress/misc/sk-dummy/*.lo + rm -f regress/misc/sk-dummy/sk-dummy.so (cd openbsd-compat && $(MAKE) clean) distclean: regressclean @@ -273,6 +308,8 @@ distclean: regressclean rm -f regress/unittests/sshbuf/test_sshbuf rm -f regress/unittests/sshkey/*.o rm -f regress/unittests/sshkey/test_sshkey + rm -f regress/unittests/sshsig/*.o + rm -f regress/unittests/sshsig/test_sshsig rm -f regress/unittests/bitmap/*.o rm -f regress/unittests/bitmap/test_bitmap rm -f regress/unittests/conversion/*.o @@ -285,8 +322,6 @@ distclean: regressclean rm -f regress/unittests/match/test_match rm -f regress/unittests/utf8/*.o rm -f regress/unittests/utf8/test_utf8 - rm -f regress/misc/kexfuzz/*.o - rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT) (cd openbsd-compat && $(MAKE) distclean) if test -d pkg ; then \ rm -fr pkg ; \ @@ -313,9 +348,15 @@ depend: depend-rebuild rm -f .depend.bak depend-rebuild: - rm -f config.h - touch config.h + mv .depend .depend.old + rm -f config.h .depend + touch config.h .depend makedepend -w1000 -Y. -f .depend *.c 2>/dev/null + (echo '# Automatically generated by makedepend.'; \ + echo '# Run "make depend" to rebuild.'; sort .depend ) >.depend.tmp + mv .depend.tmp .depend + rm -f .depend.bak + mv .depend.old .depend.bak rm -f config.h depend-check: depend-rebuild @@ -349,6 +390,7 @@ install-files: $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT) $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) $(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 @@ -365,6 +407,7 @@ install-files: $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 + $(INSTALL) -m 644 ssh-sk-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8 install-sysconf: $(MKDIR_P) $(DESTDIR)$(sysconfdir) @@ -425,6 +468,7 @@ uninstall: -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) -rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) + -rm -f $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 @@ -436,18 +480,20 @@ uninstall: -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8 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/sshsig $(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 + $(MKDIR_P) `pwd`/regress/misc/sk-dummy [ -f `pwd`/regress/Makefile ] || \ ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile @@ -502,7 +548,8 @@ UNITTESTS_TEST_SSHKEY_OBJS=\ 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.o \ + $(SKOBJS) regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a @@ -510,6 +557,17 @@ regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) +UNITTESTS_TEST_SSHSIG_OBJS=\ + sshsig.o \ + regress/unittests/sshsig/tests.o \ + $(SKOBJS) + +regress/unittests/sshsig/test_sshsig$(EXEEXT): ${UNITTESTS_TEST_SSHSIG_OBJS} \ + regress/unittests/test_helper/libtest_helper.a libssh.a + $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHSIG_OBJS) \ + regress/unittests/test_helper/libtest_helper.a \ + -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) + UNITTESTS_TEST_BITMAP_OBJS=\ regress/unittests/bitmap/tests.o @@ -531,7 +589,8 @@ regress/unittests/conversion/test_conversion$(EXEEXT): \ UNITTESTS_TEST_KEX_OBJS=\ regress/unittests/kex/tests.o \ - regress/unittests/kex/test_kex.o + regress/unittests/kex/test_kex.o \ + $(SKOBJS) regress/unittests/kex/test_kex$(EXEEXT): ${UNITTESTS_TEST_KEX_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a @@ -541,7 +600,8 @@ regress/unittests/kex/test_kex$(EXEEXT): ${UNITTESTS_TEST_KEX_OBJS} \ UNITTESTS_TEST_HOSTKEYS_OBJS=\ regress/unittests/hostkeys/tests.o \ - regress/unittests/hostkeys/test_iterate.o + regress/unittests/hostkeys/test_iterate.o \ + $(SKOBJS) regress/unittests/hostkeys/test_hostkeys$(EXEEXT): \ ${UNITTESTS_TEST_HOSTKEYS_OBJS} \ @@ -570,30 +630,39 @@ regress/unittests/utf8/test_utf8$(EXEEXT): \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) -MISC_KEX_FUZZ_OBJS=\ - regress/misc/kexfuzz/kexfuzz.o +# These all need to be compiled -fPIC, so they are treated differently. +SK_DUMMY_OBJS=\ + regress/misc/sk-dummy/sk-dummy.lo \ + regress/misc/sk-dummy/fatal.lo \ + ed25519.lo hash.lo ge25519.lo fe25519.lo sc25519.lo verify.lo -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) +SK_DUMMY_LIBRARY=@SK_DUMMY_LIBRARY@ + +.c.lo: Makefile.in config.h + $(CC) $(CFLAGS_NOPIE) $(PICFLAG) $(CPPFLAGS) -c $< -o $@ + +regress/misc/sk-dummy/sk-dummy.so: $(SK_DUMMY_OBJS) + $(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -shared -o $@ $(SK_DUMMY_OBJS) \ + -L. -Lopenbsd-compat -lopenbsd-compat $(LDFLAGS_NOPIE) $(LIBS) regress-binaries: regress-prep $(LIBCOMPAT) \ regress/modpipe$(EXEEXT) \ regress/setuid-allowed$(EXEEXT) \ regress/netcat$(EXEEXT) \ regress/check-perm$(EXEEXT) \ - regress/mkdtemp$(EXEEXT) + regress/mkdtemp$(EXEEXT) \ + $(SK_DUMMY_LIBRARY) regress-unit-binaries: regress-prep $(REGRESSLIBS) \ regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \ regress/unittests/sshkey/test_sshkey$(EXEEXT) \ + regress/unittests/sshsig/test_sshsig$(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: file-tests t-exec interop-tests unit echo all tests passed @@ -608,24 +677,8 @@ unit: regress-unit-binaries interop-tests t-exec file-tests: 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 $$?; \ + EGREP='@EGREP@' \ $(MAKE) \ .OBJDIR="$${BUILDDIR}/regress" \ .CURDIR="`pwd`" \ @@ -634,22 +687,24 @@ interop-tests t-exec file-tests: regress-prep regress-binaries $(TARGETS) 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_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_PKCS11_HELPER="$${BUILDDIR}/ssh-pkcs11-helper" \ + TEST_SSH_SK_HELPER="$${BUILDDIR}/ssh-sk-helper" \ + TEST_SSH_SFTPSERVER="$${BUILDDIR}/sftp-server" \ + 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@" \ TEST_SHELL="${TEST_SHELL}" \ EXEEXT="$(EXEEXT)" \ $@ && echo all $@ passed diff --git a/PROTOCOL b/PROTOCOL index f75c1c0ae..0b2ea60a7 100644 --- a/PROTOCOL +++ b/PROTOCOL @@ -140,7 +140,7 @@ window space and may be sent even if no window space is available. NB. due to certain broken SSH implementations aborting upon receipt of this message (in contravention of RFC4254 section 5.4), this message is only sent to OpenSSH peers (identified by banner). -Other SSH implementations may be whitelisted to receive this message +Other SSH implementations may be listed to receive this message upon request. 2.2. connection: disallow additional sessions extension @@ -169,7 +169,7 @@ Note that this is not a general defence against compromised clients NB. due to certain broken SSH implementations aborting upon receipt of this message, the no-more-sessions request is only sent to OpenSSH servers (identified by banner). Other SSH implementations may be -whitelisted to receive this message upon request. +listed to receive this message upon request. 2.3. connection: Tunnel forward extension "tun@openssh.com" @@ -194,7 +194,7 @@ layer 2 frames or layer 3 packets. It may take one of the following values: SSH_TUNMODE_ETHERNET 2 /* layer 2 frames */ The "tunnel unit number" specifies the remote interface number, or may -be 0x7fffffff to allow the server to automatically chose an interface. A +be 0x7fffffff to allow the server to automatically choose an interface. A server that is not willing to open a client-specified unit should refuse the request with a SSH_MSG_CHANNEL_OPEN_FAILURE error. On successful open, the server should reply with SSH_MSG_CHANNEL_OPEN_SUCCESS. @@ -292,13 +292,14 @@ has completed. byte SSH_MSG_GLOBAL_REQUEST string "hostkeys-00@openssh.com" + char 0 /* want-reply */ string[] hostkeys Upon receiving this message, a client should check which of the supplied host keys are present in known_hosts. Note that the server may send key types that the client does not -support. The client should disgregard such keys if they are received. +support. The client should disregard such keys if they are received. If the client identifies any keys that are not present for the host, it should send a "hostkeys-prove@openssh.com" message to request the @@ -465,6 +466,65 @@ respond with a SSH_FXP_STATUS message. This extension is advertised in the SSH_FXP_VERSION hello with version "1". +3.7. sftp: Extension request "lsetstat@openssh.com" + +This request is like the "setstat" command, but sets file attributes on +symlinks. It is implemented as a SSH_FXP_EXTENDED request with the +following format: + + uint32 id + string "lsetstat@openssh.com" + string path + ATTRS attrs + +See the "setstat" command for more details. + +This extension is advertised in the SSH_FXP_VERSION hello with version +"1". + +3.8. sftp: Extension request "limits@openssh.com" + +This request is used to determine various limits the server might impose. +Clients should not attempt to exceed these limits as the server might sever +the connection immediately. + + uint32 id + string "limits@openssh.com" + +The server will respond with a SSH_FXP_EXTENDED_REPLY reply: + + uint32 id + uint64 max-packet-length + uint64 max-read-length + uint64 max-write-length + uint64 max-open-handles + +The 'max-packet-length' applies to the total number of bytes in a +single SFTP packet. Servers SHOULD set this at least to 34000. + +The 'max-read-length' is the largest length in a SSH_FXP_READ packet. +Even if the client requests a larger size, servers will usually respond +with a shorter SSH_FXP_DATA packet. Servers SHOULD set this at least to +32768. + +The 'max-write-length' is the largest length in a SSH_FXP_WRITE packet +the server will accept. Servers SHOULD set this at least to 32768. + +The 'max-open-handles' is the maximum number of active handles that the +server allows (e.g. handles created by SSH_FXP_OPEN and SSH_FXP_OPENDIR +packets). Servers MAY count internal file handles against this limit +(e.g. system logging or stdout/stderr), so clients SHOULD NOT expect to +open this many handles in practice. + +If the server doesn't enforce a specific limit, then the field may be +set to 0. This implies the server relies on the OS to enforce limits +(e.g. available memory or file handles), and such limits might be +dynamic. The client SHOULD take care to not try to exceed reasonable +limits. + +This extension is advertised in the SSH_FXP_VERSION hello with version +"1". + 4. Miscellaneous changes 4.1 Public key format @@ -496,4 +556,4 @@ OpenSSH's connection multiplexing uses messages as described in PROTOCOL.mux over a Unix domain socket for communications between a master instance and later clients. -$OpenBSD: PROTOCOL,v 1.36 2018/10/02 12:51:58 djm Exp $ +$OpenBSD: PROTOCOL,v 1.41 2021/02/18 02:49:35 djm Exp $ diff --git a/PROTOCOL.agent b/PROTOCOL.agent index da3381942..ed47146a3 100644 --- a/PROTOCOL.agent +++ b/PROTOCOL.agent @@ -1,5 +1,5 @@ This file used to contain a description of the SSH agent protocol -implemented by OpenSSH. It has since been superseded by an Internet- -draft that is available from: +implemented by OpenSSH. It has since been superseded by +https://tools.ietf.org/html/draft-miller-ssh-agent-04 -https://tools.ietf.org/html/draft-miller-ssh-agent-02 +$OpenBSD: PROTOCOL.agent,v 1.14 2020/10/06 07:12:04 dtucker Exp $ diff --git a/PROTOCOL.certkeys b/PROTOCOL.certkeys index 48338e671..1fce87006 100644 --- a/PROTOCOL.certkeys +++ b/PROTOCOL.certkeys @@ -280,6 +280,13 @@ their data fields are: Name Format Description ----------------------------------------------------------------------------- +no-presence-required empty Flag indicating that signatures made + with this certificate need not assert + user presence. This option only make + sense for the U2F/FIDO security key + types that support this feature in + their signature formats. + permit-X11-forwarding empty Flag indicating that X11 forwarding should be permitted. X11 forwarding will be refused if this option is absent. @@ -304,4 +311,4 @@ permit-user-rc empty Flag indicating that execution of of this script will not be permitted if this option is not present. -$OpenBSD: PROTOCOL.certkeys,v 1.16 2018/10/26 01:23:03 djm Exp $ +$OpenBSD: PROTOCOL.certkeys,v 1.17 2019/11/25 00:57:51 djm Exp $ diff --git a/PROTOCOL.chacha20poly1305 b/PROTOCOL.chacha20poly1305 index 9ce2a1e3a..0bfff28d7 100644 --- a/PROTOCOL.chacha20poly1305 +++ b/PROTOCOL.chacha20poly1305 @@ -34,7 +34,7 @@ Detailed Construction The chacha20-poly1305@openssh.com cipher requires 512 bits of key material as output from the SSH key exchange. This forms two 256 bit keys (K_1 and K_2), used by two separate instances of chacha20. -The first 256 bits consitute K_2 and the second 256 bits become +The first 256 bits constitute K_2 and the second 256 bits become K_1. The instance keyed by K_1 is a stream cipher that is used only @@ -103,5 +103,5 @@ References [3] "ChaCha20 and Poly1305 based Cipher Suites for TLS", Adam Langley http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03 -$OpenBSD: PROTOCOL.chacha20poly1305,v 1.4 2018/04/10 00:10:49 djm Exp $ +$OpenBSD: PROTOCOL.chacha20poly1305,v 1.5 2020/02/21 00:04:43 dtucker Exp $ diff --git a/PROTOCOL.mux b/PROTOCOL.mux index 77a0780a5..5fc4c06b9 100644 --- a/PROTOCOL.mux +++ b/PROTOCOL.mux @@ -39,7 +39,7 @@ messages between the client and server. The client therefore must speak a significant subset of the SSH protocol, but in return is able to access basically the full suite of connection protocol features. Moreover, as no file descriptor passing is required, the connection -supporting a proxy client may iteself be forwarded or relayed to another +supporting a proxy client may itself be forwarded or relayed to another host if necessary. 1. Connection setup @@ -295,4 +295,4 @@ XXX session inspection via master XXX signals via mux request XXX list active connections via mux -$OpenBSD: PROTOCOL.mux,v 1.11 2018/09/26 07:30:05 djm Exp $ +$OpenBSD: PROTOCOL.mux,v 1.12 2020/03/13 03:17:07 djm Exp $ diff --git a/PROTOCOL.sshsig b/PROTOCOL.sshsig index 720e1f18a..78457ddfc 100644 --- a/PROTOCOL.sshsig +++ b/PROTOCOL.sshsig @@ -71,7 +71,7 @@ encoding rules for the chosen key type. For RSA signatures, the signature algorithm must be "rsa-sha2-512" or "rsa-sha2-256" (i.e. not the legacy RSA-SHA1 "ssh-rsa"). -This blob is encoded as a string using the RFC4243 encoding +This blob is encoded as a string using the RFC4253 encoding rules and base64 encoded to form the middle part of the armored signature. @@ -97,3 +97,4 @@ the reserved field if it is not empty. The data is concatenated and passed to the SSH signing function. +$OpenBSD: PROTOCOL.sshsig,v 1.4 2020/08/31 00:17:41 djm Exp $ diff --git a/PROTOCOL.u2f b/PROTOCOL.u2f new file mode 100644 index 000000000..f8ca56b11 --- /dev/null +++ b/PROTOCOL.u2f @@ -0,0 +1,309 @@ +This document describes OpenSSH's support for U2F/FIDO security keys. + +Background +---------- + +U2F is an open standard for two-factor authentication hardware, widely +used for user authentication to websites. U2F tokens are ubiquitous, +available from a number of manufacturers and are currently by far the +cheapest way for users to achieve hardware-backed credential storage. + +The U2F protocol however cannot be trivially used as an SSH protocol key +type as both the inputs to the signature operation and the resultant +signature differ from those specified for SSH. For similar reasons, +integration of U2F devices cannot be achieved via the PKCS#11 API. + +U2F also offers a number of features that are attractive in the context +of SSH authentication. They can be configured to require indication +of "user presence" for each signature operation (typically achieved +by requiring the user touch the key). They also offer an attestation +mechanism at key enrollment time that can be used to prove that a +given key is backed by hardware. Finally the signature format includes +a monotonic signature counter that can be used (at scale) to detect +concurrent use of a private key, should it be extracted from hardware. + +U2F private keys are generated through an enrollment operation, +which takes an application ID - a URL-like string, typically "ssh:" +in this case, but a HTTP origin for the case of web authentication, +and a challenge string (typically randomly generated). The enrollment +operation returns a public key, a key handle that must be used to invoke +the hardware-backed private key, some flags and signed attestation +information that may be used to verify that a private key is hosted on a +particular hardware instance. + +It is common for U2F hardware to derive private keys from the key handle +in conjunction with a small per-device secret that is unique to the +hardware, thus requiring little on-device storage for an effectively +unlimited number of supported keys. This drives the requirement that +the key handle be supplied for each signature operation. U2F tokens +primarily use ECDSA signatures in the NIST-P256 field, though the FIDO2 +standard specifies additional key types, including one based on Ed25519. + +Use of U2F security keys does not automatically imply multi-factor +authentication. From sshd's perspective, a security key constitutes a +single factor of authentication, even if protected by a PIN or biometric +authentication. To enable multi-factor authentication in ssh, please +refer to the AuthenticationMethods option in sshd_config(5). + + +SSH U2F Key formats +------------------- + +OpenSSH integrates U2F as new key and corresponding certificate types: + + sk-ecdsa-sha2-nistp256@openssh.com + sk-ecdsa-sha2-nistp256-cert-v01@openssh.com + sk-ssh-ed25519@openssh.com + sk-ssh-ed25519-cert-v01@openssh.com + +While each uses ecdsa-sha256-nistp256 as the underlying signature primitive, +keys require extra information in the public and private keys, and in +the signature object itself. As such they cannot be made compatible with +the existing ecdsa-sha2-nistp* key types. + +The format of a sk-ecdsa-sha2-nistp256@openssh.com public key is: + + string "sk-ecdsa-sha2-nistp256@openssh.com" + string curve name + ec_point Q + string application (user-specified, but typically "ssh:") + +The corresponding private key contains: + + string "sk-ecdsa-sha2-nistp256@openssh.com" + string curve name + ec_point Q + string application (user-specified, but typically "ssh:") + uint8 flags + string key_handle + string reserved + +The format of a sk-ssh-ed25519@openssh.com public key is: + + string "sk-ssh-ed25519@openssh.com" + string public key + string application (user-specified, but typically "ssh:") + +With a private half consisting of: + + string "sk-ssh-ed25519@openssh.com" + string public key + string application (user-specified, but typically "ssh:") + uint8 flags + string key_handle + string reserved + +The certificate form for SSH U2F keys appends the usual certificate +information to the public key: + + string "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" + string nonce + string curve name + ec_point Q + string application + 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 + +and for security key ed25519 certificates: + + string "sk-ssh-ed25519-cert-v01@openssh.com" + string nonce + string public key + string application + 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 + +Both security key certificates use the following encoding for private keys: + + string type (e.g. "sk-ssh-ed25519-cert-v01@openssh.com") + string pubkey (the above key/cert structure) + string application + uint8 flags + string key_handle + string reserved + +During key generation, the hardware also returns attestation information +that may be used to cryptographically prove that a given key is +hardware-backed. Unfortunately, the protocol required for this proof is +not privacy-preserving and may be used to identify U2F tokens with at +least manufacturer and batch number granularity. For this reason, we +choose not to include this information in the public key or save it by +default. + +Attestation information is useful for out-of-band key and certificate +registration workflows, e.g. proving to a CA that a key is backed +by trusted hardware before it will issue a certificate. To support this +case, OpenSSH optionally allows retaining the attestation information +at the time of key generation. It will take the following format: + + string "ssh-sk-attest-v01" + string attestation certificate + string enrollment signature + string authenticator data (CBOR encoded) + uint32 reserved flags + string reserved string + +A previous version of this format, emitted prior to OpenSSH 8.4 omitted +the authenticator data. + + string "ssh-sk-attest-v00" + string attestation certificate + string enrollment signature + uint32 reserved flags + string reserved string + +OpenSSH treats the attestation certificate and enrollment signatures as +opaque objects and does no interpretation of them itself. + +SSH U2F signatures +------------------ + +In addition to the message to be signed, the U2F signature operation +requires the key handle and a few additional parameters. The signature +is signed over a blob that consists of: + + byte[32] SHA256(application) + byte flags (including "user present", extensions present) + uint32 counter + byte[] extensions + byte[32] SHA256(message) + +No extensions are yet defined for SSH use. If any are defined in the future, +it will be possible to infer their presence from the contents of the "flags" +value. + +The signature returned from U2F hardware takes the following format: + + byte flags (including "user present") + uint32 counter + byte[] ecdsa_signature (in X9.62 format). + +For use in the SSH protocol, we wish to avoid server-side parsing of ASN.1 +format data in the pre-authentication attack surface. Therefore, the +signature format used on the wire in SSH2_USERAUTH_REQUEST packets will +be reformatted to better match the existing signature encoding: + + string "sk-ecdsa-sha2-nistp256@openssh.com" + string ecdsa_signature + byte flags + uint32 counter + +Where the "ecdsa_signature" field follows the RFC5656 ECDSA signature +encoding: + + mpint r + mpint s + +For Ed25519 keys the signature is encoded as: + + string "sk-ssh-ed25519@openssh.com" + string signature + byte flags + uint32 counter + +webauthn signatures +------------------- + +The W3C/FIDO webauthn[1] standard defines a mechanism for a web browser to +interact with FIDO authentication tokens. This standard builds upon the +FIDO standards, but requires different signature contents to raw FIDO +messages. OpenSSH supports ECDSA/p256 webauthn signatures through the +"webauthn-sk-ecdsa-sha2-nistp256@openssh.com" signature algorithm. + +The wire encoding for a webauthn-sk-ecdsa-sha2-nistp256@openssh.com +signature is similar to the sk-ecdsa-sha2-nistp256@openssh.com format: + + string "webauthn-sk-ecdsa-sha2-nistp256@openssh.com" + string ecdsa_signature + byte flags + uint32 counter + string origin + string clientData + string extensions + +Where "origin" is the HTTP origin making the signature, "clientData" is +the JSON-like structure signed by the browser and "extensions" are any +extensions used in making the signature. + +[1] https://www.w3.org/TR/webauthn-2/ + +ssh-agent protocol extensions +----------------------------- + +ssh-agent requires a protocol extension to support U2F keys. At +present the closest analogue to Security Keys in ssh-agent are PKCS#11 +tokens, insofar as they require a middleware library to communicate with +the device that holds the keys. Unfortunately, the protocol message used +to add PKCS#11 keys to ssh-agent does not include any way to send the +key handle to the agent as U2F keys require. + +To avoid this, without having to add wholly new messages to the agent +protocol, we will use the existing SSH2_AGENTC_ADD_ID_CONSTRAINED message +with a new key constraint extension to encode a path to the middleware +library for the key. The format of this constraint extension would be: + + byte SSH_AGENT_CONSTRAIN_EXTENSION + string sk-provider@openssh.com + string middleware path + +This constraint-based approach does not present any compatibility +problems. + +OpenSSH integration +------------------- + +U2F tokens may be attached via a number of means, including USB and NFC. +The USB interface is standardised around a HID protocol, but we want to +be able to support other transports as well as dummy implementations for +regress testing. For this reason, OpenSSH shall support a dynamically- +loaded middleware libraries to communicate with security keys, but offer +support for the common case of USB HID security keys internally. + +The middleware library need only expose a handful of functions and +numbers listed in sk-api.h. Included in the defined numbers is a +SSH_SK_VERSION_MAJOR that should be incremented for each incompatible +API change. + +miscellaneous options may be passed to the middleware as a NULL- +terminated array of pointers to struct sk_option. The middleware may +ignore unsupported or unknown options unless the "required" flag is set, +in which case it should return failure if an unsupported option is +requested. + +At present the following options names are supported: + + "device" + + Specifies a specific FIDO device on which to perform the + operation. The value in this field is interpreted by the + middleware but it would be typical to specify a path to + a /dev node for the device in question. + + "user" + + Specifies the FIDO2 username used when enrolling a key, + overriding OpenSSH's default of using an all-zero username. + +In OpenSSH, the middleware will be invoked by using a similar mechanism to +ssh-pkcs11-helper to provide address-space containment of the +middleware from ssh-agent. + +$OpenBSD: PROTOCOL.u2f,v 1.26 2020/09/09 03:08:01 djm Exp $ diff --git a/README b/README index 5c83aa508..0f87812a6 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -See https://www.openssh.com/releasenotes.html#8.1p1 for the release notes. +See https://www.openssh.com/releasenotes.html#8.5p1 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 @@ -15,7 +15,7 @@ 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 +support, EGD/PRNGD 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. @@ -26,37 +26,27 @@ 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 send bug reports and patches to https://bugzilla.mindrot.org or +the mailing list openssh-unix-dev@mindrot.org. To mitigate spam, the +list only allows posting from subscribed addresses. Code contribution +are welcomed, but please follow the OpenBSD style guidelines[1]. -Please refer to the INSTALL document for information on how to install -OpenSSH on your system. +Please refer to the INSTALL document for information on dependencies and +how to install OpenSSH on your system. Damien Miller 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. +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 +[1] https://man.openbsd.org/style.9 + diff --git a/README.dns b/README.dns index 97879183e..29ecaee8d 100644 --- a/README.dns +++ b/README.dns @@ -1,10 +1,10 @@ How to verify host keys using OpenSSH and DNS --------------------------------------------- -OpenSSH contains support for verifying host keys using DNS as described in -draft-ietf-secsh-dns-05.txt. The document contains very brief instructions -on how to use this feature. Configuring DNS is out of the scope of this -document. +OpenSSH contains support for verifying host keys using DNS as described +in https://tools.ietf.org/html/rfc4255. The document contains very brief +instructions on how to use this feature. Configuring DNS is out of the +scope of this document. (1) Server: Generate and publish the DNS RR diff --git a/README.md b/README.md index 4e2624161..e9ee372ca 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Portable OpenSSH +[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/openssh.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj: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). @@ -25,21 +27,27 @@ Stable release tarballs are available from a number of [download mirrors](https: ### 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. +Portable OpenSSH is built using autoconf and make. It requires a working C compiler, standard library and headers. + +``libcrypto`` from either [LibreSSL](https://www.libressl.org/) or [OpenSSL](https://www.openssl.org) may also be used, but OpenSSH may be built without it supporting a subset of crypto algorithms. + +[zlib](https://www.zlib.net/) is optional; without it transport compression is not supported. + +FIDO security token support needs [libfido2](https://github.com/Yubico/libfido2) and its dependencies. Also, certain platforms and build-time options may require additional dependencies; see README.platform for details. ### 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 +tar zxvf openssh-X.YpZ.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: @@ -64,6 +72,7 @@ Flag | Meaning ``--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. +``--with-security-key-builtin`` | Include built-in support for U2F/FIDO2 security keys. This requires [libfido2](https://github.com/Yubico/libfido2) be installed. ## Development diff --git a/README.platform b/README.platform index 9210e07c8..7b754ba42 100644 --- a/README.platform +++ b/README.platform @@ -1,19 +1,19 @@ This file contains notes about OpenSSH on specific platforms. AIX ---- -As of OpenSSH 3.8p1, sshd will now honour an accounts password expiry -settings, where previously it did not. Because of this, it's possible for -sites that have used OpenSSH's sshd exclusively to have accounts which -have passwords expired longer than the inactive time (ie the "Weeks between -password EXPIRATION and LOCKOUT" setting in SMIT or the maxexpired -chuser attribute). + +Beginning with OpenSSH 3.8p1, sshd will honour an account's password +expiry settings, where prior to that it did not. Because of this, +it's possible for sites that have used OpenSSH's sshd exclusively to +have accounts which have passwords expired longer than the inactive time +(ie the "Weeks between password EXPIRATION and LOCKOUT" setting in SMIT +or the maxexpired chuser attribute). Accounts in this state must have their passwords reset manually by the administrator. As a precaution, it is recommended that the administrative passwords be reset before upgrading from OpenSSH <3.8. -As of OpenSSH 4.0, configure will attempt to detect if your version +As of OpenSSH 4.0p1, configure will attempt to detect if your version and maintenance level of AIX has a working getaddrinfo, and will use it if found. This will enable IPv6 support. If for some reason configure gets it wrong, or if you want to build binaries to work on earlier MLs diff --git a/addr.c b/addr.c new file mode 100644 index 000000000..ba0fad4e9 --- /dev/null +++ b/addr.c @@ -0,0 +1,423 @@ +/* $OpenBSD: addr.c,v 1.1 2021/01/09 11:58:50 dtucker Exp $ */ + +/* + * Copyright (c) 2004-2008 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. + */ + +#include "includes.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "addr.h" + +#define _SA(x) ((struct sockaddr *)(x)) + +int +addr_unicast_masklen(int af) +{ + switch (af) { + case AF_INET: + return 32; + case AF_INET6: + return 128; + default: + return -1; + } +} + +static inline int +masklen_valid(int af, u_int masklen) +{ + switch (af) { + case AF_INET: + return masklen <= 32 ? 0 : -1; + case AF_INET6: + return masklen <= 128 ? 0 : -1; + default: + return -1; + } +} + +int +addr_xaddr_to_sa(const struct xaddr *xa, struct sockaddr *sa, socklen_t *len, + u_int16_t port) +{ + struct sockaddr_in *in4 = (struct sockaddr_in *)sa; + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; + + if (xa == NULL || sa == NULL || len == NULL) + return -1; + + switch (xa->af) { + case AF_INET: + if (*len < sizeof(*in4)) + return -1; + memset(sa, '\0', sizeof(*in4)); + *len = sizeof(*in4); +#ifdef SOCK_HAS_LEN + in4->sin_len = sizeof(*in4); +#endif + in4->sin_family = AF_INET; + in4->sin_port = htons(port); + memcpy(&in4->sin_addr, &xa->v4, sizeof(in4->sin_addr)); + break; + case AF_INET6: + if (*len < sizeof(*in6)) + return -1; + memset(sa, '\0', sizeof(*in6)); + *len = sizeof(*in6); +#ifdef SOCK_HAS_LEN + in6->sin6_len = sizeof(*in6); +#endif + in6->sin6_family = AF_INET6; + in6->sin6_port = htons(port); + memcpy(&in6->sin6_addr, &xa->v6, sizeof(in6->sin6_addr)); +#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID + in6->sin6_scope_id = xa->scope_id; +#endif + break; + default: + return -1; + } + return 0; +} + +/* + * Convert struct sockaddr to struct xaddr + * Returns 0 on success, -1 on failure. + */ +int +addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa) +{ + struct sockaddr_in *in4 = (struct sockaddr_in *)sa; + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; + + memset(xa, '\0', sizeof(*xa)); + + switch (sa->sa_family) { + case AF_INET: + if (slen < (socklen_t)sizeof(*in4)) + return -1; + xa->af = AF_INET; + memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4)); + break; + case AF_INET6: + if (slen < (socklen_t)sizeof(*in6)) + return -1; + xa->af = AF_INET6; + memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6)); +#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID + xa->scope_id = in6->sin6_scope_id; +#endif + break; + default: + return -1; + } + + return 0; +} + +int +addr_invert(struct xaddr *n) +{ + int i; + + if (n == NULL) + return -1; + + switch (n->af) { + case AF_INET: + n->v4.s_addr = ~n->v4.s_addr; + return 0; + case AF_INET6: + for (i = 0; i < 4; i++) + n->addr32[i] = ~n->addr32[i]; + return 0; + default: + return -1; + } +} + +/* + * Calculate a netmask of length 'l' for address family 'af' and + * store it in 'n'. + * Returns 0 on success, -1 on failure. + */ +int +addr_netmask(int af, u_int l, struct xaddr *n) +{ + int i; + + if (masklen_valid(af, l) != 0 || n == NULL) + return -1; + + memset(n, '\0', sizeof(*n)); + switch (af) { + case AF_INET: + n->af = AF_INET; + if (l == 0) + return 0; + n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff); + return 0; + case AF_INET6: + n->af = AF_INET6; + for (i = 0; i < 4 && l >= 32; i++, l -= 32) + n->addr32[i] = 0xffffffffU; + if (i < 4 && l != 0) + n->addr32[i] = htonl((0xffffffff << (32 - l)) & + 0xffffffff); + return 0; + default: + return -1; + } +} + +int +addr_hostmask(int af, u_int l, struct xaddr *n) +{ + if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1) + return -1; + return 0; +} + +/* + * Perform logical AND of addresses 'a' and 'b', storing result in 'dst'. + * Returns 0 on success, -1 on failure. + */ +int +addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b) +{ + int i; + + if (dst == NULL || a == NULL || b == NULL || a->af != b->af) + return -1; + + memcpy(dst, a, sizeof(*dst)); + switch (a->af) { + case AF_INET: + dst->v4.s_addr &= b->v4.s_addr; + return 0; + case AF_INET6: + dst->scope_id = a->scope_id; + for (i = 0; i < 4; i++) + dst->addr32[i] &= b->addr32[i]; + return 0; + default: + return -1; + } +} + +int +addr_cmp(const struct xaddr *a, const struct xaddr *b) +{ + int i; + + if (a->af != b->af) + return (a->af == AF_INET6 ? 1 : -1); + + switch (a->af) { + case AF_INET: + /* + * Can't just subtract here as 255.255.255.255 - 0.0.0.0 is + * too big to fit into a signed int + */ + if (a->v4.s_addr == b->v4.s_addr) + return 0; + return (ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1); + case AF_INET6:; + /* + * Do this a byte at a time to avoid the above issue and + * any endian problems + */ + for (i = 0; i < 16; i++) + if (a->addr8[i] - b->addr8[i] != 0) + return (a->addr8[i] - b->addr8[i]); + if (a->scope_id == b->scope_id) + return (0); + return (a->scope_id > b->scope_id ? 1 : -1); + default: + return (-1); + } +} + +int +addr_is_all0s(const struct xaddr *a) +{ + int i; + + switch (a->af) { + case AF_INET: + return (a->v4.s_addr == 0 ? 0 : -1); + case AF_INET6:; + for (i = 0; i < 4; i++) + if (a->addr32[i] != 0) + return -1; + return 0; + default: + return -1; + } +} + +/* + * Test whether host portion of address 'a', as determined by 'masklen' + * is all zeros. + * Returns 0 on if host portion of address is all-zeros, + * -1 if not all zeros or on failure. + */ +int +addr_host_is_all0s(const struct xaddr *a, u_int masklen) +{ + struct xaddr tmp_addr, tmp_mask, tmp_result; + + memcpy(&tmp_addr, a, sizeof(tmp_addr)); + if (addr_hostmask(a->af, masklen, &tmp_mask) == -1) + return -1; + if (addr_and(&tmp_result, &tmp_addr, &tmp_mask) == -1) + return -1; + return addr_is_all0s(&tmp_result); +} + +/* + * Parse string address 'p' into 'n' + * Returns 0 on success, -1 on failure. + */ +int +addr_pton(const char *p, struct xaddr *n) +{ + struct addrinfo hints, *ai; + + memset(&hints, '\0', sizeof(hints)); + hints.ai_flags = AI_NUMERICHOST; + + if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0) + return -1; + + if (ai == NULL || ai->ai_addr == NULL) + return -1; + + if (n != NULL && addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen, + n) == -1) { + freeaddrinfo(ai); + return -1; + } + + freeaddrinfo(ai); + return 0; +} + +int +addr_sa_pton(const char *h, const char *s, struct sockaddr *sa, socklen_t slen) +{ + struct addrinfo hints, *ai; + + memset(&hints, '\0', sizeof(hints)); + hints.ai_flags = AI_NUMERICHOST; + + if (h == NULL || getaddrinfo(h, s, &hints, &ai) != 0) + return -1; + + if (ai == NULL || ai->ai_addr == NULL) + return -1; + + if (sa != NULL) { + if (slen < ai->ai_addrlen) + return -1; + memcpy(sa, &ai->ai_addr, ai->ai_addrlen); + } + + freeaddrinfo(ai); + return 0; +} + +int +addr_ntop(const struct xaddr *n, char *p, size_t len) +{ + struct sockaddr_storage ss; + socklen_t slen = sizeof(ss); + + if (addr_xaddr_to_sa(n, _SA(&ss), &slen, 0) == -1) + return -1; + if (n == NULL || p == NULL || len == 0) + return -1; + if (getnameinfo(_SA(&ss), slen, p, len, NULL, 0, + NI_NUMERICHOST) == -1) + return -1; + + return 0; +} + +/* + * Parse a CIDR address (x.x.x.x/y or xxxx:yyyy::/z). + * Return -1 on parse error, -2 on inconsistency or 0 on success. + */ +int +addr_pton_cidr(const char *p, struct xaddr *n, u_int *l) +{ + struct xaddr tmp; + long unsigned int masklen = 999; + char addrbuf[64], *mp, *cp; + + /* Don't modify argument */ + if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) >= sizeof(addrbuf)) + return -1; + + if ((mp = strchr(addrbuf, '/')) != NULL) { + *mp = '\0'; + mp++; + masklen = strtoul(mp, &cp, 10); + if (*mp == '\0' || *cp != '\0' || masklen > 128) + return -1; + } + + if (addr_pton(addrbuf, &tmp) == -1) + return -1; + + if (mp == NULL) + masklen = addr_unicast_masklen(tmp.af); + if (masklen_valid(tmp.af, masklen) == -1) + return -2; + if (addr_host_is_all0s(&tmp, masklen) != 0) + return -2; + + if (n != NULL) + memcpy(n, &tmp, sizeof(*n)); + if (l != NULL) + *l = masklen; + + return 0; +} + +int +addr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen) +{ + struct xaddr tmp_mask, tmp_result; + + if (host->af != net->af) + return -1; + + if (addr_netmask(host->af, masklen, &tmp_mask) == -1) + return -1; + if (addr_and(&tmp_result, host, &tmp_mask) == -1) + return -1; + return addr_cmp(&tmp_result, net); +} diff --git a/addr.h b/addr.h new file mode 100644 index 000000000..5eff02628 --- /dev/null +++ b/addr.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2004,2005 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. + */ + +/* Address handling routines */ + +#ifndef _ADDR_H +#define _ADDR_H + +#include +#include + +struct xaddr { + sa_family_t af; + union { + struct in_addr v4; + struct in6_addr v6; + u_int8_t addr8[16]; + u_int16_t addr16[8]; + u_int32_t addr32[4]; + } xa; /* 128-bit address */ + u_int32_t scope_id; /* iface scope id for v6 */ +#define v4 xa.v4 +#define v6 xa.v6 +#define addr8 xa.addr8 +#define addr16 xa.addr16 +#define addr32 xa.addr32 +}; + +int addr_unicast_masklen(int af); +int addr_xaddr_to_sa(const struct xaddr *xa, struct sockaddr *sa, + socklen_t *len, u_int16_t port); +int addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa); +int addr_netmask(int af, u_int l, struct xaddr *n); +int addr_hostmask(int af, u_int l, struct xaddr *n); +int addr_invert(struct xaddr *n); +int addr_pton(const char *p, struct xaddr *n); +int addr_sa_pton(const char *h, const char *s, struct sockaddr *sa, + socklen_t slen); +int addr_pton_cidr(const char *p, struct xaddr *n, u_int *l); +int addr_ntop(const struct xaddr *n, char *p, size_t len); +int addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b); +int addr_cmp(const struct xaddr *a, const struct xaddr *b); +int addr_is_all0s(const struct xaddr *n); +int addr_host_is_all0s(const struct xaddr *n, u_int masklen); +int addr_netmatch(const struct xaddr *host, const struct xaddr *net, + u_int masklen); +#endif /* _ADDR_H */ diff --git a/addrmatch.c b/addrmatch.c index 5a402d065..3215c653d 100644 --- a/addrmatch.c +++ b/addrmatch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: addrmatch.c,v 1.14 2018/07/31 03:07:24 djm Exp $ */ +/* $OpenBSD: addrmatch.c,v 1.16 2021/01/09 11:58:50 dtucker Exp $ */ /* * Copyright (c) 2004-2008 Damien Miller @@ -29,337 +29,10 @@ #include #include +#include "addr.h" #include "match.h" #include "log.h" -struct xaddr { - sa_family_t af; - union { - struct in_addr v4; - struct in6_addr v6; - u_int8_t addr8[16]; - u_int32_t addr32[4]; - } xa; /* 128-bit address */ - u_int32_t scope_id; /* iface scope id for v6 */ -#define v4 xa.v4 -#define v6 xa.v6 -#define addr8 xa.addr8 -#define addr32 xa.addr32 -}; - -static int -addr_unicast_masklen(int af) -{ - switch (af) { - case AF_INET: - return 32; - case AF_INET6: - return 128; - default: - return -1; - } -} - -static inline int -masklen_valid(int af, u_int masklen) -{ - switch (af) { - case AF_INET: - return masklen <= 32 ? 0 : -1; - case AF_INET6: - return masklen <= 128 ? 0 : -1; - default: - return -1; - } -} - -/* - * Convert struct sockaddr to struct xaddr - * Returns 0 on success, -1 on failure. - */ -static int -addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa) -{ - struct sockaddr_in *in4 = (struct sockaddr_in *)sa; - struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa; - - memset(xa, '\0', sizeof(*xa)); - - switch (sa->sa_family) { - case AF_INET: - if (slen < (socklen_t)sizeof(*in4)) - return -1; - xa->af = AF_INET; - memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4)); - break; - case AF_INET6: - if (slen < (socklen_t)sizeof(*in6)) - return -1; - xa->af = AF_INET6; - memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6)); -#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID - xa->scope_id = in6->sin6_scope_id; -#endif - break; - default: - return -1; - } - - return 0; -} - -/* - * Calculate a netmask of length 'l' for address family 'af' and - * store it in 'n'. - * Returns 0 on success, -1 on failure. - */ -static int -addr_netmask(int af, u_int l, struct xaddr *n) -{ - int i; - - if (masklen_valid(af, l) != 0 || n == NULL) - return -1; - - memset(n, '\0', sizeof(*n)); - switch (af) { - case AF_INET: - n->af = AF_INET; - if (l == 0) - return 0; - n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff); - return 0; - case AF_INET6: - n->af = AF_INET6; - for (i = 0; i < 4 && l >= 32; i++, l -= 32) - n->addr32[i] = 0xffffffffU; - if (i < 4 && l != 0) - n->addr32[i] = htonl((0xffffffff << (32 - l)) & - 0xffffffff); - return 0; - default: - return -1; - } -} - -/* - * Perform logical AND of addresses 'a' and 'b', storing result in 'dst'. - * Returns 0 on success, -1 on failure. - */ -static int -addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b) -{ - int i; - - if (dst == NULL || a == NULL || b == NULL || a->af != b->af) - return -1; - - memcpy(dst, a, sizeof(*dst)); - switch (a->af) { - case AF_INET: - dst->v4.s_addr &= b->v4.s_addr; - return 0; - case AF_INET6: - dst->scope_id = a->scope_id; - for (i = 0; i < 4; i++) - dst->addr32[i] &= b->addr32[i]; - return 0; - default: - return -1; - } -} - -/* - * Compare addresses 'a' and 'b' - * Return 0 if addresses are identical, -1 if (a < b) or 1 if (a > b) - */ -static int -addr_cmp(const struct xaddr *a, const struct xaddr *b) -{ - int i; - - if (a->af != b->af) - return a->af == AF_INET6 ? 1 : -1; - - switch (a->af) { - case AF_INET: - if (a->v4.s_addr == b->v4.s_addr) - return 0; - return ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1; - case AF_INET6: - for (i = 0; i < 16; i++) - if (a->addr8[i] - b->addr8[i] != 0) - return a->addr8[i] > b->addr8[i] ? 1 : -1; - if (a->scope_id == b->scope_id) - return 0; - return a->scope_id > b->scope_id ? 1 : -1; - default: - return -1; - } -} - -/* - * Parse string address 'p' into 'n' - * Returns 0 on success, -1 on failure. - */ -static int -addr_pton(const char *p, struct xaddr *n) -{ - struct addrinfo hints, *ai = NULL; - int ret = -1; - - memset(&hints, '\0', sizeof(hints)); - hints.ai_flags = AI_NUMERICHOST; - - if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0) - goto out; - if (ai == NULL || ai->ai_addr == NULL) - goto out; - if (n != NULL && addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen, n) == -1) - goto out; - /* success */ - ret = 0; - out: - if (ai != NULL) - freeaddrinfo(ai); - return ret; -} - -/* - * Perform bitwise negation of address - * Returns 0 on success, -1 on failure. - */ -static int -addr_invert(struct xaddr *n) -{ - int i; - - if (n == NULL) - return (-1); - - switch (n->af) { - case AF_INET: - n->v4.s_addr = ~n->v4.s_addr; - return (0); - case AF_INET6: - for (i = 0; i < 4; i++) - n->addr32[i] = ~n->addr32[i]; - return (0); - default: - return (-1); - } -} - -/* - * Calculate a netmask of length 'l' for address family 'af' and - * store it in 'n'. - * Returns 0 on success, -1 on failure. - */ -static int -addr_hostmask(int af, u_int l, struct xaddr *n) -{ - if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1) - return (-1); - return (0); -} - -/* - * Test whether address 'a' is all zeros (i.e. 0.0.0.0 or ::) - * Returns 0 on if address is all-zeros, -1 if not all zeros or on failure. - */ -static int -addr_is_all0s(const struct xaddr *a) -{ - int i; - - switch (a->af) { - case AF_INET: - return (a->v4.s_addr == 0 ? 0 : -1); - case AF_INET6:; - for (i = 0; i < 4; i++) - if (a->addr32[i] != 0) - return (-1); - return (0); - default: - return (-1); - } -} - -/* - * Test whether host portion of address 'a', as determined by 'masklen' - * is all zeros. - * Returns 0 on if host portion of address is all-zeros, - * -1 if not all zeros or on failure. - */ -static int -addr_host_is_all0s(const struct xaddr *a, u_int masklen) -{ - struct xaddr tmp_addr, tmp_mask, tmp_result; - - memcpy(&tmp_addr, a, sizeof(tmp_addr)); - if (addr_hostmask(a->af, masklen, &tmp_mask) == -1) - return (-1); - if (addr_and(&tmp_result, &tmp_addr, &tmp_mask) == -1) - return (-1); - return (addr_is_all0s(&tmp_result)); -} - -/* - * Parse a CIDR address (x.x.x.x/y or xxxx:yyyy::/z). - * Return -1 on parse error, -2 on inconsistency or 0 on success. - */ -static int -addr_pton_cidr(const char *p, struct xaddr *n, u_int *l) -{ - struct xaddr tmp; - long unsigned int masklen = 999; - char addrbuf[64], *mp, *cp; - - /* Don't modify argument */ - if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) >= sizeof(addrbuf)) - return -1; - - if ((mp = strchr(addrbuf, '/')) != NULL) { - *mp = '\0'; - mp++; - masklen = strtoul(mp, &cp, 10); - if (*mp == '\0' || *cp != '\0' || masklen > 128) - return -1; - } - - if (addr_pton(addrbuf, &tmp) == -1) - return -1; - - if (mp == NULL) - masklen = addr_unicast_masklen(tmp.af); - if (masklen_valid(tmp.af, masklen) == -1) - return -2; - if (addr_host_is_all0s(&tmp, masklen) != 0) - return -2; - - if (n != NULL) - memcpy(n, &tmp, sizeof(*n)); - if (l != NULL) - *l = masklen; - - return 0; -} - -static int -addr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen) -{ - struct xaddr tmp_mask, tmp_result; - - if (host->af != net->af) - return -1; - - if (addr_netmask(host->af, masklen, &tmp_mask) == -1) - return -1; - if (addr_and(&tmp_result, host, &tmp_mask) == -1) - return -1; - return addr_cmp(&tmp_result, net); -} - /* * Match "addr" against list pattern list "_list", which may contain a * mix of CIDR addresses and old-school wildcards. @@ -381,7 +54,7 @@ addr_match_list(const char *addr, const char *_list) int ret = 0, r; if (addr != NULL && addr_pton(addr, &try_addr) != 0) { - debug2("%s: couldn't parse address %.100s", __func__, addr); + debug2_f("couldn't parse address %.100s", addr); return 0; } if ((o = list = strdup(_list)) == NULL) @@ -397,8 +70,8 @@ addr_match_list(const char *addr, const char *_list) /* Prefer CIDR address matching */ r = addr_pton_cidr(cp, &match_addr, &masklen); if (r == -2) { - debug2("%s: inconsistent mask length for " - "match network \"%.100s\"", __func__, cp); + debug2_f("inconsistent mask length for " + "match network \"%.100s\"", cp); ret = -2; break; } else if (r == 0) { @@ -441,15 +114,14 @@ addr_match_cidr_list(const char *addr, const char *_list) int ret = 0, r; if (addr != NULL && addr_pton(addr, &try_addr) != 0) { - debug2("%s: couldn't parse address %.100s", __func__, addr); + debug2_f("couldn't parse address %.100s", addr); return 0; } if ((o = list = strdup(_list)) == NULL) return -1; while ((cp = strsep(&list, ",")) != NULL) { if (*cp == '\0') { - error("%s: empty entry in list \"%.100s\"", - __func__, o); + error_f("empty entry in list \"%.100s\"", o); ret = -1; break; } @@ -462,15 +134,14 @@ addr_match_cidr_list(const char *addr, const char *_list) /* Stop junk from reaching getaddrinfo. +3 is for masklen */ if (strlen(cp) > INET6_ADDRSTRLEN + 3) { - error("%s: list entry \"%.100s\" too long", - __func__, cp); + error_f("list entry \"%.100s\" too long", cp); ret = -1; break; } #define VALID_CIDR_CHARS "0123456789abcdefABCDEF.:/" if (strspn(cp, VALID_CIDR_CHARS) != strlen(cp)) { - error("%s: list entry \"%.100s\" contains invalid " - "characters", __func__, cp); + error_f("list entry \"%.100s\" contains invalid " + "characters", cp); ret = -1; } diff --git a/auth-options.c b/auth-options.c index 90b0d7f25..55b2e9b4c 100644 --- a/auth-options.c +++ b/auth-options.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.c,v 1.89 2019/09/13 04:36:43 dtucker Exp $ */ +/* $OpenBSD: auth-options.c,v 1.94 2020/10/18 11:32:01 djm Exp $ */ /* * Copyright (c) 2018 Damien Miller * @@ -79,7 +79,7 @@ cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob, int r, ret = -1, found; if ((c = sshbuf_fromb(oblob)) == NULL) { - error("%s: sshbuf_fromb failed", __func__); + error_f("sshbuf_fromb failed"); goto out; } @@ -88,15 +88,17 @@ cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob, data = NULL; if ((r = sshbuf_get_cstring(c, &name, NULL)) != 0 || (r = sshbuf_froms(c, &data)) != 0) { - error("Unable to parse certificate options: %s", - ssh_err(r)); + error_r(r, "Unable to parse certificate options"); goto out; } debug3("found certificate option \"%.100s\" len %zu", name, sshbuf_len(data)); found = 0; if ((which & OPTIONS_EXTENSIONS) != 0) { - if (strcmp(name, "permit-X11-forwarding") == 0) { + if (strcmp(name, "no-touch-required") == 0) { + opts->no_require_user_presence = 1; + found = 1; + } else if (strcmp(name, "permit-X11-forwarding") == 0) { opts->permit_x11_forwarding_flag = 1; found = 1; } else if (strcmp(name, @@ -116,11 +118,14 @@ cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob, } } if (!found && (which & OPTIONS_CRITICAL) != 0) { - if (strcmp(name, "force-command") == 0) { + if (strcmp(name, "verify-required") == 0) { + opts->require_verify = 1; + found = 1; + } else if (strcmp(name, "force-command") == 0) { if ((r = sshbuf_get_cstring(data, &command, NULL)) != 0) { - error("Unable to parse \"%s\" " - "section: %s", name, ssh_err(r)); + error_r(r, "Unable to parse \"%s\" " + "section", name); goto out; } if (opts->force_command != NULL) { @@ -131,12 +136,11 @@ cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob, } opts->force_command = command; found = 1; - } - if (strcmp(name, "source-address") == 0) { + } else if (strcmp(name, "source-address") == 0) { if ((r = sshbuf_get_cstring(data, &allowed, NULL)) != 0) { - error("Unable to parse \"%s\" " - "section: %s", name, ssh_err(r)); + error_r(r, "Unable to parse \"%s\" " + "section", name); goto out; } if (opts->required_from_host_cert != NULL) { @@ -219,8 +223,7 @@ sshauthopt_free(struct sshauthopt *opts) free(opts->permitlisten[i]); free(opts->permitlisten); - explicit_bzero(opts, sizeof(*opts)); - free(opts); + freezero(opts, sizeof(*opts)); } struct sshauthopt * @@ -347,6 +350,10 @@ sshauthopt_parse(const char *opts, const char **errstrp) ret->permit_agent_forwarding_flag = r == 1; } else if ((r = opt_flag("x11-forwarding", 1, &opts)) != -1) { ret->permit_x11_forwarding_flag = r == 1; + } else if ((r = opt_flag("touch-required", 1, &opts)) != -1) { + ret->no_require_user_presence = r != 1; /* NB. flip */ + } else if ((r = opt_flag("verify-required", 1, &opts)) != -1) { + ret->require_verify = r == 1; } else if ((r = opt_flag("pty", 1, &opts)) != -1) { ret->permit_pty_flag = r == 1; } else if ((r = opt_flag("user-rc", 1, &opts)) != -1) { @@ -567,14 +574,18 @@ sshauthopt_merge(const struct sshauthopt *primary, goto alloc_fail; } - /* Flags are logical-AND (i.e. must be set in both for permission) */ -#define OPTFLAG(x) ret->x = (primary->x == 1) && (additional->x == 1) - OPTFLAG(permit_port_forwarding_flag); - OPTFLAG(permit_agent_forwarding_flag); - OPTFLAG(permit_x11_forwarding_flag); - OPTFLAG(permit_pty_flag); - OPTFLAG(permit_user_rc); -#undef OPTFLAG +#define OPTFLAG_AND(x) ret->x = (primary->x == 1) && (additional->x == 1) +#define OPTFLAG_OR(x) ret->x = (primary->x == 1) || (additional->x == 1) + /* Permissive flags are logical-AND (i.e. must be set in both) */ + OPTFLAG_AND(permit_port_forwarding_flag); + OPTFLAG_AND(permit_agent_forwarding_flag); + OPTFLAG_AND(permit_x11_forwarding_flag); + OPTFLAG_AND(permit_pty_flag); + OPTFLAG_AND(permit_user_rc); + OPTFLAG_AND(no_require_user_presence); + /* Restrictive flags are logical-OR (i.e. must be set in either) */ + OPTFLAG_OR(require_verify); +#undef OPTFLAG_AND /* Earliest expiry time should win */ if (primary->valid_before != 0) @@ -643,6 +654,8 @@ sshauthopt_copy(const struct sshauthopt *orig) OPTSCALAR(cert_authority); OPTSCALAR(force_tun_device); OPTSCALAR(valid_before); + OPTSCALAR(no_require_user_presence); + OPTSCALAR(require_verify); #undef OPTSCALAR #define OPTSTRING(x) \ do { \ @@ -728,9 +741,11 @@ deserialise_array(struct sshbuf *m, char ***ap, size_t *np) *np = n; n = 0; out: - for (i = 0; i < n; i++) - free(a[i]); - free(a); + if (a != NULL) { + for (i = 0; i < n; i++) + free(a[i]); + free(a); + } sshbuf_free(b); return r; } @@ -765,7 +780,7 @@ sshauthopt_serialise(const struct sshauthopt *opts, struct sshbuf *m, { int r = SSH_ERR_INTERNAL_ERROR; - /* Flag and simple integer options */ + /* Flag options */ if ((r = sshbuf_put_u8(m, opts->permit_port_forwarding_flag)) != 0 || (r = sshbuf_put_u8(m, opts->permit_agent_forwarding_flag)) != 0 || (r = sshbuf_put_u8(m, opts->permit_x11_forwarding_flag)) != 0 || @@ -773,7 +788,12 @@ sshauthopt_serialise(const struct sshauthopt *opts, struct sshbuf *m, (r = sshbuf_put_u8(m, opts->permit_user_rc)) != 0 || (r = sshbuf_put_u8(m, opts->restricted)) != 0 || (r = sshbuf_put_u8(m, opts->cert_authority)) != 0 || - (r = sshbuf_put_u64(m, opts->valid_before)) != 0) + (r = sshbuf_put_u8(m, opts->no_require_user_presence)) != 0 || + (r = sshbuf_put_u8(m, opts->require_verify)) != 0) + return r; + + /* Simple integer options */ + if ((r = sshbuf_put_u64(m, opts->valid_before)) != 0) return r; /* tunnel number can be negative to indicate "unset" */ @@ -817,6 +837,7 @@ sshauthopt_deserialise(struct sshbuf *m, struct sshauthopt **optsp) if ((opts = calloc(1, sizeof(*opts))) == NULL) return SSH_ERR_ALLOC_FAIL; + /* Flag options */ #define OPT_FLAG(x) \ do { \ if ((r = sshbuf_get_u8(m, &f)) != 0) \ @@ -830,8 +851,11 @@ sshauthopt_deserialise(struct sshbuf *m, struct sshauthopt **optsp) OPT_FLAG(permit_user_rc); OPT_FLAG(restricted); OPT_FLAG(cert_authority); + OPT_FLAG(no_require_user_presence); + OPT_FLAG(require_verify); #undef OPT_FLAG + /* Simple integer options */ if ((r = sshbuf_get_u64(m, &opts->valid_before)) != 0) goto out; diff --git a/auth-options.h b/auth-options.h index 14cbfa49d..118a32087 100644 --- a/auth-options.h +++ b/auth-options.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.h,v 1.28 2019/07/09 04:15:00 djm Exp $ */ +/* $OpenBSD: auth-options.h,v 1.30 2020/08/27 01:07:09 djm Exp $ */ /* * Copyright (c) 2018 Damien Miller @@ -68,6 +68,11 @@ struct sshauthopt { */ char *required_from_host_cert; char *required_from_host_keys; + + /* Key requires user presence asserted */ + int no_require_user_presence; + /* Key requires user verification (e.g. PIN) */ + int require_verify; }; struct sshauthopt *sshauthopt_new(void); diff --git a/auth-pam.c b/auth-pam.c index d3f400bc3..d429ef13a 100644 --- a/auth-pam.c +++ b/auth-pam.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -99,6 +100,7 @@ extern char *__progname; #include "servconf.h" #include "ssh2.h" #include "auth-options.h" +#include "misc.h" #ifdef GSSAPI #include "ssh-gss.h" #endif @@ -150,12 +152,12 @@ static struct pam_ctxt *cleanup_ctxt; */ static int sshpam_thread_status = -1; -static mysig_t sshpam_oldsig; +static sshsig_t sshpam_oldsig; static void sshpam_sigchld_handler(int sig) { - signal(SIGCHLD, SIG_DFL); + ssh_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) @@ -207,7 +209,7 @@ pthread_create(sp_pthread_t *thread, const void *attr, *thread = pid; close(ctx->pam_csock); ctx->pam_csock = -1; - sshpam_oldsig = signal(SIGCHLD, sshpam_sigchld_handler); + sshpam_oldsig = ssh_signal(SIGCHLD, sshpam_sigchld_handler); return (0); } } @@ -215,7 +217,7 @@ pthread_create(sp_pthread_t *thread, const void *attr, static int pthread_cancel(sp_pthread_t thread) { - signal(SIGCHLD, sshpam_oldsig); + ssh_signal(SIGCHLD, sshpam_oldsig); return (kill(thread, SIGTERM)); } @@ -227,7 +229,7 @@ pthread_join(sp_pthread_t thread, void **value) if (sshpam_thread_status != -1) return (sshpam_thread_status); - signal(SIGCHLD, sshpam_oldsig); + ssh_signal(SIGCHLD, sshpam_oldsig); while (waitpid(thread, &status, 0) == -1) { if (errno == EINTR) continue; @@ -299,7 +301,7 @@ sshpam_chauthtok_ruid(pam_handle_t *pamh, int flags) # define pam_chauthtok(a,b) (sshpam_chauthtok_ruid((a), (b))) #endif -void +static void sshpam_password_change_required(int reqd) { extern struct sshauthopt *auth_opts; @@ -373,7 +375,11 @@ import_environments(struct sshbuf *b) error("PAM: pam_putenv: %s", pam_strerror(sshpam_handle, r)); } - /* XXX leak env? */ + /* + * XXX this possibly leaks env because it is not documented + * what pam_putenv() does with it. Does it copy it? Does it + * take ownweship? We don't know, so it's safest just to leak. + */ } #endif } @@ -683,6 +689,12 @@ sshpam_init(struct ssh *ssh, Authctxt *authctxt) const char *pam_user, *user = authctxt->user; const char **ptr_pam_user = &pam_user; +#if defined(PAM_SUN_CODEBASE) && defined(PAM_MAX_RESP_SIZE) + /* Protect buggy PAM implementations from excessively long usernames */ + if (strlen(user) >= PAM_MAX_RESP_SIZE) + fatal("Username too long from %s port %d", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); +#endif if (sshpam_handle == NULL) { if (ssh == NULL) { fatal("%s: called initially with no " diff --git a/auth-passwd.c b/auth-passwd.c index 1e19e822b..85c9d77a2 100644 --- a/auth-passwd.c +++ b/auth-passwd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-passwd.c,v 1.47 2018/07/09 21:26:02 markus Exp $ */ +/* $OpenBSD: auth-passwd.c,v 1.48 2020/10/18 11:32:01 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -161,14 +161,14 @@ warn_expiry(Authctxt *authctxt, auth_session_t *as) if ((r = sshbuf_putf(loginmsg, "Your password will expire in %lld day%s.\n", daysleft, daysleft == 1 ? "" : "s")) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } if (actimeleft != 0 && actimeleft < acwarntime) { daysleft = actimeleft / DAY + 1; if ((r = sshbuf_putf(loginmsg, "Your account will expire in %lld day%s.\n", daysleft, daysleft == 1 ? "" : "s")) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } } diff --git a/auth-rhosts.c b/auth-rhosts.c index 7a10210b6..0bc4d424c 100644 --- a/auth-rhosts.c +++ b/auth-rhosts.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-rhosts.c,v 1.51 2019/10/02 00:42:30 djm Exp $ */ +/* $OpenBSD: auth-rhosts.c,v 1.53 2020/10/18 11:32:01 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -223,7 +223,7 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, if (!rhosts_files[rhosts_file_index] && stat(_PATH_RHOSTS_EQUIV, &st) == -1 && stat(_PATH_SSH_HOSTS_EQUIV, &st) == -1) { - debug3("%s: no hosts access files exist", __func__); + debug3_f("no hosts access files exist"); return 0; } @@ -232,7 +232,7 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, * shosts.equiv. */ if (pw->pw_uid == 0) - debug3("%s: root user, ignoring system hosts files", __func__); + debug3_f("root user, ignoring system hosts files"); else { if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr, client_user, pw->pw_name)) { @@ -298,7 +298,9 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname, * Check if we have been configured to ignore .rhosts * and .shosts files. */ - if (options.ignore_rhosts) { + if (options.ignore_rhosts == IGNORE_RHOSTS_YES || + (options.ignore_rhosts == IGNORE_RHOSTS_SHOSTS && + strcmp(rhosts_files[rhosts_file_index], ".shosts") != 0)) { auth_debug_add("Server has been configured to " "ignore %.100s.", rhosts_files[rhosts_file_index]); continue; diff --git a/auth-skey.c b/auth-skey.c deleted file mode 100644 index b347527f6..000000000 --- a/auth-skey.c +++ /dev/null @@ -1,107 +0,0 @@ -/* $OpenBSD: auth-skey.c,v 1.27 2007/01/21 01:41:54 stevesk 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 SKEY - -#include - -#include -#include - -#include - -#include "xmalloc.h" -#include "hostfile.h" -#include "auth.h" -#include "ssh-gss.h" -#include "log.h" -#include "monitor_wrap.h" - -static void * -skey_init_ctx(Authctxt *authctxt) -{ - return authctxt; -} - -int -skey_query(void *ctx, char **name, char **infotxt, - u_int* numprompts, char ***prompts, u_int **echo_on) -{ - Authctxt *authctxt = ctx; - char challenge[1024]; - struct skey skey; - - if (_compat_skeychallenge(&skey, authctxt->user, challenge, - sizeof(challenge)) == -1) - return -1; - - *name = xstrdup(""); - *infotxt = xstrdup(""); - *numprompts = 1; - *prompts = xcalloc(*numprompts, sizeof(char *)); - *echo_on = xcalloc(*numprompts, sizeof(u_int)); - - xasprintf(*prompts, "%s%s", challenge, SKEY_PROMPT); - - return 0; -} - -int -skey_respond(void *ctx, u_int numresponses, char **responses) -{ - Authctxt *authctxt = ctx; - - if (authctxt->valid && - numresponses == 1 && - skey_haskey(authctxt->pw->pw_name) == 0 && - skey_passcheck(authctxt->pw->pw_name, responses[0]) != -1) - return 0; - return -1; -} - -static void -skey_free_ctx(void *ctx) -{ - /* we don't have a special context */ -} - -KbdintDevice skey_device = { - "skey", - skey_init_ctx, - skey_query, - skey_respond, - skey_free_ctx -}; - -KbdintDevice mm_skey_device = { - "skey", - skey_init_ctx, - mm_skey_query, - mm_skey_respond, - skey_free_ctx -}; -#endif /* SKEY */ diff --git a/auth.c b/auth.c index 6df668165..ffa1db5d0 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.141 2019/10/02 00:42:30 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.151 2020/12/22 00:12:22 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -84,6 +84,7 @@ /* import */ extern ServerOptions options; +extern struct include_list includes; extern int use_privsep; extern struct sshbuf *loginmsg; extern struct passwd *privsep_pw; @@ -481,7 +482,7 @@ check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host, const struct hostkey_entry *found; hostkeys = init_hostkeys(); - load_hostkeys(hostkeys, host, sysfile); + load_hostkeys(hostkeys, host, sysfile, 0); if (userfile != NULL) { user_hostfile = tilde_expand_filename(userfile, pw->pw_uid); if (options.strict_modes && @@ -495,7 +496,7 @@ check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host, user_hostfile); } else { temporarily_use_uid(pw); - load_hostkeys(hostkeys, host, user_hostfile); + load_hostkeys(hostkeys, host, user_hostfile, 0); restore_uid(); } free(user_hostfile); @@ -503,12 +504,12 @@ check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host, host_status = check_key_in_hostkeys(hostkeys, key, &found); if (host_status == HOST_REVOKED) error("WARNING: revoked key for %s attempted authentication", - found->host); + host); else if (host_status == HOST_OK) - debug("%s: key for %s found at %s:%ld", __func__, + debug_f("key for %s found at %s:%ld", found->host, found->file, found->line); else - debug("%s: key for host %s not found", __func__, host); + debug_f("key for host %s not found", host); free_hostkeys(hostkeys); @@ -600,6 +601,7 @@ getpwnamallow(struct ssh *ssh, const char *user) #endif struct passwd *pw; struct connection_info *ci; + u_int i; ci = get_connection_info(ssh, 1, options.use_dns); #ifdef WINDOWS @@ -611,9 +613,11 @@ getpwnamallow(struct ssh *ssh, const char *user) ci->user = pw? xstrdup(pw->pw_name): user; #else ci->user = user; -#endif // WINDOWS - parse_server_match_config(&options, ci); + parse_server_match_config(&options, &includes, ci); log_change_level(options.log_level); + log_verbose_reset(); + for (i = 0; i < options.num_log_verbose; i++) + log_verbose_add(options.log_verbose[i]); process_permitopen(ssh, &options); #if defined(_AIX) && defined(HAVE_SETAUTHDB) @@ -641,7 +645,7 @@ getpwnamallow(struct ssh *ssh, const char *user) if (!allowed_user(ssh, pw)) return (NULL); #ifdef HAVE_LOGIN_CAP - if ((lc = login_getclass(pw->pw_class)) == NULL) { + if ((lc = login_getpwclass(pw)) == NULL) { debug("unable to get login class: %s", user); return (NULL); } @@ -672,7 +676,7 @@ auth_key_is_revoked(struct sshkey *key) 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)); + error_fr(r, "fingerprint key"); goto out; } @@ -685,9 +689,9 @@ auth_key_is_revoked(struct sshkey *key) 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)); + error_r(r, "Error checking authentication key %s %s in " + "revoked keys file %s", sshkey_type(key), fp, + options.revoked_keys_file); goto out; } @@ -713,7 +717,7 @@ auth_debug_add(const char *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)); + fatal_fr(r, "sshbuf_put_cstring"); } void @@ -726,8 +730,7 @@ auth_debug_send(struct ssh *ssh) 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)); + fatal_fr(r, "sshbuf_get_cstring"); ssh_packet_send_debug(ssh, "%s", msg); free(msg); } @@ -739,7 +742,7 @@ 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__); + fatal_f("sshbuf_new failed"); } struct passwd * @@ -790,7 +793,7 @@ remote_hostname(struct ssh *ssh) if (getpeername(ssh_packet_get_connection_in(ssh), (struct sockaddr *)&from, &fromlen) == -1) { debug("getpeername failed: %.100s", strerror(errno)); - return strdup(ntop); + return xstrdup(ntop); } ipv64_normalise_mapped(&from, &fromlen); @@ -802,7 +805,7 @@ remote_hostname(struct ssh *ssh) if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), NULL, 0, NI_NAMEREQD) != 0) { /* Host name not found. Use ip address. */ - return strdup(ntop); + return xstrdup(ntop); } /* @@ -817,7 +820,7 @@ remote_hostname(struct ssh *ssh) logit("Nasty PTR record \"%s\" is set up for %s, ignoring", name, ntop); freeaddrinfo(ai); - return strdup(ntop); + return xstrdup(ntop); } /* Names are stored in lowercase. */ @@ -838,7 +841,7 @@ remote_hostname(struct ssh *ssh) if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { logit("reverse mapping checking getaddrinfo for %.700s " "[%s] failed.", name, ntop); - return strdup(ntop); + return xstrdup(ntop); } /* Look for the address from the list of addresses. */ for (ai = aitop; ai; ai = ai->ai_next) { @@ -853,9 +856,9 @@ remote_hostname(struct ssh *ssh) /* 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 xstrdup(ntop); } - return strdup(name); + return xstrdup(name); } /* @@ -879,195 +882,6 @@ auth_get_canonical_hostname(struct ssh *ssh, int use_dns) } } -/* - * 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 (!path_absolute(av[0])) { - error("%s path is not absolute", tag); - return 0; - } - temporarily_use_uid(pw); - if (stat(av[0], &st) == -1) { - error("Could not stat %s \"%s\": %s", tag, - av[0], strerror(errno)); - restore_uid(); - return 0; - } -#ifdef WINDOWS - if (check_secure_file_permission(av[0], pw, 1) != 0) { - error("Permissions on %s:\"%s\" are too open", tag, av[0]); - restore_uid(); - return 0; - } -#else - 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; - } -#endif - - /* Prepare to keep the child's stdout if requested */ - if (pipe(p) == -1) { - error("%s: pipe: %s", tag, strerror(errno)); - restore_uid(); - return 0; - } - restore_uid(); - -#ifdef FORK_NOT_SUPPORTED - { - posix_spawn_file_actions_t actions; - pid = -1; - - if (posix_spawn_file_actions_init(&actions) != 0 || - posix_spawn_file_actions_adddup2(&actions, p[1], STDOUT_FILENO) != 0) - fatal("posix_spawn initialization failed"); - else { - /* If the user's SID is the System SID and sshd is running as system, - * launch as a child process. - */ - if (IsWellKnownSid(get_sid(pw->pw_name), WinLocalSystemSid) && am_system()) { - debug("starting subprocess using posix_spawnp"); - if (posix_spawnp((pid_t*)&pid, av[0], &actions, NULL, av, NULL) != 0) - fatal("posix_spawnp: %s", strerror(errno)); - } - else { - debug("starting subprocess as user using __posix_spawn_asuser"); - if (__posix_spawn_asuser((pid_t*)&pid, av[0], &actions, NULL, av, NULL, pw->pw_name) != 0) - fatal("posix_spawn_user: %s", strerror(errno)); - } - } - - posix_spawn_file_actions_destroy(&actions); - } -#else - 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) == -1) { - 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) == -1) { - 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; - } -#endif - - 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 */ @@ -1084,16 +898,18 @@ auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote) 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", + snprintf(msg, sizeof(msg), "key options:%s%s%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", + opts->no_require_user_presence ? " no-touch-required" : "", do_permitopen ? " permitopen" : "", do_permitlisten ? " permitlisten" : "", opts->permit_port_forwarding_flag ? " port-forwarding" : "", opts->cert_principals == NULL ? "" : " principals", opts->permit_pty_flag ? " pty" : "", + opts->require_verify ? " uv" : "", opts->force_tun_device == -1 ? "" : " tun=", opts->force_tun_device == -1 ? "" : buf, opts->permit_user_rc ? " user-rc" : "", @@ -1145,7 +961,7 @@ 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__); + debug_f("setting new authentication options"); if ((auth_opts = sshauthopt_merge(old, opts, &emsg)) == NULL) { error("Inconsistent authentication options: %s", emsg); return -1; @@ -1159,7 +975,7 @@ auth_restrict_session(struct ssh *ssh) { struct sshauthopt *restricted; - debug("%s: restricting session", __func__); + debug_f("restricting session"); /* A blank sshauthopt defaults to permitting nothing */ restricted = sshauthopt_new(); @@ -1167,7 +983,7 @@ auth_restrict_session(struct ssh *ssh) restricted->restricted = 1; if (auth_activate_options(ssh, restricted) != 0) - fatal("%s: failed to restrict session", __func__); + fatal_f("failed to restrict session"); sshauthopt_free(restricted); } @@ -1242,8 +1058,7 @@ auth_authorise_keyopts(struct ssh *ssh, struct passwd *pw, case -1: default: /* invalid */ - error("%s: Certificate source-address invalid", - loc); + error("%s: Certificate source-address invalid", loc); /* FALLTHROUGH */ case 0: logit("%s: Authentication tried for %.100s with valid " diff --git a/auth.h b/auth.h index becc672b5..43c7d3d40 100644 --- a/auth.h +++ b/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.100 2019/09/06 05:23:55 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.101 2020/12/22 00:12:22 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -225,12 +225,6 @@ 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) diff --git a/auth2-chall.c b/auth2-chall.c index 671f2f05f..021df8291 100644 --- a/auth2-chall.c +++ b/auth2-chall.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-chall.c,v 1.51 2019/09/06 04:53:27 djm Exp $ */ +/* $OpenBSD: auth2-chall.c,v 1.54 2020/10/18 11:32:01 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Per Allansson. All rights reserved. @@ -29,9 +29,9 @@ #include #include -#include #include #include +#include #include "xmalloc.h" #include "ssh2.h" @@ -112,15 +112,14 @@ kbdint_alloc(const char *devs) kbdintctxt = xcalloc(1, sizeof(KbdintAuthctxt)); if (strcmp(devs, "") == 0) { if ((b = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); for (i = 0; devices[i]; i++) { if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) ? "," : "", devices[i]->name)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } if ((kbdintctxt->devices = sshbuf_dup_string(b)) == NULL) - fatal("%s: sshbuf_dup_string failed", __func__); + fatal_f("sshbuf_dup_string failed"); sshbuf_free(b); } else { kbdintctxt->devices = xstrdup(devs); @@ -147,8 +146,7 @@ kbdint_free(KbdintAuthctxt *kbdintctxt) if (kbdintctxt->device) kbdint_reset_device(kbdintctxt); free(kbdintctxt->devices); - explicit_bzero(kbdintctxt, sizeof(*kbdintctxt)); - free(kbdintctxt); + freezero(kbdintctxt, sizeof(*kbdintctxt)); } /* get next device */ static int @@ -269,15 +267,15 @@ send_userauth_info_request(struct ssh *ssh) (r = sshpkt_put_cstring(ssh, instr)) != 0 || (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language not used */ (r = sshpkt_put_u32(ssh, kbdintctxt->nreq)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "start packet"); for (i = 0; i < kbdintctxt->nreq; i++) { if ((r = sshpkt_put_cstring(ssh, prompts[i])) != 0 || (r = sshpkt_put_u8(ssh, echo_on[i])) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble packet"); } if ((r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "send packet"); for (i = 0; i < kbdintctxt->nreq; i++) free(prompts[i]); @@ -300,29 +298,29 @@ input_userauth_info_response(int type, u_int32_t seq, struct ssh *ssh) char **response = NULL; if (authctxt == NULL) - fatal("input_userauth_info_response: no authctxt"); + fatal_f("no authctxt"); kbdintctxt = authctxt->kbdintctxt; if (kbdintctxt == NULL || kbdintctxt->ctxt == NULL) - fatal("input_userauth_info_response: no kbdintctxt"); + fatal_f("no kbdintctxt"); if (kbdintctxt->device == NULL) - fatal("input_userauth_info_response: no device"); + fatal_f("no device"); authctxt->postponed = 0; /* reset */ if ((r = sshpkt_get_u32(ssh, &nresp)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse packet"); if (nresp != kbdintctxt->nreq) - fatal("input_userauth_info_response: wrong number of replies"); + fatal_f("wrong number of replies"); if (nresp > 100) - fatal("input_userauth_info_response: too many replies"); + fatal_f("too many replies"); if (nresp > 0) { response = xcalloc(nresp, sizeof(char *)); - for (i = 0; i < nresp; i++) - if ((r = sshpkt_get_cstring(ssh, &response[i], - NULL)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + for (i = 0; i < nresp; i++) { + if ((r = sshpkt_get_cstring(ssh, &response[i], NULL)) != 0) + fatal_fr(r, "parse response"); + } } if ((r = sshpkt_get_end(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse packet"); res = kbdintctxt->device->respond(kbdintctxt->ctxt, nresp, response); diff --git a/auth2-gss.c b/auth2-gss.c index 9351e0428..60e36961c 100644 --- a/auth2-gss.c +++ b/auth2-gss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-gss.c,v 1.29 2018/07/31 03:10:27 djm Exp $ */ +/* $OpenBSD: auth2-gss.c,v 1.32 2021/01/27 10:15:08 djm Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. @@ -44,6 +44,7 @@ #include "misc.h" #include "servconf.h" #include "packet.h" +#include "kex.h" #include "ssh-gss.h" #include "monitor_wrap.h" @@ -71,7 +72,7 @@ userauth_gssapi(struct ssh *ssh) u_char *doid = NULL; if ((r = sshpkt_get_u32(ssh, &mechs)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse packet"); if (mechs == 0) { debug("Mechanism negotiation is not supported"); @@ -85,7 +86,7 @@ userauth_gssapi(struct ssh *ssh) present = 0; if ((r = sshpkt_get_string(ssh, &doid, &len)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse oid"); if (len > 2 && doid[0] == SSH_GSS_OIDTYPE && doid[1] == len - 2) { @@ -104,7 +105,7 @@ userauth_gssapi(struct ssh *ssh) } if (!authctxt->valid || authctxt->user == NULL) { - debug2("%s: disabled because of invalid user", __func__); + debug2_f("disabled because of invalid user"); free(doid); return (0); } @@ -123,7 +124,7 @@ userauth_gssapi(struct ssh *ssh) if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE)) != 0 || (r = sshpkt_put_string(ssh, doid, len)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "send packet"); free(doid); @@ -152,7 +153,7 @@ input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh) gssctxt = authctxt->methoddata; if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || (r = sshpkt_get_end(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse packet"); recv_tok.value = p; recv_tok.length = len; @@ -168,7 +169,7 @@ input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh) (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "send ERRTOK packet"); } authctxt->postponed = 0; ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); @@ -180,7 +181,7 @@ input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh) (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "send TOKEN packet"); } if (maj_status == GSS_S_COMPLETE) { ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); @@ -216,7 +217,7 @@ input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh) gssctxt = authctxt->methoddata; if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || (r = sshpkt_get_end(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse packet"); recv_tok.value = p; recv_tok.length = len; @@ -258,7 +259,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh) */ if ((r = sshpkt_get_end(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse packet"); authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); @@ -293,16 +294,16 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) gssctxt = authctxt->methoddata; if ((r = sshpkt_get_string(ssh, &p, &len)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse packet"); if ((b = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); mic.value = p; mic.length = len; ssh_gssapi_buildmic(b, authctxt->user, authctxt->service, - "gssapi-with-mic"); + "gssapi-with-mic", ssh->kex->session_id); if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) - fatal("%s: sshbuf_mutable_ptr failed", __func__); + fatal_f("sshbuf_mutable_ptr failed"); gssbuf.length = sshbuf_len(b); if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) diff --git a/auth2-hostbased.c b/auth2-hostbased.c index d46047084..002e7e4ee 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.41 2019/09/06 04:53:27 djm Exp $ */ +/* $OpenBSD: auth2-hostbased.c,v 1.46 2021/01/27 10:05:28 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -35,6 +35,7 @@ #include "xmalloc.h" #include "ssh2.h" #include "packet.h" +#include "kex.h" #include "sshbuf.h" #include "log.h" #include "misc.h" @@ -54,8 +55,6 @@ /* import */ extern ServerOptions options; -extern u_char *session_id2; -extern u_int session_id2_len; static int userauth_hostbased(struct ssh *ssh) @@ -74,9 +73,9 @@ userauth_hostbased(struct ssh *ssh) (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)); + fatal_fr(r, "parse packet"); - debug("%s: cuser %s chost %s pkalg %s slen %zu", __func__, + debug_f("cuser %s chost %s pkalg %s slen %zu", cuser, chost, pkalg, slen); #ifdef DEBUG_PK debug("signature:"); @@ -85,21 +84,21 @@ userauth_hostbased(struct ssh *ssh) pktype = sshkey_type_from_name(pkalg); if (pktype == KEY_UNSPEC) { /* this is perfectly legal */ - logit("%s: unsupported public key algorithm: %s", - __func__, pkalg); + logit_f("unsupported public key algorithm: %s", + pkalg); goto done; } if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { - error("%s: key_from_blob: %s", __func__, ssh_err(r)); + error_fr(r, "key_from_blob"); goto done; } if (key == NULL) { - error("%s: cannot decode key: %s", __func__, pkalg); + error_f("cannot decode key: %s", pkalg); goto done; } if (key->type != pktype) { - error("%s: type mismatch for decoded key " - "(received %d, expected %d)", __func__, key->type, pktype); + error_f("type mismatch for decoded key " + "(received %d, expected %d)", key->type, pktype); goto done; } if (sshkey_type_plain(key->type) == KEY_RSA && @@ -108,28 +107,28 @@ userauth_hostbased(struct ssh *ssh) "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)); + if (match_pattern_list(pkalg, options.hostbased_accepted_algos, 0) != 1) { + logit_f("key type %s not in HostbasedAcceptedAlgorithms", + 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__, + logit_fr(r, "certificate signature algorithm %s", (key->cert == NULL || key->cert->signature_type == NULL) ? - "(null)" : key->cert->signature_type, ssh_err(r)); + "(null)" : key->cert->signature_type); goto done; } if (!authctxt->valid || authctxt->user == NULL) { - debug2("%s: disabled because of invalid user", __func__); + debug2_f("disabled because of invalid user"); goto done; } if ((b = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); /* reconstruct packet */ - if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 || + if ((r = sshbuf_put_stringb(b, ssh->kex->session_id)) != 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 || @@ -138,7 +137,7 @@ userauth_hostbased(struct ssh *ssh) (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)); + fatal_fr(r, "reconstruct packet"); #ifdef DEBUG_PK sshbuf_dump(b, stderr); #endif @@ -151,13 +150,13 @@ userauth_hostbased(struct ssh *ssh) 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) + sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat, NULL)) == 0) authenticated = 1; auth2_record_key(authctxt, authenticated, key); sshbuf_free(b); done: - debug2("%s: authenticated %d", __func__, authenticated); + debug2_f("authenticated %d", authenticated); sshkey_free(key); free(pkalg); free(pkblob); @@ -183,7 +182,7 @@ hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, resolvedname = auth_get_canonical_hostname(ssh, options.use_dns); ipaddr = ssh_remote_ipaddr(ssh); - debug2("%s: chost %s resolvedname %s ipaddr %s", __func__, + debug2_f("chost %s resolvedname %s ipaddr %s", chost, resolvedname, ipaddr); if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') { @@ -193,9 +192,8 @@ hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, 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); + debug2_f("auth_rhosts2 refused user \"%.100s\" " + "host \"%.100s\" (from packet)", cuser, chost); return 0; } lookup = chost; @@ -205,17 +203,17 @@ hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, "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 " + debug2_f("auth_rhosts2 refused " "user \"%.100s\" host \"%.100s\" addr \"%.100s\"", - __func__, cuser, resolvedname, ipaddr); + cuser, resolvedname, ipaddr); return 0; } lookup = resolvedname; } - debug2("%s: access allowed by auth_rhosts2", __func__); + debug2_f("access allowed by auth_rhosts2"); if (sshkey_is_cert(key) && - sshkey_cert_check_authority(key, 1, 0, lookup, &reason)) { + sshkey_cert_check_authority(key, 1, 0, 0, lookup, &reason)) { error("%s", reason); auth_debug_add("%s", reason); return 0; @@ -237,7 +235,7 @@ hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, 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__); + fatal_f("sshkey_fingerprint fail"); verbose("Accepted certificate ID \"%s\" signed by " "%s CA %s from %s@%s", key->cert->key_id, sshkey_type(key->cert->signature_key), fp, @@ -245,7 +243,7 @@ hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, } else { if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) - fatal("%s: sshkey_fingerprint fail", __func__); + fatal_f("sshkey_fingerprint fail"); verbose("Accepted %s public key %s from %s@%s", sshkey_type(key), fp, cuser, lookup); } diff --git a/auth2-kbdint.c b/auth2-kbdint.c index f88ef2c39..111f2d29f 100644 --- a/auth2-kbdint.c +++ b/auth2-kbdint.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-kbdint.c,v 1.10 2019/09/06 04:53:27 djm Exp $ */ +/* $OpenBSD: auth2-kbdint.c,v 1.12 2020/10/18 11:32:01 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -27,10 +27,9 @@ #include -#include - #include #include +#include #include "xmalloc.h" #include "packet.h" @@ -53,7 +52,7 @@ userauth_kbdint(struct ssh *ssh) if ((r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &devs, NULL)) != 0 || (r = sshpkt_get_end(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse packet"); debug("keyboard-interactive devs %s", devs); diff --git a/auth2-none.c b/auth2-none.c index dacb5fb83..02d6e341c 100644 --- a/auth2-none.c +++ b/auth2-none.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-none.c,v 1.22 2018/07/09 21:35:50 markus Exp $ */ +/* $OpenBSD: auth2-none.c,v 1.23 2020/10/18 11:32:01 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -65,7 +65,7 @@ userauth_none(struct ssh *ssh) none_enabled = 0; if ((r = sshpkt_get_end(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse packet"); if (options.permit_empty_passwd && options.password_authentication) return (PRIVSEP(auth_password(ssh, ""))); return (0); diff --git a/auth2-passwd.c b/auth2-passwd.c index 6601e8664..be4b8606a 100644 --- a/auth2-passwd.c +++ b/auth2-passwd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-passwd.c,v 1.17 2019/09/06 04:53:27 djm Exp $ */ +/* $OpenBSD: auth2-passwd.c,v 1.19 2020/10/18 11:32:01 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -60,14 +60,13 @@ userauth_passwd(struct ssh *ssh) (r = sshpkt_get_cstring(ssh, &password, &len)) != 0 || (change && (r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0) || (r = sshpkt_get_end(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse packet"); if (change) logit("password change not supported"); else if (PRIVSEP(auth_password(ssh, password)) == 1) authenticated = 1; - explicit_bzero(password, len); - free(password); + freezero(password, len); return authenticated; } diff --git a/auth2-pubkey.c b/auth2-pubkey.c index d342ca681..d18f6f027 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.94 2019/09/06 04:53:27 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.106 2021/01/27 10:05:28 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -47,6 +47,7 @@ #include "ssh.h" #include "ssh2.h" #include "packet.h" +#include "kex.h" #include "sshbuf.h" #include "log.h" #include "misc.h" @@ -68,11 +69,10 @@ #include "ssherr.h" #include "channels.h" /* XXX for session.h */ #include "session.h" /* XXX for child_set_env(); refactor? */ +#include "sk-api.h" /* import */ extern ServerOptions options; -extern u_char *session_id2; -extern u_int session_id2_len; static char * format_key(const struct sshkey *key) @@ -96,23 +96,24 @@ userauth_pubkey(struct ssh *ssh) u_char *pkblob = NULL, *sig = NULL, have_sig; size_t blen, slen; int r, pktype; - int authenticated = 0; + int req_presence = 0, req_verify = 0, authenticated = 0; struct sshauthopt *authopts = NULL; + struct sshkey_sig_details *sig_details = 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)); + fatal_fr(r, "parse packet"); 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__); + fatal_f("sshbuf_from failed"); if ((keystring = sshbuf_dtob64_string(pkbuf, 0)) == NULL) - fatal("%s: sshbuf_dtob64 failed", __func__); - debug2("%s: %s user %s %s public key %s %s", __func__, + fatal_f("sshbuf_dtob64 failed"); + debug2_f("%s user %s %s public key %s %s", authctxt->valid ? "valid" : "invalid", authctxt->user, have_sig ? "attempting" : "querying", pkalg, keystring); sshbuf_free(pkbuf); @@ -122,21 +123,20 @@ userauth_pubkey(struct ssh *ssh) pktype = sshkey_type_from_name(pkalg); if (pktype == KEY_UNSPEC) { /* this is perfectly legal */ - verbose("%s: unsupported public key algorithm: %s", - __func__, pkalg); + verbose_f("unsupported public key algorithm: %s", pkalg); goto done; } if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { - error("%s: could not parse key: %s", __func__, ssh_err(r)); + error_fr(r, "parse key"); goto done; } if (key == NULL) { - error("%s: cannot decode key: %s", __func__, pkalg); + error_f("cannot decode key: %s", pkalg); goto done; } if (key->type != pktype) { - error("%s: type mismatch for decoded key " - "(received %d, expected %d)", __func__, key->type, pktype); + error_f("type mismatch for decoded key " + "(received %d, expected %d)", key->type, pktype); goto done; } if (sshkey_type_plain(key->type) == KEY_RSA && @@ -149,16 +149,16 @@ userauth_pubkey(struct ssh *ssh) 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)); + if (match_pattern_list(pkalg, options.pubkey_accepted_algos, 0) != 1) { + logit_f("key type %s not in PubkeyAcceptedAlgorithms", + 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__, + logit_fr(r, "certificate signature algorithm %s", (key->cert == NULL || key->cert->signature_type == NULL) ? - "(null)" : key->cert->signature_type, ssh_err(r)); + "(null)" : key->cert->signature_type); goto done; } key_s = format_key(key); @@ -166,30 +166,24 @@ userauth_pubkey(struct ssh *ssh) 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); + debug3_f("have %s signature for %s%s%s", 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)); + fatal_fr(r, "parse signature packet"); if ((b = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + if ((r = sshbuf_putb(b, ssh->kex->session_id)) != 0) + fatal_fr(r, "put old session id"); } 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 ((r = sshbuf_put_stringb(b, + ssh->kex->session_id)) != 0) + fatal_fr(r, "put session id"); } - if (!authctxt->valid || authctxt->user == NULL) { - debug2("%s: disabled because of invalid user", - __func__); - goto done; + if (!authctxt->valid || authctxt->user == NULL) { + debug2_f("disabled because of invalid user"); + goto done; } /* reconstruct packet */ xasprintf(&userstyle, "%s%s%s", authctxt->user, @@ -202,8 +196,7 @@ userauth_pubkey(struct ssh *ssh) (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)); + fatal_fr(r, "reconstruct packet"); #ifdef DEBUG_PK sshbuf_dump(b, stderr); #endif @@ -213,22 +206,54 @@ userauth_pubkey(struct ssh *ssh) PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), (ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL, - ssh->compat)) == 0) { + ssh->compat, &sig_details)) == 0) { authenticated = 1; } + if (authenticated == 1 && sig_details != NULL) { + auth2_record_info(authctxt, "signature count = %u", + sig_details->sk_counter); + debug_f("sk_counter = %u, sk_flags = 0x%02x", + sig_details->sk_counter, sig_details->sk_flags); + req_presence = (options.pubkey_auth_options & + PUBKEYAUTH_TOUCH_REQUIRED) || + !authopts->no_require_user_presence; + if (req_presence && (sig_details->sk_flags & + SSH_SK_USER_PRESENCE_REQD) == 0) { + error("public key %s signature for %s%s from " + "%.128s port %d rejected: user presence " + "(authenticator touch) requirement " + "not met ", key_s, + authctxt->valid ? "" : "invalid user ", + authctxt->user, ssh_remote_ipaddr(ssh), + ssh_remote_port(ssh)); + authenticated = 0; + goto done; + } + req_verify = (options.pubkey_auth_options & + PUBKEYAUTH_VERIFY_REQUIRED) || + authopts->require_verify; + if (req_verify && (sig_details->sk_flags & + SSH_SK_USER_VERIFICATION_REQD) == 0) { + error("public key %s signature for %s%s from " + "%.128s port %d rejected: user " + "verification requirement not met ", key_s, + authctxt->valid ? "" : "invalid user ", + authctxt->user, ssh_remote_ipaddr(ssh), + ssh_remote_port(ssh)); + authenticated = 0; + goto done; + } + } 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); + debug_f("test pkalg %s pkblob %s%s%s", 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)); + fatal_fr(r, "parse packet"); if (!authctxt->valid || authctxt->user == NULL) { - debug2("%s: disabled because of invalid user", - __func__); + debug2_f("disabled because of invalid user"); goto done; } /* XXX fake reply and always send PK_OK ? */ @@ -246,16 +271,16 @@ userauth_pubkey(struct ssh *ssh) (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)); + fatal_fr(r, "send packet"); authctxt->postponed = 1; } } done: if (authenticated == 1 && auth_activate_options(ssh, authopts) != 0) { - debug("%s: key options inconsistent with existing", __func__); + debug_f("key options inconsistent with existing"); authenticated = 0; } - debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg); + debug2_f("authenticated %d pkalg %s", authenticated, pkalg); sshbuf_free(b); sshauthopt_free(authopts); @@ -266,6 +291,7 @@ done: free(key_s); free(ca_s); free(sig); + sshkey_sig_details_free(sig_details); return authenticated; } @@ -442,7 +468,7 @@ match_principals_command(struct ssh *ssh, struct passwd *user_pw, * NB. all returns later this function should go via "out" to * ensure the original SIGCHLD handler is restored properly. */ - osigchld = signal(SIGCHLD, SIG_DFL); + osigchld = ssh_signal(SIGCHLD, SIG_DFL); /* Prepare and verify the user for the command */ username = percent_expand(options.authorized_principals_command_user, @@ -467,20 +493,20 @@ match_principals_command(struct ssh *ssh, struct passwd *user_pw, } if ((ca_fp = sshkey_fingerprint(cert->signature_key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { - error("%s: sshkey_fingerprint failed", __func__); + error_f("sshkey_fingerprint failed"); goto out; } if ((key_fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { - error("%s: sshkey_fingerprint failed", __func__); + error_f("sshkey_fingerprint failed"); goto out; } if ((r = sshkey_to_base64(cert->signature_key, &catext)) != 0) { - error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r)); + error_fr(r, "sshkey_to_base64 failed"); goto out; } if ((r = sshkey_to_base64(key, &keytext)) != 0) { - error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r)); + error_fr(r, "sshkey_to_base64 failed"); goto out; } snprintf(serial_s, sizeof(serial_s), "%llu", @@ -502,16 +528,17 @@ match_principals_command(struct ssh *ssh, struct passwd *user_pw, "s", serial_s, (char *)NULL); if (tmp == NULL) - fatal("%s: percent_expand failed", __func__); + fatal_f("percent_expand failed"); 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, + if ((pid = subprocess("AuthorizedPrincipalsCommand", command, ac, av, &f, - SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0) + SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, + runas_pw, temporarily_use_uid, restore_uid)) == 0) goto out; uid_swapped = 1; @@ -530,7 +557,7 @@ match_principals_command(struct ssh *ssh, struct passwd *user_pw, out: if (f != NULL) fclose(f); - signal(SIGCHLD, osigchld); + ssh_signal(SIGCHLD, osigchld); for (i = 0; i < ac; i++) free(av[i]); free(av); @@ -565,7 +592,7 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key, *authoptsp = NULL; if ((found = sshkey_new(want_keytype)) == NULL) { - debug3("%s: keytype %d failed", __func__, want_keytype); + debug3_f("keytype %d failed", want_keytype); goto out; } @@ -607,7 +634,7 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key, /* 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__); + fatal_f("fingerprint failed"); debug("%s: matching %s found: %s %s", loc, sshkey_is_cert(key) ? "CA" : "key", sshkey_type(found), fp); @@ -652,7 +679,7 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key, reason = "Certificate does not contain an authorized principal"; goto fail_reason; } - if (sshkey_cert_check_authority(key, 0, 0, + if (sshkey_cert_check_authority(key, 0, 0, 0, keyopts->cert_principals == NULL ? pw->pw_name : NULL, &reason) != 0) goto fail_reason; @@ -664,7 +691,7 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key, success: if (finalopts == NULL) - fatal("%s: internal error: missing options", __func__); + fatal_f("internal error: missing options"); if (authoptsp != NULL) { *authoptsp = finalopts; finalopts = NULL; @@ -743,9 +770,9 @@ user_cert_trusted_ca(struct ssh *ssh, struct passwd *pw, struct sshkey *key, 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__, + debug2_fr(r, "CA %s %s is not listed in %s", sshkey_type(key->cert->signature_key), ca_fp, - options.trusted_user_ca_keys, ssh_err(r)); + options.trusted_user_ca_keys); goto out; } /* @@ -770,8 +797,8 @@ user_cert_trusted_ca(struct ssh *ssh, struct passwd *pw, struct sshkey *key, 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, + fatal_f("internal error: missing principals_opts"); + if (sshkey_cert_check_authority(key, 0, 1, 0, use_authorized_principals ? NULL : pw->pw_name, &reason) != 0) goto fail_reason; @@ -880,7 +907,7 @@ user_key_command_allowed2(struct ssh *ssh, struct passwd *user_pw, * NB. all returns later this function should go via "out" to * ensure the original SIGCHLD handler is restored properly. */ - osigchld = signal(SIGCHLD, SIG_DFL); + osigchld = ssh_signal(SIGCHLD, SIG_DFL); /* Prepare and verify the user for the command */ username = percent_expand(options.authorized_keys_command_user, @@ -895,23 +922,23 @@ user_key_command_allowed2(struct ssh *ssh, struct passwd *user_pw, /* Prepare AuthorizedKeysCommand */ if ((key_fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { - error("%s: sshkey_fingerprint failed", __func__); + error_f("sshkey_fingerprint failed"); goto out; } if ((r = sshkey_to_base64(key, &keytext)) != 0) { - error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r)); + error_fr(r, "sshkey_to_base64 failed"); 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); + options.authorized_keys_command); goto out; } if (ac == 0) { error("AuthorizedKeysCommand \"%s\" yielded no arguments", - command); + options.authorized_keys_command); goto out; } snprintf(uidstr, sizeof(uidstr), "%llu", @@ -926,7 +953,7 @@ user_key_command_allowed2(struct ssh *ssh, struct passwd *user_pw, "k", keytext, (char *)NULL); if (tmp == NULL) - fatal("%s: percent_expand failed", __func__); + fatal_f("percent_expand failed"); free(av[i]); av[i] = tmp; } @@ -947,9 +974,10 @@ user_key_command_allowed2(struct ssh *ssh, struct passwd *user_pw, xasprintf(&command, "%s %s", av[0], av[1]); } - if ((pid = subprocess("AuthorizedKeysCommand", runas_pw, command, + if ((pid = subprocess("AuthorizedKeysCommand", command, ac, av, &f, - SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0) + SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, + runas_pw, temporarily_use_uid, restore_uid)) == 0) goto out; uid_swapped = 1; @@ -969,7 +997,7 @@ user_key_command_allowed2(struct ssh *ssh, struct passwd *user_pw, out: if (f != NULL) fclose(f); - signal(SIGCHLD, osigchld); + ssh_signal(SIGCHLD, osigchld); for (i = 0; i < ac; i++) free(av[i]); free(av); diff --git a/auth2.c b/auth2.c index 0e7762242..3c8a67bbc 100644 --- a/auth2.c +++ b/auth2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2.c,v 1.157 2019/09/06 04:53:27 djm Exp $ */ +/* $OpenBSD: auth2.c,v 1.160 2021/01/27 10:05:28 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -61,8 +61,6 @@ /* import */ extern ServerOptions options; -extern u_char *session_id2; -extern u_int session_id2_len; extern struct sshbuf *loginmsg; /* methods */ @@ -145,7 +143,7 @@ userauth_send_banner(struct ssh *ssh, const char *msg) (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)); + fatal_fr(r, "send packet"); debug("%s: sent", __func__); } @@ -217,7 +215,7 @@ input_service_request(int type, u_int32_t seq, struct ssh *ssh) r = 0; out: free(service); - return 0; + return r; } #define MIN_FAIL_DELAY_SECONDS 0.005 @@ -232,11 +230,11 @@ user_specific_delay(const char *user) (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__); + fatal_f("ssh_digest_memory"); /* 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); + debug3_f("user specific delay %0.3lfms", delay/1000); return MIN_FAIL_DELAY_SECONDS + delay; } @@ -252,8 +250,8 @@ ensure_minimum_time_since(double start, double seconds) 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); + debug3_f("elapsed %0.3lfms, delaying %0.3lfms (requested %0.3lfms)", + elapsed*1000, remain*1000, req*1000); nanosleep(&ts, NULL); } @@ -286,8 +284,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) authctxt->user = xstrdup(user); if (authctxt->pw && strcmp(service, "ssh-connection")==0) { authctxt->valid = 1; - debug2("%s: setting up authctxt for %s", - __func__, user); + debug2_f("setting up authctxt for %s", user); } else { /* Invalid user, fake password information */ authctxt->pw = fakepw(); @@ -390,20 +387,20 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, #ifdef USE_PAM if (options.use_pam && authenticated) { - int r; + int r, success = PRIVSEP(do_pam_account()); - 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(ssh, sshbuf_ptr(loginmsg)); - if ((r = ssh_packet_write_wait(ssh)) != 0) { - sshpkt_fatal(ssh, r, - "%s: send PAM banner", __func__); - } + /* 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(ssh, sshbuf_ptr(loginmsg)); + if ((r = ssh_packet_write_wait(ssh)) != 0) { + sshpkt_fatal(ssh, r, + "%s: send PAM banner", __func__); } + } + if (!success) { fatal("Access denied for user %s by PAM account " "configuration", authctxt->user); } @@ -417,7 +414,7 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, 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)); + fatal_fr(r, "send success packet"); /* now we can break out */ authctxt->success = 1; ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); @@ -433,14 +430,14 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, auth_maxtries_exceeded(ssh); } methods = authmethods_get(authctxt); - debug3("%s: failure partial=%d next methods=\"%s\"", __func__, + debug3_f("failure partial=%d next methods=\"%s\"", partial, methods); 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)); + fatal_fr(r, "send failure packet"); free(methods); } } @@ -478,7 +475,7 @@ authmethods_get(Authctxt *authctxt) int i, r; if ((b = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); for (i = 0; authmethods[i] != NULL; i++) { if (strcmp(authmethods[i]->name, "none") == 0) continue; @@ -490,10 +487,10 @@ authmethods_get(Authctxt *authctxt) continue; if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) ? "," : "", authmethods[i]->name)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } if ((list = sshbuf_dup_string(b)) == NULL) - fatal("%s: sshbuf_dup_string failed", __func__); + fatal_f("sshbuf_dup_string failed"); sshbuf_free(b); return list; } @@ -585,7 +582,7 @@ auth2_setup_methods_lists(Authctxt *authctxt) if (options.num_auth_methods == 0) return 0; - debug3("%s: checking methods", __func__); + debug3_f("checking methods"); authctxt->auth_methods = xcalloc(options.num_auth_methods, sizeof(*authctxt->auth_methods)); authctxt->num_auth_methods = 0; @@ -673,7 +670,7 @@ auth2_update_methods_lists(Authctxt *authctxt, const char *method, { u_int i, found = 0; - debug3("%s: updating methods list after \"%s\"", __func__, method); + debug3_f("updating methods list after \"%s\"", method); for (i = 0; i < authctxt->num_auth_methods; i++) { if (!remove_method(&(authctxt->auth_methods[i]), method, submethod)) @@ -688,7 +685,7 @@ auth2_update_methods_lists(Authctxt *authctxt, const char *method, } /* This should not happen, but would be bad if it did */ if (!found) - fatal("%s: method not in AuthenticationMethods", __func__); + fatal_f("method not in AuthenticationMethods"); return 0; } @@ -716,7 +713,7 @@ auth2_record_info(Authctxt *authctxt, const char *fmt, ...) va_end(ap); if (i == -1) - fatal("%s: vasprintf failed", __func__); + fatal_f("vasprintf failed"); } /* @@ -732,7 +729,7 @@ auth2_record_key(Authctxt *authctxt, int authenticated, int r; if ((r = sshkey_from_private(key, &dup)) != 0) - fatal("%s: copy key: %s", __func__, ssh_err(r)); + fatal_fr(r, "copy key"); sshkey_free(authctxt->auth_method_key); authctxt->auth_method_key = dup; @@ -741,11 +738,11 @@ auth2_record_key(Authctxt *authctxt, int authenticated, /* 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)); + fatal_fr(r, "copy key"); 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__); + fatal_f("reallocarray failed"); authctxt->prev_keys = tmp; authctxt->prev_keys[authctxt->nprev_keys] = dup; authctxt->nprev_keys++; @@ -763,7 +760,7 @@ auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key) 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__, + debug3_f("key already used: %s %s", sshkey_type(authctxt->prev_keys[i]), fp == NULL ? "UNKNOWN" : fp); free(fp); @@ -785,35 +782,34 @@ auth2_update_session_info(Authctxt *authctxt, const char *method, if (authctxt->session_info == NULL) { if ((authctxt->session_info = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); } /* 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)); + fatal_fr(r, "append method"); /* 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)); + fatal_fr(r, "append key"); } 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__); + fatal_f("auth_method_info contains \\n"); 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)); + fatal_fr(r, "append method info"); } } if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0) - fatal("%s: append: %s", __func__, ssh_err(r)); + fatal_fr(r, "append"); } diff --git a/authfd.c b/authfd.c index a5162790f..9f092f7cf 100644 --- a/authfd.c +++ b/authfd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.c,v 1.117 2019/09/03 08:29:15 djm Exp $ */ +/* $OpenBSD: authfd.c,v 1.127 2021/01/26 00:46:17 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -44,8 +44,8 @@ #include #include #include -#include #include +#include #include #include @@ -62,7 +62,7 @@ #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 */ +#define MAX_AGENT_REPLY_LEN (256 * 1024) /* Max bytes in agent reply */ /* macro to check for "agent failure" message */ #define agent_failed(x) \ @@ -82,21 +82,16 @@ decode_reply(u_char type) return SSH_ERR_INVALID_FORMAT; } -/* Returns the number of the authentication fd, or -1 if there is none. */ +/* + * Opens an authentication socket at the provided path and stores the file + * descriptor in fdp. Returns 0 on success and an error on failure. + */ int -ssh_get_authentication_socket(int *fdp) +ssh_get_authentication_socket_path(const char *authsocket, 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 == 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)); @@ -119,6 +114,25 @@ ssh_get_authentication_socket(int *fdp) return 0; } +/* + * Opens the default authentication socket and stores the file descriptor in + * fdp. Returns 0 on success and an error on failure. + */ +int +ssh_get_authentication_socket(int *fdp) +{ + const char *authsocket; + + if (fdp != NULL) + *fdp = -1; + + authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); + if (authsocket == NULL || *authsocket == '\0') + return SSH_ERR_AGENT_NOT_PRESENT; + + return ssh_get_authentication_socket_path(authsocket, fdp); +} + /* Communicate with agent: send request and read reply */ static int ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply) @@ -163,6 +177,27 @@ ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply) return 0; } +/* Communicate with agent: sent request, read and decode status reply */ +static int +ssh_request_reply_decode(int sock, struct sshbuf *request) +{ + struct sshbuf *reply; + int r; + u_char type; + + if ((reply = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = ssh_request_reply(sock, request, reply)) != 0 || + (r = sshbuf_get_u8(reply, &type)) != 0 || + (r = decode_reply(type)) != 0) + goto out; + /* success */ + r = 0; + out: + sshbuf_free(reply); + return r; +} + /* * Closes the agent socket if it should be closed (depends on how it was * obtained). The argument must have been returned by @@ -186,13 +221,11 @@ ssh_lock_agent(int sock, int lock, const char *password) 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) + (r = sshbuf_put_cstring(msg, password)) != 0 || + (r = ssh_request_reply_decode(sock, msg)) != 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); + /* success */ + r = 0; out: sshbuf_free(msg); return r; @@ -322,13 +355,13 @@ ssh_free_identitylist(struct ssh_identitylist *idl) * Returns 0 if found, or a negative SSH_ERR_* error code on failure. */ int -ssh_agent_has_key(int sock, struct sshkey *key) +ssh_agent_has_key(int sock, const struct sshkey *key) { int r, ret = SSH_ERR_KEY_NOT_FOUND; size_t i; struct ssh_identitylist *idlist = NULL; - if ((r = ssh_fetch_identitylist(sock, &idlist)) < 0) { + if ((r = ssh_fetch_identitylist(sock, &idlist)) != 0) { return r; } @@ -423,7 +456,8 @@ ssh_agent_sign(int sock, const struct sshkey *key, static int -encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign) +encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign, + const char *provider) { int r; @@ -441,6 +475,14 @@ encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign) (r = sshbuf_put_u32(m, maxsign)) != 0) goto out; } + if (provider != NULL) { + if ((r = sshbuf_put_u8(m, + SSH_AGENT_CONSTRAIN_EXTENSION)) != 0 || + (r = sshbuf_put_cstring(m, + "sk-provider@openssh.com")) != 0 || + (r = sshbuf_put_cstring(m, provider)) != 0) + goto out; + } r = 0; out: return r; @@ -452,10 +494,11 @@ encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign) */ int ssh_add_identity_constrained(int sock, struct sshkey *key, - const char *comment, u_int life, u_int confirm, u_int maxsign) + const char *comment, u_int life, u_int confirm, u_int maxsign, + const char *provider) { struct sshbuf *msg; - int r, constrained = (life || confirm || maxsign); + int r, constrained = (life || confirm || maxsign || provider); u_char type; if ((msg = sshbuf_new()) == NULL) @@ -469,9 +512,13 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, case KEY_DSA_CERT: case KEY_ECDSA: case KEY_ECDSA_CERT: + case KEY_ECDSA_SK: + case KEY_ECDSA_SK_CERT: #endif case KEY_ED25519: case KEY_ED25519_CERT: + case KEY_ED25519_SK: + case KEY_ED25519_SK_CERT: case KEY_XMSS: case KEY_XMSS_CERT: type = constrained ? @@ -479,7 +526,7 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, SSH2_AGENTC_ADD_IDENTITY; if ((r = sshbuf_put_u8(msg, type)) != 0 || (r = sshkey_private_serialize_maxsign(key, msg, maxsign, - NULL)) != 0 || + 0)) != 0 || (r = sshbuf_put_cstring(msg, comment)) != 0) goto out; break; @@ -488,13 +535,13 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, goto out; } if (constrained && - (r = encode_constraints(msg, life, confirm, maxsign)) != 0) + (r = encode_constraints(msg, life, confirm, maxsign, + provider)) != 0) goto out; - if ((r = ssh_request_reply(sock, msg, msg)) != 0) + if ((r = ssh_request_reply_decode(sock, msg)) != 0) goto out; - if ((r = sshbuf_get_u8(msg, &type)) != 0) - goto out; - r = decode_reply(type); + /* success */ + r = 0; out: sshbuf_free(msg); return r; @@ -505,11 +552,11 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, * This call is intended only for use by ssh-add(1) and like applications. */ int -ssh_remove_identity(int sock, struct sshkey *key) +ssh_remove_identity(int sock, const struct sshkey *key) { struct sshbuf *msg; int r; - u_char type, *blob = NULL; + u_char *blob = NULL; size_t blen; if ((msg = sshbuf_new()) == NULL) @@ -526,16 +573,13 @@ ssh_remove_identity(int sock, struct sshkey *key) r = SSH_ERR_INVALID_ARGUMENT; goto out; } - if ((r = ssh_request_reply(sock, msg, msg)) != 0) + if ((r = ssh_request_reply_decode(sock, msg)) != 0) goto out; - if ((r = sshbuf_get_u8(msg, &type)) != 0) - goto out; - r = decode_reply(type); + /* success */ + r = 0; out: - if (blob != NULL) { - explicit_bzero(blob, blen); - free(blob); - } + if (blob != NULL) + freezero(blob, blen); sshbuf_free(msg); return r; } @@ -566,13 +610,12 @@ ssh_update_card(int sock, int add, const char *reader_id, const char *pin, (r = sshbuf_put_cstring(msg, pin)) != 0) goto out; if (constrained && - (r = encode_constraints(msg, life, confirm, 0)) != 0) + (r = encode_constraints(msg, life, confirm, 0, NULL)) != 0) goto out; - if ((r = ssh_request_reply(sock, msg, msg)) != 0) + if ((r = ssh_request_reply_decode(sock, msg)) != 0) goto out; - if ((r = sshbuf_get_u8(msg, &type)) != 0) - goto out; - r = decode_reply(type); + /* success */ + r = 0; out: sshbuf_free(msg); return r; @@ -599,11 +642,10 @@ ssh_remove_all_identities(int sock, int version) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, type)) != 0) goto out; - if ((r = ssh_request_reply(sock, msg, msg)) != 0) + if ((r = ssh_request_reply_decode(sock, msg)) != 0) goto out; - if ((r = sshbuf_get_u8(msg, &type)) != 0) - goto out; - r = decode_reply(type); + /* success */ + r = 0; out: sshbuf_free(msg); return r; diff --git a/authfd.h b/authfd.h index 579076504..4fbf82f8c 100644 --- a/authfd.h +++ b/authfd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.h,v 1.46 2019/09/03 08:29:15 djm Exp $ */ +/* $OpenBSD: authfd.h,v 1.49 2020/06/26 05:03:36 djm Exp $ */ /* * Author: Tatu Ylonen @@ -24,15 +24,17 @@ struct ssh_identitylist { }; int ssh_get_authentication_socket(int *fdp); +int ssh_get_authentication_socket_path(const char *authsocket, int *fdp); void ssh_close_authentication_socket(int sock); int ssh_lock_agent(int sock, int lock, const char *password); int ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp); void ssh_free_identitylist(struct ssh_identitylist *idl); int ssh_add_identity_constrained(int sock, struct sshkey *key, - const char *comment, u_int life, u_int confirm, u_int maxsign); -int ssh_agent_has_key(int sock, struct sshkey *key); -int ssh_remove_identity(int sock, struct sshkey *key); + const char *comment, u_int life, u_int confirm, u_int maxsign, + const char *provider); +int ssh_agent_has_key(int sock, const struct sshkey *key); +int ssh_remove_identity(int sock, const struct sshkey *key); int ssh_update_card(int sock, int add, const char *reader_id, const char *pin, u_int life, u_int confirm); int ssh_remove_all_identities(int sock, int version); @@ -77,6 +79,7 @@ int ssh_agent_sign(int sock, const struct sshkey *key, #define SSH_AGENT_CONSTRAIN_LIFETIME 1 #define SSH_AGENT_CONSTRAIN_CONFIRM 2 #define SSH_AGENT_CONSTRAIN_MAXSIGN 3 +#define SSH_AGENT_CONSTRAIN_EXTENSION 255 /* extended failure messages */ #define SSH2_AGENT_FAILURE 30 diff --git a/authfile.c b/authfile.c index 0fd35b31e..e6a16a6f7 100644 --- a/authfile.c +++ b/authfile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: authfile.c,v 1.135 2019/09/03 08:30:47 djm Exp $ */ +/* $OpenBSD: authfile.c,v 1.141 2020/06/18 23:33:38 djm Exp $ */ /* * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. * @@ -56,20 +56,13 @@ static int sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename) { - int fd, oerrno; + int r; + mode_t omask; - if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) == -1) - return SSH_ERR_SYSTEM_ERROR; - if (atomicio(vwrite, fd, sshbuf_mutable_ptr(keybuf), - sshbuf_len(keybuf)) != sshbuf_len(keybuf)) { - oerrno = errno; - close(fd); - unlink(filename); - errno = oerrno; - return SSH_ERR_SYSTEM_ERROR; - } - close(fd); - return 0; + omask = umask(077); + r = sshbuf_write_file(filename, keybuf); + umask(omask); + return r; } int @@ -93,49 +86,6 @@ sshkey_save_private(struct sshkey *key, const char *filename, return r; } -/* Load a key from a fd into a buffer */ -int -sshkey_load_file(int fd, struct sshbuf *blob) -{ - u_char buf[1024]; - size_t len; - struct stat st; - int r; - - if (fstat(fd, &st) == -1) - return SSH_ERR_SYSTEM_ERROR; - if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && - st.st_size > MAX_KEY_FILE_SIZE) - return SSH_ERR_INVALID_FORMAT; - for (;;) { - if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) { - if (errno == EPIPE) - break; - r = SSH_ERR_SYSTEM_ERROR; - goto out; - } - if ((r = sshbuf_put(blob, buf, len)) != 0) - goto out; - if (sshbuf_len(blob) > MAX_KEY_FILE_SIZE) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - } - if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && - st.st_size != (off_t)sshbuf_len(blob)) { - r = SSH_ERR_FILE_CHANGED; - goto out; - } - r = 0; - - out: - explicit_bzero(buf, sizeof(buf)); - if (r != 0) - sshbuf_reset(blob); - return r; -} - - /* XXX remove error() calls from here? */ int sshkey_perm_ok(int fd, const char *filename) @@ -200,6 +150,14 @@ sshkey_load_private_type(int type, const char *filename, const char *passphrase, return r; } +int +sshkey_load_private(const char *filename, const char *passphrase, + struct sshkey **keyp, char **commentp) +{ + return sshkey_load_private_type(KEY_UNSPEC, filename, passphrase, + keyp, commentp); +} + int sshkey_load_private_type_fd(int fd, int type, const char *passphrase, struct sshkey **keyp, char **commentp) @@ -209,11 +167,7 @@ sshkey_load_private_type_fd(int fd, int type, const char *passphrase, if (keyp != NULL) *keyp = NULL; - if ((buffer = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshkey_load_file(fd, buffer)) != 0 || + if ((r = sshbuf_load_fd(fd, &buffer)) != 0 || (r = sshkey_parse_private_fileblob_type(buffer, type, passphrase, keyp, commentp)) != 0) goto out; @@ -225,56 +179,57 @@ sshkey_load_private_type_fd(int fd, int type, const char *passphrase, return r; } -/* XXX this is almost identical to sshkey_load_private_type() */ -int -sshkey_load_private(const char *filename, const char *passphrase, - struct sshkey **keyp, char **commentp) +/* Load a pubkey from the unencrypted envelope of a new-format private key */ +static int +sshkey_load_pubkey_from_private(const char *filename, struct sshkey **pubkeyp) { struct sshbuf *buffer = NULL; + struct sshkey *pubkey = NULL; int r, fd; - if (keyp != NULL) - *keyp = NULL; - if (commentp != NULL) - *commentp = NULL; + if (pubkeyp != NULL) + *pubkeyp = NULL; if ((fd = open(filename, O_RDONLY)) == -1) return SSH_ERR_SYSTEM_ERROR; - if (sshkey_perm_ok(fd, filename) != 0) { - r = SSH_ERR_KEY_BAD_PERMISSIONS; + if ((r = sshbuf_load_fd(fd, &buffer)) != 0 || + (r = sshkey_parse_pubkey_from_private_fileblob_type(buffer, + KEY_UNSPEC, &pubkey)) != 0) goto out; + if ((r = sshkey_set_filename(pubkey, filename)) != 0) + goto out; + /* success */ + if (pubkeyp != NULL) { + *pubkeyp = pubkey; + pubkey = NULL; } - - if ((buffer = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshkey_load_file(fd, buffer)) != 0 || - (r = sshkey_parse_private_fileblob(buffer, passphrase, keyp, - commentp)) != 0) - goto out; - if (keyp && *keyp && - (r = sshkey_set_filename(*keyp, filename)) != 0) - goto out; r = 0; out: close(fd); sshbuf_free(buffer); + sshkey_free(pubkey); return r; } static int -sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp) +sshkey_try_load_public(struct sshkey **kp, const char *filename, + char **commentp) { FILE *f; char *line = NULL, *cp; size_t linesize = 0; int r; + struct sshkey *k = NULL; + *kp = NULL; if (commentp != NULL) *commentp = NULL; if ((f = fopen(filename, "r")) == NULL) return SSH_ERR_SYSTEM_ERROR; + if ((k = sshkey_new(KEY_UNSPEC)) == NULL) { + fclose(f); + return SSH_ERR_ALLOC_FAIL; + } while (getline(&line, &linesize, f) != -1) { cp = line; switch (*cp) { @@ -299,12 +254,15 @@ sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp) if (*commentp == NULL) r = SSH_ERR_ALLOC_FAIL; } + /* success */ + *kp = k; free(line); fclose(f); return r; } } } + free(k); free(line); fclose(f); return SSH_ERR_INVALID_FORMAT; @@ -314,44 +272,35 @@ sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp) int sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp) { - struct sshkey *pub = NULL; - char *file = NULL; - int r; + char *pubfile = NULL; + int r, oerrno; if (keyp != NULL) *keyp = NULL; if (commentp != NULL) *commentp = NULL; - if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) { - if (keyp != NULL) { - *keyp = pub; - pub = NULL; - } - r = 0; + if ((r = sshkey_try_load_public(keyp, filename, commentp)) == 0) goto out; - } - sshkey_free(pub); /* try .pub suffix */ - if (asprintf(&file, "%s.pub", filename) == -1) + if (asprintf(&pubfile, "%s.pub", filename) == -1) return SSH_ERR_ALLOC_FAIL; - if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; + if ((r = sshkey_try_load_public(keyp, pubfile, commentp)) == 0) goto out; - } - if ((r = sshkey_try_load_public(pub, file, commentp)) == 0) { - if (keyp != NULL) { - *keyp = pub; - pub = NULL; - } - r = 0; - } + + /* finally, try to extract public key from private key file */ + if ((r = sshkey_load_pubkey_from_private(filename, keyp)) == 0) + goto out; + + /* Pretend we couldn't find the key */ + r = SSH_ERR_SYSTEM_ERROR; + errno = ENOENT; + out: - free(file); - sshkey_free(pub); + oerrno = errno; + free(pubfile); + errno = oerrno; return r; } @@ -369,18 +318,7 @@ sshkey_load_cert(const char *filename, struct sshkey **keyp) if (asprintf(&file, "%s-cert.pub", filename) == -1) return SSH_ERR_ALLOC_FAIL; - if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) { - goto out; - } - if ((r = sshkey_try_load_public(pub, file, NULL)) != 0) - goto out; - /* success */ - if (keyp != NULL) { - *keyp = pub; - pub = NULL; - } - r = 0; - out: + r = sshkey_try_load_public(keyp, file, NULL); free(file); sshkey_free(pub); return r; @@ -560,3 +498,34 @@ sshkey_advance_past_options(char **cpp) return (*cp == '\0' && quoted) ? -1 : 0; } +/* Save a public key */ +int +sshkey_save_public(const struct sshkey *key, const char *path, + const char *comment) +{ + int fd, oerrno; + FILE *f = NULL; + int r = SSH_ERR_INTERNAL_ERROR; + + if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) + return SSH_ERR_SYSTEM_ERROR; + if ((f = fdopen(fd, "w")) == NULL) { + r = SSH_ERR_SYSTEM_ERROR; + goto fail; + } + if ((r = sshkey_write(key, f)) != 0) + goto fail; + fprintf(f, " %s\n", comment); + if (ferror(f) || fclose(f) != 0) { + r = SSH_ERR_SYSTEM_ERROR; + fail: + oerrno = errno; + if (f != NULL) + fclose(f); + else + close(fd); + errno = oerrno; + return r; + } + return 0; +} diff --git a/authfile.h b/authfile.h index 9c8a95a01..1db067a81 100644 --- a/authfile.h +++ b/authfile.h @@ -1,4 +1,4 @@ -/* $OpenBSD: authfile.h,v 1.23 2019/09/03 08:30:47 djm Exp $ */ +/* $OpenBSD: authfile.h,v 1.25 2020/01/25 23:02:13 djm Exp $ */ /* * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. @@ -35,7 +35,6 @@ struct sshkey; int sshkey_save_private(struct sshkey *, const char *, const char *, const char *, int, const char *, int); -int sshkey_load_file(int, struct sshbuf *); int sshkey_load_cert(const char *, struct sshkey **); int sshkey_load_public(const char *, struct sshkey **, char **); int sshkey_load_private(const char *, const char *, struct sshkey **, char **); @@ -49,5 +48,7 @@ int sshkey_perm_ok(int, const char *); int sshkey_in_file(struct sshkey *, const char *, int, int); int sshkey_check_revoked(struct sshkey *key, const char *revoked_keys_file); int sshkey_advance_past_options(char **cpp); +int sshkey_save_public(const struct sshkey *key, const char *path, + const char *comment); #endif diff --git a/buildpkg.sh.in b/buildpkg.sh.in index 4ccc5f8d1..15555cd7e 100644 --- a/buildpkg.sh.in +++ b/buildpkg.sh.in @@ -268,7 +268,7 @@ then touch space else cat > space << _EOF -# extra space required by start/stop links added by installf +# extra space required by start/stop links added by installf # in postinstall $TEST_DIR/etc/rc0.d/${SYSVINITSTOPT}${SYSVINIT_NAME} 0 1 $TEST_DIR/etc/rc2.d/${SYSVINITSTART}${SYSVINIT_NAME} 0 1 @@ -293,7 +293,7 @@ cat >> preinstall << _EOF # if [ "\${PRE_INS_STOP}" = "yes" ] then - if [ $DO_SMF -eq 1 ] + if [ $DO_SMF -eq 1 ] then svcadm disable $OPENSSH_FMRI else @@ -326,7 +326,7 @@ cat > postinstall << _EOF if [ $DO_SMF -eq 1 ] then - # Delete the existing service, if it exists, then import the + # Delete the existing service, if it exists, then import the # new one. if svcs $OPENSSH_FMRI > /dev/null 2>&1 then @@ -438,7 +438,7 @@ echo "Building preremove file..." cat > preremove << _EOF #! ${SCRIPT_SHELL} # -if [ $DO_SMF -eq 1 ] +if [ $DO_SMF -eq 1 ] then svcadm disable $OPENSSH_FMRI else diff --git a/canohost.c b/canohost.c index abea9c6e6..a810da0ee 100644 --- a/canohost.c +++ b/canohost.c @@ -1,4 +1,4 @@ -/* $OpenBSD: canohost.c,v 1.74 2019/06/28 13:35:04 deraadt Exp $ */ +/* $OpenBSD: canohost.c,v 1.75 2020/10/18 11:32:01 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -96,7 +96,7 @@ get_socket_address(int sock, int remote, int flags) /* Get the address in ascii. */ if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop, sizeof(ntop), NULL, 0, flags)) != 0) { - error("%s: getnameinfo %d failed: %s", __func__, + error_f("getnameinfo %d failed: %s", flags, ssh_gai_strerror(r)); return NULL; } @@ -141,7 +141,7 @@ get_local_name(int fd) /* Handle the case where we were passed a pipe */ if (gethostname(myname, sizeof(myname)) == -1) { - verbose("%s: gethostname: %s", __func__, strerror(errno)); + verbose_f("gethostname: %s", strerror(errno)); host = xstrdup("UNKNOWN"); } else { host = xstrdup(myname); @@ -186,7 +186,7 @@ get_sock_port(int sock, int local) /* Return port number. */ if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0, strport, sizeof(strport), NI_NUMERICSERV)) != 0) - fatal("%s: getnameinfo NI_NUMERICSERV failed: %s", __func__, + fatal_f("getnameinfo NI_NUMERICSERV failed: %s", ssh_gai_strerror(r)); return atoi(strport); } diff --git a/channels.c b/channels.c index 36f048dff..fc95c1aa5 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.394 2019/07/07 01:05:00 dtucker Exp $ */ +/* $OpenBSD: channels.c,v 1.405 2021/02/15 20:43:15 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -228,7 +228,7 @@ channel_init_channels(struct ssh *ssh) struct ssh_channels *sc; if ((sc = calloc(1, sizeof(*sc))) == NULL) - fatal("%s: allocation failed", __func__); + fatal_f("allocation failed"); sc->channels_alloc = 10; sc->channels = xcalloc(sc->channels_alloc, sizeof(*sc->channels)); sc->IPv4or6 = AF_UNSPEC; @@ -243,12 +243,12 @@ 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); + logit_f("%d: bad id", id); return NULL; } c = ssh->chanctxt->channels[id]; if (c == NULL) { - logit("%s: %d: bad id: channel free", __func__, id); + logit_f("%d: bad id: channel free", id); return NULL; } return c; @@ -354,6 +354,7 @@ channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd, struct ssh_channels *sc = ssh->chanctxt; u_int i, found; Channel *c; + int r; /* Try to find a free slot where to put the new channel. */ for (i = 0; i < sc->channels_alloc; i++) { @@ -370,8 +371,8 @@ channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd, */ found = sc->channels_alloc; if (sc->channels_alloc > CHANNELS_MAX_CHANNELS) - fatal("%s: internal error: channels_alloc %d too big", - __func__, sc->channels_alloc); + fatal_f("internal error: channels_alloc %d too big", + sc->channels_alloc); sc->channels = xrecallocarray(sc->channels, sc->channels_alloc, sc->channels_alloc + 10, sizeof(*sc->channels)); sc->channels_alloc += 10; @@ -382,7 +383,9 @@ channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd, if ((c->input = sshbuf_new()) == NULL || (c->output = sshbuf_new()) == NULL || (c->extended = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); + if ((r = sshbuf_set_max_size(c->input, CHAN_INPUT_MAX)) != 0) + fatal_fr(r, "sshbuf_set_max_size"); c->ostate = CHAN_OUTPUT_OPEN; c->istate = CHAN_INPUT_OPEN; channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, 0); @@ -454,7 +457,7 @@ fwd_perm_clear(struct permission *perm) free(perm->host_to_connect); free(perm->listen_host); free(perm->listen_path); - bzero(perm, sizeof(*perm)); + memset(perm, 0, sizeof(*perm)); } /* Returns an printable name for the specified forwarding permission list */ @@ -489,7 +492,7 @@ permission_set_get(struct ssh *ssh, int where) return &sc->remote_perms; break; default: - fatal("%s: invalid forwarding direction %d", __func__, where); + fatal_f("invalid forwarding direction %d", where); } } @@ -510,7 +513,7 @@ permission_set_get_array(struct ssh *ssh, int who, int where, *npermpp = &pset->num_permitted_admin; break; default: - fatal("%s: invalid forwarding client %d", __func__, who); + fatal_f("invalid forwarding client %d", who); } } @@ -527,7 +530,7 @@ permission_set_add(struct ssh *ssh, int who, int where, permission_set_get_array(ssh, who, where, &permp, &npermp); if (*npermp >= INT_MAX) - fatal("%s: %s overflow", __func__, fwd_ident(who, where)); + fatal_f("%s overflow", fwd_ident(who, where)); *permp = xrecallocarray(*permp, *npermp, *npermp + 1, sizeof(**permp)); n = (*npermp)++; @@ -567,8 +570,7 @@ mux_remove_remote_forwardings(struct ssh *ssh, Channel *c) 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)); + fatal_fr(r, "channel %i", c->self); } fwd_perm_clear(perm); /* unregister */ } @@ -603,6 +605,10 @@ channel_free(struct ssh *ssh, Channel *c) if (c->type == SSH_CHANNEL_MUX_CLIENT) mux_remove_remote_forwardings(ssh, c); + else if (c->type == SSH_CHANNEL_MUX_LISTENER) { + free(c->mux_ctx); + c->mux_ctx = NULL; + } if (log_level_get() >= SYSLOG_LEVEL_DEBUG3) { s = channel_open_message(ssh); @@ -625,14 +631,12 @@ channel_free(struct ssh *ssh, Channel *c) 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); + freezero(cc, sizeof(*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); + freezero(c, sizeof(*c)); } void @@ -766,7 +770,7 @@ channel_still_open(struct ssh *ssh) case SSH_CHANNEL_MUX_PROXY: return 1; default: - fatal("%s: bad channel type %d", __func__, c->type); + fatal_f("bad channel type %d", c->type); /* NOTREACHED */ } } @@ -808,7 +812,7 @@ channel_find_open(struct ssh *ssh) case SSH_CHANNEL_X11_OPEN: return i; default: - fatal("%s: bad channel type %d", __func__, c->type); + fatal_f("bad channel type %d", c->type); /* NOTREACHED */ } } @@ -865,10 +869,10 @@ channel_open_message(struct ssh *ssh) char *cp, *ret; if ((buf = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); if ((r = sshbuf_putf(buf, "The following connections are open:\r\n")) != 0) - fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_putf"); for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { c = ssh->chanctxt->channels[i]; if (c == NULL) @@ -899,18 +903,17 @@ channel_open_message(struct ssh *ssh) 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)); + fatal_fr(r, "sshbuf_putf"); } free(cp); continue; default: - fatal("%s: bad channel type %d", __func__, c->type); + fatal_f("bad channel type %d", c->type); /* NOTREACHED */ } } if ((ret = sshbuf_dup_string(buf)) == NULL) - fatal("%s: sshbuf_dup_string", __func__); + fatal_f("sshbuf_dup_string"); sshbuf_free(buf); return ret; } @@ -925,7 +928,7 @@ open_preamble(struct ssh *ssh, const char *where, Channel *c, const char *type) (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)); + fatal_r(r, "%s: channel %i: open", where, c->self); } } @@ -942,7 +945,7 @@ channel_send_open(struct ssh *ssh, int id) 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)); + fatal_fr(r, "channel %i", c->self); } void @@ -952,18 +955,18 @@ channel_request_start(struct ssh *ssh, int id, char *service, int wantconfirm) int r; if (c == NULL) { - logit("%s: %d: unknown channel id", __func__, id); + logit_f("%d: unknown channel id", id); return; } if (!c->have_remote_id) - fatal(":%s: channel %d: no remote id", __func__, c->self); + fatal_f("channel %d: no remote id", 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)); + fatal_fr(r, "channel %i", c->self); } } @@ -975,7 +978,7 @@ channel_register_status_confirm(struct ssh *ssh, int id, Channel *c; if ((c = channel_lookup(ssh, id)) == NULL) - fatal("%s: %d: bad id", __func__, id); + fatal_f("%d: bad id", id); cc = xcalloc(1, sizeof(*cc)); cc->cb = cb; @@ -991,7 +994,7 @@ channel_register_open_confirm(struct ssh *ssh, int id, Channel *c = channel_lookup(ssh, id); if (c == NULL) { - logit("%s: %d: bad id", __func__, id); + logit_f("%d: bad id", id); return; } c->open_confirm = fn; @@ -1005,7 +1008,7 @@ channel_register_cleanup(struct ssh *ssh, int id, Channel *c = channel_by_id(ssh, id); if (c == NULL) { - logit("%s: %d: bad id", __func__, id); + logit_f("%d: bad id", id); return; } c->detach_user = fn; @@ -1018,7 +1021,7 @@ 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); + logit_f("%d: bad id", id); return; } c->detach_user = NULL; @@ -1032,7 +1035,7 @@ channel_register_filter(struct ssh *ssh, int id, channel_infilter_fn *ifn, Channel *c = channel_lookup(ssh, id); if (c == NULL) { - logit("%s: %d: bad id", __func__, id); + logit_f("%d: bad id", id); return; } c->input_filter = ifn; @@ -1051,7 +1054,7 @@ channel_set_fds(struct ssh *ssh, int id, int rfd, int wfd, int efd, 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); + fatal_f("channel %d: no remote id", c->self); channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, is_tty); c->type = SSH_CHANNEL_OPEN; @@ -1061,7 +1064,7 @@ channel_set_fds(struct ssh *ssh, int id, int rfd, int wfd, int efd, (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)); + fatal_fr(r, "channel %i", c->self); } static void @@ -1290,24 +1293,21 @@ channel_decode_socks4(Channel *c, struct sshbuf *input, struct sshbuf *output) (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)); + debug_r(r, "channels %d: decode socks4", c->self); 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); + error("channel %d: decode socks4: unterminated user", 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)); - } + if ((r = sshbuf_consume(input, len)) != 0) + fatal_fr(r, "channel %d: consume", c->self); free(c->path); c->path = NULL; if (need == 1) { /* SOCKS4: one string */ @@ -1331,10 +1331,8 @@ channel_decode_socks4(Channel *c, struct sshbuf *input, struct sshbuf *output) 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)); - } + if ((r = sshbuf_consume(input, len)) != 0) + fatal_fr(r, "channel %d: consume", c->self); } c->host_port = ntohs(s4_req.dest_port); @@ -1350,10 +1348,8 @@ channel_decode_socks4(Channel *c, struct sshbuf *input, struct sshbuf *output) 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)); - } + if ((r = sshbuf_put(output, &s4_rsp, sizeof(s4_rsp))) != 0) + fatal_fr(r, "channel %d: append reply", c->self); return 1; } @@ -1406,16 +1402,12 @@ channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output) c->self); return -1; } - if ((r = sshbuf_consume(input, nmethods + 2)) != 0) { - fatal("%s: channel %d: consume: %s", __func__, - c->self, ssh_err(r)); - } + if ((r = sshbuf_consume(input, nmethods + 2)) != 0) + fatal_fr(r, "channel %d: consume", c->self); /* 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)); - } + (r = sshbuf_put_u8(output, SSH_SOCKS5_NOAUTH)) != 0) + fatal_fr(r, "channel %d: append reply", c->self); c->flags |= SSH_SOCKS5_AUTHDONE; debug2("channel %d: socks5 auth done", c->self); return 0; /* need more */ @@ -1452,20 +1444,16 @@ channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output) 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 ((r = sshbuf_consume(input, sizeof(s5_req))) != 0) + fatal_fr(r, "channel %d: consume", c->self); 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_consume(input, 1)) != 0) + fatal_fr(r, "channel %d: consume", c->self); } 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)); + debug_r(r, "channel %d: parse addr/port", c->self); return -1; } dest_addr[addrlen] = '\0'; @@ -1497,8 +1485,7 @@ channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output) 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)); + fatal_fr(r, "channel %d: append reply", c->self); return 1; } @@ -1508,7 +1495,7 @@ channel_connect_stdio_fwd(struct ssh *ssh, { Channel *c; - debug("%s %s:%d", __func__, host_to_connect, port_to_connect); + debug_f("%s:%d", 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, @@ -1597,10 +1584,8 @@ channel_before_prepare_select_rdynamic(struct ssh *ssh, Channel *c) /* 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)); - } + if ((r = sshbuf_consume(c->output, have)) != 0) + fatal_fr(r, "channel %d: consume", c->self); rdynamic_close(ssh, c); return; } @@ -1632,13 +1617,10 @@ channel_before_prepare_select_rdynamic(struct ssh *ssh, Channel *c) (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)); + fatal_fr(r, "channel %i: rdynamic", c->self); } + if ((r = sshbuf_consume(c->input, len)) != 0) + fatal_fr(r, "channel %d: consume", c->self); c->remote_window -= len; } } else if (rdynamic_connect_finish(ssh, c) < 0) { @@ -1691,11 +1673,10 @@ channel_post_x11_listener(struct ssh *ssh, Channel *c, 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)); + fatal_fr(r, "channel %i: reply", c->self); } if ((r = sshpkt_send(ssh)) != 0) - fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r)); + fatal_fr(r, "channel %i: send", c->self); free(remote_ipaddr); } @@ -1726,46 +1707,34 @@ port_open_helper(struct ssh *ssh, Channel *c, char *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)); - } + (r = sshpkt_put_u32(ssh, c->host_port)) != 0) + fatal_fr(r, "channel %i: reply", c->self); } 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)); - } + if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) + fatal_fr(r, "channel %i: reply", c->self); } 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)); - } + if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) + fatal_fr(r, "channel %i: reply", c->self); } 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)); - } + (r = sshpkt_put_u32(ssh, local_port)) != 0) + fatal_fr(r, "channel %i: reply", c->self); } 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)); - } + if ((r = sshpkt_put_cstring(ssh, "")) != 0) + fatal_fr(r, "channel %i: reply", c->self); } 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)); - } + (r = sshpkt_put_u32(ssh, (u_int)remote_port)) != 0) + fatal_fr(r, "channel %i: reply", c->self); } if ((r = sshpkt_send(ssh)) != 0) - fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r)); + fatal_fr(r, "channel %i: send", c->self); free(remote_ipaddr); free(local_ipaddr); } @@ -1865,7 +1834,7 @@ channel_post_auth_listener(struct ssh *ssh, Channel *c, 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)); + fatal_fr(r, "channel %i", c->self); } static void @@ -1878,7 +1847,7 @@ channel_post_connecting(struct ssh *ssh, Channel *c, if (!FD_ISSET(c->sock, writeset)) return; if (!c->have_remote_id) - fatal(":%s: channel %d: no remote id", __func__, c->self); + fatal_f("channel %d: no remote id", 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) == -1) { @@ -1898,13 +1867,9 @@ channel_post_connecting(struct ssh *ssh, Channel *c, (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)); + (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal_fr(r, "channel %i open confirm", c->self); } } else { debug("channel %d: connection failed: %s", @@ -1929,13 +1894,9 @@ channel_post_connecting(struct ssh *ssh, Channel *c, (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)); + (r = sshpkt_put_cstring(ssh, "")) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal_fr(r, "channel %i: failure", c->self); chan_mark_dead(ssh, c); } } @@ -1983,12 +1944,9 @@ channel_handle_rfd(struct ssh *ssh, Channel *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)); - } + fatal_fr(r, "channel %i: put datagram", c->self); + } else if ((r = sshbuf_put(c->input, buf, len)) != 0) + fatal_fr(r, "channel %i: put data", c->self); return 1; } @@ -2018,8 +1976,7 @@ channel_handle_wfd(struct ssh *ssh, Channel *c, } } 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)); + fatal_fr(r, "channel %i: get datagram", c->self); buf = data; } else { buf = data = sshbuf_mutable_ptr(c->output); @@ -2071,15 +2028,12 @@ channel_handle_wfd(struct ssh *ssh, Channel *c, */ 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)); + fatal_fr(r, "channel %i: ignore", c->self); } } #endif /* BROKEN_TCGETATTR_ICANON */ - if ((r = sshbuf_consume(c->output, len)) != 0) { - fatal("%s: channel %d: consume: %s", - __func__, c->self, ssh_err(r)); - } + if ((r = sshbuf_consume(c->output, len)) != 0) + fatal_fr(r, "channel %i: consume", c->self); out: c->local_consumed += olen - sshbuf_len(c->output); @@ -2106,10 +2060,8 @@ channel_handle_efd_write(struct ssh *ssh, Channel *c, 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)); - } + if ((r = sshbuf_consume(c->extended, len)) != 0) + fatal_fr(r, "channel %i: consume", c->self); c->local_consumed += len; } return 1; @@ -2134,18 +2086,12 @@ channel_handle_efd_read(struct ssh *ssh, Channel *c, errno == EWOULDBLOCK) && !force))) return 1; if (len <= 0) { - debug2("channel %d: closing read-efd %d", - c->self, c->efd); + 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)); - } - } + } 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_fr(r, "channel %i: append", c->self); return 1; } @@ -2179,19 +2125,16 @@ channel_check_window(struct ssh *ssh, Channel *c) 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); + fatal_f("channel %d: no remote id", 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)); + fatal_fr(r, "channel %i", c->self); } - debug2("channel %d: window %d sent adjust %d", - c->self, c->local_window, - c->local_consumed); + 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; } @@ -2226,10 +2169,8 @@ read_mux(struct ssh *ssh, Channel *c, u_int need) 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)); - } + } else if ((r = sshbuf_put(c->input, buf, len)) != 0) + fatal_fr(r, "channel %i: append", c->self); } return sshbuf_len(c->input); } @@ -2290,8 +2231,7 @@ channel_post_mux_client_write(struct ssh *ssh, Channel *c, return; } if ((r = sshbuf_consume(c->output, len)) != 0) - fatal("%s: channel %d: consume: %s", __func__, - c->self, ssh_err(r)); + fatal_fr(r, "channel %i: consume", c->self); } static void @@ -2325,15 +2265,14 @@ channel_post_mux_listener(struct ssh *ssh, Channel *c, addrlen = sizeof(addr); if ((newsock = accept(c->sock, (struct sockaddr*)&addr, &addrlen)) == -1) { - error("%s accept: %s", __func__, strerror(errno)); + error_f("accept: %s", strerror(errno)); if (errno == EMFILE || errno == ENFILE) c->notbefore = monotime() + 1; return; } if (getpeereid(newsock, &euid, &egid) == -1) { - error("%s getpeereid failed: %s", __func__, - strerror(errno)); + error_f("getpeereid failed: %s", strerror(errno)); close(newsock); return; } @@ -2348,7 +2287,7 @@ channel_post_mux_listener(struct ssh *ssh, Channel *c, 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); + debug3_f("new mux channel %d fd %d", nc->self, nc->sock); /* establish state */ nc->mux_rcb(ssh, nc); /* mux state transitions must not elicit protocol messages */ @@ -2362,7 +2301,7 @@ channel_handler_init(struct ssh_channels *sc) if ((pre = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*pre))) == NULL || (post = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*post))) == NULL) - fatal("%s: allocation failed", __func__); + fatal_f("allocation failed"); pre[SSH_CHANNEL_OPEN] = &channel_pre_open; pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; @@ -2454,8 +2393,8 @@ channel_handler(struct ssh *ssh, int table, * Collect the time that the earliest * channel comes off pause. */ - debug3("%s: chan %d: skip for %d more seconds", - __func__, c->self, + debug3_f("chan %d: skip for %d more " + "seconds", c->self, (int)(c->notbefore - now)); if (*unpause_secs == 0 || (c->notbefore - now) < *unpause_secs) @@ -2465,8 +2404,8 @@ channel_handler(struct ssh *ssh, int table, channel_garbage_collect(ssh, c); } if (unpause_secs != NULL && *unpause_secs != 0) - debug3("%s: first channel unpauses in %d seconds", - __func__, (int)*unpause_secs); + debug3_f("first channel unpauses in %d seconds", + (int)*unpause_secs); } /* @@ -2565,13 +2504,12 @@ channel_output_poll_input_open(struct ssh *ssh, Channel *c) } if (!c->have_remote_id) - fatal(":%s: channel %d: no remote id", __func__, c->self); + fatal_f("channel %d: no remote id", 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)); + fatal_fr(r, "channel %i: get datagram", c->self); /* * XXX this does tail-drop on the datagram queue which is * usually suboptimal compared to head-drop. Better to have @@ -2585,10 +2523,8 @@ channel_output_poll_input_open(struct ssh *ssh, Channel *c) 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)); - } + (r = sshpkt_send(ssh)) != 0) + fatal_fr(r, "channel %i: send datagram", c->self); c->remote_window -= plen; return; } @@ -2603,13 +2539,10 @@ channel_output_poll_input_open(struct ssh *ssh, Channel *c) 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)); - } + (r = sshpkt_send(ssh)) != 0) + fatal_fr(r, "channel %i: send data", c->self); if ((r = sshbuf_consume(c->input, len)) != 0) - fatal("%s: channel %i: consume: %s", __func__, - c->self, ssh_err(r)); + fatal_fr(r, "channel %i: consume", c->self); c->remote_window -= len; } @@ -2634,18 +2567,15 @@ channel_output_poll_extended_read(struct ssh *ssh, Channel *c) if (len == 0) return; if (!c->have_remote_id) - fatal(":%s: channel %d: no remote id", __func__, c->self); + fatal_f("channel %d: no remote id", 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)); - } + (r = sshpkt_send(ssh)) != 0) + fatal_fr(r, "channel %i: data", c->self); if ((r = sshbuf_consume(c->extended, len)) != 0) - fatal("%s: channel %i: consume: %s", __func__, - c->self, ssh_err(r)); + fatal_fr(r, "channel %i: consume", c->self); c->remote_window -= len; debug2("channel %d: sent ext data %zu", c->self, len); } @@ -2742,11 +2672,11 @@ channel_proxy_downstream(struct ssh *ssh, Channel *downstream) /* 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)); + error_fr(r, "parse"); return -1; } if (have < 2) { - error("%s: short message", __func__); + error_f("short message"); return -1; } type = cp[1]; @@ -2754,19 +2684,19 @@ channel_proxy_downstream(struct ssh *ssh, Channel *downstream) cp += 2; have -= 2; if (ssh_packet_log_type(type)) - debug3("%s: channel %u: down->up: type %u", __func__, + debug3_f("channel %u: down->up: type %u", 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__); + error_f("alloc"); 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)); + error_fr(r, "parse"); goto out; } c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY, @@ -2776,7 +2706,7 @@ channel_proxy_downstream(struct ssh *ssh, Channel *downstream) 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)); + error_fr(r, "compose"); channel_free(ssh, c); goto out; } @@ -2788,12 +2718,12 @@ channel_proxy_downstream(struct ssh *ssh, Channel *downstream) */ if ((original = sshbuf_from(cp, have)) == NULL || (modified = sshbuf_new()) == NULL) { - error("%s: alloc", __func__); + error_f("alloc"); 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)); + error_fr(r, "parse"); goto out; } c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY, @@ -2805,33 +2735,33 @@ channel_proxy_downstream(struct ssh *ssh, Channel *downstream) 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)); + error_fr(r, "compose"); channel_free(ssh, c); goto out; } break; case SSH2_MSG_GLOBAL_REQUEST: if ((original = sshbuf_from(cp, have)) == NULL) { - error("%s: alloc", __func__); + error_f("alloc"); goto out; } if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0) { - error("%s: parse error %s", __func__, ssh_err(r)); + error_fr(r, "parse"); goto out; } if (strcmp(ctype, "tcpip-forward") != 0) { - error("%s: unsupported request %s", __func__, ctype); + error_f("unsupported request %s", 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)); + error_fr(r, "parse"); goto out; } if (listen_port > 65535) { - error("%s: tcpip-forward for %s: bad port %u", - __func__, listen_host, listen_port); + error_f("tcpip-forward for %s: bad port %u", + listen_host, listen_port); goto out; } /* Record that connection to this host/port is permitted. */ @@ -2855,14 +2785,14 @@ channel_proxy_downstream(struct ssh *ssh, Channel *downstream) 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)); + error_fr(r, "send"); 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)); + error_fr(r, "send"); goto out; } } @@ -2913,18 +2843,17 @@ channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh) case SSH2_MSG_CHANNEL_REQUEST: break; default: - debug2("%s: channel %u: unsupported type %u", __func__, - c->self, type); + debug2_f("channel %u: unsupported type %u", c->self, type); return 0; } if ((b = sshbuf_new()) == NULL) { - error("%s: alloc reply", __func__); + error_f("alloc reply"); goto out; } /* get remaining payload (after id) */ cp = sshpkt_ptr(ssh, &len); if (cp == NULL) { - error("%s: no packet", __func__); + error_f("no packet"); goto out; } /* translate id and send to muxclient */ @@ -2933,13 +2862,12 @@ channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh) (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)); + error_fr(r, "compose muxclient"); goto out; } /* sshbuf_dump(b, stderr); */ if (ssh_packet_log_type(type)) - debug3("%s: channel %u: up->down: type %u", __func__, c->self, - type); + debug3_f("channel %u: up->down: type %u", c->self, type); out: /* update state */ switch (type) { @@ -2971,11 +2899,11 @@ channel_parse_id(struct ssh *ssh, const char *where, const char *what) int r; if ((r = sshpkt_get_u32(ssh, &id)) != 0) { - error("%s: parse id: %s", where, ssh_err(r)); + error_r(r, "%s: parse id", where); ssh_packet_disconnect(ssh, "Invalid %s message", what); } if (id > INT_MAX) { - error("%s: bad channel id %u: %s", where, id, ssh_err(r)); + error_r(r, "%s: bad channel id %u", where, id); ssh_packet_disconnect(ssh, "Invalid %s channel id", what); } return (int)id; @@ -3016,8 +2944,7 @@ channel_input_data(int type, u_int32_t seq, struct ssh *ssh) /* Get the data. */ 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)); + fatal_fr(r, "channel %i: get data", c->self); win_len = data_len; if (c->datagram) @@ -3048,11 +2975,9 @@ channel_input_data(int type, u_int32_t seq, struct ssh *ssh) 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)); + fatal_fr(r, "channel %i: append datagram", c->self); } else if ((r = sshbuf_put(c->output, data, data_len)) != 0) - fatal("%s: channel %d: append data: %s", - __func__, c->self, ssh_err(r)); + fatal_fr(r, "channel %i: append data", c->self); return 0; } @@ -3073,7 +2998,7 @@ channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh) return 0; } if (c->flags & CHAN_EOF_RCVD) { - if (datafellows & SSH_BUG_EXTEOF) + if (ssh->compat & SSH_BUG_EXTEOF) debug("channel %d: accepting ext data after eof", c->self); else @@ -3082,7 +3007,7 @@ channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh) } if ((r = sshpkt_get_u32(ssh, &tcode)) != 0) { - error("%s: parse tcode: %s", __func__, ssh_err(r)); + error_fr(r, "parse tcode"); ssh_packet_disconnect(ssh, "Invalid extended_data message"); } if (c->efd == -1 || @@ -3093,7 +3018,7 @@ channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh) } 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)); + error_fr(r, "parse data"); ssh_packet_disconnect(ssh, "Invalid extended_data message"); } @@ -3105,7 +3030,7 @@ channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh) 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)); + error_fr(r, "append"); c->local_window -= data_len; return 0; } @@ -3117,7 +3042,7 @@ channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh) int r; if ((r = sshpkt_get_end(ssh)) != 0) { - error("%s: parse data: %s", __func__, ssh_err(r)); + error_fr(r, "parse data"); ssh_packet_disconnect(ssh, "Invalid ieof message"); } @@ -3144,7 +3069,7 @@ channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh) if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if ((r = sshpkt_get_end(ssh)) != 0) { - error("%s: parse data: %s", __func__, ssh_err(r)); + error_fr(r, "parse data"); ssh_packet_disconnect(ssh, "Invalid oclose message"); } chan_rcvd_oclose(ssh, c); @@ -3171,7 +3096,7 @@ channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh) (r = sshpkt_get_u32(ssh, &remote_window)) != 0 || (r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0 || (r = sshpkt_get_end(ssh)) != 0) { - error("%s: window/maxpacket: %s", __func__, ssh_err(r)); + error_fr(r, "window/maxpacket"); ssh_packet_disconnect(ssh, "Invalid open confirmation message"); } @@ -3180,9 +3105,9 @@ channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh) c->remote_maxpacket = remote_maxpacket; c->type = SSH_CHANNEL_OPEN; if (c->open_confirm) { - debug2("%s: channel %d: callback start", __func__, c->self); + debug2_f("channel %d: callback start", c->self); c->open_confirm(ssh, c->self, 1, c->open_confirm_ctx); - debug2("%s: channel %d: callback done", __func__, c->self); + debug2_f("channel %d: callback done", c->self); } debug2("channel %d: open confirm rwindow %u rmax %u", c->self, c->remote_window, c->remote_maxpacket); @@ -3219,23 +3144,23 @@ channel_input_open_failure(int type, u_int32_t seq, struct ssh *ssh) 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)); + error_fr(r, "parse reason"); 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_end(ssh)) != 0) { - error("%s: message/lang: %s", __func__, ssh_err(r)); + error_fr(r, "parse msg/lang"); ssh_packet_disconnect(ssh, "Invalid open failure message"); } 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); + debug2_f("channel %d: callback start", c->self); c->open_confirm(ssh, c->self, 0, c->open_confirm_ctx); - debug2("%s: channel %d: callback done", __func__, c->self); + debug2_f("channel %d: callback done", c->self); } /* Schedule the channel for cleanup/deletion. */ chan_mark_dead(ssh, c); @@ -3260,7 +3185,7 @@ channel_input_window_adjust(int type, u_int32_t seq, struct ssh *ssh) return 0; if ((r = sshpkt_get_u32(ssh, &adjust)) != 0 || (r = sshpkt_get_end(ssh)) != 0) { - error("%s: adjust: %s", __func__, ssh_err(r)); + error_fr(r, "parse adjust"); ssh_packet_disconnect(ssh, "Invalid window adjust message"); } debug2("channel %d: rcvd adjust %u", c->self, adjust); @@ -3282,10 +3207,10 @@ channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh) /* Reset keepalive timeout */ ssh_packet_set_alive_timeouts(ssh, 0); - debug2("%s: type %d id %d", __func__, type, id); + debug2_f("type %d id %d", type, id); if ((c = channel_lookup(ssh, id)) == NULL) { - logit("%s: %d: unknown", __func__, id); + logit_f("%d: unknown", id); return 0; } if (channel_proxy_upstream(c, type, seq, ssh)) @@ -3296,8 +3221,7 @@ channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh) return 0; cc->cb(ssh, type, c, cc->ctx); TAILQ_REMOVE(&c->status_confirms, cc, entry); - explicit_bzero(cc, sizeof(*cc)); - free(cc); + freezero(cc, sizeof(*cc)); return 0; } @@ -3337,7 +3261,7 @@ channel_fwd_bind_addr(struct ssh *ssh, const char *listen_addr, int *wildcardp, if (fwd_opts->gateway_ports) wildcard = 1; } else if (fwd_opts->gateway_ports || is_client) { - if (((datafellows & SSH_OLD_FORWARD_ADDR) && + if (((ssh->compat & 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)) { @@ -3357,7 +3281,12 @@ channel_fwd_bind_addr(struct ssh *ssh, const char *listen_addr, int *wildcardp, } 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 */ + /* + * Accept explicit localhost address when + * GatewayPorts=yes. The "localhost" hostname is + * deliberately skipped here so it will listen on all + * available local address families. + */ addr = listen_addr; } } else if (strcmp(listen_addr, "127.0.0.1") == 0 || @@ -3406,8 +3335,8 @@ channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type, /* Determine the bind address, cf. channel_fwd_bind_addr() comment */ 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); + debug3_f("type %d wildcard %d addr %s", type, wildcard, + (addr == NULL) ? "NULL" : addr); /* * getaddrinfo returns a loopback address if the hostname is @@ -3424,7 +3353,7 @@ channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type, ssh_packet_disconnect(ssh, "getaddrinfo: fatal error: %s", ssh_gai_strerror(r)); } else { - error("%s: getaddrinfo(%.64s): %s", __func__, addr, + error_f("getaddrinfo(%.64s): %s", addr, ssh_gai_strerror(r)); } return 0; @@ -3456,7 +3385,7 @@ channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type, if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { - error("%s: getnameinfo failed", __func__); + error_f("getnameinfo failed"); continue; } /* Create a port to listen for the host. */ @@ -3521,15 +3450,14 @@ channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type, 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)) + !(ssh->compat & 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); + error_f("cannot listen to port: %d", fwd->listen_port); freeaddrinfo(aitop); return success; } @@ -3572,7 +3500,7 @@ channel_setup_fwd_listener_streamlocal(struct ssh *ssh, int type, port = PORT_STREAMLOCAL; break; default: - error("%s: unexpected channel type %d", __func__, type); + error_f("unexpected channel type %d", type); return 0; } @@ -3585,7 +3513,7 @@ channel_setup_fwd_listener_streamlocal(struct ssh *ssh, int type, return 0; } - debug3("%s: type %d path %s", __func__, type, fwd->listen_path); + debug3_f("type %d path %s", type, fwd->listen_path); /* Start a Unix domain listener. */ omask = umask(fwd_opts->streamlocal_bind_mask); @@ -3620,7 +3548,7 @@ channel_cancel_rport_listener_tcpip(struct ssh *ssh, 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); + debug2_f("close channel %d", i); channel_free(ssh, c); found = 1; } @@ -3642,7 +3570,7 @@ channel_cancel_rport_listener_streamlocal(struct ssh *ssh, const char *path) if (c->path == NULL) continue; if (strcmp(c->path, path) == 0) { - debug2("%s: close channel %d", __func__, i); + debug2_f("close channel %d", i); channel_free(ssh, c); found = 1; } @@ -3690,7 +3618,7 @@ channel_cancel_lport_listener_tcpip(struct ssh *ssh, (c->listening_addr != NULL && addr == NULL)) continue; if (addr == NULL || strcmp(c->listening_addr, addr) == 0) { - debug2("%s: close channel %d", __func__, i); + debug2_f("close channel %d", i); channel_free(ssh, c); found = 1; } @@ -3706,7 +3634,7 @@ channel_cancel_lport_listener_streamlocal(struct ssh *ssh, const char *path) int found = 0; if (path == NULL) { - error("%s: no path specified.", __func__); + error_f("no path specified."); return 0; } @@ -3717,7 +3645,7 @@ channel_cancel_lport_listener_streamlocal(struct ssh *ssh, const char *path) if (c->listening_addr == NULL) continue; if (strcmp(c->listening_addr, path) == 0) { - debug2("%s: close channel %d", __func__, i); + debug2_f("close channel %d", i); channel_free(ssh, c); found = 1; } @@ -3889,8 +3817,7 @@ channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd) (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)); + fatal_fr(r, "request streamlocal"); } else { if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "tcpip-forward")) != 0 || @@ -3900,8 +3827,7 @@ channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd) (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)); + fatal_fr(r, "request tcpip-forward"); } /* Assume that server accepts the request */ success = 1; @@ -4000,7 +3926,7 @@ channel_request_rforward_cancel_tcpip(struct ssh *ssh, struct permission_set *pset = &sc->local_perms; int r; u_int i; - struct permission *perm; + struct permission *perm = NULL; for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; @@ -4009,7 +3935,7 @@ channel_request_rforward_cancel_tcpip(struct ssh *ssh, perm = NULL; } if (perm == NULL) { - debug("%s: requested forward not found", __func__); + debug_f("requested forward not found"); return -1; } if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || @@ -4018,7 +3944,7 @@ channel_request_rforward_cancel_tcpip(struct ssh *ssh, (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)); + fatal_fr(r, "send cancel"); fwd_perm_clear(perm); /* unregister */ @@ -4036,7 +3962,7 @@ channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path) struct permission_set *pset = &sc->local_perms; int r; u_int i; - struct permission *perm; + struct permission *perm = NULL; for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; @@ -4045,7 +3971,7 @@ channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path) perm = NULL; } if (perm == NULL) { - debug("%s: requested forward not found", __func__); + debug_f("requested forward not found"); return -1; } if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || @@ -4054,7 +3980,7 @@ channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path) (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)); + fatal_fr(r, "send cancel"); fwd_perm_clear(perm); /* unregister */ @@ -4149,8 +4075,8 @@ 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); + debug_f("index out of range: %d num_permitted_user %d", + idx, pset->num_permitted_user); return; } debug("%s allowed port %d for forwarding to host %s port %d", @@ -4162,7 +4088,7 @@ channel_update_permission(struct ssh *ssh, int idx, int newport) fwd_perm_clear(&pset->permitted_user[idx]); else { pset->permitted_user[idx].listen_port = - (datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport; + (ssh->compat & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport; } } @@ -4217,7 +4143,7 @@ connect_next(struct channel_connect *cctx) continue; } if (set_nonblock(sock) == -1) - fatal("%s: set_nonblock(%d)", __func__, sock); + fatal_f("set_nonblock(%d)", sock); if (connect(sock, cctx->ai->ai_addr, cctx->ai->ai_addrlen) == -1 && errno != EINPROGRESS) { debug("connect_next: host %.100s ([%.100s]:%s): " @@ -4520,8 +4446,7 @@ channel_send_window_changes(struct ssh *ssh) (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)); + fatal_fr(r, "channel %u; send window-change", i); } } @@ -4545,10 +4470,8 @@ rdynamic_connect_prepare(struct ssh *ssh, char *ctype, char *rname) (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)); - } + (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) + fatal_fr(r, "channel %i; confirm", c->self); return c; } @@ -4556,9 +4479,28 @@ rdynamic_connect_prepare(struct ssh *ssh, char *ctype, char *rname) static int rdynamic_connect_finish(struct ssh *ssh, Channel *c) { + struct ssh_channels *sc = ssh->chanctxt; + struct permission_set *pset = &sc->local_perms; + struct permission *perm; struct channel_connect cctx; + u_int i, permit_adm = 1; int sock; + 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, c->path, c->host_port)) { + permit_adm = 1; + break; + } + } + } + if (!permit_adm) { + debug_f("requested forward not permitted"); + return -1; + } + memset(&cctx, 0, sizeof(cctx)); sock = connect_to_helper(ssh, c->path, c->host_port, SOCK_STREAM, NULL, NULL, &cctx, NULL, NULL); @@ -4635,8 +4577,8 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, if (x11_use_localhost) set_reuseaddr(sock); if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) { - debug2("%s: bind port %d: %.100s", __func__, - port, strerror(errno)); + debug2_f("bind port %d: %.100s", port, + strerror(errno)); close(sock); for (n = 0; n < num_socks; n++) close(socks[n]); @@ -4894,9 +4836,10 @@ x11_request_forwarding_with_spoofing(struct ssh *ssh, int client_session_id, /* 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) + 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; @@ -4918,6 +4861,6 @@ x11_request_forwarding_with_spoofing(struct ssh *ssh, int client_session_id, (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)); + fatal_fr(r, "send x11-req"); free(new_data); } diff --git a/channels.h b/channels.h index aa2a87c10..74e9b3f87 100644 --- a/channels.h +++ b/channels.h @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.h,v 1.132 2018/10/04 00:10:11 djm Exp $ */ +/* $OpenBSD: channels.h,v 1.135 2020/09/20 05:47:25 djm Exp $ */ /* * Author: Tatu Ylonen @@ -52,11 +52,11 @@ #define SSH_CHANNEL_DYNAMIC 13 #define SSH_CHANNEL_ZOMBIE 14 /* Almost dead. */ #define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */ -#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */ +#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux client */ #define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */ #define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */ #define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */ -#define SSH_CHANNEL_MUX_PROXY 20 /* proxy channel for mux-slave */ +#define SSH_CHANNEL_MUX_PROXY 20 /* proxy channel for mux-client */ #define SSH_CHANNEL_RDYNAMIC_OPEN 21 /* reverse SOCKS, parsing request */ #define SSH_CHANNEL_RDYNAMIC_FINISH 22 /* reverse SOCKS, finishing connect */ #define SSH_CHANNEL_MAX_TYPE 23 @@ -105,8 +105,16 @@ struct channel_connect { /* Callbacks for mux channels back into client-specific code */ typedef int mux_callback_fn(struct ssh *, struct Channel *); +/* + * NB. channel IDs on the wire and in c->remote_id are uint32, but local + * channel IDs (e.g. c->self) only ever use the int32 subset of this range, + * because we use local channel ID -1 for housekeeping. Remote channels have + * a dedicated "have_remote_id" flag to indicate their validity. + */ + struct Channel { int type; /* channel type/state */ + int self; /* my own channel identifier */ uint32_t remote_id; /* channel identifier for remote peer */ int have_remote_id; /* non-zero if remote_id is valid */ @@ -215,6 +223,9 @@ struct Channel { /* Read buffer size */ #define CHAN_RBUF (16*1024) +/* Maximum channel input buffer size */ +#define CHAN_INPUT_MAX (16*1024*1024) + /* Hard limit on number of channels */ #define CHANNELS_MAX_CHANNELS (16*1024) diff --git a/cipher-chachapoly-libcrypto.c b/cipher-chachapoly-libcrypto.c new file mode 100644 index 000000000..719f9c843 --- /dev/null +++ b/cipher-chachapoly-libcrypto.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2013 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. + */ + +/* $OpenBSD: cipher-chachapoly-libcrypto.c,v 1.1 2020/04/03 04:32:21 djm Exp $ */ + +#include "includes.h" +#ifdef WITH_OPENSSL +#include "openbsd-compat/openssl-compat.h" +#endif + +#if defined(HAVE_EVP_CHACHA20) && !defined(HAVE_BROKEN_CHACHA20) + +#include +#include /* needed for log.h */ +#include +#include /* needed for misc.h */ + +#include + +#include "log.h" +#include "sshbuf.h" +#include "ssherr.h" +#include "cipher-chachapoly.h" + +struct chachapoly_ctx { + EVP_CIPHER_CTX *main_evp, *header_evp; +}; + +struct chachapoly_ctx * +chachapoly_new(const u_char *key, u_int keylen) +{ + struct chachapoly_ctx *ctx; + + if (keylen != (32 + 32)) /* 2 x 256 bit keys */ + return NULL; + if ((ctx = calloc(1, sizeof(*ctx))) == NULL) + return NULL; + if ((ctx->main_evp = EVP_CIPHER_CTX_new()) == NULL || + (ctx->header_evp = EVP_CIPHER_CTX_new()) == NULL) + goto fail; + if (!EVP_CipherInit(ctx->main_evp, EVP_chacha20(), key, NULL, 1)) + goto fail; + if (!EVP_CipherInit(ctx->header_evp, EVP_chacha20(), key + 32, NULL, 1)) + goto fail; + if (EVP_CIPHER_CTX_iv_length(ctx->header_evp) != 16) + goto fail; + return ctx; + fail: + chachapoly_free(ctx); + return NULL; +} + +void +chachapoly_free(struct chachapoly_ctx *cpctx) +{ + if (cpctx == NULL) + return; + EVP_CIPHER_CTX_free(cpctx->main_evp); + EVP_CIPHER_CTX_free(cpctx->header_evp); + freezero(cpctx, sizeof(*cpctx)); +} + +/* + * chachapoly_crypt() operates as following: + * En/decrypt with header key 'aadlen' bytes from 'src', storing result + * to 'dest'. The ciphertext here is treated as additional authenticated + * data for MAC calculation. + * En/decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. Use + * POLY1305_TAGLEN bytes at offset 'len'+'aadlen' as the authentication + * tag. This tag is written on encryption and verified on decryption. + */ +int +chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest, + const u_char *src, u_int len, u_int aadlen, u_int authlen, int do_encrypt) +{ + u_char seqbuf[16]; /* layout: u64 counter || u64 seqno */ + int r = SSH_ERR_INTERNAL_ERROR; + u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN]; + + /* + * Run ChaCha20 once to generate the Poly1305 key. The IV is the + * packet sequence number. + */ + memset(seqbuf, 0, sizeof(seqbuf)); + POKE_U64(seqbuf + 8, seqnr); + memset(poly_key, 0, sizeof(poly_key)); + if (!EVP_CipherInit(ctx->main_evp, NULL, NULL, seqbuf, 1) || + EVP_Cipher(ctx->main_evp, poly_key, + poly_key, sizeof(poly_key)) < 0) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + + /* If decrypting, check tag before anything else */ + if (!do_encrypt) { + const u_char *tag = src + aadlen + len; + + poly1305_auth(expected_tag, src, aadlen + len, poly_key); + if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) { + r = SSH_ERR_MAC_INVALID; + goto out; + } + } + + /* Crypt additional data */ + if (aadlen) { + if (!EVP_CipherInit(ctx->header_evp, NULL, NULL, seqbuf, 1) || + EVP_Cipher(ctx->header_evp, dest, src, aadlen) < 0) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + } + + /* Set Chacha's block counter to 1 */ + seqbuf[0] = 1; + if (!EVP_CipherInit(ctx->main_evp, NULL, NULL, seqbuf, 1) || + EVP_Cipher(ctx->main_evp, dest + aadlen, src + aadlen, len) < 0) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + + /* If encrypting, calculate and append tag */ + if (do_encrypt) { + poly1305_auth(dest + aadlen + len, dest, aadlen + len, + poly_key); + } + r = 0; + out: + explicit_bzero(expected_tag, sizeof(expected_tag)); + explicit_bzero(seqbuf, sizeof(seqbuf)); + explicit_bzero(poly_key, sizeof(poly_key)); + return r; +} + +/* Decrypt and extract the encrypted packet length */ +int +chachapoly_get_length(struct chachapoly_ctx *ctx, + u_int *plenp, u_int seqnr, const u_char *cp, u_int len) +{ + u_char buf[4], seqbuf[16]; + + if (len < 4) + return SSH_ERR_MESSAGE_INCOMPLETE; + memset(seqbuf, 0, sizeof(seqbuf)); + POKE_U64(seqbuf + 8, seqnr); + if (!EVP_CipherInit(ctx->header_evp, NULL, NULL, seqbuf, 0)) + return SSH_ERR_LIBCRYPTO_ERROR; + if (EVP_Cipher(ctx->header_evp, buf, (u_char *)cp, sizeof(buf)) < 0) + return SSH_ERR_LIBCRYPTO_ERROR; + *plenp = PEEK_U32(buf); + return 0; +} +#endif /* defined(HAVE_EVP_CHACHA20) && !defined(HAVE_BROKEN_CHACHA20) */ diff --git a/cipher-chachapoly.c b/cipher-chachapoly.c index 0899c5ad5..716f8d426 100644 --- a/cipher-chachapoly.c +++ b/cipher-chachapoly.c @@ -14,9 +14,14 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: cipher-chachapoly.c,v 1.8 2016/08/03 05:41:57 djm Exp $ */ +/* $OpenBSD: cipher-chachapoly.c,v 1.9 2020/04/03 04:27:03 djm Exp $ */ #include "includes.h" +#ifdef WITH_OPENSSL +#include "openbsd-compat/openssl-compat.h" +#endif + +#if !defined(HAVE_EVP_CHACHA20) || defined(HAVE_BROKEN_CHACHA20) #include #include /* needed for log.h */ @@ -28,15 +33,28 @@ #include "ssherr.h" #include "cipher-chachapoly.h" -int -chachapoly_init(struct chachapoly_ctx *ctx, - const u_char *key, u_int keylen) +struct chachapoly_ctx { + struct chacha_ctx main_ctx, header_ctx; +}; + +struct chachapoly_ctx * +chachapoly_new(const u_char *key, u_int keylen) { + struct chachapoly_ctx *ctx; + if (keylen != (32 + 32)) /* 2 x 256 bit keys */ - return SSH_ERR_INVALID_ARGUMENT; + return NULL; + if ((ctx = calloc(1, sizeof(*ctx))) == NULL) + return NULL; chacha_keysetup(&ctx->main_ctx, key, 256); chacha_keysetup(&ctx->header_ctx, key + 32, 256); - return 0; + return ctx; +} + +void +chachapoly_free(struct chachapoly_ctx *cpctx) +{ + freezero(cpctx, sizeof(*cpctx)); } /* @@ -117,3 +135,5 @@ chachapoly_get_length(struct chachapoly_ctx *ctx, *plenp = PEEK_U32(buf); return 0; } + +#endif /* !defined(HAVE_EVP_CHACHA20) || defined(HAVE_BROKEN_CHACHA20) */ diff --git a/cipher-chachapoly.h b/cipher-chachapoly.h index b7072be7d..026d2de93 100644 --- a/cipher-chachapoly.h +++ b/cipher-chachapoly.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher-chachapoly.h,v 1.4 2014/06/24 01:13:21 djm Exp $ */ +/* $OpenBSD: cipher-chachapoly.h,v 1.5 2020/04/03 04:27:03 djm Exp $ */ /* * Copyright (c) Damien Miller 2013 @@ -24,13 +24,12 @@ #define CHACHA_KEYLEN 32 /* Only 256 bit keys used here */ -struct chachapoly_ctx { - struct chacha_ctx main_ctx, header_ctx; -}; +struct chachapoly_ctx; + +struct chachapoly_ctx *chachapoly_new(const u_char *key, u_int keylen) + __attribute__((__bounded__(__buffer__, 1, 2))); +void chachapoly_free(struct chachapoly_ctx *cpctx); -int chachapoly_init(struct chachapoly_ctx *cpctx, - const u_char *key, u_int keylen) - __attribute__((__bounded__(__buffer__, 2, 3))); int chachapoly_crypt(struct chachapoly_ctx *cpctx, u_int seqnr, u_char *dest, const u_char *src, u_int len, u_int aadlen, u_int authlen, int do_encrypt); diff --git a/cipher.c b/cipher.c index 25f98ba8e..639511cfd 100644 --- a/cipher.c +++ b/cipher.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher.c,v 1.113 2019/09/06 05:23:55 djm Exp $ */ +/* $OpenBSD: cipher.c,v 1.118 2020/12/21 11:09:32 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -59,7 +59,7 @@ struct sshcipher_ctx { int plaintext; int encrypt; EVP_CIPHER_CTX *evp; - struct chachapoly_ctx cp_ctx; /* XXX union with evp? */ + struct chachapoly_ctx *cp_ctx; struct aesctr_ctx ac_ctx; /* XXX union with evp? */ const struct sshcipher *cipher; }; @@ -91,8 +91,6 @@ static const struct sshcipher ciphers[] = { { "aes128-cbc", 16, 16, 0, 0, CFLAG_CBC, EVP_aes_128_cbc }, { "aes192-cbc", 16, 24, 0, 0, CFLAG_CBC, EVP_aes_192_cbc }, { "aes256-cbc", 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc }, - { "rijndael-cbc@lysator.liu.se", - 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc }, { "aes128-ctr", 16, 16, 0, 0, 0, EVP_aes_128_ctr }, { "aes192-ctr", 16, 24, 0, 0, 0, EVP_aes_192_ctr }, { "aes256-ctr", 16, 32, 0, 0, 0, EVP_aes_256_ctr }, @@ -143,6 +141,17 @@ cipher_alg_list(char sep, int auth_only) return ret; } +const char * +compression_alg_list(int compression) +{ +#ifdef WITH_ZLIB + return compression ? "zlib@openssh.com,zlib,none" : + "none,zlib@openssh.com,zlib"; +#else + return "none"; +#endif +} + u_int cipher_blocksize(const struct sshcipher *c) { @@ -262,7 +271,8 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher, cc->cipher = cipher; if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { - ret = chachapoly_init(&cc->cp_ctx, key, keylen); + cc->cp_ctx = chachapoly_new(key, keylen); + ret = cc->cp_ctx != NULL ? 0 : SSH_ERR_INVALID_ARGUMENT; goto out; } if ((cc->cipher->flags & CFLAG_NONE) != 0) { @@ -317,8 +327,7 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher, #ifdef WITH_OPENSSL EVP_CIPHER_CTX_free(cc->evp); #endif /* WITH_OPENSSL */ - explicit_bzero(cc, sizeof(*cc)); - free(cc); + freezero(cc, sizeof(*cc)); } } return ret; @@ -327,7 +336,7 @@ cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher, /* * cipher_crypt() operates as following: * Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'. - * Theses bytes are treated as additional authenticated data for + * These bytes are treated as additional authenticated data for * authenticated encryption modes. * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag. @@ -339,7 +348,7 @@ cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest, const u_char *src, u_int len, u_int aadlen, u_int authlen) { if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { - return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, + return chachapoly_crypt(cc->cp_ctx, seqnr, dest, src, len, aadlen, authlen, cc->encrypt); } if ((cc->cipher->flags & CFLAG_NONE) != 0) { @@ -402,7 +411,7 @@ cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr, const u_char *cp, u_int len) { if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) - return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr, + return chachapoly_get_length(cc->cp_ctx, plenp, seqnr, cp, len); if (len < 4) return SSH_ERR_MESSAGE_INCOMPLETE; @@ -415,16 +424,16 @@ cipher_free(struct sshcipher_ctx *cc) { if (cc == NULL) return; - if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) - explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx)); - else if ((cc->cipher->flags & CFLAG_AESCTR) != 0) + if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { + chachapoly_free(cc->cp_ctx); + cc->cp_ctx = NULL; + } else if ((cc->cipher->flags & CFLAG_AESCTR) != 0) explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx)); #ifdef WITH_OPENSSL EVP_CIPHER_CTX_free(cc->evp); cc->evp = NULL; #endif - explicit_bzero(cc, sizeof(*cc)); - free(cc); + freezero(cc, sizeof(*cc)); } /* diff --git a/cipher.h b/cipher.h index 5843aab49..1a591cd7f 100644 --- a/cipher.h +++ b/cipher.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher.h,v 1.54 2019/09/06 05:23:55 djm Exp $ */ +/* $OpenBSD: cipher.h,v 1.55 2020/01/23 10:24:29 dtucker Exp $ */ /* * Author: Tatu Ylonen @@ -54,6 +54,7 @@ const struct sshcipher *cipher_by_name(const char *); const char *cipher_warning_message(const struct sshcipher_ctx *); int ciphers_valid(const char *); char *cipher_alg_list(char, int); +const char *compression_alg_list(int); int cipher_init(struct sshcipher_ctx **, const struct sshcipher *, const u_char *, u_int, const u_char *, u_int, int); int cipher_crypt(struct sshcipher_ctx *, u_int, u_char *, const u_char *, diff --git a/clientloop.c b/clientloop.c index b5a1f7038..70f492f89 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.327 2019/07/24 08:57:00 mestre Exp $ */ +/* $OpenBSD: clientloop.c,v 1.358 2021/01/27 10:05:28 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -77,10 +77,10 @@ #include #endif #include -#include #include #include #include +#include #include #include #include @@ -134,6 +134,12 @@ extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */ */ extern char *host; +/* + * If this field is not NULL, the ForwardAgent socket is this path and different + * instead of SSH_AUTH_SOCK. + */ +extern char *forward_agent_sock_path; + /* * 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 @@ -143,9 +149,6 @@ extern char *host; 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; @@ -159,6 +162,7 @@ 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 time_t server_alive_time; /* Time to do server_alive_check */ static void client_init_dispatch(struct ssh *ssh); int session_ident = -1; @@ -190,17 +194,6 @@ static struct global_confirms 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. @@ -240,13 +233,13 @@ set_control_persist_exit_time(struct ssh *ssh) } else if (channel_still_open(ssh)) { /* some client connections are still open */ if (control_persist_exit_time > 0) - debug2("%s: cancel scheduled exit", __func__); + debug2_f("cancel scheduled exit"); 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__, + debug2_f("schedule exit in %d seconds", options.control_persist_timeout); } /* else we are already counting down to the timeout */ @@ -314,7 +307,7 @@ client_x11_get_proto(struct ssh *ssh, const char *display, if ((r = snprintf(xdisplay, sizeof(xdisplay), "unix:%s", display + 10)) < 0 || (size_t)r >= sizeof(xdisplay)) { - error("%s: display name too long", __func__); + error_f("display name too long"); return -1; } display = xdisplay; @@ -329,15 +322,14 @@ client_x11_get_proto(struct ssh *ssh, const char *display, */ mktemp_proto(xauthdir, sizeof(xauthdir)); if (mkdtemp(xauthdir) == NULL) { - error("%s: mkdtemp: %s", - __func__, strerror(errno)); + error_f("mkdtemp: %s", 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__); + error_f("xauthfile path too long"); rmdir(xauthdir); return -1; } @@ -363,7 +355,7 @@ client_x11_get_proto(struct ssh *ssh, const char *display, SSH_X11_PROTO, x11_timeout_real, _PATH_DEVNULL); } - debug2("%s: xauth command: %s", __func__, cmd); + debug2_f("xauth command: %s", cmd); if (timeout != 0 && x11_refuse_time == 0) { now = monotime() + 1; @@ -451,11 +443,8 @@ client_check_window_change(struct ssh *ssh) { if (!received_window_change_signal) return; - /** XXX race */ received_window_change_signal = 0; - - debug2("%s: changed", __func__); - + debug2_f("changed"); channel_send_window_changes(ssh); } @@ -470,14 +459,20 @@ client_global_request_reply(int type, u_int32_t seq, struct ssh *ssh) 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); + freezero(gc, sizeof(*gc)); } ssh_packet_set_alive_timeouts(ssh, 0); return 0; } +static void +schedule_server_alive_check(void) +{ + if (options.server_alive_interval > 0) + server_alive_time = monotime() + options.server_alive_interval; +} + static void server_alive_check(struct ssh *ssh) { @@ -491,9 +486,10 @@ server_alive_check(struct ssh *ssh) (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)); + fatal_fr(r, "send packet"); /* Insert an empty placeholder to maintain ordering */ client_register_global_confirm(NULL, NULL); + schedule_server_alive_check(); } /* @@ -507,7 +503,7 @@ client_wait_until_can_do_something(struct ssh *ssh, { struct timeval tv, *tvp; int timeout_secs; - time_t minwait_secs = 0, server_alive_time = 0, now = monotime(); + time_t minwait_secs = 0, now = monotime(); int r, ret; /* Add any selections by the channel mechanism. */ @@ -536,10 +532,8 @@ client_wait_until_can_do_something(struct ssh *ssh, */ 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.server_alive_interval > 0) + timeout_secs = MAXIMUM(server_alive_time - now, 0); if (options.rekey_interval > 0 && !rekeying) timeout_secs = MINIMUM(timeout_secs, ssh_packet_get_rekey_timeout(ssh)); @@ -569,23 +563,21 @@ client_wait_until_can_do_something(struct ssh *ssh, */ 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)); + fatal_fr(r, "sshbuf_putf"); quit_pending = 1; - } else if (ret == 0) { + } else if (options.server_alive_interval > 0 && !FD_ISSET(connection_in, + *readsetp) && monotime() >= server_alive_time) /* - * Timeout. Could have been either keepalive or rekeying. - * Keepalive we check here, rekeying is checked in clientloop. + * ServerAlive check is needed. We can't rely on the select + * timing out since traffic on the client side such as port + * forwards can keep waking it up. */ - if (server_alive_time != 0 && server_alive_time <= monotime()) - server_alive_check(ssh); - } - + server_alive_check(ssh); } static void @@ -625,6 +617,7 @@ client_process_net_input(struct ssh *ssh, fd_set *readset) * the packet subsystem. */ if (FD_ISSET(connection_in, readset)) { + schedule_server_alive_check(); /* Read as much as possible. */ len = read(connection_in, buf, sizeof(buf)); if (len == 0) { @@ -635,8 +628,7 @@ client_process_net_input(struct ssh *ssh, fd_set *readset) 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)); + fatal_fr(r, "sshbuf_putf"); quit_pending = 1; return; } @@ -656,8 +648,7 @@ client_process_net_input(struct ssh *ssh, fd_set *readset) 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)); + fatal_fr(r, "sshbuf_putf"); quit_pending = 1; return; } @@ -707,8 +698,7 @@ client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx) if (tochan) { if ((r = sshbuf_put(c->extended, errmsg, strlen(errmsg))) != 0) - fatal("%s: buffer error %s", __func__, - ssh_err(r)); + fatal_fr(r, "sshbuf_put"); } else error("%s", errmsg); if (cr->action == CONFIRM_TTY) { @@ -756,8 +746,8 @@ client_register_global_confirm(global_confirm_cb *cb, void *ctx) 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); + fatal_f("last_gc->ref_count = %d", + last_gc->ref_count); return; } @@ -779,7 +769,7 @@ process_cmdline(struct ssh *ssh) memset(&fwd, 0, sizeof(fwd)); leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); - handler = signal(SIGINT, SIG_IGN); + handler = ssh_signal(SIGINT, SIG_IGN); cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); if (s == NULL) goto out; @@ -877,7 +867,7 @@ process_cmdline(struct ssh *ssh) } out: - signal(SIGINT, handler); + ssh_signal(SIGINT, handler); enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); free(cmd); free(fwd.listen_host); @@ -920,7 +910,7 @@ print_escape_help(struct sshbuf *b, int escape_char, int mux_client, if ((r = sshbuf_putf(b, "%c?\r\nSupported escape sequences:\r\n", escape_char)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_putf"); suppress_flags = (mux_client ? SUPPRESS_MUXCLIENT : 0) | @@ -932,14 +922,14 @@ print_escape_help(struct sshbuf *b, int escape_char, int mux_client, 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)); + fatal_fr(r, "sshbuf_putf"); } 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)); + fatal_fr(r, "sshbuf_putf"); } /* @@ -979,8 +969,7 @@ process_escapes(struct ssh *ssh, Channel *c, /* Terminate the connection. */ if ((r = sshbuf_putf(berr, "%c.\r\n", efc->escape_char)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_putf"); if (c && c->ctl_chan != -1) { chan_read_failed(ssh, c); chan_write_failed(ssh, c); @@ -1009,16 +998,14 @@ process_escapes(struct ssh *ssh, Channel *c, "%c%s escape not available to " "multiplexed sessions\r\n", efc->escape_char, b)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_putf"); 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)); + fatal_fr(r, "sshbuf_putf"); /* Restore terminal modes and suspend. */ client_suspend_self(bin, bout, berr); @@ -1029,17 +1016,15 @@ process_escapes(struct ssh *ssh, Channel *c, case 'B': if ((r = sshbuf_putf(berr, "%cB\r\n", efc->escape_char)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_putf"); channel_request_start(ssh, c->self, "break", 0); if ((r = sshpkt_put_u32(ssh, 1000)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal("%s: send packet: %s", __func__, - ssh_err(r)); + fatal_fr(r, "send packet"); continue; case 'R': - if (datafellows & SSH_BUG_NOREKEY) + if (ssh->compat & SSH_BUG_NOREKEY) logit("Server does not " "support re-keying"); else @@ -1055,8 +1040,7 @@ process_escapes(struct ssh *ssh, Channel *c, 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)); + fatal_fr(r, "sshbuf_putf"); continue; } if (ch == 'V' && options.log_level > @@ -1069,8 +1053,7 @@ process_escapes(struct ssh *ssh, Channel *c, "%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)); + fatal_fr(r, "sshbuf_putf"); continue; case '&': @@ -1088,11 +1071,9 @@ process_escapes(struct ssh *ssh, Channel *c, /* 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)); + if ((r = sshbuf_putf(berr, "%c& " + "[backgrounded]\n", efc->escape_char)) != 0) + fatal_fr(r, "sshbuf_putf"); /* Fork into background. */ pid = fork(); @@ -1107,8 +1088,7 @@ process_escapes(struct ssh *ssh, Channel *c, /* 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)); + fatal_fr(r, "sshbuf_put_u8"); return -1; case '?': print_escape_help(berr, efc->escape_char, @@ -1119,12 +1099,10 @@ process_escapes(struct ssh *ssh, Channel *c, case '#': if ((r = sshbuf_putf(berr, "%c#\r\n", efc->escape_char)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_putf"); s = channel_open_message(ssh); if ((r = sshbuf_put(berr, s, strlen(s))) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_put"); free(s); continue; @@ -1138,8 +1116,7 @@ process_escapes(struct ssh *ssh, Channel *c, if (ch != efc->escape_char) { if ((r = sshbuf_put_u8(bin, efc->escape_char)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_put_u8"); bytes++; } /* Escaped characters fall through here */ @@ -1166,7 +1143,7 @@ process_escapes(struct ssh *ssh, Channel *c, */ last_was_cr = (ch == '\r' || ch == '\n'); if ((r = sshbuf_put_u8(bin, ch)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_put_u8"); bytes++; } return bytes; @@ -1244,7 +1221,6 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, 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."); @@ -1253,30 +1229,30 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, debug("pledge: id"); if (pledge("stdio rpath wpath cpath unix inet dns recvfd sendfd proc exec id tty", NULL) == -1) - fatal("%s pledge(): %s", __func__, strerror(errno)); + fatal_f("pledge(): %s", 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)); + fatal_f("pledge(): %s", 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)); + fatal_f("pledge(): %s", 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)); + fatal_f("pledge(): %s", strerror(errno)); } else { debug("pledge: network"); if (pledge("stdio unix inet dns proc tty", NULL) == -1) - fatal("%s pledge(): %s", __func__, strerror(errno)); + fatal_f("pledge(): %s", strerror(errno)); } start_time = monotime_double(); @@ -1292,7 +1268,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, /* Initialize buffer. */ if ((stderr_buffer = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); client_init_dispatch(ssh); @@ -1300,15 +1276,15 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, * 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 (ssh_signal(SIGHUP, SIG_IGN) != SIG_IGN) + ssh_signal(SIGHUP, signal_handler); + if (ssh_signal(SIGINT, SIG_IGN) != SIG_IGN) + ssh_signal(SIGINT, signal_handler); + if (ssh_signal(SIGQUIT, SIG_IGN) != SIG_IGN) + ssh_signal(SIGQUIT, signal_handler); + if (ssh_signal(SIGTERM, SIG_IGN) != SIG_IGN) + ssh_signal(SIGTERM, signal_handler); + ssh_signal(SIGWINCH, window_change_handler); if (have_pty) enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); @@ -1326,6 +1302,8 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, client_channel_closed, 0); } + schedule_server_alive_check(); + /* Main loop of the client for the interactive session mode. */ while (!quit_pending) { @@ -1341,8 +1319,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, /* manual rekey request */ debug("need rekeying"); if ((r = kex_start_rekex(ssh)) != 0) - fatal("%s: kex_start_rekex: %s", __func__, - ssh_err(r)); + fatal_fr(r, "kex_start_rekex"); need_rekeying = 0; } else { /* @@ -1386,8 +1363,12 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, * Send as much buffered packet data as possible to the * sender. */ - if (FD_ISSET(connection_out, writeset)) - ssh_packet_write_poll(ssh); + if (FD_ISSET(connection_out, writeset)) { + if ((r = ssh_packet_write_poll(ssh)) != 0) { + sshpkt_fatal(ssh, r, + "%s: ssh_packet_write_poll", __func__); + } + } /* * If we are a backgrounded control master, and the @@ -1407,7 +1388,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, /* Terminate the session. */ /* Stop watching for window change. */ - signal(SIGWINCH, SIG_DFL); + ssh_signal(SIGWINCH, SIG_DFL); if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_BY_APPLICATION)) != 0 || @@ -1415,7 +1396,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, (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)); + fatal_fr(r, "send disconnect"); channel_free_all(ssh); @@ -1452,7 +1433,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, 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)); + fatal_fr(r, "sshbuf_putf"); } /* Output any buffered data for stderr. */ @@ -1463,11 +1444,10 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, 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)); + fatal_fr(r, "sshbuf_consume"); } /* Clear and free any buffers. */ - explicit_bzero(buf, sizeof(buf)); sshbuf_free(stderr_buffer); /* Report bytes transferred, and transfer rates. */ @@ -1501,15 +1481,15 @@ client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type, (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)); + fatal_fr(r, "parse packet"); - debug("%s: listen %s port %d, originator %s port %d", __func__, + debug_f("listen %s port %d, originator %s port %d", listen_address, listen_port, originator_address, originator_port); if (listen_port > 0xffff) - error("%s: invalid listen port", __func__); + error_f("invalid listen port"); else if (originator_port > 0xffff) - error("%s: invalid originator port", __func__); + error_f("invalid originator port"); else { c = channel_connect_by_listen_address(ssh, listen_address, listen_port, "forwarded-tcpip", @@ -1518,7 +1498,7 @@ client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type, if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { if ((b = sshbuf_new()) == NULL) { - error("%s: alloc reply", __func__); + error_f("alloc reply"); goto out; } /* reconstruct and send to muxclient */ @@ -1533,8 +1513,7 @@ client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type, (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)); + error_fr(r, "compose for muxclient"); goto out; } } @@ -1558,9 +1537,9 @@ client_request_forwarded_streamlocal(struct ssh *ssh, 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)); + fatal_fr(r, "parse packet"); - debug("%s: request: %s", __func__, listen_path); + debug_f("request: %s", listen_path); c = channel_connect_by_listen_path(ssh, listen_path, "forwarded-streamlocal@openssh.com", "forwarded-streamlocal"); @@ -1590,7 +1569,7 @@ client_request_x11(struct ssh *ssh, const char *request_type, int rchan) 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)); + fatal_fr(r, "parse packet"); /* XXX check permission */ /* XXX range check originator port? */ debug("client_request_x11: request from %s %u", originator, @@ -1618,10 +1597,14 @@ client_request_agent(struct ssh *ssh, const char *request_type, int rchan) "malicious server."); return NULL; } - if ((r = ssh_get_authentication_socket(&sock)) != 0) { + if (forward_agent_sock_path == NULL) { + r = ssh_get_authentication_socket(&sock); + } else { + r = ssh_get_authentication_socket_path(forward_agent_sock_path, &sock); + } + if (r != 0) { if (r != SSH_ERR_AGENT_NOT_PRESENT) - debug("%s: ssh_get_authentication_socket: %s", - __func__, ssh_err(r)); + debug_fr(r, "ssh_get_authentication_socket"); return NULL; } c = channel_new(ssh, "authentication agent connection", @@ -1634,7 +1617,7 @@ client_request_agent(struct ssh *ssh, const char *request_type, int rchan) char * client_request_tun_fwd(struct ssh *ssh, int tun_mode, - int local_tun, int remote_tun) + int local_tun, int remote_tun, channel_open_fn *cb, void *cbctx) { Channel *c; int r, fd; @@ -1662,6 +1645,9 @@ client_request_tun_fwd(struct ssh *ssh, int tun_mode, sys_tun_outfilter, NULL, NULL); #endif + if (cb != NULL) + channel_register_open_confirm(ssh, c->self, cb, cbctx); + 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 || @@ -1779,16 +1765,15 @@ client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) 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); + debug_f("no sink for exit-status on channel %d", + id); } 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); + fatal_f("channel %d: no remote_id", c->self); if ((r = sshpkt_start(ssh, success ? SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || @@ -1808,12 +1793,13 @@ struct hostkeys_update_ctx { /* * 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_match 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; + u_int *keys_match; /* mask of HKF_MATCH_* from hostfile.h */ + int *keys_verified; /* flag for new keys verified by server */ + size_t nkeys, nnew, nincomplete; /* total, new keys, incomplete match */ /* * Keys that are in known_hosts, but were not present in the update @@ -1822,6 +1808,12 @@ struct hostkeys_update_ctx { */ struct sshkey **old_keys; size_t nold; + + /* Various special cases. */ + int complex_hostspec; /* wildcard or manual pattern-list host name */ + int ca_available; /* saw CA key for this host */ + int old_key_seen; /* saw old key with other name/addr */ + int other_name_seen; /* saw key with other name/addr */ }; static void @@ -1834,7 +1826,8 @@ hostkeys_update_ctx_free(struct hostkeys_update_ctx *ctx) for (i = 0; i < ctx->nkeys; i++) sshkey_free(ctx->keys[i]); free(ctx->keys); - free(ctx->keys_seen); + free(ctx->keys_match); + free(ctx->keys_verified); for (i = 0; i < ctx->nold; i++) sshkey_free(ctx->old_keys[i]); free(ctx->old_keys); @@ -1843,6 +1836,30 @@ hostkeys_update_ctx_free(struct hostkeys_update_ctx *ctx) free(ctx); } +/* + * Returns non-zero if a known_hosts hostname list is not of a form that + * can be handled by UpdateHostkeys. These include wildcard hostnames and + * hostnames lists that do not follow the form host[,ip]. + */ +static int +hostspec_is_complex(const char *hosts) +{ + char *cp; + + /* wildcard */ + if (strchr(hosts, '*') != NULL || strchr(hosts, '?') != NULL) + return 1; + /* single host/ip = ok */ + if ((cp = strchr(hosts, ',')) == NULL) + return 0; + /* more than two entries on the line */ + if (strchr(cp + 1, ',') != NULL) + return 1; + /* XXX maybe parse cp+1 and ensure it is an IP? */ + return 0; +} + +/* callback to search for ctx->keys in known_hosts */ static int hostkeys_find(struct hostkey_foreach_line *l, void *_ctx) { @@ -1850,25 +1867,73 @@ hostkeys_find(struct hostkey_foreach_line *l, void *_ctx) size_t i; struct sshkey **tmp; - if (l->status != HKF_STATUS_MATCHED || l->key == NULL) + if (l->key == NULL) return 0; + if (l->status != HKF_STATUS_MATCHED) { + /* Record if one of the keys appears on a non-matching line */ + for (i = 0; i < ctx->nkeys; i++) { + if (sshkey_equal(l->key, ctx->keys[i])) { + ctx->other_name_seen = 1; + debug3_f("found %s key under different " + "name/addr at %s:%ld", + sshkey_ssh_name(ctx->keys[i]), + l->path, l->linenum); + return 0; + } + } + return 0; + } + /* Don't proceed if revocation or CA markers are present */ + /* XXX relax this */ + if (l->marker != MRK_NONE) { + debug3_f("hostkeys file %s:%ld has CA/revocation marker", + l->path, l->linenum); + ctx->complex_hostspec = 1; + return 0; + } + + /* If CheckHostIP is enabled, then check for mismatched hostname/addr */ + if (ctx->ip_str != NULL && strchr(l->hosts, ',') != NULL) { + if ((l->match & HKF_MATCH_HOST) == 0) { + /* Record if address matched a different hostname. */ + ctx->other_name_seen = 1; + debug3_f("found address %s against different hostname " + "at %s:%ld", ctx->ip_str, l->path, l->linenum); + return 0; + } else if ((l->match & HKF_MATCH_IP) == 0) { + /* Record if hostname matched a different address. */ + ctx->other_name_seen = 1; + debug3_f("found hostname %s against different address " + "at %s:%ld", ctx->host_str, l->path, l->linenum); + } + } + + /* + * UpdateHostkeys is skipped for wildcard host names and hostnames + * that contain more than two entries (ssh never writes these). + */ + if (hostspec_is_complex(l->hosts)) { + debug3_f("hostkeys file %s:%ld complex host specification", + l->path, l->linenum); + ctx->complex_hostspec = 1; + 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; - } + if (!sshkey_equal(l->key, ctx->keys[i])) + continue; + debug3_f("found %s key at %s:%ld", + sshkey_ssh_name(ctx->keys[i]), l->path, l->linenum); + ctx->keys_match[i] |= l->match; + 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); + debug3_f("deprecated %s key at %s:%ld", 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); + fatal_f("recallocarray failed nold = %zu", ctx->nold); ctx->old_keys = tmp; ctx->old_keys[ctx->nold++] = l->key; l->key = NULL; @@ -1876,31 +1941,103 @@ hostkeys_find(struct hostkey_foreach_line *l, void *_ctx) return 0; } +/* callback to search for ctx->old_keys in known_hosts under other names */ +static int +hostkeys_check_old(struct hostkey_foreach_line *l, void *_ctx) +{ + struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; + size_t i; + int hashed; + + /* only care about lines that *don't* match the active host spec */ + if (l->status == HKF_STATUS_MATCHED || l->key == NULL) + return 0; + + hashed = l->match & (HKF_MATCH_HOST_HASHED|HKF_MATCH_IP_HASHED); + for (i = 0; i < ctx->nold; i++) { + if (!sshkey_equal(l->key, ctx->old_keys[i])) + continue; + debug3_f("found deprecated %s key at %s:%ld as %s", + sshkey_ssh_name(ctx->keys[i]), l->path, l->linenum, + hashed ? "[HASHED]" : l->hosts); + ctx->old_key_seen = 1; + break; + } + return 0; +} + +/* + * Check known_hosts files for deprecated keys under other names. Returns 0 + * on success or -1 on failure. Updates ctx->old_key_seen if deprecated keys + * exist under names other than the active hostname/IP. + */ +static int +check_old_keys_othernames(struct hostkeys_update_ctx *ctx) +{ + size_t i; + int r; + + debug2_f("checking for %zu deprecated keys", ctx->nold); + for (i = 0; i < options.num_user_hostfiles; i++) { + debug3_f("searching %s for %s / %s", + options.user_hostfiles[i], ctx->host_str, + ctx->ip_str ? ctx->ip_str : "(none)"); + if ((r = hostkeys_foreach(options.user_hostfiles[i], + hostkeys_check_old, ctx, ctx->host_str, ctx->ip_str, + HKF_WANT_PARSE_KEY, 0)) != 0) { + if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) { + debug_f("hostkeys file %s does not exist", + options.user_hostfiles[i]); + continue; + } + error_fr(r, "hostkeys_foreach failed for %s", + options.user_hostfiles[i]); + return -1; + } + } + return 0; +} + +static void +hostkey_change_preamble(LogLevel loglevel) +{ + do_log2(loglevel, "The server has updated its host keys."); + do_log2(loglevel, "These changes were verified by the server's " + "existing trusted key."); +} + static void update_known_hosts(struct hostkeys_update_ctx *ctx) { - int r, was_raw = 0; - LogLevel loglevel = options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK ? - SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_VERBOSE; + int r, was_raw = 0, first = 1; + int asking = options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK; + LogLevel loglevel = asking ? SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_VERBOSE; char *fp, *response; size_t i; + struct stat sb; for (i = 0; i < ctx->nkeys; i++) { - if (ctx->keys_seen[i] != 2) + if (!ctx->keys_verified[i]) continue; if ((fp = sshkey_fingerprint(ctx->keys[i], options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) - fatal("%s: sshkey_fingerprint failed", __func__); + fatal_f("sshkey_fingerprint failed"); + if (first && asking) + hostkey_change_preamble(loglevel); do_log2(loglevel, "Learned new hostkey: %s %s", sshkey_type(ctx->keys[i]), fp); + first = 0; 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__); + fatal_f("sshkey_fingerprint failed"); + if (first && asking) + hostkey_change_preamble(loglevel); do_log2(loglevel, "Deprecating obsolete hostkey: %s %s", sshkey_type(ctx->old_keys[i]), fp); + first = 0; free(fp); } if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) { @@ -1930,19 +2067,38 @@ update_known_hosts(struct hostkeys_update_ctx *ctx) if (was_raw) enter_raw_mode(1); } - + if (options.update_hostkeys == 0) + return; /* * 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)); + for (i = 0; i < options.num_user_hostfiles; i++) { + /* + * NB. keys are only added to hostfiles[0], for the rest we + * just delete the hostname entries. + */ + if (stat(options.user_hostfiles[i], &sb) != 0) { + if (errno == ENOENT) { + debug_f("known hosts file %s does not " + "exist", options.user_hostfiles[i]); + } else { + error_f("known hosts file %s " + "inaccessible: %s", + options.user_hostfiles[i], strerror(errno)); + } + continue; + } + if ((r = hostfile_replace_entries(options.user_hostfiles[i], + ctx->host_str, ctx->ip_str, + i == 0 ? ctx->keys : NULL, i == 0 ? ctx->nkeys : 0, + options.hash_known_hosts, 0, + options.fingerprint_hash)) != 0) { + error_fr(r, "hostfile_replace_entries failed for %s", + options.user_hostfiles[i]); + } + } } static void @@ -1957,7 +2113,7 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type, size_t siglen; if (ctx->nnew == 0) - fatal("%s: ctx->nnew == 0", __func__); /* sanity */ + fatal_f("ctx->nnew == 0"); /* sanity */ if (type != SSH2_MSG_REQUEST_SUCCESS) { error("Server failed to confirm ownership of " "private host keys"); @@ -1968,31 +2124,26 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type, 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__); + fatal_f("sshbuf_new failed"); /* * 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. + * ctx->keys where the corresponding ctx->keys_match[i] == 0. */ for (ndone = i = 0; i < ctx->nkeys; i++) { - if (ctx->keys_seen[i]) + if (ctx->keys_match[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 = sshbuf_put_stringb(signdata, + ssh->kex->session_id)) != 0 || (r = sshkey_puts(ctx->keys[i], signdata)) != 0) - fatal("%s: failed to prepare signature: %s", - __func__, ssh_err(r)); + fatal_fr(r, "compose signdata"); /* 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)); + error_fr(r, "parse sig"); goto out; } /* @@ -2003,20 +2154,21 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type, 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); + use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0, + NULL)) != 0) { + error_f("server gave bad signature for %s key %zu", + sshkey_type(ctx->keys[i]), i); goto out; } /* Key is good. Mark it as 'seen' */ - ctx->keys_seen[i] = 2; + ctx->keys_verified[i] = 1; ndone++; } + /* Shouldn't happen */ if (ndone != ctx->nnew) - fatal("%s: ndone != ctx->nnew (%zu / %zu)", __func__, - ndone, ctx->nnew); /* Shouldn't happen */ + fatal_f("ndone != ctx->nnew (%zu / %zu)", ndone, ctx->nnew); if ((r = sshpkt_get_end(ssh)) != 0) { - error("%s: protocol error", __func__); + error_f("protocol error"); goto out; } @@ -2034,8 +2186,7 @@ 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; + const char *hostkeyalgs = options.hostkeyalgorithms; if (key == NULL || key->type == KEY_UNSPEC) return 0; @@ -2063,9 +2214,10 @@ client_input_hostkeys(struct ssh *ssh) static int hostkeys_seen = 0; /* XXX use struct ssh */ extern struct sockaddr_storage hostaddr; /* XXX from ssh.c */ struct hostkeys_update_ctx *ctx = NULL; + u_int want; if (hostkeys_seen) - fatal("%s: server already sent hostkeys", __func__); + fatal_f("server already sent hostkeys"); if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK && options.batch_mode) return 1; /* won't ask in batchmode, so don't even try */ @@ -2077,57 +2229,59 @@ client_input_hostkeys(struct ssh *ssh) 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)); + error_fr(r, "parse key"); goto out; } if ((r = sshkey_from_blob(blob, len, &key)) != 0) { - error("%s: parse key: %s", __func__, ssh_err(r)); - goto out; + do_log2_fr(r, r == SSH_ERR_KEY_TYPE_UNKNOWN ? + SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_ERROR, + "convert key"); + continue; } fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); - debug3("%s: received %s key %s", __func__, - sshkey_type(key), fp); + debug3_f("received %s key %s", 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)); + debug3_f("%s key not permitted by " + "HostkeyAlgorithms", 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)); + debug3_f("%s key is a certificate; skipping", + 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)); + error_f("received duplicated %s host key", + 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); + fatal_f("recallocarray failed nkeys = %zu", + ctx->nkeys); ctx->keys = tmp; ctx->keys[ctx->nkeys++] = key; key = NULL; } if (ctx->nkeys == 0) { - debug("%s: server sent no hostkeys", __func__); + debug_f("server sent no hostkeys"); goto out; } - if ((ctx->keys_seen = calloc(ctx->nkeys, - sizeof(*ctx->keys_seen))) == NULL) - fatal("%s: calloc failed", __func__); + if ((ctx->keys_match = calloc(ctx->nkeys, + sizeof(*ctx->keys_match))) == NULL || + (ctx->keys_verified = calloc(ctx->nkeys, + sizeof(*ctx->keys_verified))) == NULL) + fatal_f("calloc failed"); get_hostfile_hostname_ipaddr(host, options.check_host_ip ? (struct sockaddr *)&hostaddr : NULL, @@ -2135,59 +2289,109 @@ client_input_hostkeys(struct ssh *ssh) 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; + for (i = 0; i < options.num_user_hostfiles; i++) { + debug_f("searching %s for %s / %s", + options.user_hostfiles[i], ctx->host_str, + ctx->ip_str ? ctx->ip_str : "(none)"); + if ((r = hostkeys_foreach(options.user_hostfiles[i], + hostkeys_find, ctx, ctx->host_str, ctx->ip_str, + HKF_WANT_PARSE_KEY, 0)) != 0) { + if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) { + debug_f("hostkeys file %s does not exist", + options.user_hostfiles[i]); + continue; + } + error_fr(r, "hostkeys_foreach failed for %s", + options.user_hostfiles[i]); + goto out; + } } /* Figure out if we have any new keys to add */ - ctx->nnew = 0; + ctx->nnew = ctx->nincomplete = 0; + want = HKF_MATCH_HOST | ( options.check_host_ip ? HKF_MATCH_IP : 0); for (i = 0; i < ctx->nkeys; i++) { - if (!ctx->keys_seen[i]) + if (ctx->keys_match[i] == 0) ctx->nnew++; + if ((ctx->keys_match[i] & want) != want) + ctx->nincomplete++; } - debug3("%s: %zu keys from server: %zu new, %zu retained. %zu to remove", - __func__, ctx->nkeys, ctx->nnew, ctx->nkeys - ctx->nnew, ctx->nold); + debug3_f("%zu server keys: %zu new, %zu retained, " + "%zu incomplete match. %zu to remove", ctx->nkeys, ctx->nnew, + ctx->nkeys - ctx->nnew - ctx->nincomplete, + ctx->nincomplete, 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 (ctx->nnew == 0 && ctx->nold == 0) { + debug_f("no new or deprecated keys from server"); + goto out; + } + + /* Various reasons why we cannot proceed with the update */ + if (ctx->complex_hostspec) { + debug_f("CA/revocation marker, manual host list or wildcard " + "host pattern found, skipping UserKnownHostsFile update"); + goto out; + } + if (ctx->other_name_seen) { + debug_f("host key found matching a different name/address, " + "skipping UserKnownHostsFile update"); + goto out; + } + /* + * If removing keys, check whether they appear under different + * names/addresses and refuse to proceed if they do. This avoids + * cases such as hosts with multiple names becoming inconsistent + * with regards to CheckHostIP entries. + * XXX UpdateHostkeys=force to override this (and other) checks? + */ + if (ctx->nold != 0) { + if (check_old_keys_othernames(ctx) != 0) + goto out; /* error already logged */ + if (ctx->old_key_seen) { + debug_f("key(s) for %s%s%s exist under other names; " + "skipping UserKnownHostsFile update", + ctx->host_str, ctx->ip_str == NULL ? "" : ",", + ctx->ip_str == NULL ? "" : ctx->ip_str); + goto out; } - 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 */ } + if (ctx->nnew == 0) { + /* + * We have some keys to remove or fix matching for. + * We can proceed to do this without requiring a fresh proof + * from the server. + */ + update_known_hosts(ctx); + goto out; + } + /* + * We have received previously-unseen keys from the server. + * Ask the server to confirm ownership of the private halves. + */ + debug3_f("asking server to prove ownership for %zu keys", 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_fr(r, "prepare hostkeys-prove"); + if ((buf = sshbuf_new()) == NULL) + fatal_f("sshbuf_new"); + for (i = 0; i < ctx->nkeys; i++) { + if (ctx->keys_match[i]) + continue; + sshbuf_reset(buf); + if ((r = sshkey_putb(ctx->keys[i], buf)) != 0 || + (r = sshpkt_put_stringb(ssh, buf)) != 0) + fatal_fr(r, "assemble hostkeys-prove"); + } + if ((r = sshpkt_send(ssh)) != 0) + fatal_fr(r, "send hostkeys-prove"); + client_register_global_confirm( + client_global_hostkeys_private_confirm, ctx); + ctx = NULL; /* will be freed in callback */ + /* Success */ out: hostkeys_update_ctx_free(ctx); @@ -2227,6 +2431,19 @@ client_input_global_request(int type, u_int32_t seq, struct ssh *ssh) return r; } +static void +client_send_env(struct ssh *ssh, int id, const char *name, const char *val) +{ + int r; + + debug("channel %d: setting env %s = \"%s\"", id, name, val); + channel_request_start(ssh, id, "env", 0); + if ((r = sshpkt_put_cstring(ssh, name)) != 0 || + (r = sshpkt_put_cstring(ssh, val)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal_fr(r, "send setenv"); +} + 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, @@ -2236,10 +2453,10 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, char *name, *val; Channel *c = NULL; - debug2("%s: id %d", __func__, id); + debug2_f("id %d", id); if ((c = channel_lookup(ssh, id)) == NULL) - fatal("%s: channel %d: unknown channel", __func__, id); + fatal_f("channel %d: unknown channel", id); ssh_packet_set_interactive(ssh, want_tty, options.ip_qos_interactive, options.ip_qos_bulk); @@ -2259,12 +2476,12 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, (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)); + fatal_fr(r, "build pty-req"); if (tiop == NULL) tiop = get_saved_tio(); ssh_tty_make_modes(ssh, -1, tiop); if ((r = sshpkt_send(ssh)) != 0) - fatal("%s: send packet: %s", __func__, ssh_err(r)); + fatal_fr(r, "send pty-req"); /* XXX wait for reply */ c->client_tty = 1; } @@ -2293,15 +2510,7 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, free(name); continue; } - - debug("Sending env %s = %s", name, val); - channel_request_start(ssh, id, "env", 0); - 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)); - } + client_send_env(ssh, id, name, val); free(name); } } @@ -2313,13 +2522,7 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, continue; } *val++ = '\0'; - - debug("Setting env %s = %s", name, val); - channel_request_start(ssh, id, "env", 0); - 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)); + client_send_env(ssh, id, name, val); free(name); } @@ -2341,14 +2544,12 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, } if ((r = sshpkt_put_stringb(ssh, cmd)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal("%s: send command: %s", __func__, ssh_err(r)); + fatal_fr(r, "send command"); } else { channel_request_start(ssh, id, "shell", 1); client_expect_confirm(ssh, id, "shell", CONFIRM_CLOSE); - if ((r = sshpkt_send(ssh)) != 0) { - fatal("%s: send shell request: %s", - __func__, ssh_err(r)); - } + if ((r = sshpkt_send(ssh)) != 0) + fatal_fr(r, "send shell"); } } @@ -2398,7 +2599,6 @@ 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(); diff --git a/clientloop.h b/clientloop.h index bf79c87bf..31630551b 100644 --- a/clientloop.h +++ b/clientloop.h @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.h,v 1.36 2018/07/09 21:03:30 markus Exp $ */ +/* $OpenBSD: clientloop.h,v 1.37 2020/04/03 02:40:32 djm Exp $ */ /* * Author: Tatu Ylonen @@ -46,7 +46,8 @@ int client_x11_get_proto(struct ssh *, const char *, const char *, void client_global_request_reply_fwd(int, u_int32_t, void *); void client_session2_setup(struct ssh *, int, int, int, const char *, struct termios *, int, struct sshbuf *, char **); -char *client_request_tun_fwd(struct ssh *, int, int, int); +char *client_request_tun_fwd(struct ssh *, int, int, int, + channel_open_fn *, void *); void client_stop_mux(void); /* Escape filter for protocol 2 sessions */ diff --git a/compat.c b/compat.c index 0624dc6de..69befa96f 100644 --- a/compat.c +++ b/compat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: compat.c,v 1.113 2018/08/13 02:41:05 djm Exp $ */ +/* $OpenBSD: compat.c,v 1.117 2021/01/27 09:26:54 djm Exp $ */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * @@ -38,11 +38,9 @@ #include "match.h" #include "kex.h" -int datafellows = 0; - -/* datafellows bug compatibility */ -u_int -compat_datafellows(const char *version) +/* determine bug flags from SSH protocol banner */ +void +compat_banner(struct ssh *ssh, const char *version) { int i; static struct { @@ -145,89 +143,63 @@ compat_datafellows(const char *version) }; /* process table, return first match */ + ssh->compat = 0; for (i = 0; check[i].pat; i++) { if (match_pattern_list(version, check[i].pat, 0) == 1) { - debug("match: %s pat %s compat 0x%08x", + debug_f("match: %s pat %s compat 0x%08x", version, check[i].pat, check[i].bugs); - datafellows = check[i].bugs; /* XXX for now */ - return check[i].bugs; + ssh->compat = check[i].bugs; + return; } } - debug("no match: %s", version); - return 0; -} - -#define SEP "," -int -proto_spec(const char *spec) -{ - char *s, *p, *q; - int ret = SSH_PROTO_UNKNOWN; - - if (spec == NULL) - return ret; - q = s = strdup(spec); - if (s == NULL) - return ret; - for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) { - switch (atoi(p)) { - case 2: - ret |= SSH_PROTO_2; - break; - default: - logit("ignoring bad proto spec: '%s'.", p); - break; - } - } - free(s); - return ret; + debug_f("no match: %s", version); } char * -compat_cipher_proposal(char *cipher_prop) +compat_cipher_proposal(struct ssh *ssh, char *cipher_prop) { - if (!(datafellows & SSH_BUG_BIGENDIANAES)) + if (!(ssh->compat & SSH_BUG_BIGENDIANAES)) return cipher_prop; - debug2("%s: original cipher proposal: %s", __func__, cipher_prop); - if ((cipher_prop = match_filter_blacklist(cipher_prop, "aes*")) == NULL) - fatal("match_filter_blacklist failed"); - debug2("%s: compat cipher proposal: %s", __func__, cipher_prop); + debug2_f("original cipher proposal: %s", cipher_prop); + if ((cipher_prop = match_filter_denylist(cipher_prop, "aes*")) == NULL) + fatal("match_filter_denylist failed"); + debug2_f("compat cipher proposal: %s", cipher_prop); if (*cipher_prop == '\0') fatal("No supported ciphers found"); return cipher_prop; } char * -compat_pkalg_proposal(char *pkalg_prop) +compat_pkalg_proposal(struct ssh *ssh, char *pkalg_prop) { - if (!(datafellows & SSH_BUG_RSASIGMD5)) + if (!(ssh->compat & SSH_BUG_RSASIGMD5)) return pkalg_prop; - debug2("%s: original public key proposal: %s", __func__, pkalg_prop); - if ((pkalg_prop = match_filter_blacklist(pkalg_prop, "ssh-rsa")) == NULL) - fatal("match_filter_blacklist failed"); - debug2("%s: compat public key proposal: %s", __func__, pkalg_prop); + debug2_f("original public key proposal: %s", pkalg_prop); + if ((pkalg_prop = match_filter_denylist(pkalg_prop, "ssh-rsa")) == NULL) + fatal("match_filter_denylist failed"); + debug2_f("compat public key proposal: %s", pkalg_prop); if (*pkalg_prop == '\0') fatal("No supported PK algorithms found"); return pkalg_prop; } char * -compat_kex_proposal(char *p) +compat_kex_proposal(struct ssh *ssh, char *p) { - if ((datafellows & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0) + if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0) return p; - debug2("%s: original KEX proposal: %s", __func__, p); - if ((datafellows & SSH_BUG_CURVE25519PAD) != 0) - if ((p = match_filter_blacklist(p, + debug2_f("original KEX proposal: %s", p); + if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0) + if ((p = match_filter_denylist(p, "curve25519-sha256@libssh.org")) == NULL) - fatal("match_filter_blacklist failed"); - if ((datafellows & SSH_OLD_DHGEX) != 0) { - if ((p = match_filter_blacklist(p, + fatal("match_filter_denylist failed"); + if ((ssh->compat & SSH_OLD_DHGEX) != 0) { + if ((p = match_filter_denylist(p, "diffie-hellman-group-exchange-sha256," "diffie-hellman-group-exchange-sha1")) == NULL) - fatal("match_filter_blacklist failed"); + fatal("match_filter_denylist failed"); } - debug2("%s: compat KEX proposal: %s", __func__, p); + debug2_f("compat KEX proposal: %s", p); if (*p == '\0') fatal("No supported key exchange algorithms found"); return p; diff --git a/compat.h b/compat.h index d611d33e7..c197fafc5 100644 --- a/compat.h +++ b/compat.h @@ -1,4 +1,4 @@ -/* $OpenBSD: compat.h,v 1.54 2018/08/13 02:41:05 djm Exp $ */ +/* $OpenBSD: compat.h,v 1.56 2021/01/27 09:26:54 djm Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. @@ -27,11 +27,6 @@ #ifndef COMPAT_H #define COMPAT_H -#define SSH_PROTO_UNKNOWN 0x00 -#define SSH_PROTO_1 0x01 -#define SSH_PROTO_1_PREFERRED 0x02 -#define SSH_PROTO_2 0x04 - #define SSH_BUG_UTF8TTYMODE 0x00000001 #define SSH_BUG_SIGTYPE 0x00000002 /* #define unused 0x00000004 */ @@ -63,11 +58,10 @@ #define SSH_BUG_HOSTKEYS 0x20000000 #define SSH_BUG_DHGEX_LARGE 0x40000000 -u_int compat_datafellows(const char *); -int proto_spec(const char *); -char *compat_cipher_proposal(char *); -char *compat_pkalg_proposal(char *); -char *compat_kex_proposal(char *); +struct ssh; -extern int datafellows; +void compat_banner(struct ssh *, const char *); +char *compat_cipher_proposal(struct ssh *, char *); +char *compat_pkalg_proposal(struct ssh *, char *); +char *compat_kex_proposal(struct ssh *, char *); #endif diff --git a/config.guess b/config.guess index c4bd827a7..11fda528b 100755 --- a/config.guess +++ b/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2016 Free Software Foundation, Inc. +# Copyright 1992-2020 Free Software Foundation, Inc. -timestamp='2016-05-15' +timestamp='2020-04-26' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2016-05-15' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -27,7 +27,7 @@ timestamp='2016-05-15' # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . @@ -39,7 +39,7 @@ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -50,7 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2016 Free Software Foundation, Inc. +Copyright 1992-2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -84,8 +84,6 @@ if test $# != 0; then exit 1 fi -trap 'exit 1' 1 2 15 - # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a @@ -96,34 +94,40 @@ trap 'exit 1' 1 2 15 # Portable tmp directory creation inspired by the Autoconf team. -set_cc_for_build=' -trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; -trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; -: ${TMPDIR=/tmp} ; - { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || - { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || - { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || - { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; -dummy=$tmp/dummy ; -tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; -case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; - for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac ; set_cc_for_build= ;' +tmp= +# shellcheck disable=SC2172 +trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 + +set_cc_for_build() { + # prevent multiple calls if $tmp is already set + test "$tmp" && return 0 + : "${TMPDIR=/tmp}" + # shellcheck disable=SC2039 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } + dummy=$tmp/dummy + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in + ,,) echo "int x;" > "$dummy.c" + for driver in cc gcc c89 c99 ; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD="$driver" + break + fi + done + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; + esac +} # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then +if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi @@ -132,14 +136,14 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown -case "${UNAME_SYSTEM}" in +case "$UNAME_SYSTEM" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu - eval $set_cc_for_build - cat <<-EOF > $dummy.c + set_cc_for_build + cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc @@ -149,13 +153,20 @@ Linux|GNU|GNU/*) LIBC=gnu #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi ;; esac # Note: order is significant - the case branches are not exclusive. -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, @@ -169,30 +180,30 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ - /sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ echo unknown)` - case "${UNAME_MACHINE_ARCH}" in + case "$UNAME_MACHINE_ARCH" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) - arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` - endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` - machine=${arch}${endian}-unknown + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. - case "${UNAME_MACHINE_ARCH}" in + case "$UNAME_MACHINE_ARCH" in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build + set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then @@ -208,10 +219,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ;; esac # Determine ABI tags. - case "${UNAME_MACHINE_ARCH}" in + case "$UNAME_MACHINE_ARCH" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' - abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; esac # The OS release @@ -219,45 +230,60 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in + case "$UNAME_VERSION" in Debian*) release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}${abi}" + echo "$machine-${os}${release}${abi-}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" + exit ;; + *:OS108:*:*) + echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:Sortix:*:*) - echo ${UNAME_MACHINE}-unknown-sortix + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Twizzler:*:*) + echo "$UNAME_MACHINE"-unknown-twizzler + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in @@ -310,28 +336,19 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos + echo "$UNAME_MACHINE"-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos + echo "$UNAME_MACHINE"-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition @@ -343,7 +360,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} + echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos @@ -370,19 +387,19 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} + echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build + set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. @@ -395,13 +412,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in SUN_ARCH=x86_64 fi fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in @@ -410,25 +427,25 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" exit ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) - echo sparc-sun-sunos${UNAME_RELEASE} + echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} + echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not @@ -439,44 +456,44 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} + echo m68k-milan-mint"$UNAME_RELEASE" exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} + echo m68k-hades-mint"$UNAME_RELEASE" exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} + echo m68k-unknown-mint"$UNAME_RELEASE" exit ;; m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} + echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} + echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} + echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} + echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} + echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { @@ -485,23 +502,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} + echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax @@ -527,17 +544,17 @@ EOF AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] then - echo m88k-dg-dgux${UNAME_RELEASE} + echo m88k-dg-dgux"$UNAME_RELEASE" else - echo m88k-dg-dguxbcs${UNAME_RELEASE} + echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else - echo i586-dg-dgux${UNAME_RELEASE} + echo i586-dg-dgux"$UNAME_RELEASE" fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) @@ -554,7 +571,7 @@ EOF echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id @@ -566,14 +583,14 @@ EOF if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" #include main() @@ -584,7 +601,7 @@ EOF exit(0); } EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then echo "$SYSTEM_NAME" else @@ -598,7 +615,7 @@ EOF exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc @@ -607,18 +624,18 @@ EOF IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx @@ -633,28 +650,28 @@ EOF echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in + case "$sc_cpu_version" in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in + case "$sc_kernel_bits" in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + if [ "$HP_ARCH" = "" ]; then + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include @@ -687,13 +704,13 @@ EOF exit (0); } EOF - (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = hppa2.0w ] + if [ "$HP_ARCH" = hppa2.0w ] then - eval $set_cc_for_build + set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -712,15 +729,15 @@ EOF HP_ARCH=hppa64 fi fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" #include int main () @@ -745,11 +762,11 @@ EOF exit (0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) @@ -758,7 +775,7 @@ EOF *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) @@ -766,9 +783,9 @@ EOF exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk + echo "$UNAME_MACHINE"-unknown-osf1mk else - echo ${UNAME_MACHINE}-unknown-osf1 + echo "$UNAME_MACHINE"-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) @@ -793,130 +810,123 @@ EOF echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} + echo sparc-unknown-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" + exit ;; + arm:FreeBSD:*:*) + UNAME_PROCESSOR=`uname -p` + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi + else + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf + fi exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in + case "$UNAME_PROCESSOR" in amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin + echo "$UNAME_MACHINE"-pc-cygwin exit ;; *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 + echo "$UNAME_MACHINE"-pc-mingw64 exit ;; *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 + echo "$UNAME_MACHINE"-pc-mingw32 exit ;; *:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 + echo "$UNAME_MACHINE"-pc-msys exit ;; i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 + echo "$UNAME_MACHINE"-pc-pw32 exit ;; *:Interix*:*) - case ${UNAME_MACHINE} in + case "$UNAME_MACHINE" in x86) - echo i586-pc-interix${UNAME_RELEASE} + echo i586-pc-interix"$UNAME_RELEASE" exit ;; authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} + echo x86_64-unknown-interix"$UNAME_RELEASE" exit ;; IA64) - echo ia64-unknown-interix${UNAME_RELEASE} + echo ia64-unknown-interix"$UNAME_RELEASE" exit ;; esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin + echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) - echo x86_64-unknown-cygwin - exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin + echo x86_64-pc-cygwin exit ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; *:GNU:*:*) # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" exit ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix + *:Minix:*:*) + echo "$UNAME_MACHINE"-unknown-minix exit ;; aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; @@ -927,134 +937,168 @@ EOF esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arc:Linux:*:* | arceb:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) - eval $set_cc_for_build + set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi else - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf fi fi exit ;; avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; e2k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; k1om:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + set_cc_for_build + IS_GLIBC=0 + test x"${LIBC}" = xgnu && IS_GLIBC=1 + sed 's/^ //' << EOF > "$dummy.c" #undef CPU - #undef ${UNAME_MACHINE} - #undef ${UNAME_MACHINE}el + #undef mips + #undef mipsel + #undef mips64 + #undef mips64el + #if ${IS_GLIBC} && defined(_ABI64) + LIBCABI=gnuabi64 + #else + #if ${IS_GLIBC} && defined(_ABIN32) + LIBCABI=gnuabin32 + #else + LIBCABI=${LIBC} + #endif + #endif + + #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa64r6 + #else + #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa32r6 + #else + #if defined(__mips64) + CPU=mips64 + #else + CPU=mips + #endif + #endif + #endif + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=${UNAME_MACHINE}el + MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=${UNAME_MACHINE} + MIPS_ENDIAN= #else - CPU= + MIPS_ENDIAN= #endif #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`" + test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; openrisc*:Linux:*:*) - echo or1k-unknown-linux-${LIBC} + echo or1k-unknown-linux-"$LIBC" exit ;; or32:Linux:*:* | or1k*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; padre:Linux:*:*) - echo sparc-unknown-linux-${LIBC} + echo sparc-unknown-linux-"$LIBC" exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-${LIBC} + echo hppa64-unknown-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; - PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; - *) echo hppa-unknown-linux-${LIBC} ;; + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; esac exit ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-${LIBC} + echo powerpc64-unknown-linux-"$LIBC" exit ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-${LIBC} + echo powerpc-unknown-linux-"$LIBC" exit ;; ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-${LIBC} + echo powerpc64le-unknown-linux-"$LIBC" exit ;; ppcle:Linux:*:*) - echo powerpcle-unknown-linux-${LIBC} + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. @@ -1068,34 +1112,34 @@ EOF # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx + echo "$UNAME_MACHINE"-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop + echo "$UNAME_MACHINE"-unknown-stop exit ;; i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos + echo "$UNAME_MACHINE"-unknown-atheos exit ;; i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable + echo "$UNAME_MACHINE"-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} + echo i386-unknown-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp + echo "$UNAME_MACHINE"-pc-msdosdjgpp exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi exit ;; i*86:*:5:[678]*) @@ -1105,12 +1149,12 @@ EOF *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 @@ -1120,9 +1164,9 @@ EOF && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv32 + echo "$UNAME_MACHINE"-pc-sysv32 fi exit ;; pc:*:*:*) @@ -1142,9 +1186,9 @@ EOF exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) @@ -1164,9 +1208,9 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; @@ -1175,28 +1219,28 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} + echo m68k-unknown-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} + echo sparc-unknown-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} + echo rs6000-unknown-lynxos"$UNAME_RELEASE" exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} + echo powerpc-unknown-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} + echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 @@ -1207,7 +1251,7 @@ EOF *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 + echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi @@ -1227,23 +1271,23 @@ EOF exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos + echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} + echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv"$UNAME_RELEASE" else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv"$UNAME_RELEASE" fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. @@ -1262,60 +1306,68 @@ EOF echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} + echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} + echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} + echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} + echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} + echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} + echo sx8r-nec-superux"$UNAME_RELEASE" exit ;; SX-ACE:SUPER-UX:*:*) - echo sxace-nec-superux${UNAME_RELEASE} + echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} + echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) - UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build - if test "$UNAME_PROCESSOR" = unknown ; then - UNAME_PROCESSOR=powerpc + UNAME_PROCESSOR=`uname -p` + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + if command -v xcode-select > /dev/null 2> /dev/null && \ + ! xcode-select --print-path > /dev/null 2> /dev/null ; then + # Avoid executing cc if there is no toolchain installed as + # cc will be a stub that puts up a graphical alert + # prompting the user to install developer tools. + CC_FOR_BUILD=no_compiler_found + else + set_cc_for_build fi - if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then - if [ "$CC_FOR_BUILD" != no_compiler_found ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac - fi + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc fi elif test "$UNAME_PROCESSOR" = i386 ; then - # Avoid executing cc on OS X 10.9, as it ships with a stub - # that puts up a graphical alert prompting to install - # developer tools. Any system running Mac OS X 10.7 or - # later (Darwin 11 and later) is required to have a 64-bit - # processor. This is not true of the ARM version of Darwin - # that Apple uses in portable devices. - UNAME_PROCESSOR=x86_64 + # uname -m returns i386 or x86_64 + UNAME_PROCESSOR=$UNAME_MACHINE fi - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` @@ -1323,19 +1375,25 @@ EOF UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} + echo nse-tandem-nsk"$UNAME_RELEASE" exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux @@ -1344,18 +1402,19 @@ EOF echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. + # shellcheck disable=SC2154 if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi - echo ${UNAME_MACHINE}-unknown-plan9 + echo "$UNAME_MACHINE"-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 @@ -1376,14 +1435,14 @@ EOF echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} + echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in + case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; @@ -1392,32 +1451,190 @@ EOF echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" exit ;; i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos + echo "$UNAME_MACHINE"-pc-rdos exit ;; i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros + echo "$UNAME_MACHINE"-pc-aros exit ;; x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx + echo "$UNAME_MACHINE"-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; + *:Unleashed:*:*) + echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE" + exit ;; +esac + +# No uname command or uname output not recognized. +set_cc_for_build +cat > "$dummy.c" < +#include +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#include +#if defined(_SIZE_T_) || defined(SIGLOST) +#include +#endif +#endif +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); +#endif + +#if defined (vax) +#if !defined (ultrix) +#include +#if defined (BSD) +#if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +#else +#if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#endif +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#else +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname un; + uname (&un); + printf ("vax-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname *un; + uname (&un); + printf ("mips-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("mips-dec-ultrix\n"); exit (0); +#endif +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. +test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } + +echo "$0: unable to guess system type" >&2 + +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 <&2 </dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" EOF +fi exit 1 # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/config.sub b/config.sub index 9feb73bf0..973a2980a 100755 --- a/config.sub +++ b/config.sub @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2016 Free Software Foundation, Inc. +# Copyright 1992-2020 Free Software Foundation, Inc. -timestamp='2016-06-20' +timestamp='2020-05-04' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2016-06-20' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -33,7 +33,7 @@ timestamp='2016-06-20' # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -57,7 +57,7 @@ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -67,7 +67,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright 1992-2016 Free Software Foundation, Inc. +Copyright 1992-2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -89,12 +89,12 @@ while test $# -gt 0 ; do - ) # Use stdin as input. break ;; -* ) - echo "$me: invalid option $1$help" + echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) # First pass through any local machine types. - echo $1 + echo "$1" exit ;; * ) @@ -110,1242 +110,1164 @@ case $# in exit 1;; esac -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ - kopensolaris*-gnu* | \ - storm-chaos* | os2-emx* | rtmk-nova*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - android-linux) - os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac +# Split fields of configuration type +# shellcheck disable=SC2162 +IFS="-" read field1 field2 field3 field4 <&2 + exit 1 ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze*) - os= - basic_machine=$1 + *-*-*-*) + basic_machine=$field1-$field2 + os=$field3-$field4 ;; - -bluegene*) - os=-cnk + *-*-*) + # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two + # parts + maybe_os=$field2-$field3 + case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc \ + | linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \ + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ + | storm-chaos* | os2-emx* | rtmk-nova*) + basic_machine=$field1 + os=$maybe_os + ;; + android-linux) + basic_machine=$field1-unknown + os=linux-android + ;; + *) + basic_machine=$field1-$field2 + os=$field3 + ;; + esac ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 + *-*) + # A lone config we happen to match not fitting any pattern + case $field1-$field2 in + decstation-3100) + basic_machine=mips-dec + os= + ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* \ + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ + | ultra | tti* | harris | dolphin | highlevel | gould \ + | cbm | ns | masscomp | apple | axis | knuth | cray \ + | microblaze* | sim | cisco \ + | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + os= + ;; + *) + basic_machine=$field1 + os=$field2 + ;; + esac + ;; + esac ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco6) - os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco5v6*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*178) - os=-lynxos178 - ;; - -lynx*5) - os=-lynxos5 - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint + *) + # Convert single-component short-hands not valid as part of + # multi-component configurations. + case $field1 in + 386bsd) + basic_machine=i386-pc + os=bsd + ;; + a29khif) + basic_machine=a29k-amd + os=udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=scout + ;; + alliant) + basic_machine=fx80-alliant + os= + ;; + altos | altos3068) + basic_machine=m68k-altos + os= + ;; + am29k) + basic_machine=a29k-none + os=bsd + ;; + amdahl) + basic_machine=580-amdahl + os=sysv + ;; + amiga) + basic_machine=m68k-unknown + os= + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=bsd + ;; + aros) + basic_machine=i386-pc + os=aros + ;; + aux) + basic_machine=m68k-apple + os=aux + ;; + balance) + basic_machine=ns32k-sequent + os=dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=linux + ;; + cegcc) + basic_machine=arm-unknown + os=cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=bsd + ;; + convex-c2) + basic_machine=c2-convex + os=bsd + ;; + convex-c32) + basic_machine=c32-convex + os=bsd + ;; + convex-c34) + basic_machine=c34-convex + os=bsd + ;; + convex-c38) + basic_machine=c38-convex + os=bsd + ;; + cray) + basic_machine=j90-cray + os=unicos + ;; + crds | unos) + basic_machine=m68k-crds + os= + ;; + da30) + basic_machine=m68k-da30 + os= + ;; + decstation | pmax | pmin | dec3100 | decstatn) + basic_machine=mips-dec + os= + ;; + delta88) + basic_machine=m88k-motorola + os=sysv3 + ;; + dicos) + basic_machine=i686-pc + os=dicos + ;; + djgpp) + basic_machine=i586-pc + os=msdosdjgpp + ;; + ebmon29k) + basic_machine=a29k-amd + os=ebmon + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=ose + ;; + gmicro) + basic_machine=tron-gmicro + os=sysv + ;; + go32) + basic_machine=i386-pc + os=go32 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=hms + ;; + harris) + basic_machine=m88k-harris + os=sysv3 + ;; + hp300 | hp300hpux) + basic_machine=m68k-hp + os=hpux + ;; + hp300bsd) + basic_machine=m68k-hp + os=bsd + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=proelf + ;; + i386mach) + basic_machine=i386-mach + os=mach + ;; + isi68 | isi) + basic_machine=m68k-isi + os=sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=linux + ;; + magnum | m3230) + basic_machine=mips-mips + os=sysv + ;; + merlin) + basic_machine=ns32k-utek + os=sysv + ;; + mingw64) + basic_machine=x86_64-pc + os=mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=mingw32ce + ;; + monitor) + basic_machine=m68k-rom68k + os=coff + ;; + morphos) + basic_machine=powerpc-unknown + os=morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=moxiebox + ;; + msdos) + basic_machine=i386-pc + os=msdos + ;; + msys) + basic_machine=i686-pc + os=msys + ;; + mvs) + basic_machine=i370-ibm + os=mvs + ;; + nacl) + basic_machine=le32-unknown + os=nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=sysv4 + ;; + netbsd386) + basic_machine=i386-pc + os=netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=newsos + ;; + news1000) + basic_machine=m68030-sony + os=newsos + ;; + necv70) + basic_machine=v70-nec + os=sysv + ;; + nh3000) + basic_machine=m68k-harris + os=cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=cxux + ;; + nindy960) + basic_machine=i960-intel + os=nindy + ;; + mon960) + basic_machine=i960-intel + os=mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=nonstopux + ;; + os400) + basic_machine=powerpc-ibm + os=os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=ose + ;; + os68k) + basic_machine=m68k-none + os=os68k + ;; + paragon) + basic_machine=i860-intel + os=osf + ;; + parisc) + basic_machine=hppa-unknown + os=linux + ;; + pw32) + basic_machine=i586-unknown + os=pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=rdos + ;; + rdos32) + basic_machine=i386-pc + os=rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=coff + ;; + sa29200) + basic_machine=a29k-amd + os=udi + ;; + sei) + basic_machine=mips-sei + os=seiux + ;; + sequent) + basic_machine=i386-sequent + os= + ;; + sps7) + basic_machine=m68k-bull + os=sysv2 + ;; + st2000) + basic_machine=m68k-tandem + os= + ;; + stratus) + basic_machine=i860-stratus + os=sysv4 + ;; + sun2) + basic_machine=m68000-sun + os= + ;; + sun2os3) + basic_machine=m68000-sun + os=sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=sunos4 + ;; + sun3) + basic_machine=m68k-sun + os= + ;; + sun3os3) + basic_machine=m68k-sun + os=sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=sunos4 + ;; + sun4) + basic_machine=sparc-sun + os= + ;; + sun4os3) + basic_machine=sparc-sun + os=sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=solaris2 + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + os= + ;; + sv1) + basic_machine=sv1-cray + os=unicos + ;; + symmetry) + basic_machine=i386-sequent + os=dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=unicos + ;; + t90) + basic_machine=t90-cray + os=unicos + ;; + toad1) + basic_machine=pdp10-xkl + os=tops20 + ;; + tpf) + basic_machine=s390x-ibm + os=tpf + ;; + udi29k) + basic_machine=a29k-amd + os=udi + ;; + ultra3) + basic_machine=a29k-nyu + os=sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=none + ;; + vaxv) + basic_machine=vax-dec + os=sysv + ;; + vms) + basic_machine=vax-dec + os=vms + ;; + vsta) + basic_machine=i386-pc + os=vsta + ;; + vxworks960) + basic_machine=i960-wrs + os=vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=vxworks + ;; + xbox) + basic_machine=i686-pc + os=mingw32 + ;; + ymp) + basic_machine=ymp-cray + os=unicos + ;; + *) + basic_machine=$1 + os= + ;; + esac ;; esac -# Decode aliases for certain CPU-COMPANY combinations. +# Decode 1-component or ad-hoc basic machines case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | aarch64 | aarch64_be \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ - | am33_2.0 \ - | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ - | avr | avr32 \ - | ba \ - | be32 | be64 \ - | bfin \ - | c4x | c8051 | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | e2k | epiphany \ - | fido | fr30 | frv | ft32 \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | hexagon \ - | i370 | i860 | i960 | ia64 \ - | ip2k | iq2000 \ - | k1om \ - | le32 | le64 \ - | lm32 \ - | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64octeon | mips64octeonel \ - | mips64orion | mips64orionel \ - | mips64r5900 | mips64r5900el \ - | mips64vr | mips64vrel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mips64vr5900 | mips64vr5900el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa32r6 | mipsisa32r6el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64r2 | mipsisa64r2el \ - | mipsisa64r6 | mipsisa64r6el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ - | msp430 \ - | nds32 | nds32le | nds32be \ - | nios | nios2 | nios2eb | nios2el \ - | ns16k | ns32k \ - | open8 | or1k | or1knd | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle \ - | pyramid \ - | riscv32 | riscv64 \ - | rl78 | rx \ - | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu \ - | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ - | ubicom32 \ - | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | visium \ - | we32k \ - | x86 | xc16x | xstormy16 | xtensa \ - | z8k | z80) - basic_machine=$basic_machine-unknown + # Here we handle the default manufacturer of certain CPU types. It is in + # some cases the only manufacturer, in others, it is the most popular. + w89k) + cpu=hppa1.1 + vendor=winbond ;; - c54x) - basic_machine=tic54x-unknown + op50n) + cpu=hppa1.1 + vendor=oki ;; - c55x) - basic_machine=tic55x-unknown + op60c) + cpu=hppa1.1 + vendor=oki ;; - c6x) - basic_machine=tic6x-unknown + ibm*) + cpu=i370 + vendor=ibm + ;; + orion105) + cpu=clipper + vendor=highlevel + ;; + mac | mpw | mac-mpw) + cpu=m68k + vendor=apple + ;; + pmac | pmac-mpw) + cpu=powerpc + vendor=apple + ;; + + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + cpu=m68000 + vendor=att + ;; + 3b*) + cpu=we32k + vendor=att + ;; + bluegene*) + cpu=powerpc + vendor=ibm + os=cnk + ;; + decsystem10* | dec10*) + cpu=pdp10 + vendor=dec + os=tops10 + ;; + decsystem20* | dec20*) + cpu=pdp10 + vendor=dec + os=tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + cpu=m68k + vendor=motorola + ;; + dpx2*) + cpu=m68k + vendor=bull + os=sysv3 + ;; + encore | umax | mmax) + cpu=ns32k + vendor=encore + ;; + elxsi) + cpu=elxsi + vendor=elxsi + os=${os:-bsd} + ;; + fx2800) + cpu=i860 + vendor=alliant + ;; + genix) + cpu=ns32k + vendor=ns + ;; + h3050r* | hiux*) + cpu=hppa1.1 + vendor=hitachi + os=hiuxwe2 + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + cpu=m68000 + vendor=hp + ;; + hp9k3[2-9][0-9]) + cpu=m68k + vendor=hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + i*86v32) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=sysv32 + ;; + i*86v4*) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=sysv4 + ;; + i*86v) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=sysv + ;; + i*86sol2) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + os=solaris2 + ;; + j90 | j90-cray) + cpu=j90 + vendor=cray + os=${os:-unicos} + ;; + iris | iris4d) + cpu=mips + vendor=sgi + case $os in + irix*) + ;; + *) + os=irix4 + ;; + esac + ;; + miniframe) + cpu=m68000 + vendor=convergent + ;; + *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) + cpu=m68k + vendor=atari + os=mint + ;; + news-3600 | risc-news) + cpu=mips + vendor=sony + os=newsos + ;; + next | m*-next) + cpu=m68k + vendor=next + case $os in + openstep*) + ;; + nextstep*) + ;; + ns2*) + os=nextstep2 + ;; + *) + os=nextstep3 + ;; + esac + ;; + np1) + cpu=np1 + vendor=gould + ;; + op50n-* | op60c-*) + cpu=hppa1.1 + vendor=oki + os=proelf + ;; + pa-hitachi) + cpu=hppa1.1 + vendor=hitachi + os=hiuxwe2 + ;; + pbd) + cpu=sparc + vendor=tti + ;; + pbb) + cpu=m68k + vendor=tti + ;; + pc532) + cpu=ns32k + vendor=pc532 + ;; + pn) + cpu=pn + vendor=gould + ;; + power) + cpu=power + vendor=ibm + ;; + ps2) + cpu=i386 + vendor=ibm + ;; + rm[46]00) + cpu=mips + vendor=siemens + ;; + rtpc | rtpc-*) + cpu=romp + vendor=ibm + ;; + sde) + cpu=mipsisa32 + vendor=sde + os=${os:-elf} + ;; + simso-wrs) + cpu=sparclite + vendor=wrs + os=vxworks + ;; + tower | tower-32) + cpu=m68k + vendor=ncr + ;; + vpp*|vx|vx-*) + cpu=f301 + vendor=fujitsu + ;; + w65) + cpu=w65 + vendor=wdc + ;; + w89k-*) + cpu=hppa1.1 + vendor=winbond + os=proelf + ;; + none) + cpu=none + vendor=none ;; leon|leon[3-9]) - basic_machine=sparc-$basic_machine + cpu=sparc + vendor=$basic_machine ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - ms1) - basic_machine=mt-unknown + leon-*|leon[3-9]-*) + cpu=sparc + vendor=`echo "$basic_machine" | sed 's/-.*//'` ;; - strongarm | thumb | xscale) - basic_machine=arm-unknown + *-*) + # shellcheck disable=SC2162 + IFS="-" read cpu vendor <&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | aarch64-* | aarch64_be-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* | avr32-* \ - | ba-* \ - | be32-* | be64-* \ - | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | c8051-* | clipper-* | craynv-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ - | e2k-* | elxsi-* \ - | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* | iq2000-* \ - | k1om-* \ - | le32-* | le64-* \ - | lm32-* \ - | m32c-* | m32r-* | m32rle-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ - | microblaze-* | microblazeel-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64octeon-* | mips64octeonel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64r5900-* | mips64r5900el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mips64vr5900-* | mips64vr5900el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa32r6-* | mipsisa32r6el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64r2-* | mipsisa64r2el-* \ - | mipsisa64r6-* | mipsisa64r6el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ - | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* | nios2eb-* | nios2el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | open8-* \ - | or1k*-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ - | pyramid-* \ - | riscv32-* | riscv64-* \ - | rl78-* | romp-* | rs6000-* | rx-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ - | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ - | tahoe-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ - | tile*-* \ - | tron-* \ - | ubicom32-* \ - | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ - | vax-* \ - | visium-* \ - | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* \ - | xstormy16-* | xtensa*-* \ - | ymp-* \ - | z8k-* | z80-*) - ;; - # Recognize the basic CPU types without company name, with glob match. - xtensa*) - basic_machine=$basic_machine-unknown - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - abacus) - basic_machine=abacus-unknown - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amd64) - basic_machine=x86_64-pc - ;; - amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aros) - basic_machine=i386-pc - os=-aros - ;; - asmjs) - basic_machine=asmjs-unknown - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - blackfin) - basic_machine=bfin-unknown - os=-linux - ;; - blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - bluegene*) - basic_machine=powerpc-ibm - os=-cnk - ;; - c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; - cegcc) - basic_machine=arm-unknown - os=-cegcc - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | j90) - basic_machine=j90-cray - os=-unicos - ;; - craynv) - basic_machine=craynv-cray - os=-unicosmp - ;; - cr16 | cr16-*) - basic_machine=cr16-unknown - os=-elf - ;; - crds | unos) - basic_machine=m68k-crds - ;; - crisv32 | crisv32-* | etraxfs*) - basic_machine=crisv32-axis - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - crx) - basic_machine=crx-unknown - os=-elf - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dicos) - basic_machine=i686-pc - os=-dicos - ;; - djgpp) - basic_machine=i586-pc - os=-msdosdjgpp - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - e500v[12]) - basic_machine=powerpc-unknown - os=$os"spe" - ;; - e500v[12]-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - os=$os"spe" - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - leon-*|leon[3-9]-*) - basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` - ;; - m68knommu) - basic_machine=m68k-unknown - os=-linux - ;; - m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - microblaze*) - basic_machine=microblaze-xilinx - ;; - mingw64) - basic_machine=x86_64-pc - os=-mingw64 - ;; - mingw32) - basic_machine=i686-pc - os=-mingw32 - ;; - mingw32ce) - basic_machine=arm-unknown - os=-mingw32ce - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; - moxiebox) - basic_machine=moxie-unknown - os=-moxiebox - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` - ;; - msys) - basic_machine=i686-pc - os=-msys - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - nacl) - basic_machine=le32-unknown - os=-nacl - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - neo-tandem) - basic_machine=neo-tandem - ;; - nse-tandem) - basic_machine=nse-tandem - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - openrisc | openrisc-*) - basic_machine=or32-unknown - ;; - os400) - basic_machine=powerpc-ibm - os=-os400 - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - parisc) - basic_machine=hppa-unknown - os=-linux - ;; - parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` - os=-linux - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 + cpu=$basic_machine + vendor=pc ;; + # These rules are duplicated from below for sake of the special case above; + # i.e. things that normalized to x86 arches should also default to "pc" pc98) - basic_machine=i386-pc + cpu=i386 + vendor=pc ;; - pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + x64 | amd64) + cpu=x86_64 + vendor=pc ;; - pentium | p5 | k5 | k6 | nexgen | viac3) - basic_machine=i586-pc + # Recognize the basic CPU types without company name. + *) + cpu=$basic_machine + vendor=unknown ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) - basic_machine=i686-pc +esac + +unset -v basic_machine + +# Decode basic machines in the full and proper CPU-Company form. +case $cpu-$vendor in + # Here we handle the default manufacturer of certain CPU types in canonical form. It is in + # some cases the only manufacturer, in others, it is the most popular. + craynv-unknown) + vendor=cray + os=${os:-unicosmp} ;; - pentiumii | pentium2 | pentiumiii | pentium3) - basic_machine=i686-pc + c90-unknown | c90-cray) + vendor=cray + os=${os:-unicos} ;; - pentium4) - basic_machine=i786-pc + fx80-unknown) + vendor=alliant ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + romp-unknown) + vendor=ibm ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + mmix-unknown) + vendor=knuth ;; - pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + microblaze-unknown | microblazeel-unknown) + vendor=xilinx ;; - pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + rs6000-unknown) + vendor=ibm ;; - pn) - basic_machine=pn-gould + vax-unknown) + vendor=dec ;; - power) basic_machine=power-ibm + pdp11-unknown) + vendor=dec ;; - ppc | ppcbe) basic_machine=powerpc-unknown + we32k-unknown) + vendor=att ;; - ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + cydra-unknown) + vendor=cydrome ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown + i370-ibm*) + vendor=ibm ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + orion-unknown) + vendor=highlevel ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rdos | rdos64) - basic_machine=x86_64-pc - os=-rdos - ;; - rdos32) - basic_machine=i386-pc - os=-rdos - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - s390 | s390-*) - basic_machine=s390-ibm - ;; - s390x | s390x-*) - basic_machine=s390x-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; - sde) - basic_machine=mipsisa32-sde - os=-elf - ;; - sei) - basic_machine=mips-sei - os=-seiux - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sh5el) - basic_machine=sh5le-unknown - ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=alphaev5-cray - os=-unicos - ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tile*) - basic_machine=$basic_machine-unknown - os=-linux-gnu - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - tpf) - basic_machine=s390x-ibm - os=-tpf - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - xbox) - basic_machine=i686-pc - os=-mingw32 - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` - ;; - ymp) - basic_machine=ymp-cray - os=-unicos - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none + xps-unknown | xps100-unknown) + cpu=xps100 + vendor=honeywell ;; -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond + # Here we normalize CPU types with a missing or matching vendor + dpx20-unknown | dpx20-bull) + cpu=rs6000 + vendor=bull + os=${os:-bosx} ;; - op50n) - basic_machine=hppa1.1-oki + + # Here we normalize CPU types irrespective of the vendor + amd64-*) + cpu=x86_64 ;; - op60c) - basic_machine=hppa1.1-oki + blackfin-*) + cpu=bfin + os=linux ;; - romp) - basic_machine=romp-ibm + c54x-*) + cpu=tic54x ;; - mmix) - basic_machine=mmix-knuth + c55x-*) + cpu=tic55x ;; - rs6000) - basic_machine=rs6000-ibm + c6x-*) + cpu=tic6x ;; - vax) - basic_machine=vax-dec + e500v[12]-*) + cpu=powerpc + os=$os"spe" ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown + mips3*-*) + cpu=mips64 ;; - pdp11) - basic_machine=pdp11-dec + ms1-*) + cpu=mt ;; - we32k) - basic_machine=we32k-att + m68knommu-*) + cpu=m68k + os=linux ;; - sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) - basic_machine=sh-unknown + m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*) + cpu=s12z ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun + openrisc-*) + cpu=or32 ;; - cydra) - basic_machine=cydra-cydrome + parisc-*) + cpu=hppa + os=linux ;; - orion) - basic_machine=orion-highlevel + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + cpu=i586 ;; - orion105) - basic_machine=clipper-highlevel + pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*) + cpu=i686 ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + cpu=i686 ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple + pentium4-*) + cpu=i786 ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. + pc98-*) + cpu=i386 ;; + ppc-* | ppcbe-*) + cpu=powerpc + ;; + ppcle-* | powerpclittle-*) + cpu=powerpcle + ;; + ppc64-*) + cpu=powerpc64 + ;; + ppc64le-* | powerpc64little-*) + cpu=powerpc64le + ;; + sb1-*) + cpu=mipsisa64sb1 + ;; + sb1el-*) + cpu=mipsisa64sb1el + ;; + sh5e[lb]-*) + cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'` + ;; + spur-*) + cpu=spur + ;; + strongarm-* | thumb-*) + cpu=arm + ;; + tx39-*) + cpu=mipstx39 + ;; + tx39el-*) + cpu=mipstx39el + ;; + x64-*) + cpu=x86_64 + ;; + xscale-* | xscalee[bl]-*) + cpu=`echo "$cpu" | sed 's/^xscale/arm/'` + ;; + + # Recognize the canonical CPU Types that limit and/or modify the + # company names they are paired with. + cr16-*) + os=${os:-elf} + ;; + crisv32-* | etraxfs*-*) + cpu=crisv32 + vendor=axis + ;; + cris-* | etrax*-*) + cpu=cris + vendor=axis + ;; + crx-*) + os=${os:-elf} + ;; + neo-tandem) + cpu=neo + vendor=tandem + ;; + nse-tandem) + cpu=nse + vendor=tandem + ;; + nsr-tandem) + cpu=nsr + vendor=tandem + ;; + nsv-tandem) + cpu=nsv + vendor=tandem + ;; + nsx-tandem) + cpu=nsx + vendor=tandem + ;; + s390-*) + cpu=s390 + vendor=ibm + ;; + s390x-*) + cpu=s390x + vendor=ibm + ;; + tile*-*) + os=${os:-linux-gnu} + ;; + *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 + # Recognize the canonical CPU types that are allowed with any + # company name. + case $cpu in + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | abacus \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ + | alphapca5[67] | alpha64pca5[67] \ + | am33_2.0 \ + | amdgcn \ + | arc | arceb \ + | arm | arm[lb]e | arme[lb] | armv* \ + | avr | avr32 \ + | asmjs \ + | ba \ + | be32 | be64 \ + | bfin | bpf | bs2000 \ + | c[123]* | c30 | [cjt]90 | c4x \ + | c8051 | clipper | craynv | csky | cydra \ + | d10v | d30v | dlx | dsp16xx \ + | e2k | elxsi | epiphany \ + | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ + | h8300 | h8500 \ + | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i*86 | i860 | i960 | ia16 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle \ + | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \ + | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \ + | m88110 | m88k | maxq | mb | mcore | mep | metag \ + | microblaze | microblazeel \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64eb | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mmix \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nfp \ + | nios | nios2 | nios2eb | nios2el \ + | none | np1 | ns16k | ns32k | nvptx \ + | open8 \ + | or1k* \ + | or32 \ + | orion \ + | picochip \ + | pdp10 | pdp11 | pj | pjl | pn | power \ + | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \ + | pru \ + | pyramid \ + | riscv | riscv32 | riscv64 \ + | rl78 | romp | rs6000 | rx \ + | score \ + | sh | shl \ + | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \ + | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \ + | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ + | spu \ + | tahoe \ + | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ + | tron \ + | ubicom32 \ + | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ + | vax \ + | visium \ + | w65 \ + | wasm32 | wasm64 \ + | we32k \ + | x86 | x86_64 | xc16x | xgate | xps100 \ + | xstormy16 | xtensa* \ + | ymp \ + | z8k | z80) + ;; + + *) + echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2 + exit 1 + ;; + esac ;; esac # Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` +case $vendor in + digital*) + vendor=dec ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + commodore*) + vendor=cbm ;; *) ;; @@ -1353,200 +1275,244 @@ esac # Decode manufacturer-specific aliases for certain operating systems. -if [ x"$os" != x"" ] +if [ x$os != x ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -auroraux) - os=-auroraux + # First match some system type aliases that might get confused + # with valid system types. + # solaris* is a basic system type, with this one exception. + auroraux) + os=auroraux ;; - -solaris1 | -solaris1.*) + bluegene*) + os=cnk + ;; + solaris1 | solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; - -solaris) - os=-solaris2 + solaris) + os=solaris2 ;; - -svr4*) - os=-sysv4 + unixware*) + os=sysv4.2uw ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) + gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; - # First accept the basic system types. + # es1800 is here to avoid being matched by es* (a different OS) + es1800*) + os=ose + ;; + # Some version numbers need modification + chorusos*) + os=chorusos + ;; + isc) + os=isc2.2 + ;; + sco6) + os=sco5v6 + ;; + sco5) + os=sco3.2v5 + ;; + sco4) + os=sco3.2v4 + ;; + sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + ;; + sco3.2v[4-9]* | sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + ;; + scout) + # Don't match below + ;; + sco*) + os=sco3.2v2 + ;; + psos*) + os=psos + ;; + # Now accept the basic system types. # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* | -plan9* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* | -cloudabi* | -sortix* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ - | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ - | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ - | -onefs* | -tirtos* | -phoenix*) + # Each alternative MUST end in a * to match a version number. + # sysv* is not here because it comes later, after sysvr4. + gnu* | bsd* | mach* | minix* | genix* | ultrix* | irix* \ + | *vms* | esix* | aix* | cnk* | sunos | sunos[34]*\ + | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \ + | sym* | kopensolaris* | plan9* \ + | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \ + | aos* | aros* | cloudabi* | sortix* | twizzler* \ + | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ + | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ + | knetbsd* | mirbsd* | netbsd* \ + | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \ + | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \ + | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ + | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ + | udi* | eabi* | lites* | ieee* | go32* | aux* | hcos* \ + | chorusrdb* | cegcc* | glidix* \ + | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ + | midipix* | mingw32* | mingw64* | linux-gnu* | linux-android* \ + | linux-newlib* | linux-musl* | linux-uclibc* \ + | uxpv* | beos* | mpeix* | udk* | moxiebox* \ + | interix* | uwin* | mks* | rhapsody* | darwin* \ + | openstep* | oskit* | conix* | pw32* | nonstopux* \ + | storm-chaos* | tops10* | tenex* | tops20* | its* \ + | os2* | vos* | palmos* | uclinux* | nucleus* \ + | morphos* | superux* | rtmk* | windiss* \ + | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \ + | skyos* | haiku* | rdos* | toppers* | drops* | es* \ + | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ + | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ + | nsk* | powerunix* | genode*) # Remember, each alternative MUST END IN *, to match a version number. ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) + qnx*) + case $cpu in + x86 | i*86) ;; *) - os=-nto$os + os=nto-$os ;; esac ;; - -nto-qnx*) + hiux*) + os=hiuxwe2 ;; - -nto*) + nto-qnx*) + ;; + nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + sim | xray | os68k* | v88r* \ + | windows* | osx | abug | netware* | os9* \ + | macos* | mpw* | magic* | mmixware* | mon960* | lnews*) ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` + linux-dietlibc) + os=linux-dietlibc ;; - -linux-dietlibc) - os=-linux-dietlibc - ;; - -linux*) + linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` + lynx*178) + os=lynxos178 ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` + lynx*5) + os=lynxos5 ;; - -opened*) - os=-openedition + lynx*) + os=lynxos ;; - -os400*) - os=-os400 + mac*) + os=`echo "$os" | sed -e 's|mac|macos|'` ;; - -wince*) - os=-wince + opened*) + os=openedition ;; - -osfrose*) - os=-osfrose + os400*) + os=os400 ;; - -osf*) - os=-osf + sunos5*) + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; - -utek*) - os=-bsd + sunos6*) + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; - -dynix*) - os=-bsd + wince*) + os=wince ;; - -acis*) - os=-aos + utek*) + os=bsd ;; - -atheos*) - os=-atheos + dynix*) + os=bsd ;; - -syllable*) - os=-syllable + acis*) + os=aos ;; - -386bsd) - os=-bsd + atheos*) + os=atheos ;; - -ctix* | -uts*) - os=-sysv + syllable*) + os=syllable ;; - -nova*) - os=-rtmk-nova + 386bsd) + os=bsd ;; - -ns2 ) - os=-nextstep2 + ctix* | uts*) + os=sysv ;; - -nsk*) - os=-nsk + nova*) + os=rtmk-nova + ;; + ns2) + os=nextstep2 ;; # Preserve the version number of sinix5. - -sinix5.*) + sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; - -sinix*) - os=-sysv4 + sinix*) + os=sysv4 ;; - -tpf*) - os=-tpf + tpf*) + os=tpf ;; - -triton*) - os=-sysv3 + triton*) + os=sysv3 ;; - -oss*) - os=-sysv3 + oss*) + os=sysv3 ;; - -svr4) - os=-sysv4 + svr4*) + os=sysv4 ;; - -svr3) - os=-sysv3 + svr3) + os=sysv3 ;; - -sysvr4) - os=-sysv4 + sysvr4) + os=sysv4 ;; - # This must come after -sysvr4. - -sysv*) + # This must come after sysvr4. + sysv*) ;; - -ose*) - os=-ose + ose*) + os=ose ;; - -es1800*) - os=-ose + *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) + os=mint ;; - -xenix) - os=-xenix + zvmoe) + os=zvmoe ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint + dicos*) + os=dicos ;; - -aros*) - os=-aros + pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $cpu in + arm*) + os=eabi + ;; + *) + os=elf + ;; + esac ;; - -zvmoe) - os=-zvmoe + nacl*) ;; - -dicos*) - os=-dicos + ios) ;; - -nacl*) + none) ;; - -ios) - ;; - -none) + *-eabi) ;; *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; esac @@ -1562,261 +1528,265 @@ else # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. -case $basic_machine in +case $cpu-$vendor in score-*) - os=-elf + os=elf ;; spu-*) - os=-elf + os=elf ;; *-acorn) - os=-riscix1.2 + os=riscix1.2 ;; arm*-rebel) - os=-linux + os=linux ;; arm*-semi) - os=-aout + os=aout ;; c4x-* | tic4x-*) - os=-coff + os=coff ;; c8051-*) - os=-elf + os=elf + ;; + clipper-intergraph) + os=clix ;; hexagon-*) - os=-elf + os=elf ;; tic54x-*) - os=-coff + os=coff ;; tic55x-*) - os=-coff + os=coff ;; tic6x-*) - os=-coff + os=coff ;; # This must come before the *-dec entry. pdp10-*) - os=-tops20 + os=tops20 ;; pdp11-*) - os=-none + os=none ;; *-dec | vax-*) - os=-ultrix4.2 + os=ultrix4.2 ;; m68*-apollo) - os=-domain + os=domain ;; i386-sun) - os=-sunos4.0.2 + os=sunos4.0.2 ;; m68000-sun) - os=-sunos3 + os=sunos3 ;; m68*-cisco) - os=-aout + os=aout ;; mep-*) - os=-elf + os=elf ;; mips*-cisco) - os=-elf + os=elf ;; mips*-*) - os=-elf + os=elf ;; or32-*) - os=-coff + os=coff ;; *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 + os=sysv3 ;; sparc-* | *-sun) - os=-sunos4.1.1 + os=sunos4.1.1 + ;; + pru-*) + os=elf ;; *-be) - os=-beos - ;; - *-haiku) - os=-haiku + os=beos ;; *-ibm) - os=-aix + os=aix ;; *-knuth) - os=-mmixware + os=mmixware ;; *-wec) - os=-proelf + os=proelf ;; *-winbond) - os=-proelf + os=proelf ;; *-oki) - os=-proelf + os=proelf ;; *-hp) - os=-hpux + os=hpux ;; *-hitachi) - os=-hiux + os=hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv + os=sysv ;; *-cbm) - os=-amigaos + os=amigaos ;; *-dg) - os=-dgux + os=dgux ;; *-dolphin) - os=-sysv3 + os=sysv3 ;; m68k-ccur) - os=-rtu + os=rtu ;; m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs + os=luna ;; *-next) - os=-nextstep3 + os=nextstep + ;; + *-sequent) + os=ptx + ;; + *-crds) + os=unos + ;; + *-ns) + os=genix + ;; + i370-*) + os=mvs ;; *-gould) - os=-sysv + os=sysv ;; *-highlevel) - os=-bsd + os=bsd ;; *-encore) - os=-bsd + os=bsd ;; *-sgi) - os=-irix + os=irix ;; *-siemens) - os=-sysv4 + os=sysv4 ;; *-masscomp) - os=-rtu + os=rtu ;; f30[01]-fujitsu | f700-fujitsu) - os=-uxpv + os=uxpv ;; *-rom68k) - os=-coff + os=coff ;; *-*bug) - os=-coff + os=coff ;; *-apple) - os=-macos + os=macos ;; *-atari*) - os=-mint + os=mint + ;; + *-wrs) + os=vxworks ;; *) - os=-none + os=none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) +case $vendor in + unknown) case $os in - -riscix*) + riscix*) vendor=acorn ;; - -sunos*) + sunos*) vendor=sun ;; - -cnk*|-aix*) + cnk*|-aix*) vendor=ibm ;; - -beos*) + beos*) vendor=be ;; - -hpux*) + hpux*) vendor=hp ;; - -mpeix*) + mpeix*) vendor=hp ;; - -hiux*) + hiux*) vendor=hitachi ;; - -unos*) + unos*) vendor=crds ;; - -dgux*) + dgux*) vendor=dg ;; - -luna*) + luna*) vendor=omron ;; - -genix*) + genix*) vendor=ns ;; - -mvs* | -opened*) + clix*) + vendor=intergraph + ;; + mvs* | opened*) vendor=ibm ;; - -os400*) + os400*) vendor=ibm ;; - -ptx*) + ptx*) vendor=sequent ;; - -tpf*) + tpf*) vendor=ibm ;; - -vxsim* | -vxworks* | -windiss*) + vxsim* | vxworks* | windiss*) vendor=wrs ;; - -aux*) + aux*) vendor=apple ;; - -hms*) + hms*) vendor=hitachi ;; - -mpw* | -macos*) + mpw* | macos*) vendor=apple ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + *mint | mint[0-9]* | *MiNT | MiNT[0-9]*) vendor=atari ;; - -vos*) + vos*) vendor=stratus ;; esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac -echo $basic_machine$os +echo "$cpu-$vendor-$os" exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/configure.ac b/configure.ac index 3e93c0276..1c2757ca5 100644 --- a/configure.ac +++ b/configure.ac @@ -14,12 +14,23 @@ # 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_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([ssh.c]) AC_LANG([C]) -AC_CONFIG_HEADER([config.h]) +AC_CONFIG_HEADERS([config.h]) AC_PROG_CC([cc gcc]) + +# XXX relax this after reimplementing logit() etc. +AC_MSG_CHECKING([if $CC supports C99-style variadic macros]) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +int f(int a, int b, int c) { return a + b + c; } +#define F(a, ...) f(a, __VA_ARGS__) +]], [[return F(1, 2, -3);]])], + [ AC_MSG_RESULT([yes]) ], + [ AC_MSG_ERROR([*** OpenSSH requires support for C99-style variadic macros]) ] +) + AC_CANONICAL_HOST AC_C_BIGENDIAN @@ -34,8 +45,6 @@ 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]) @@ -93,6 +102,7 @@ AC_SUBST([LD]) AC_C_INLINE AC_CHECK_DECL([LLONG_MAX], [have_llong_max=1], , [#include ]) +AC_CHECK_DECL([LONG_LONG_MAX], [have_long_long_max=1], , [#include ]) AC_CHECK_DECL([SYSTR_POLICY_KILL], [have_systr_policy_kill=1], , [ #include #include @@ -163,7 +173,9 @@ if test "$GCC" = "yes" || test "$GCC" = "egcs"; then 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-parameter], [-Wno-unused-parameter]) OSSH_CHECK_CFLAG_COMPILE([-Wunused-result], [-Wno-unused-result]) + OSSH_CHECK_CFLAG_COMPILE([-Wimplicit-fallthrough]) OSSH_CHECK_CFLAG_COMPILE([-fno-strict-aliasing]) if test "x$use_toolchain_hardening" = "x1"; then OSSH_CHECK_CFLAG_COMPILE([-mretpoline]) # clang @@ -213,20 +225,26 @@ if test "$GCC" = "yes" || test "$GCC" = "egcs"; then CFLAGS="$CFLAGS $t -Werror" LDFLAGS="$LDFLAGS $t -Werror" AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ #include ]], + [AC_LANG_PROGRAM([[ + #include + int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} + ]], [[ char x[256]; - snprintf(x, sizeof(x), "XXX"); + snprintf(x, sizeof(x), "XXX%d", func(1)); ]])], [ 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 ]], + [AC_LANG_PROGRAM([[ + #include + int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} + ]], [[ char x[256]; - snprintf(x, sizeof(x), "XXX"); + snprintf(x, sizeof(x), "XXX%d", func(1)); ]])], [ AC_MSG_RESULT([yes]) break ], @@ -279,6 +297,16 @@ typedef void foo(const char *, ...) __attribute__((format(printf, 1, 2)));]], [compiler does not accept __attribute__ on prototype args]) ] ) +AC_MSG_CHECKING([if compiler supports variable length arrays]) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include ]], + [[ int i; for (i=0; i<3; i++){int a[i]; a[i-1]=0;} exit(0); ]])], + [ AC_MSG_RESULT([yes]) + AC_DEFINE(VARIABLE_LENGTH_ARRAYS, [1], + [compiler supports variable length arrays]) ], + [ AC_MSG_RESULT([no]) ] +) + if test "x$no_attrib_nonnull" != "x1" ; then AC_DEFINE([HAVE_ATTRIBUTE__NONNULL__], [1], [Have attribute nonnull]) fi @@ -376,6 +404,7 @@ AC_CHECK_HEADERS([ \ features.h \ fcntl.h \ floatingpoint.h \ + fnmatch.h \ getopt.h \ glob.h \ ia.h \ @@ -405,6 +434,7 @@ AC_CHECK_HEADERS([ \ string.h \ strings.h \ sys/bitypes.h \ + sys/byteorder.h \ sys/bsdtty.h \ sys/cdefs.h \ sys/dir.h \ @@ -642,7 +672,9 @@ case "$host" in *-*-darwin*) use_pie=auto AC_MSG_CHECKING([if we have working getaddrinfo]) - AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include +#include main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) exit(0); else @@ -691,8 +723,10 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) ;; *-*-haiku*) LIBS="$LIBS -lbsd " + CFLAGS="$CFLAGS -D_BSD_SOURCE" AC_CHECK_LIB([network], [socket]) AC_DEFINE([HAVE_U_INT64_T]) + AC_DEFINE([DISABLE_UTMPX], [1], [no utmpx]) MANTYPE=man ;; *-*-hpux*) @@ -900,6 +934,9 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) ;; esac ;; + riscv64-*) + seccomp_audit_arch=AUDIT_ARCH_RISCV64 + ;; esac if test "x$seccomp_audit_arch" != "x" ; then AC_MSG_RESULT(["$seccomp_audit_arch"]) @@ -1192,8 +1229,25 @@ mips-sony-bsd|mips-sony-newsos4) *-*-ultrix*) AC_DEFINE([BROKEN_GETGROUPS], [1], [getgroups(0,NULL) will return -1]) - AC_DEFINE([NEED_SETPGRP]) + AC_DEFINE([NEED_SETPGRP], [1], [Need setpgrp to for controlling tty]) AC_DEFINE([HAVE_SYS_SYSLOG_H], [1], [Force use of sys/syslog.h on Ultrix]) + AC_DEFINE([DISABLE_UTMPX], [1], [Disable utmpx]) + # DISABLE_FD_PASSING so that we call setpgrp as root, otherwise we + # don't get a controlling tty. + AC_DEFINE([DISABLE_FD_PASSING], [1], [Need to call setpgrp as root]) + # On Ultrix some headers are not protected against multiple includes, + # so we create wrappers and put it where the compiler will find it. + AC_MSG_WARN([creating compat wrappers for headers]) + mkdir -p netinet + for header in netinet/ip.h netdb.h resolv.h; do + name=`echo $header | tr 'a-z/.' 'A-Z__'` + cat >$header < ]], [[ exit(0); ]])], +AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) @@ -1228,6 +1282,7 @@ AC_CHECK_FUNCS([dirname], [AC_CHECK_HEADERS([libgen.h])] , [ [AC_LANG_SOURCE([[ #include #include +#include int main(int argc, char **argv) { char *s, buf[32]; @@ -1260,11 +1315,12 @@ AC_CHECK_FUNC([getspnam], , AC_SEARCH_LIBS([basename], [gen], [AC_DEFINE([HAVE_BASENAME], [1], [Define if you have the basename function.])]) -dnl zlib is required +dnl zlib defaults to enabled +zlib=yes AC_ARG_WITH([zlib], [ --with-zlib=PATH Use zlib in PATH], [ if test "x$withval" = "xno" ; then - AC_MSG_ERROR([*** zlib is required ***]) + zlib=no elif test "x$withval" != "xyes"; then if test -d "$withval/lib"; then if test -n "${rpath_opt}"; then @@ -1287,8 +1343,14 @@ AC_ARG_WITH([zlib], fi ] ) -AC_CHECK_HEADER([zlib.h], ,[AC_MSG_ERROR([*** zlib.h missing - please install first or check config.log ***])]) -AC_CHECK_LIB([z], [deflate], , +AC_MSG_CHECKING([for zlib]) +if test "x${zlib}" = "xno"; then + AC_MSG_RESULT([no]) +else + AC_MSG_RESULT([yes]) + AC_DEFINE([WITH_ZLIB], [1], [Enable zlib]) + 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" @@ -1307,18 +1369,18 @@ AC_CHECK_LIB([z], [deflate], , ] ) ] -) + ) -AC_ARG_WITH([zlib-version-check], + 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([[ + AC_MSG_CHECKING([for possibly buggy zlib]) + AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include #include #include @@ -1356,7 +1418,8 @@ See http://www.gzip.org/zlib/ for details.]) fi ], [ AC_MSG_WARN([cross compiling: not checking zlib version]) ] -) + ) +fi dnl UnixWare 2.x AC_CHECK_FUNC([strcasecmp], @@ -1383,6 +1446,10 @@ AC_CHECK_FUNCS([fmt_scaled scan_scaled login logout openpty updwtmp logwtmp]) AC_SEARCH_LIBS([inet_ntop], [resolv nsl]) AC_SEARCH_LIBS([gethostbyname], [resolv nsl]) +# Some Linux distribtions ship the BSD libc hashing functions in +# separate libraries. +AC_SEARCH_LIBS([SHA256Update], [md bsd]) + # "Particular Function Checks" # see https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Functions.html AC_FUNC_STRFTIME @@ -1471,7 +1538,9 @@ AC_MSG_CHECKING([whether struct dirent allocates space for d_name]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include -#include ]], +#include +#include + ]], [[ struct dirent d; exit(sizeof(d.d_name)<=sizeof(char)); @@ -1506,8 +1575,6 @@ AC_ARG_WITH(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 @@ -1531,7 +1598,9 @@ AC_ARG_WITH(ldns, [AC_LANG_SOURCE([[ #include #include -#include +#ifdef HAVE_STDINT_H +# include +#endif #include int main() { ldns_status status = ldns_verify_trusted(NULL, NULL, NULL, NULL); status=LDNS_STATUS_OK; exit(0); } ]]) @@ -1585,7 +1654,10 @@ AC_ARG_WITH([libedit], ) AC_MSG_CHECKING([if libedit version is compatible]) AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([[ #include ]], + [AC_LANG_PROGRAM([[ +#include +#include + ]], [[ int i = H_SETSIZE; el_init("", NULL, NULL, NULL); @@ -1698,6 +1770,18 @@ if test "x$use_pie" != "xno"; then fi fi +AC_MSG_CHECKING([whether -fPIC is accepted]) +SAVED_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -fPIC" +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( [[ #include ]], [[ exit(0); ]] )], + [AC_MSG_RESULT([yes]) + PICFLAG="-fPIC"; ], + [AC_MSG_RESULT([no]) + PICFLAG=""; ]) +CFLAGS="$SAVED_CFLAGS" +AC_SUBST([PICFLAG]) + dnl Checks for library functions. Please keep in alphabetical order AC_CHECK_FUNCS([ \ Blowfish_initstate \ @@ -1725,11 +1809,13 @@ AC_CHECK_FUNCS([ \ err \ errx \ explicit_bzero \ + explicit_memset \ fchmod \ fchmodat \ fchown \ fchownat \ flock \ + fnmatch \ freeaddrinfo \ freezero \ fstatfs \ @@ -1757,7 +1843,9 @@ AC_CHECK_FUNCS([ \ inet_ntop \ innetgr \ llabs \ + localtime_r \ login_getcapbool \ + login_getpwclass \ md5_crypt \ memmem \ memmove \ @@ -1774,6 +1862,7 @@ AC_CHECK_FUNCS([ \ raise \ readpassphrase \ reallocarray \ + realpath \ recvmsg \ recallocarray \ rresvport_af \ @@ -1831,7 +1920,7 @@ AC_CHECK_FUNCS([ \ warn \ ]) -AC_CHECK_DECLS([bzero]) +AC_CHECK_DECLS([bzero, memmem]) dnl Wide character support. AC_CHECK_FUNCS([mblen mbtowc nl_langinfo wcwidth]) @@ -1871,16 +1960,29 @@ AC_ARG_ENABLE([pkcs11], ] ) -# 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 ] - ) - ) -fi +disable_sk= +AC_ARG_ENABLE([security-key], + [ --disable-security-key disable U2F/FIDO support code [no]], + [ + if test "x$enableval" = "xno" ; then + disable_sk=1 + fi + ] +) +enable_sk_internal= +AC_ARG_WITH([security-key-builtin], + [ --with-security-key-builtin include builtin U2F/FIDO support], + [ + if test "x$withval" != "xno" ; then + enable_sk_internal=yes + fi + ] +) +test "x$disable_sk" != "x" && enable_sk_internal="" + +AC_SEARCH_LIBS([dlopen], [dl]) +AC_CHECK_FUNCS([dlopen]) +AC_CHECK_DECL([RTLD_NOW], [], [], [#include ]) # IRIX has a const char return value for gai_strerror() AC_CHECK_FUNCS([gai_strerror], [ @@ -1904,6 +2006,19 @@ AC_SEARCH_LIBS([nanosleep], [rt posix4], [AC_DEFINE([HAVE_NANOSLEEP], [1], AC_SEARCH_LIBS([clock_gettime], [rt], [AC_DEFINE([HAVE_CLOCK_GETTIME], [1], [Have clock_gettime])]) +dnl check if we need -D_REENTRANT for localtime_r declaration. +AC_CHECK_DECL([localtime_r], [], + [ saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -D_REENTRANT" + unset ac_cv_have_decl_localtime_r + AC_CHECK_DECL([localtime_r], [], + [ CPPFLAGS="$saved_CPPFLAGS" ], + [ #include ] + ) + ], + [ #include ] +) + dnl Make sure prototypes are defined for these before using them. AC_CHECK_DECL([strsep], [AC_CHECK_FUNCS([strsep])], @@ -1923,10 +2038,11 @@ AC_CHECK_DECL([tcsendbreak], AC_CHECK_DECLS([h_errno], , ,[#include ]) -AC_CHECK_DECLS([SHUT_RD], , , +AC_CHECK_DECLS([SHUT_RD, getpeereid], , , [ #include #include +#include ]) AC_CHECK_DECLS([O_NONBLOCK], , , @@ -2033,7 +2149,11 @@ AC_CHECK_FUNCS([setresgid], [ AC_MSG_CHECKING([for working fflush(NULL)]) AC_RUN_IFELSE( - [AC_LANG_PROGRAM([[#include ]], [[fflush(NULL); exit(0);]])], + [AC_LANG_PROGRAM([[ +#include +#include + ]], + [[fflush(NULL); exit(0);]])], AC_MSG_RESULT([yes]), [AC_MSG_RESULT([no]) AC_DEFINE([FFLUSH_NULL_BUG], [1], @@ -2069,7 +2189,10 @@ AC_CHECK_FUNC([getpagesize], 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 ]], + [AC_LANG_PROGRAM([[ +#include +#include + ]], [[ char b[5]; snprintf(b,5,"123456789"); @@ -2092,6 +2215,8 @@ if test "x$ac_cv_func_snprintf" = "xyes" ; then [AC_LANG_PROGRAM([[ #include #include +#include +#include ]], [[ size_t a = 1, b = 2; @@ -2178,39 +2303,14 @@ if test "x$ac_cv_func_getpeereid" != "xyes" -a "x$ac_cv_func_getpeerucred" != "x ]) 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 - ]], [[ - 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 +#include +#include #include #include #include @@ -2257,6 +2357,7 @@ if test "x$ac_cv_func_getaddrinfo" = "xyes" && \ AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include +#include #include #include #include @@ -2325,6 +2426,7 @@ if test "x$ac_cv_func_getaddrinfo" = "xyes" && \ AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include +#include #include #include #include @@ -2387,7 +2489,10 @@ 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 ]], + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include + ]], [[ exit(0); ]])], [ AC_MSG_RESULT([no]) @@ -2417,6 +2522,7 @@ if test "x$ac_cv_func_strnvis" = "xyes"; then #include #include #include +#include #include static void sighandler(int sig) { _exit(1); } ]], [[ @@ -2435,6 +2541,46 @@ static void sighandler(int sig) { _exit(1); } ) fi +AC_MSG_CHECKING([if SA_RESTARTed signals interrupt select()]) +AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ +#ifdef HAVE_SYS_SELECT +# include +#endif +#include +#include +#include +#include +#include +static void sighandler(int sig) { } + ]], [[ + int r; + pid_t pid; + struct sigaction sa; + + sa.sa_handler = sighandler; + sa.sa_flags = SA_RESTART; + (void)sigaction(SIGTERM, &sa, NULL); + if ((pid = fork()) == 0) { /* child */ + pid = getppid(); + sleep(1); + kill(pid, SIGTERM); + sleep(1); + if (getppid() == pid) /* if parent did not exit, shoot it */ + kill(pid, SIGKILL); + exit(0); + } else { /* parent */ + r = select(0, NULL, NULL, NULL, NULL); + } + exit(r == -1 ? 0 : 1); + ]])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_DEFINE([NO_SA_RESTART], [1], + [SA_RESTARTed signals do no interrupt select])], + [AC_MSG_WARN([cross compiling: assuming yes])] +) + AC_CHECK_FUNCS([getpgrp],[ AC_MSG_CHECKING([if getpgrp accepts zero args]) AC_COMPILE_IFELSE( @@ -2562,6 +2708,7 @@ if test "x$openssl" = "xyes" ; then AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include + #include #include #include #include @@ -2623,6 +2770,7 @@ if test "x$openssl" = "xyes" ; then AC_MSG_CHECKING([whether OpenSSL's headers match the library]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ + #include #include #include #include @@ -2723,6 +2871,7 @@ if test "x$openssl" = "xyes" ; then EVP_CIPHER_CTX_iv \ EVP_CIPHER_CTX_iv_noconst \ EVP_CIPHER_CTX_get_iv \ + EVP_CIPHER_CTX_get_updated_iv \ EVP_CIPHER_CTX_set_iv \ RSA_get0_crt_params \ RSA_get0_factors \ @@ -2740,6 +2889,7 @@ if test "x$openssl" = "xyes" ; then EVP_PKEY_get0_RSA \ EVP_MD_CTX_new \ EVP_MD_CTX_free \ + EVP_chacha20 \ ]) if test "x$openssl_engine" = "xyes" ; then @@ -2761,6 +2911,7 @@ if test "x$openssl" = "xyes" ; then AC_MSG_CHECKING([whether OpenSSL has crippled AES support]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ + #include #include #include ]], [[ @@ -2780,6 +2931,7 @@ if test "x$openssl" = "xyes" ; then AC_MSG_CHECKING([whether OpenSSL has AES CTR via EVP]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ + #include #include #include ]], [[ @@ -2801,6 +2953,7 @@ if test "x$openssl" = "xyes" ; then AC_MSG_CHECKING([whether OpenSSL has AES GCM via EVP]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ + #include #include #include ]], [[ @@ -2828,6 +2981,7 @@ if test "x$openssl" = "xyes" ; then AC_MSG_CHECKING([if EVP_DigestUpdate returns an int]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ + #include #include #include ]], [[ @@ -2860,15 +3014,6 @@ if test "x$openssl" = "xyes" ; then # Check for SHA256, SHA384 and SHA512 support in OpenSSL AC_CHECK_FUNCS([EVP_sha256 EVP_sha384 EVP_sha512]) - # 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( @@ -2923,6 +3068,7 @@ if test "x$openssl" = "xyes" ; then AC_MSG_CHECKING([if OpenSSL's NID_secp521r1 is functional]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ + #include #include #include #include @@ -2950,6 +3096,9 @@ if test "x$openssl" = "xyes" ; then test x$enable_nistp521 = x1; then AC_DEFINE(OPENSSL_HAS_ECC, [1], [OpenSSL has ECC]) AC_CHECK_FUNCS([EC_KEY_METHOD_new]) + openssl_ecc=yes + else + openssl_ecc=no fi if test x$enable_nistp256 = x1; then AC_DEFINE([OPENSSL_HAS_NISTP256], [1], @@ -2990,6 +3139,94 @@ else AC_CHECK_FUNCS([crypt]) fi +# PKCS11/U2F depend on OpenSSL and dlopen(). +enable_pkcs11=yes +enable_sk=yes +if test "x$openssl" != "xyes" ; then + enable_pkcs11="disabled; missing libcrypto" + enable_sk="disabled; missing libcrypto" +fi +if test "x$openssl_ecc" != "xyes" ; then + enable_sk="disabled; OpenSSL has no ECC support" +fi +if test "x$ac_cv_func_dlopen" != "xyes" ; then + enable_pkcs11="disabled; missing dlopen(3)" + enable_sk="disabled; missing dlopen(3)" +fi +if test "x$ac_cv_have_decl_RTLD_NOW" != "xyes" ; then + enable_pkcs11="disabled; missing RTLD_NOW" + enable_sk="disabled; missing RTLD_NOW" +fi +if test ! -z "$disable_pkcs11" ; then + enable_pkcs11="disabled by user" +fi +if test ! -z "$disable_sk" ; then + enable_sk="disabled by user" +fi + +AC_MSG_CHECKING([whether to enable PKCS11]) +if test "x$enable_pkcs11" = "xyes" ; then + AC_DEFINE([ENABLE_PKCS11], [], [Enable for PKCS#11 support]) +fi +AC_MSG_RESULT([$enable_pkcs11]) + +AC_MSG_CHECKING([whether to enable U2F]) +if test "x$enable_sk" = "xyes" ; then + AC_DEFINE([ENABLE_SK], [], [Enable for U2F/FIDO support]) + AC_SUBST(SK_DUMMY_LIBRARY, [regress/misc/sk-dummy/sk-dummy.so]) +else + # Do not try to build sk-dummy library. + AC_SUBST(SK_DUMMY_LIBRARY, [""]) +fi +AC_MSG_RESULT([$enable_sk]) + +# Now check for built-in security key support. +if test "x$enable_sk" = "xyes" -a "x$enable_sk_internal" = "xyes" ; then + AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no]) + use_pkgconfig_for_libfido2= + if test "x$PKGCONFIG" != "xno"; then + AC_MSG_CHECKING([if $PKGCONFIG knows about libfido2]) + if "$PKGCONFIG" libfido2; then + AC_MSG_RESULT([yes]) + use_pkgconfig_for_libfido2=yes + else + AC_MSG_RESULT([no]) + fi + fi + if test "x$use_pkgconfig_for_libfido2" = "xyes"; then + LIBFIDO2=`$PKGCONFIG --libs libfido2` + CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libfido2`" + else + LIBFIDO2="-lfido2 -lcbor" + fi + OTHERLIBS=`echo $LIBFIDO2 | sed 's/-lfido2//'` + AC_CHECK_LIB([fido2], [fido_init], + [ + AC_SUBST([LIBFIDO2]) + AC_DEFINE([ENABLE_SK_INTERNAL], [], + [Enable for built-in U2F/FIDO support]) + enable_sk="built-in" + ], [ AC_MSG_ERROR([no usable libfido2 found]) ], + [ $OTHERLIBS ] + ) + saved_LIBS="$LIBS" + LIBS="$LIBS $LIBFIDO2" + AC_CHECK_FUNCS([ \ + fido_cred_prot \ + fido_cred_set_prot \ + fido_dev_get_touch_begin \ + fido_dev_get_touch_status \ + fido_dev_supports_cred_prot \ + ]) + LIBS="$saved_LIBS" + AC_CHECK_HEADER([fido.h], [], + AC_MSG_ERROR([missing fido.h from libfido2])) + AC_CHECK_HEADER([fido/credman.h], [], + AC_MSG_ERROR([missing fido/credman.h from libfido2]), + [#include ] + ) +fi + AC_CHECK_FUNCS([ \ arc4random \ arc4random_buf \ @@ -3014,6 +3251,7 @@ if test "x$openssl" = "xyes" ; then AC_MSG_CHECKING([whether OpenSSL's PRNG is internally seeded]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ + #include #include #include ]], [[ @@ -3440,11 +3678,12 @@ if test "x$ac_cv_sizeof_long_long_int" = "x4" ; then fi # compute LLONG_MIN and LLONG_MAX if we don't know them. -if test -z "$have_llong_max"; then +if test -z "$have_llong_max" && test -z "$have_long_long_max"; then AC_MSG_CHECKING([for max value of long long]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include +#include /* Why is this so damn hard? */ #ifdef __GNUC__ # undef __GNUC__ @@ -3535,6 +3774,17 @@ fprint_ll(FILE *f, long long n) ) fi +AC_CHECK_DECLS([UINT32_MAX], , , [[ +#ifdef HAVE_SYS_LIMITS_H +# include +#endif +#ifdef HAVE_LIMITS_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +]]) # More checks for data types AC_CACHE_CHECK([for u_int type], ac_cv_have_u_int, [ @@ -3715,7 +3965,9 @@ fi AC_CHECK_TYPES([intmax_t, uintmax_t], , , [ #include -#include +#ifdef HAVE_STDINT_H +# include +#endif ]) TYPE_SOCKLEN_T @@ -3734,7 +3986,8 @@ AC_CHECK_TYPES([fsblkcnt_t, fsfilcnt_t], , , [ #endif ]) -AC_CHECK_MEMBERS([struct statfs.f_flags], [], [], [[ +AC_CHECK_MEMBERS([struct statfs.f_files, struct statfs.f_flags], [], [], [[ +#include #include #ifdef HAVE_SYS_BITYPES_H #include @@ -3748,6 +4001,9 @@ AC_CHECK_MEMBERS([struct statfs.f_flags], [], [], [[ #ifdef HAVE_SYS_VFS_H #include #endif +#ifdef HAVE_SYS_MOUNT_H +#include +#endif ]]) @@ -3905,7 +4161,24 @@ if test "x$ac_cv_have_struct_timeval" = "xyes" ; then have_struct_timeval=1 fi -AC_CHECK_TYPES([struct timespec]) +AC_CACHE_CHECK([for struct timespec], ac_cv_have_struct_timespec, [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #ifdef HAVE_SYS_TIME_H + # include + #endif + #ifdef HAVE_TIME_H + # include + #endif + ]], + [[ struct timespec ts; ts.tv_sec = 1;]])], + [ ac_cv_have_struct_timespec="yes" ], + [ ac_cv_have_struct_timespec="no" + ]) +]) +if test "x$ac_cv_have_struct_timespec" = "xyes" ; then + AC_DEFINE([HAVE_STRUCT_TIMESPEC], [1], [define if you have struct timespec]) + have_struct_timespec=1 +fi # We need int64_t or else certain parts of the compile will fail. if test "x$ac_cv_have_int64_t" = "xno" && \ @@ -3920,6 +4193,7 @@ dnl test snprintf (broken on SCO w/gcc) AC_RUN_IFELSE( [AC_LANG_SOURCE([[ #include +#include #include #ifdef HAVE_SNPRINTF main() @@ -3964,6 +4238,7 @@ 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]) +OSSH_CHECK_HEADER_FOR_FIELD([ut_ss], [utmpx.h], [HAVE_SS_IN_UTMPX]) AC_CHECK_MEMBERS([struct stat.st_blksize]) AC_CHECK_MEMBERS([struct stat.st_mtim]) @@ -4022,6 +4297,7 @@ AC_CACHE_CHECK([for msg_accrights field in struct msghdr], #include #include #include +#include ]], [[ #ifdef msg_accrights #error "msg_accrights is a macro" @@ -4083,6 +4359,7 @@ AC_CACHE_CHECK([for msg_control field in struct msghdr], #include #include #include +#include ]], [[ #ifdef msg_control #error "msg_control is a macro" @@ -4103,7 +4380,7 @@ if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then fi AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [ - AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ extern char *__progname; printf("%s", __progname); ]])], [ ac_cv_libc_defines___progname="yes" ], [ ac_cv_libc_defines___progname="no" @@ -4175,7 +4452,7 @@ if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then fi AC_CACHE_CHECK([if libc defines sys_errlist], ac_cv_libc_defines_sys_errlist, [ - AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ 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" @@ -4188,7 +4465,7 @@ fi AC_CACHE_CHECK([if libc defines sys_nerr], ac_cv_libc_defines_sys_nerr, [ - AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ extern int sys_nerr; printf("%i", sys_nerr);]])], [ ac_cv_libc_defines_sys_nerr="yes" ], [ ac_cv_libc_defines_sys_nerr="no" @@ -4282,13 +4559,10 @@ AC_ARG_WITH([selinux], 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" + LIBS="$save_LIBS $LIBSELINUX" fi ] ) -AC_SUBST([SSHLIBS]) AC_SUBST([SSHDLIBS]) # Check whether user wants Kerberos 5 support @@ -4500,6 +4774,7 @@ AC_ARG_WITH([maildir], AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include +#include #include #ifdef HAVE_PATHS_H #include @@ -4744,6 +5019,7 @@ otherwise scp will not work.]) [AC_LANG_PROGRAM([[ /* find out what STDPATH is */ #include +#include #ifdef HAVE_PATHS_H # include #endif @@ -5171,6 +5447,12 @@ AC_SUBST([DEPEND], [$(cat $srcdir/.depend)]) CFLAGS="${CFLAGS} ${CFLAGS_AFTER}" LDFLAGS="${LDFLAGS} ${LDFLAGS_AFTER}" +# Make a copy of CFLAGS/LDFLAGS without PIE options. +LDFLAGS_NOPIE=`echo "$LDFLAGS" | sed 's/ -pie//'` +CFLAGS_NOPIE=`echo "$CFLAGS" | sed 's/ -fPIE//'` +AC_SUBST([LDFLAGS_NOPIE]) +AC_SUBST([CFLAGS_NOPIE]) + AC_EXEEXT AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \ openbsd-compat/Makefile openbsd-compat/regress/Makefile \ @@ -5229,6 +5511,8 @@ 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 " PKCS#11 support: $enable_pkcs11" +echo " U2F/FIDO support: $enable_sk" echo "" @@ -5241,9 +5525,6 @@ echo " Libraries: ${LIBS}" if test ! -z "${SSHDLIBS}"; then echo " +for sshd: ${SSHDLIBS}" fi -if test ! -z "${SSHLIBS}"; then -echo " +for ssh: ${SSHLIBS}" -fi echo "" diff --git a/contrib/cygwin/README b/contrib/cygwin/README index 250baa3a4..3745051f5 100644 --- a/contrib/cygwin/README +++ b/contrib/cygwin/README @@ -60,7 +60,7 @@ Options: Please note that OpenSSH does never use the value of $HOME to search for the users configuration files! It always uses the value of the pw_dir field in /etc/passwd as the home directory. -If no home diretory is set in /etc/passwd, the root directory +If no home directory is set in /etc/passwd, the root directory is used instead! ================ diff --git a/contrib/gnome-ssh-askpass2.c b/contrib/gnome-ssh-askpass2.c index 535a69274..f7912727c 100644 --- a/contrib/gnome-ssh-askpass2.c +++ b/contrib/gnome-ssh-askpass2.c @@ -39,6 +39,10 @@ #define GRAB_TRIES 16 #define GRAB_WAIT 250 /* milliseconds */ +#define PROMPT_ENTRY 0 +#define PROMPT_CONFIRM 1 +#define PROMPT_NONE 2 + /* * Compile with: * @@ -52,9 +56,11 @@ #include #include #include + #include #include #include +#include static void report_failed_grab (GtkWidget *parent_window, const char *what) @@ -81,48 +87,148 @@ ok_dialog(GtkWidget *entry, gpointer dialog) gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); } +static gboolean +check_none(GtkWidget *widget, GdkEventKey *event, gpointer dialog) +{ + switch (event->keyval) { + case GDK_KEY_Escape: + /* esc -> close dialog */ + gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE); + return TRUE; + case GDK_KEY_Tab: + /* tab -> focus close button */ + gtk_widget_grab_focus(gtk_dialog_get_widget_for_response( + dialog, GTK_RESPONSE_CLOSE)); + return TRUE; + default: + /* eat all other key events */ + return TRUE; + } +} + static int -passphrase_dialog(char *message) +parse_env_hex_color(const char *env, GdkColor *c) +{ + const char *s; + unsigned long ul; + char *ep; + size_t n; + + if ((s = getenv(env)) == NULL) + return 0; + + memset(c, 0, sizeof(*c)); + + /* Permit hex rgb or rrggbb optionally prefixed by '#' or '0x' */ + if (*s == '#') + s++; + else if (strncmp(s, "0x", 2) == 0) + s += 2; + n = strlen(s); + if (n != 3 && n != 6) + goto bad; + ul = strtoul(s, &ep, 16); + if (*ep != '\0' || ul > 0xffffff) { + bad: + fprintf(stderr, "Invalid $%s - invalid hex color code\n", env); + return 0; + } + /* Valid hex sequence; expand into a GdkColor */ + if (n == 3) { + /* 4-bit RGB */ + c->red = ((ul >> 8) & 0xf) << 12; + c->green = ((ul >> 4) & 0xf) << 12; + c->blue = (ul & 0xf) << 12; + } else { + /* 8-bit RGB */ + c->red = ((ul >> 16) & 0xff) << 8; + c->green = ((ul >> 8) & 0xff) << 8; + c->blue = (ul & 0xff) << 8; + } + return 1; +} + +static int +passphrase_dialog(char *message, int prompt_type) { const char *failed; char *passphrase, *local; int result, grab_tries, grab_server, grab_pointer; + int buttons, default_response; GtkWidget *parent_window, *dialog, *entry; GdkGrabStatus status; + GdkColor fg, bg; + int fg_set = 0, bg_set = 0; grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL); grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL); grab_tries = 0; + fg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_FG_COLOR", &fg); + bg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_BG_COLOR", &bg); + /* Create an invisible parent window so that GtkDialog doesn't * complain. */ parent_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - dialog = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_OK_CANCEL, - "%s", - message); + switch (prompt_type) { + case PROMPT_CONFIRM: + buttons = GTK_BUTTONS_YES_NO; + default_response = GTK_RESPONSE_YES; + break; + case PROMPT_NONE: + buttons = GTK_BUTTONS_CLOSE; + default_response = GTK_RESPONSE_CLOSE; + break; + default: + buttons = GTK_BUTTONS_OK_CANCEL; + default_response = GTK_RESPONSE_OK; + break; + } - entry = gtk_entry_new(); - gtk_box_pack_start( - GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), entry, - FALSE, FALSE, 0); - gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); - gtk_widget_grab_focus(entry); - gtk_widget_show(entry); + dialog = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0, + GTK_MESSAGE_QUESTION, buttons, "%s", message); gtk_window_set_title(GTK_WINDOW(dialog), "OpenSSH"); gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); - - /* Make close dialog */ - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); - g_signal_connect(G_OBJECT(entry), "activate", - G_CALLBACK(ok_dialog), dialog); - + gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_response); gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); + if (fg_set) + gtk_widget_modify_fg(dialog, GTK_STATE_NORMAL, &fg); + if (bg_set) + gtk_widget_modify_bg(dialog, GTK_STATE_NORMAL, &bg); + + if (prompt_type == PROMPT_ENTRY || prompt_type == PROMPT_NONE) { + entry = gtk_entry_new(); + if (fg_set) + gtk_widget_modify_fg(entry, GTK_STATE_NORMAL, &fg); + if (bg_set) + gtk_widget_modify_bg(entry, GTK_STATE_NORMAL, &bg); + gtk_box_pack_start( + GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + entry, FALSE, FALSE, 0); + gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); + gtk_widget_grab_focus(entry); + if (prompt_type == PROMPT_ENTRY) { + gtk_widget_show(entry); + /* Make close dialog */ + g_signal_connect(G_OBJECT(entry), "activate", + G_CALLBACK(ok_dialog), dialog); + } else { + /* + * Ensure the 'close' button is not focused by default + * but is still reachable via tab. This is a bit of a + * hack - it uses a hidden entry that responds to a + * couple of keypress events (escape and tab only). + */ + gtk_widget_realize(entry); + g_signal_connect(G_OBJECT(entry), "key_press_event", + G_CALLBACK(check_none), dialog); + } + } + /* Grab focus */ gtk_widget_show_now(dialog); if (grab_pointer) { @@ -166,32 +272,37 @@ passphrase_dialog(char *message) gdk_flush(); /* Report passphrase if user selected OK */ - passphrase = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))); - if (result == GTK_RESPONSE_OK) { - local = g_locale_from_utf8(passphrase, strlen(passphrase), - NULL, NULL, NULL); - if (local != NULL) { - puts(local); - memset(local, '\0', strlen(local)); - g_free(local); - } else { - puts(passphrase); + if (prompt_type == PROMPT_ENTRY) { + passphrase = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry))); + if (result == GTK_RESPONSE_OK) { + local = g_locale_from_utf8(passphrase, + strlen(passphrase), NULL, NULL, NULL); + if (local != NULL) { + puts(local); + memset(local, '\0', strlen(local)); + g_free(local); + } else { + puts(passphrase); + } } + /* Zero passphrase in memory */ + memset(passphrase, '\b', strlen(passphrase)); + gtk_entry_set_text(GTK_ENTRY(entry), passphrase); + memset(passphrase, '\0', strlen(passphrase)); + g_free(passphrase); } - - /* Zero passphrase in memory */ - memset(passphrase, '\b', strlen(passphrase)); - gtk_entry_set_text(GTK_ENTRY(entry), passphrase); - memset(passphrase, '\0', strlen(passphrase)); - g_free(passphrase); - - gtk_widget_destroy(dialog); - return (result == GTK_RESPONSE_OK ? 0 : -1); - /* At least one grab failed - ungrab what we got, and report - the failure to the user. Note that XGrabServer() cannot - fail. */ + gtk_widget_destroy(dialog); + if (result != GTK_RESPONSE_OK && result != GTK_RESPONSE_YES) + return -1; + return 0; + nograbkb: + /* + * At least one grab failed - ungrab what we got, and report + * the failure to the user. Note that XGrabServer() cannot + * fail. + */ gdk_pointer_ungrab(GDK_CURRENT_TIME); nograb: if (grab_server) @@ -206,8 +317,8 @@ passphrase_dialog(char *message) int main(int argc, char **argv) { - char *message; - int result; + char *message, *prompt_mode; + int result, prompt_type = PROMPT_ENTRY; gtk_init(&argc, &argv); @@ -217,8 +328,15 @@ main(int argc, char **argv) message = g_strdup("Enter your OpenSSH passphrase:"); } + if ((prompt_mode = getenv("SSH_ASKPASS_PROMPT")) != NULL) { + if (strcasecmp(prompt_mode, "confirm") == 0) + prompt_type = PROMPT_CONFIRM; + else if (strcasecmp(prompt_mode, "none") == 0) + prompt_type = PROMPT_NONE; + } + setvbuf(stdout, 0, _IONBF, 0); - result = passphrase_dialog(message); + result = passphrase_dialog(message, prompt_type); g_free(message); return (result); diff --git a/contrib/redhat/openssh.spec b/contrib/redhat/openssh.spec index a440a11c2..908cafdac 100644 --- a/contrib/redhat/openssh.spec +++ b/contrib/redhat/openssh.spec @@ -1,78 +1,78 @@ -%define ver 8.1p1 -%define rel 1%{?dist} +%global ver 8.5p1 +%global rel 1%{?dist} # OpenSSH privilege separation requires a user & group ID -%define sshd_uid 74 -%define sshd_gid 74 +%global sshd_uid 74 +%global sshd_gid 74 # Version of ssh-askpass -%define aversion 1.2.4.1 +%global aversion 1.2.4.1 # Do we want to disable building of x11-askpass? (1=yes 0=no) -%define no_x11_askpass 0 +%global no_x11_askpass 0 # Do we want to disable building of gnome-askpass? (1=yes 0=no) -%define no_gnome_askpass 0 +%global no_gnome_askpass 0 # Do we want to link against a static libcrypto? (1=yes 0=no) -%define static_libcrypto 0 +%global static_libcrypto 0 # Do we want smartcard support (1=yes 0=no) -%define scard 0 +%global scard 0 # Use GTK2 instead of GNOME in gnome-ssh-askpass -%define gtk2 1 +%global gtk2 1 # Use build6x options for older RHEL builds # RHEL 7 not yet supported %if 0%{?rhel} > 6 -%define build6x 0 +%global build6x 0 %else -%define build6x 1 +%global build6x 1 %endif %if 0%{?fedora} >= 26 -%define compat_openssl 1 +%global compat_openssl 1 %else -%define compat_openssl 0 +%global compat_openssl 0 %endif # Do we want kerberos5 support (1=yes 0=no) -%define kerberos5 1 +%global 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} +%{?skip_x11_askpass:%global no_x11_askpass 1} +%{?skip_gnome_askpass:%global 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} +%{?no_gtk2:%global gtk2 0} # Is this a build for RHL 6.x or earlier? -%{?build_6x:%define build6x 1} +%{?build_6x:%global build6x 1} # If this is RHL 6.x, the default configuration has sysconfdir in /usr/etc. %if %{build6x} -%define _sysconfdir /etc +%global _sysconfdir /etc %endif # Options for static OpenSSL link: # rpm -ba|--rebuild --define "static_openssl 1" -%{?static_openssl:%define static_libcrypto 1} +%{?static_openssl:%global static_libcrypto 1} # Options for Smartcard support: (needs libsectok and openssl-engine) # rpm -ba|--rebuild --define "smartcard 1" -%{?smartcard:%define scard 1} +%{?smartcard:%global 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} +%global rescue 0 +%{?build_rescue:%global rescue 1} # Turn off some stuff for resuce builds %if %{rescue} -%define kerberos5 0 +%global kerberos5 0 %endif Summary: The OpenSSH implementation of SSH protocol version 2. @@ -363,8 +363,10 @@ fi %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(0755,root,root) %{_libexecdir}/openssh/ssh-sk-helper %attr(0644,root,root) %{_mandir}/man8/ssh-keysign.8* %attr(0644,root,root) %{_mandir}/man8/ssh-pkcs11-helper.8* +%attr(0644,root,root) %{_mandir}/man8/ssh-sk-helper.8* %endif %if %{scard} %attr(0755,root,root) %dir %{_datadir}/openssh @@ -422,6 +424,9 @@ fi %endif %changelog +* Mon Jul 20 2020 Damien Miller +- Add ssh-sk-helper and corresponding manual page. + * Sat Feb 10 2018 Darren Tucker - Update openssl-devel dependency to match current requirements. - Handle Fedora >=6 openssl 1.0 compat libs. diff --git a/contrib/ssh-copy-id b/contrib/ssh-copy-id index b83b83619..cd122def3 100644 --- a/contrib/ssh-copy-id +++ b/contrib/ssh-copy-id @@ -1,6 +1,8 @@ #!/bin/sh -# Copyright (c) 1999-2016 Philip Hands +# Copyright (c) 1999-2020 Philip Hands +# 2020 Matthias Blümel +# 2017 Sebastien Boyron # 2013 Martin Kletzander # 2010 Adeodato =?iso-8859-1?Q?Sim=F3?= # 2010 Eric Moret @@ -33,13 +35,15 @@ # Shell script to install your public key(s) on a remote machine # See the ssh-copy-id(1) man page for details +# shellcheck shell=dash + # check that we have something mildly sane as our shell, or try to find something better if false ^ printf "%s: WARNING: ancient shell, hunting for a more modern one... " "$0" then SANE_SH=${SANE_SH:-/usr/bin/ksh} if printf 'true ^ false\n' | "$SANE_SH" then - printf "'%s' seems viable.\n" "$SANE_SH" + printf "'%s' seems viable.\\n" "$SANE_SH" exec "$SANE_SH" "$0" "$@" else cat <<-EOF @@ -51,36 +55,39 @@ then a bug describing your setup, and the shell you used to make it work. EOF - printf "%s: ERROR: Less dimwitted shell required.\n" "$0" + printf '%s: ERROR: Less dimwitted shell required.\n' "$0" exit 1 fi fi -most_recent_id="$(cd "$HOME" ; ls -t .ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1)" -DEFAULT_PUB_ID_FILE="${most_recent_id:+$HOME/}$most_recent_id" +# shellcheck disable=SC2010 +DEFAULT_PUB_ID_FILE=$(ls -t "${HOME}"/.ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1) +SSH="ssh -a -x" +umask 0177 usage () { - printf 'Usage: %s [-h|-?|-f|-n] [-i [identity_file]] [-p port] [[-o ] ...] [user@]hostname\n' "$0" >&2 + printf 'Usage: %s [-h|-?|-f|-n|-s] [-i [identity_file]] [-p port] [-F alternative ssh_config file] [[-o ] ...] [user@]hostname\n' "$0" >&2 printf '\t-f: force mode -- copy keys without trying to check if they are already installed\n' >&2 printf '\t-n: dry run -- no keys are actually copied\n' >&2 + printf '\t-s: use sftp -- use sftp instead of executing remote-commands. Can be useful if the remote only allows sftp\n' >&2 printf '\t-h|-?: print this help\n' >&2 exit 1 } # escape any single quotes in an argument quote() { - printf "%s\n" "$1" | sed -e "s/'/'\\\\''/g" + printf '%s\n' "$1" | sed -e "s/'/'\\\\''/g" } use_id_file() { - local L_ID_FILE="$1" + L_ID_FILE="$1" if [ -z "$L_ID_FILE" ] ; then - printf "%s: ERROR: no ID file found\n" "$0" + printf '%s: ERROR: no ID file found\n' "$0" exit 1 fi - if expr "$L_ID_FILE" : ".*\.pub$" >/dev/null ; then + if expr "$L_ID_FILE" : '.*\.pub$' >/dev/null ; then PUB_ID_FILE="$L_ID_FILE" else PUB_ID_FILE="$L_ID_FILE.pub" @@ -91,9 +98,9 @@ use_id_file() { # check that the files are readable for f in "$PUB_ID_FILE" ${PRIV_ID_FILE:+"$PRIV_ID_FILE"} ; do ErrMSG=$( { : < "$f" ; } 2>&1 ) || { - local L_PRIVMSG="" + L_PRIVMSG="" [ "$f" = "$PRIV_ID_FILE" ] && L_PRIVMSG=" (to install the contents of '$PUB_ID_FILE' anyway, look at the -f option)" - printf "\n%s: ERROR: failed to open ID file '%s': %s\n" "$0" "$f" "$(printf "%s\n%s\n" "$ErrMSG" "$L_PRIVMSG" | sed -e 's/.*: *//')" + printf "\\n%s: ERROR: failed to open ID file '%s': %s\\n" "$0" "$f" "$(printf '%s\n%s\n' "$ErrMSG" "$L_PRIVMSG" | sed -e 's/.*: *//')" exit 1 } done @@ -105,80 +112,36 @@ if [ -n "$SSH_AUTH_SOCK" ] && ssh-add -L >/dev/null 2>&1 ; then GET_ID="ssh-add -L" fi -while test "$#" -gt 0 +while getopts "i:o:p:F:fnsh?" OPT do - [ "${SEEN_OPT_I}" ] && expr "$1" : "[-]i" >/dev/null && { - printf "\n%s: ERROR: -i option must not be specified more than once\n\n" "$0" - usage - } - - OPT= OPTARG= - # implement something like getopt to avoid Solaris pain - case "$1" in - -i?*|-o?*|-p?*) - OPT="$(printf -- "$1"|cut -c1-2)" - OPTARG="$(printf -- "$1"|cut -c3-)" - shift - ;; - -o|-p) - OPT="$1" - OPTARG="$2" - shift 2 - ;; - -i) - OPT="$1" - test "$#" -le 2 || expr "$2" : "[-]" >/dev/null || { - OPTARG="$2" - shift - } - shift - ;; - -f|-n|-h|-\?) - OPT="$1" - OPTARG= - shift - ;; - --) - shift - while test "$#" -gt 0 - do - SAVEARGS="${SAVEARGS:+$SAVEARGS }'$(quote "$1")'" - shift - done - break - ;; - -*) - printf "\n%s: ERROR: invalid option (%s)\n\n" "$0" "$1" - usage - ;; - *) - SAVEARGS="${SAVEARGS:+$SAVEARGS }'$(quote "$1")'" - shift - continue - ;; - esac - case "$OPT" in - -i) + i) + [ "${SEEN_OPT_I}" ] && { + printf '\n%s: ERROR: -i option must not be specified more than once\n\n' "$0" + usage + } SEEN_OPT_I="yes" use_id_file "${OPTARG:-$DEFAULT_PUB_ID_FILE}" ;; - -o|-p) - SSH_OPTS="${SSH_OPTS:+$SSH_OPTS }$OPT '$(quote "$OPTARG")'" + o|p|F) + SSH_OPTS="${SSH_OPTS:+$SSH_OPTS }-$OPT '$(quote "${OPTARG}")'" ;; - -f) + f) FORCED=1 ;; - -n) + n) DRY_RUN=1 ;; - -h|-\?) + s) + SFTP=sftp + ;; + h|\?) usage ;; esac done - -eval set -- "$SAVEARGS" +#shift all args to keep only USER_HOST +shift $((OPTIND-1)) if [ $# = 0 ] ; then usage @@ -189,71 +152,74 @@ if [ $# != 1 ] ; then fi # drop trailing colon -USER_HOST=$(printf "%s\n" "$1" | sed 's/:$//') +USER_HOST="$*" # tack the hostname onto SSH_OPTS SSH_OPTS="${SSH_OPTS:+$SSH_OPTS }'$(quote "$USER_HOST")'" # and populate "$@" for later use (only way to get proper quoting of options) eval set -- "$SSH_OPTS" +# shellcheck disable=SC2086 if [ -z "$(eval $GET_ID)" ] && [ -r "${PUB_ID_FILE:=$DEFAULT_PUB_ID_FILE}" ] ; then use_id_file "$PUB_ID_FILE" fi +# shellcheck disable=SC2086 if [ -z "$(eval $GET_ID)" ] ; then printf '%s: ERROR: No identities found\n' "$0" >&2 exit 1 fi +# filter_ids() +# tries to log in using the keys piped to it, and filters out any that work +filter_ids() { + L_SUCCESS="$1" + L_TMP_ID_FILE="$SCRATCH_DIR"/popids_tmp_id + L_OUTPUT_FILE="$SCRATCH_DIR"/popids_output + + # repopulate "$@" inside this function + eval set -- "$SSH_OPTS" + + while read -r ID || [ "$ID" ] ; do + printf '%s\n' "$ID" > "$L_TMP_ID_FILE" + + # the next line assumes $PRIV_ID_FILE only set if using a single id file - this + # assumption will break if we implement the possibility of multiple -i options. + # The point being that if file based, ssh needs the private key, which it cannot + # find if only given the contents of the .pub file in an unrelated tmpfile + $SSH -i "${PRIV_ID_FILE:-$L_TMP_ID_FILE}" \ + -o ControlPath=none \ + -o LogLevel=INFO \ + -o PreferredAuthentications=publickey \ + -o IdentitiesOnly=yes "$@" exit >"$L_OUTPUT_FILE" 2>&1 /dev/null + # this error counts as a success if we're setting up an sftp connection + } + then + : > "$L_TMP_ID_FILE" + else + grep 'Permission denied' "$L_OUTPUT_FILE" >/dev/null || { + sed -e 's/^/ERROR: /' <"$L_OUTPUT_FILE" >"$L_TMP_ID_FILE" + cat >/dev/null #consume the other keys, causing loop to end + } + fi + + cat "$L_TMP_ID_FILE" + done +} + # populate_new_ids() uses several global variables ($USER_HOST, $SSH_OPTS ...) # and has the side effect of setting $NEW_IDS populate_new_ids() { - local L_SUCCESS="$1" - if [ "$FORCED" ] ; then + # shellcheck disable=SC2086 NEW_IDS=$(eval $GET_ID) return fi - # repopulate "$@" inside this function - eval set -- "$SSH_OPTS" - - umask 0177 - local L_TMP_ID_FILE=$(mktemp ~/.ssh/ssh-copy-id_id.XXXXXXXXXX) - if test $? -ne 0 || test "x$L_TMP_ID_FILE" = "x" ; then - printf '%s: ERROR: mktemp failed\n' "$0" >&2 - exit 1 - fi - local L_CLEANUP="rm -f \"$L_TMP_ID_FILE\" \"${L_TMP_ID_FILE}.stderr\"" - trap "$L_CLEANUP" EXIT TERM INT QUIT printf '%s: INFO: attempting to log in with the new key(s), to filter out any that are already installed\n' "$0" >&2 - NEW_IDS=$( - eval $GET_ID | { - while read ID || [ "$ID" ] ; do - printf '%s\n' "$ID" > "$L_TMP_ID_FILE" - - # the next line assumes $PRIV_ID_FILE only set if using a single id file - this - # assumption will break if we implement the possibility of multiple -i options. - # The point being that if file based, ssh needs the private key, which it cannot - # find if only given the contents of the .pub file in an unrelated tmpfile - ssh -i "${PRIV_ID_FILE:-$L_TMP_ID_FILE}" \ - -o ControlPath=none \ - -o LogLevel=INFO \ - -o PreferredAuthentications=publickey \ - -o IdentitiesOnly=yes "$@" exit 2>"$L_TMP_ID_FILE.stderr" "$L_TMP_ID_FILE" - else - grep 'Permission denied' "$L_TMP_ID_FILE.stderr" >/dev/null || { - sed -e 's/^/ERROR: /' <"$L_TMP_ID_FILE.stderr" >"$L_TMP_ID_FILE" - cat >/dev/null #consume the other keys, causing loop to end - } - fi - - cat "$L_TMP_ID_FILE" - done - } - ) - eval "$L_CLEANUP" && trap - EXIT TERM INT QUIT + # shellcheck disable=SC2086 + NEW_IDS=$(eval $GET_ID | filter_ids $1) if expr "$NEW_IDS" : "^ERROR: " >/dev/null ; then printf '\n%s: %s\n\n' "$0" "$NEW_IDS" >&2 @@ -261,43 +227,130 @@ populate_new_ids() { fi if [ -z "$NEW_IDS" ] ; then printf '\n%s: WARNING: All keys were skipped because they already exist on the remote system.\n' "$0" >&2 - printf '\t\t(if you think this is a mistake, you may want to use -f option)\n\n' "$0" >&2 + printf '\t\t(if you think this is a mistake, you may want to use -f option)\n\n' >&2 exit 0 fi printf '%s: INFO: %d key(s) remain to be installed -- if you are prompted now it is to install the new keys\n' "$0" "$(printf '%s\n' "$NEW_IDS" | wc -l)" >&2 } -REMOTE_VERSION=$(ssh -v -o PreferredAuthentications=',' -o ControlPath=none "$@" 2>&1 | +# installkey_sh [target_path] +# produce a one-liner to add the keys to remote authorized_keys file +# optionally takes an alternative path for authorized_keys +installkeys_sh() { + AUTH_KEY_FILE=${1:-.ssh/authorized_keys} + AUTH_KEY_DIR=$(dirname "${AUTH_KEY_FILE}") + + # In setting INSTALLKEYS_SH: + # the tr puts it all on one line (to placate tcsh) + # (hence the excessive use of semi-colons (;) ) + # then in the command: + # cd to be at $HOME, just in case; + # the -z `tail ...` checks for a trailing newline. The echo adds one if was missing + # the cat adds the keys we're getting via STDIN + # and if available restorecon is used to restore the SELinux context + INSTALLKEYS_SH=$(tr '\t\n' ' ' <<-EOF + cd; + umask 077; + mkdir -p "${AUTH_KEY_DIR}" && + { [ -z \`tail -1c ${AUTH_KEY_FILE} 2>/dev/null\` ] || + echo >> "${AUTH_KEY_FILE}" || exit 1; } && + cat >> "${AUTH_KEY_FILE}" || exit 1; + if type restorecon >/dev/null 2>&1; then + restorecon -F "${AUTH_KEY_DIR}" "${AUTH_KEY_FILE}"; + fi + EOF + ) + + # to defend against quirky remote shells: use 'exec sh -c' to get POSIX; + printf "exec sh -c '%s'" "${INSTALLKEYS_SH}" +} + +#shellcheck disable=SC2120 # the 'eval set' confuses this +installkeys_via_sftp() { + + # repopulate "$@" inside this function + eval set -- "$SSH_OPTS" + + L_KEYS=$SCRATCH_DIR/authorized_keys + L_SHARED_CON=$SCRATCH_DIR/master-conn + $SSH -f -N -M -S "$L_SHARED_CON" "$@" + L_CLEANUP="$SSH -S $L_SHARED_CON -O exit 'ignored' >/dev/null 2>&1 ; $SCRATCH_CLEANUP" + #shellcheck disable=SC2064 + trap "$L_CLEANUP" EXIT TERM INT QUIT + sftp -b - -o "ControlPath=$L_SHARED_CON" "ignored" <<-EOF || return 1 + -get .ssh/authorized_keys $L_KEYS + EOF + # add a newline or create file if it's missing, same like above + [ -z "$(tail -1c "$L_KEYS" 2>/dev/null)" ] || echo >> "$L_KEYS" + # append the keys being piped in here + cat >> "$L_KEYS" + sftp -b - -o "ControlPath=$L_SHARED_CON" "ignored" <<-EOF || return 1 + -mkdir .ssh + chmod 700 .ssh + put $L_KEYS .ssh/authorized_keys + chmod 600 .ssh/authorized_keys + EOF + #shellcheck disable=SC2064 + eval "$L_CLEANUP" && trap "$SCRATCH_CLEANUP" EXIT TERM INT QUIT +} + + +# create a scratch dir for any temporary files needed +if SCRATCH_DIR=$(mktemp -d ~/.ssh/ssh-copy-id.XXXXXXXXXX) && + [ "$SCRATCH_DIR" ] && [ -d "$SCRATCH_DIR" ] +then + chmod 0700 "$SCRATCH_DIR" + SCRATCH_CLEANUP="rm -rf \"$SCRATCH_DIR\"" + #shellcheck disable=SC2064 + trap "$SCRATCH_CLEANUP" EXIT TERM INT QUIT +else + printf '%s: ERROR: failed to create required temporary directory under ~/.ssh\n' "$0" >&2 + exit 1 +fi + +REMOTE_VERSION=$($SSH -v -o PreferredAuthentications=',' -o ControlPath=none "$@" 2>&1 | sed -ne 's/.*remote software version //p') +# shellcheck disable=SC2029 case "$REMOTE_VERSION" in NetScreen*) populate_new_ids 1 for KEY in $(printf "%s" "$NEW_IDS" | cut -d' ' -f2) ; do - KEY_NO=$(($KEY_NO + 1)) - printf "%s\n" "$KEY" | grep ssh-dss >/dev/null || { + KEY_NO=$((KEY_NO + 1)) + printf '%s\n' "$KEY" | grep ssh-dss >/dev/null || { printf '%s: WARNING: Non-dsa key (#%d) skipped (NetScreen only supports DSA keys)\n' "$0" "$KEY_NO" >&2 continue } - [ "$DRY_RUN" ] || printf 'set ssh pka-dsa key %s\nsave\nexit\n' "$KEY" | ssh -T "$@" >/dev/null 2>&1 + [ "$DRY_RUN" ] || printf 'set ssh pka-dsa key %s\nsave\nexit\n' "$KEY" | $SSH -T "$@" >/dev/null 2>&1 if [ $? = 255 ] ; then printf '%s: ERROR: installation of key #%d failed (please report a bug describing what caused this, so that we can make this message useful)\n' "$0" "$KEY_NO" >&2 else - ADDED=$(($ADDED + 1)) + ADDED=$((ADDED + 1)) fi done if [ -z "$ADDED" ] ; then exit 1 fi ;; + dropbear*) + populate_new_ids 0 + [ "$DRY_RUN" ] || printf '%s\n' "$NEW_IDS" | \ + $SSH "$@" "$(installkeys_sh /etc/dropbear/authorized_keys)" \ + || exit 1 + ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l) + ;; *) # Assuming that the remote host treats ~/.ssh/authorized_keys as one might expect populate_new_ids 0 - # in ssh below - to defend against quirky remote shells: use 'exec sh -c' to get POSIX; - # 'cd' to be at $HOME; add a newline if it's missing; and all on one line, because tcsh. - [ "$DRY_RUN" ] || printf '%s\n' "$NEW_IDS" | \ - ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && { [ -z "'`tail -1c .ssh/authorized_keys 2>/dev/null`'" ] || echo >> .ssh/authorized_keys ; } && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \ - || exit 1 + if ! [ "$DRY_RUN" ] ; then + printf '%s\n' "$NEW_IDS" | \ + if [ "$SFTP" ] ; then + #shellcheck disable=SC2119 + installkeys_via_sftp + else + $SSH "$@" "$(installkeys_sh)" + fi || exit 1 + fi ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l) ;; esac @@ -315,7 +368,7 @@ else Number of key(s) added: $ADDED - Now try logging into the machine, with: "ssh $SSH_OPTS" + Now try logging into the machine, with: "${SFTP:-ssh} $SSH_OPTS" and check to make sure that only the key(s) you wanted were added. EOF diff --git a/contrib/ssh-copy-id.1 b/contrib/ssh-copy-id.1 index 8850cceda..c141a296f 100644 --- a/contrib/ssh-copy-id.1 +++ b/contrib/ssh-copy-id.1 @@ -1,5 +1,5 @@ .ig \" -*- nroff -*- -Copyright (c) 1999-2013 hands.com Ltd. +Copyright (c) 1999-2020 hands.com Ltd. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -31,6 +31,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .Nm .Op Fl f .Op Fl n +.Op Fl s .Op Fl i Op Ar identity_file .Op Fl p Ar port .Op Fl o Ar ssh_option @@ -84,6 +85,12 @@ in more than one copy of the key being installed on the remote system. .It Fl n do a dry-run. Instead of installing keys on the remote system simply prints the key(s) that would have been installed. +.It Fl s +SFTP mode: usually the public keys are installed by executing commands on the remote side. +With this option the user's +.Pa ~/.ssh/authorized_keys +file will be downloaded, modified locally and uploaded with sftp. +This option is useful if the server has restrictions on commands which can be used on the remote side. .It Fl h , Fl ? Print Usage summary .It Fl p Ar port , Fl o Ar ssh_option @@ -158,7 +165,7 @@ asked for confirmation, which is your cue to log back out and run The reason you might want to specify the -i option in this case is to ensure that the comment on the installed key is the one from the .Pa .pub -file, rather than just the filename that was loaded into you agent. +file, rather than just the filename that was loaded into your agent. It also ensures that only the id you intended is installed, rather than all the keys that you have in your .Xr ssh-agent 1 . diff --git a/contrib/suse/openssh.spec b/contrib/suse/openssh.spec index 8c081acc0..fe950303e 100644 --- a/contrib/suse/openssh.spec +++ b/contrib/suse/openssh.spec @@ -13,7 +13,7 @@ Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation Name: openssh -Version: 8.1p1 +Version: 8.5p1 URL: https://www.openssh.com/ Release: 1 Source0: openssh-%{version}.tar.gz @@ -75,6 +75,8 @@ patented algorithms to separate libraries (OpenSSL). This package contains an X Window System passphrase dialog for OpenSSH. %changelog +* Mon Jul 20 2020 Damien Miller +- Add ssh-sk-helper and corresponding manual page. * Wed Oct 26 2005 Iain Morgan - Removed accidental inclusion of --without-zlib-version-check * Tue Oct 25 2005 Iain Morgan @@ -211,6 +213,7 @@ rm -rf $RPM_BUILD_ROOT %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(0755,root,root) %{_libdir}/ssh/ssh-sk-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* @@ -224,6 +227,7 @@ rm -rf $RPM_BUILD_ROOT %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/ssh-sk-helper.8* %attr(0644,root,root) %doc %{_mandir}/man8/sshd.8* %attr(0644,root,root) /var/adm/fillup-templates/sysconfig.ssh diff --git a/crypto_api.h b/crypto_api.h index eb05251ff..5c3d97eaa 100644 --- a/crypto_api.h +++ b/crypto_api.h @@ -1,4 +1,4 @@ -/* $OpenBSD: crypto_api.h,v 1.5 2019/01/21 10:20:12 djm Exp $ */ +/* $OpenBSD: crypto_api.h,v 1.7 2021/01/08 02:33:13 dtucker Exp $ */ /* * Assembled from generated headers and source files by Markus Friedl. @@ -21,6 +21,8 @@ typedef int16_t crypto_int16; typedef uint16_t crypto_uint16; typedef int32_t crypto_int32; typedef uint32_t crypto_uint32; +typedef int64_t crypto_int64; +typedef uint64_t crypto_uint64; #define randombytes(buf, buf_len) arc4random_buf((buf), (buf_len)) #define small_random32() arc4random() @@ -42,15 +44,15 @@ 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 +#define crypto_kem_sntrup761_PUBLICKEYBYTES 1158 +#define crypto_kem_sntrup761_SECRETKEYBYTES 1763 +#define crypto_kem_sntrup761_CIPHERTEXTBYTES 1039 +#define crypto_kem_sntrup761_BYTES 32 -int crypto_kem_sntrup4591761_enc(unsigned char *cstr, unsigned char *k, +int crypto_kem_sntrup761_enc(unsigned char *cstr, unsigned char *k, const unsigned char *pk); -int crypto_kem_sntrup4591761_dec(unsigned char *k, +int crypto_kem_sntrup761_dec(unsigned char *k, const unsigned char *cstr, const unsigned char *sk); -int crypto_kem_sntrup4591761_keypair(unsigned char *pk, unsigned char *sk); +int crypto_kem_sntrup761_keypair(unsigned char *pk, unsigned char *sk); #endif /* crypto_api_h */ diff --git a/defines.h b/defines.h index 7855fbf90..d6a1d014c 100644 --- a/defines.h +++ b/defines.h @@ -96,6 +96,9 @@ enum #ifndef IPTOS_DSCP_EF # define IPTOS_DSCP_EF 0xb8 #endif /* IPTOS_DSCP_EF */ +#ifndef IPTOS_DSCP_LE +# define IPTOS_DSCP_LE 0x01 +#endif /* IPTOS_DSCP_LE */ #ifndef IPTOS_PREC_CRITIC_ECP # define IPTOS_PREC_CRITIC_ECP 0xa0 #endif @@ -251,6 +254,21 @@ typedef unsigned int u_int32_t; #define __BIT_TYPES_DEFINED__ #endif +#if !defined(LLONG_MIN) && defined(LONG_LONG_MIN) +#define LLONG_MIN LONG_LONG_MIN +#endif +#if !defined(LLONG_MAX) && defined(LONG_LONG_MAX) +#define LLONG_MAX LONG_LONG_MAX +#endif + +#ifndef UINT32_MAX +# if defined(HAVE_DECL_UINT32_MAX) && (HAVE_DECL_UINT32_MAX == 0) +# if (SIZEOF_INT == 4) +# define UINT32_MAX UINT_MAX +# endif +# endif +#endif + /* 64-bit types */ #ifndef HAVE_INT64_T # if (SIZEOF_LONG_INT == 8) @@ -333,6 +351,7 @@ typedef unsigned int size_t; #ifndef HAVE_SSIZE_T typedef int ssize_t; +#define SSIZE_MAX INT_MAX # define HAVE_SSIZE_T #endif /* HAVE_SSIZE_T */ @@ -810,10 +829,6 @@ struct winsize { # define getgroups(a,b) ((a)==0 && (b)==NULL ? NGROUPS_MAX : getgroups((a),(b))) #endif -#if defined(HAVE_MMAP) && defined(BROKEN_MMAP) -# undef HAVE_MMAP -#endif - #ifndef IOV_MAX # if defined(_XOPEN_IOV_MAX) # define IOV_MAX _XOPEN_IOV_MAX @@ -879,4 +894,11 @@ struct winsize { # define USE_SYSTEM_GLOB #endif +/* + * sntrup761 uses variable length arrays, only enable if the compiler + * supports them. + */ +#ifdef VARIABLE_LENGTH_ARRAYS +# define USE_SNTRUP761X25519 1 +#endif #endif /* _DEFINES_H */ diff --git a/dh.c b/dh.c index f68050275..89532fb2e 100644 --- a/dh.c +++ b/dh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dh.c,v 1.71 2019/09/06 06:08:11 djm Exp $ */ +/* $OpenBSD: dh.c,v 1.72 2020/10/18 11:32:01 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * @@ -284,7 +284,7 @@ dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub) } if ((tmp = BN_new()) == NULL) { - error("%s: BN_new failed", __func__); + error_f("BN_new failed"); return 0; } if (!BN_sub(tmp, dh_p, BN_value_one()) || @@ -502,7 +502,7 @@ dh_new_group18(void) DH * dh_new_group_fallback(int max) { - debug3("%s: requested max size %d", __func__, max); + debug3_f("requested max size %d", max); if (max < 3072) { debug3("using 2k bit group 14"); return dh_new_group14(); diff --git a/digest-libc.c b/digest-libc.c index 12737e5d5..86a1dbf29 100644 --- a/digest-libc.c +++ b/digest-libc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: digest-libc.c,v 1.6 2017/05/08 22:57:38 djm Exp $ */ +/* $OpenBSD: digest-libc.c,v 1.7 2020/02/26 13:40:09 jsg Exp $ */ /* * Copyright (c) 2013 Damien Miller * Copyright (c) 2014 Markus Friedl. All rights reserved. @@ -230,8 +230,7 @@ ssh_digest_free(struct ssh_digest_ctx *ctx) if (digest) { explicit_bzero(ctx->mdctx, digest->ctx_len); free(ctx->mdctx); - explicit_bzero(ctx, sizeof(*ctx)); - free(ctx); + freezero(ctx, sizeof(*ctx)); } } } diff --git a/digest-openssl.c b/digest-openssl.c index 11efbf7c0..e073a807b 100644 --- a/digest-openssl.c +++ b/digest-openssl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: digest-openssl.c,v 1.7 2017/05/08 22:57:38 djm Exp $ */ +/* $OpenBSD: digest-openssl.c,v 1.9 2020/10/29 02:52:43 djm Exp $ */ /* * Copyright (c) 2013 Damien Miller * @@ -32,9 +32,6 @@ #include "digest.h" #include "ssherr.h" -#ifndef HAVE_EVP_RIPEMD160 -# define EVP_ripemd160 NULL -#endif #ifndef HAVE_EVP_SHA256 # define EVP_sha256 NULL #endif @@ -59,11 +56,11 @@ struct ssh_digest { /* NB. Indexed directly by algorithm number */ const struct ssh_digest digests[] = { - { SSH_DIGEST_MD5, "MD5", 16, EVP_md5 }, - { SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 }, - { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 }, + { SSH_DIGEST_MD5, "MD5", 16, EVP_md5 }, + { SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 }, + { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 }, { SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 }, - { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 }, + { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 }, { -1, NULL, 0, NULL }, }; diff --git a/dns.c b/dns.c index e4f9bf830..91c6e9f04 100644 --- a/dns.c +++ b/dns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dns.c,v 1.38 2018/02/23 15:58:37 markus Exp $ */ +/* $OpenBSD: dns.c,v 1.39 2020/10/18 11:32:01 djm Exp $ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. @@ -128,8 +128,7 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, if (*algorithm && *digest_type) { if ((r = sshkey_fingerprint_raw(key, fp_alg, digest, digest_len)) != 0) - fatal("%s: sshkey_fingerprint_raw: %s", __func__, - ssh_err(r)); + fatal_fr(r, "sshkey_fingerprint_raw"); success = 1; } else { *digest = NULL; @@ -348,7 +347,7 @@ export_dns_rr(const char *hostname, struct sshkey *key, FILE *f, int generic) /* No SSHFP record was generated at all */ if (success == 0) { - error("%s: unsupported algorithm and/or digest_type", __func__); + error_f("unsupported algorithm and/or digest_type"); } return success; diff --git a/entropy.c b/entropy.c index 5de68016b..19ddeeafa 100644 --- a/entropy.c +++ b/entropy.c @@ -84,7 +84,7 @@ get_random_bytes_prngd(unsigned char *buf, int len, 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; + sshsig_t old_sigpipe; /* Sanity checks */ if (socket_path == NULL && tcp_port == 0) @@ -110,7 +110,7 @@ get_random_bytes_prngd(unsigned char *buf, int len, strlen(socket_path) + 1; } - old_sigpipe = signal(SIGPIPE, SIG_IGN); + old_sigpipe = ssh_signal(SIGPIPE, SIG_IGN); errors = 0; rval = -1; @@ -160,7 +160,7 @@ reopen: rval = 0; done: - signal(SIGPIPE, old_sigpipe); + ssh_signal(SIGPIPE, old_sigpipe); if (fd != -1) close(fd); return rval; diff --git a/fatal.c b/fatal.c index 5e5aa3fe1..16fbd3204 100644 --- a/fatal.c +++ b/fatal.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fatal.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */ +/* $OpenBSD: fatal.c,v 1.11 2020/10/19 08:07:08 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * @@ -34,12 +34,13 @@ /* Fatal messages. This function never returns. */ void -fatal(const char *fmt,...) +sshfatal(const char *file, const char *func, int line, int showfunc, + LogLevel level, const char *suffix, const char *fmt, ...) { va_list args; va_start(args, fmt); - do_log(SYSLOG_LEVEL_FATAL, fmt, args); + sshlogv(file, func, line, showfunc, level, suffix, fmt, args); va_end(args); cleanup_exit(255); } diff --git a/gss-genr.c b/gss-genr.c index d56257b4a..685280517 100644 --- a/gss-genr.c +++ b/gss-genr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gss-genr.c,v 1.26 2018/07/10 09:13:30 djm Exp $ */ +/* $OpenBSD: gss-genr.c,v 1.28 2021/01/27 10:05:28 djm Exp $ */ /* * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. @@ -44,9 +44,6 @@ #include "ssh-gss.h" -extern u_char *session_id2; -extern u_int session_id2_len; - /* sshbuf_get for gss_buffer_desc */ int ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) @@ -115,7 +112,7 @@ ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status, int r; if ((b = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if (major_status != NULL) *major_status = ctxt->major; @@ -130,7 +127,7 @@ ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status, if ((r = sshbuf_put(b, msg.value, msg.length)) != 0 || (r = sshbuf_put_u8(b, '\n')) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble GSS_CODE"); gss_release_buffer(&lmin, &msg); } while (ctx != 0); @@ -142,13 +139,13 @@ ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status, if ((r = sshbuf_put(b, msg.value, msg.length)) != 0 || (r = sshbuf_put_u8(b, '\n')) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble MECH_CODE"); gss_release_buffer(&lmin, &msg); } while (ctx != 0); if ((r = sshbuf_put_u8(b, '\n')) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble newline"); ret = xstrdup((const char *)sshbuf_ptr(b)); sshbuf_free(b); return (ret); @@ -259,17 +256,17 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) void ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, - const char *context) + const char *context, const struct sshbuf *session_id) { int r; sshbuf_reset(b); - if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 || + if ((r = sshbuf_put_stringb(b, session_id)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshbuf_put_cstring(b, user)) != 0 || (r = sshbuf_put_cstring(b, service)) != 0 || (r = sshbuf_put_cstring(b, context)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble buildmic"); } int diff --git a/gss-serv.c b/gss-serv.c index a4d8b9a09..8774ca3c6 100644 --- a/gss-serv.c +++ b/gss-serv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gss-serv.c,v 1.31 2018/07/09 21:37:55 markus Exp $ */ +/* $OpenBSD: gss-serv.c,v 1.32 2020/03/13 03:17:07 djm Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. @@ -337,7 +337,7 @@ ssh_gssapi_storecreds(void) debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism"); } -/* This allows GSSAPI methods to do things to the childs environment based +/* This allows GSSAPI methods to do things to the child's environment based * on the passed authentication process and credentials. */ /* As user */ diff --git a/hash.c b/hash.c index 5875d41fa..fb81e4786 100644 --- a/hash.c +++ b/hash.c @@ -1,27 +1,45 @@ /* $OpenBSD: hash.c,v 1.4 2017/12/14 21:07:39 naddy Exp $ */ -/* $OpenBSD: hash.c,v 1.5 2018/01/13 00:24:09 naddy Exp $ */ +/* $OpenBSD: hash.c,v 1.6 2019/11/29 00:11:21 djm Exp $ */ /* * Public domain. Author: Christian Weisgerber * API compatible reimplementation of function from nacl */ +#include "includes.h" + #include "crypto_api.h" #include -#include "digest.h" -#include "log.h" -#include "ssherr.h" +#ifdef WITH_OPENSSL +#include int crypto_hash_sha512(unsigned char *out, const unsigned char *in, unsigned long long inlen) { - int r; - if ((r = ssh_digest_memory(SSH_DIGEST_SHA512, in, inlen, out, - crypto_hash_sha512_BYTES)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + if (!EVP_Digest(in, inlen, out, NULL, EVP_sha512(), NULL)) + return -1; return 0; } + +#else +# ifdef HAVE_SHA2_H +# include +# endif + +int +crypto_hash_sha512(unsigned char *out, const unsigned char *in, + unsigned long long inlen) +{ + + SHA2_CTX ctx; + + SHA512Init(&ctx); + SHA512Update(&ctx, in, inlen); + SHA512Final(out, &ctx); + return 0; +} +#endif /* WITH_OPENSSL */ diff --git a/hmac.c b/hmac.c index 32688876d..7b588019e 100644 --- a/hmac.c +++ b/hmac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hmac.c,v 1.13 2019/09/06 04:53:27 djm Exp $ */ +/* $OpenBSD: hmac.c,v 1.14 2020/02/26 13:40:09 jsg Exp $ */ /* * Copyright (c) 2014 Markus Friedl. All rights reserved. * @@ -131,8 +131,7 @@ ssh_hmac_free(struct ssh_hmac_ctx *ctx) explicit_bzero(ctx->buf, ctx->buf_len); free(ctx->buf); } - explicit_bzero(ctx, sizeof(*ctx)); - free(ctx); + freezero(ctx, sizeof(*ctx)); } } diff --git a/hostfile.c b/hostfile.c index 96ab880d4..f5d3dde9b 100644 --- a/hostfile.c +++ b/hostfile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hostfile.c,v 1.76 2019/07/07 01:05:00 dtucker Exp $ */ +/* $OpenBSD: hostfile.c,v 1.89 2021/01/26 00:51:30 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -57,14 +57,11 @@ #include "hostfile.h" #include "log.h" #include "misc.h" +#include "pathnames.h" #include "ssherr.h" #include "digest.h" #include "hmac.h" - -struct hostkeys { - struct hostkey_entry *entries; - u_int num_entries; -}; +#include "sshbuf.h" /* XXX hmac is too easy to dictionary attack; use bcrypt? */ @@ -140,12 +137,12 @@ host_hash(const char *host, const char *name_from_hostfile, u_int src_len) ssh_hmac_init(ctx, salt, len) < 0 || ssh_hmac_update(ctx, host, strlen(host)) < 0 || ssh_hmac_final(ctx, result, sizeof(result))) - fatal("%s: ssh_hmac failed", __func__); + fatal_f("ssh_hmac failed"); ssh_hmac_free(ctx); if (__b64_ntop(salt, len, uu_salt, sizeof(uu_salt)) == -1 || __b64_ntop(result, len, uu_result, sizeof(uu_result)) == -1) - fatal("%s: __b64_ntop failed", __func__); + fatal_f("__b64_ntop failed"); snprintf(encoded, sizeof(encoded), "%s%s%c%s", HASH_MAGIC, uu_salt, HASH_DELIM, uu_result); @@ -245,7 +242,7 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx) return 0; } - debug3("%s: found %skey type %s in file %s:%lu", __func__, + debug3_f("found %skey type %s in file %s:%lu", l->marker == MRK_NONE ? "" : (l->marker == MRK_CA ? "ca " : "revoked "), sshkey_type(l->key), l->path, l->linenum); @@ -259,6 +256,7 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx) hostkeys->entries[hostkeys->num_entries].key = l->key; l->key = NULL; /* steal it */ hostkeys->entries[hostkeys->num_entries].marker = l->marker; + hostkeys->entries[hostkeys->num_entries].note = l->note; hostkeys->num_entries++; ctx->num_loaded++; @@ -266,7 +264,8 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx) } void -load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path) +load_hostkeys_file(struct hostkeys *hostkeys, const char *host, + const char *path, FILE *f, u_int note) { int r; struct load_callback_ctx ctx; @@ -275,15 +274,28 @@ load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path) ctx.num_loaded = 0; ctx.hostkeys = hostkeys; - if ((r = hostkeys_foreach(path, record_hostkey, &ctx, host, NULL, - HKF_WANT_MATCH|HKF_WANT_PARSE_KEY)) != 0) { + if ((r = hostkeys_foreach_file(path, f, record_hostkey, &ctx, host, + NULL, HKF_WANT_MATCH|HKF_WANT_PARSE_KEY, note)) != 0) { if (r != SSH_ERR_SYSTEM_ERROR && errno != ENOENT) - debug("%s: hostkeys_foreach failed for %s: %s", - __func__, path, ssh_err(r)); + debug_fr(r, "hostkeys_foreach failed for %s", path); } if (ctx.num_loaded != 0) - debug3("%s: loaded %lu keys from %s", __func__, - ctx.num_loaded, host); + debug3_f("loaded %lu keys from %s", ctx.num_loaded, host); +} + +void +load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path, + u_int note) +{ + FILE *f; + + if ((f = fopen(path, "r")) == NULL) { + debug_f("fopen %s: %s", path, strerror(errno)); + return; + } + + load_hostkeys_file(hostkeys, host, path, f, note); + fclose(f); } void @@ -298,8 +310,7 @@ free_hostkeys(struct hostkeys *hostkeys) explicit_bzero(hostkeys->entries + i, sizeof(*hostkeys->entries)); } free(hostkeys->entries); - explicit_bzero(hostkeys, sizeof(*hostkeys)); - free(hostkeys); + freezero(hostkeys, sizeof(*hostkeys)); } static int @@ -313,7 +324,7 @@ check_key_not_revoked(struct hostkeys *hostkeys, struct sshkey *k) continue; if (sshkey_equal_public(k, hostkeys->entries[i].key)) return -1; - if (is_cert && + if (is_cert && k != NULL && sshkey_equal_public(k->cert->signature_key, hostkeys->entries[i].key)) return -1; @@ -338,7 +349,7 @@ check_key_not_revoked(struct hostkeys *hostkeys, struct sshkey *k) */ static HostStatus check_hostkeys_by_key_or_type(struct hostkeys *hostkeys, - struct sshkey *k, int keytype, const struct hostkey_entry **found) + struct sshkey *k, int keytype, int nid, const struct hostkey_entry **found) { u_int i; HostStatus end_return = HOST_NEW; @@ -354,6 +365,10 @@ check_hostkeys_by_key_or_type(struct hostkeys *hostkeys, if (k == NULL) { if (hostkeys->entries[i].key->type != keytype) continue; + if (nid != -1 && + sshkey_type_plain(keytype) == KEY_ECDSA && + hostkeys->entries[i].key->ecdsa_nid != nid) + continue; end_return = HOST_FOUND; if (found != NULL) *found = hostkeys->entries + i; @@ -396,17 +411,29 @@ check_key_in_hostkeys(struct hostkeys *hostkeys, struct sshkey *key, { if (key == NULL) fatal("no key to look up"); - return check_hostkeys_by_key_or_type(hostkeys, key, 0, found); + return check_hostkeys_by_key_or_type(hostkeys, key, 0, -1, found); } int -lookup_key_in_hostkeys_by_type(struct hostkeys *hostkeys, int keytype, +lookup_key_in_hostkeys_by_type(struct hostkeys *hostkeys, int keytype, int nid, const struct hostkey_entry **found) { - return (check_hostkeys_by_key_or_type(hostkeys, NULL, keytype, + return (check_hostkeys_by_key_or_type(hostkeys, NULL, keytype, nid, found) == HOST_FOUND); } +int +lookup_marker_in_hostkeys(struct hostkeys *hostkeys, int want_marker) +{ + u_int i; + + for (i = 0; i < hostkeys->num_entries; i++) { + if (hostkeys->entries[i].marker == (HostkeyMarker)want_marker) + return 1; + } + return 0; +} + static int write_host_entry(FILE *f, const char *host, const char *ip, const struct sshkey *key, int store_hash) @@ -419,7 +446,7 @@ write_host_entry(FILE *f, const char *host, const char *ip, if (store_hash) { if ((hashed_host = host_hash(lhost, NULL, 0)) == NULL) { - error("%s: host_hash failed", __func__); + error_f("host_hash failed"); free(lhost); return 0; } @@ -433,11 +460,52 @@ write_host_entry(FILE *f, const char *host, const char *ip, if ((r = sshkey_write(key, f)) == 0) success = 1; else - error("%s: sshkey_write failed: %s", __func__, ssh_err(r)); + error_fr(r, "sshkey_write"); fputc('\n', f); + /* If hashing is enabled, the IP address needs to go on its own line */ + if (success && store_hash && ip != NULL) + success = write_host_entry(f, ip, NULL, key, 1); return success; } +/* + * Create user ~/.ssh directory if it doesn't exist and we want to write to it. + * If notify is set, a message will be emitted if the directory is created. + */ +void +hostfile_create_user_ssh_dir(const char *filename, int notify) +{ + char *dotsshdir = NULL, *p; + size_t len; + struct stat st; + + if ((p = strrchr(filename, '/')) == NULL) + return; + len = p - filename; + dotsshdir = tilde_expand_filename("~/" _PATH_SSH_USER_DIR, getuid()); + if (strlen(dotsshdir) > len || strncmp(filename, dotsshdir, len) != 0) + goto out; /* not ~/.ssh prefixed */ + if (stat(dotsshdir, &st) == 0) + goto out; /* dir already exists */ + else if (errno != ENOENT) + error("Could not stat %s: %s", dotsshdir, strerror(errno)); + else { +#ifdef WITH_SELINUX + ssh_selinux_setfscreatecon(dotsshdir); +#endif + if (mkdir(dotsshdir, 0700) == -1) + error("Could not create directory '%.200s' (%s).", + dotsshdir, strerror(errno)); + else if (notify) + logit("Created directory '%s'.", dotsshdir); +#ifdef WITH_SELINUX + ssh_selinux_setfscreatecon(NULL); +#endif + } + out: + free(dotsshdir); +} + /* * Appends an entry to the host file. Returns false if the entry could not * be appended. @@ -451,6 +519,7 @@ add_host_to_hostfile(const char *filename, const char *host, if (key == NULL) return 1; /* XXX ? */ + hostfile_create_user_ssh_dir(filename, 0); f = fopen(filename, "a"); if (!f) return 0; @@ -462,8 +531,8 @@ add_host_to_hostfile(const char *filename, const char *host, struct host_delete_ctx { FILE *out; int quiet; - const char *host; - int *skip_keys; /* XXX split for host/ip? might want to ensure both */ + const char *host, *ip; + u_int *match_keys; /* mask of HKF_MATCH_* for this key */ struct sshkey * const *keys; size_t nkeys; int modified; @@ -476,26 +545,21 @@ host_delete(struct hostkey_foreach_line *l, void *_ctx) int loglevel = ctx->quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_VERBOSE; size_t i; - if (l->status == HKF_STATUS_MATCHED) { - if (l->marker != MRK_NONE) { - /* Don't remove CA and revocation lines */ - fprintf(ctx->out, "%s\n", l->line); - return 0; - } - + /* Don't remove CA and revocation lines */ + if (l->status == HKF_STATUS_MATCHED && l->marker == MRK_NONE) { /* * If this line contains one of the keys that we will be * adding later, then don't change it and mark the key for * skipping. */ for (i = 0; i < ctx->nkeys; i++) { - if (sshkey_equal(ctx->keys[i], l->key)) { - ctx->skip_keys[i] = 1; - fprintf(ctx->out, "%s\n", l->line); - debug3("%s: %s key already at %s:%ld", __func__, - sshkey_type(l->key), l->path, l->linenum); - return 0; - } + if (!sshkey_equal(ctx->keys[i], l->key)) + continue; + ctx->match_keys[i] |= l->match; + fprintf(ctx->out, "%s\n", l->line); + debug3_f("%s key already at %s:%ld", + sshkey_type(l->key), l->path, l->linenum); + return 0; } /* @@ -526,15 +590,19 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip, int loglevel = quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_VERBOSE; struct host_delete_ctx ctx; char *fp, *temp = NULL, *back = NULL; + const char *what; mode_t omask; size_t i; + u_int want; omask = umask(077); memset(&ctx, 0, sizeof(ctx)); ctx.host = host; + ctx.ip = ip; ctx.quiet = quiet; - if ((ctx.skip_keys = calloc(nkeys, sizeof(*ctx.skip_keys))) == NULL) + + if ((ctx.match_keys = calloc(nkeys, sizeof(*ctx.match_keys))) == NULL) return SSH_ERR_ALLOC_FAIL; ctx.keys = keys; ctx.nkeys = nkeys; @@ -551,42 +619,65 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip, if ((fd = mkstemp(temp)) == -1) { oerrno = errno; - error("%s: mkstemp: %s", __func__, strerror(oerrno)); + error_f("mkstemp: %s", strerror(oerrno)); r = SSH_ERR_SYSTEM_ERROR; goto fail; } if ((ctx.out = fdopen(fd, "w")) == NULL) { oerrno = errno; close(fd); - error("%s: fdopen: %s", __func__, strerror(oerrno)); + error_f("fdopen: %s", strerror(oerrno)); r = SSH_ERR_SYSTEM_ERROR; goto fail; } - /* Remove all entries for the specified host from the file */ + /* Remove stale/mismatching entries for the specified host */ if ((r = hostkeys_foreach(filename, host_delete, &ctx, host, ip, - HKF_WANT_PARSE_KEY)) != 0) { - error("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r)); + HKF_WANT_PARSE_KEY, 0)) != 0) { + oerrno = errno; + error_fr(r, "hostkeys_foreach"); goto fail; } - /* Add the requested keys */ + /* Re-add the requested keys */ + want = HKF_MATCH_HOST | (ip == NULL ? 0 : HKF_MATCH_IP); for (i = 0; i < nkeys; i++) { - if (ctx.skip_keys[i]) + if ((want & ctx.match_keys[i]) == want) continue; if ((fp = sshkey_fingerprint(keys[i], hash_alg, SSH_FP_DEFAULT)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } - do_log2(loglevel, "%s%sAdding new key for %s to %s: %s %s", - quiet ? __func__ : "", quiet ? ": " : "", host, filename, + /* write host/ip */ + what = ""; + if (ctx.match_keys[i] == 0) { + what = "Adding new key"; + if (!write_host_entry(ctx.out, host, ip, + keys[i], store_hash)) { + r = SSH_ERR_INTERNAL_ERROR; + goto fail; + } + } else if ((want & ~ctx.match_keys[i]) == HKF_MATCH_HOST) { + what = "Fixing match (hostname)"; + if (!write_host_entry(ctx.out, host, NULL, + keys[i], store_hash)) { + r = SSH_ERR_INTERNAL_ERROR; + goto fail; + } + } else if ((want & ~ctx.match_keys[i]) == HKF_MATCH_IP) { + what = "Fixing match (address)"; + if (!write_host_entry(ctx.out, ip, NULL, + keys[i], store_hash)) { + r = SSH_ERR_INTERNAL_ERROR; + goto fail; + } + } + do_log2(loglevel, "%s%s%s for %s%s%s to %s: %s %s", + quiet ? __func__ : "", quiet ? ": " : "", what, + host, ip == NULL ? "" : ",", ip == NULL ? "" : ip, filename, sshkey_ssh_name(keys[i]), fp); free(fp); - if (!write_host_entry(ctx.out, host, ip, keys[i], store_hash)) { - r = SSH_ERR_INTERNAL_ERROR; - goto fail; - } ctx.modified = 1; } fclose(ctx.out); @@ -596,30 +687,28 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip, /* Backup the original file and replace it with the temporary */ if (unlink(back) == -1 && errno != ENOENT) { oerrno = errno; - error("%s: unlink %.100s: %s", __func__, - back, strerror(errno)); + error_f("unlink %.100s: %s", back, strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; goto fail; } if (link(filename, back) == -1) { oerrno = errno; - error("%s: link %.100s to %.100s: %s", __func__, - filename, back, strerror(errno)); + error_f("link %.100s to %.100s: %s", filename, + back, strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; goto fail; } if (rename(temp, filename) == -1) { oerrno = errno; - error("%s: rename \"%s\" to \"%s\": %s", __func__, - temp, filename, strerror(errno)); + error_f("rename \"%s\" to \"%s\": %s", temp, + filename, strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; goto fail; } } else { /* No changes made; just delete the temporary file */ if (unlink(temp) != 0) - error("%s: unlink \"%s\": %s", __func__, - temp, strerror(errno)); + error_f("unlink \"%s\": %s", temp, strerror(errno)); } /* success */ @@ -631,7 +720,7 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip, free(back); if (ctx.out != NULL) fclose(ctx.out); - free(ctx.skip_keys); + free(ctx.match_keys); umask(omask); if (r == SSH_ERR_SYSTEM_ERROR) errno = oerrno; @@ -657,10 +746,9 @@ match_maybe_hashed(const char *host, const char *names, int *was_hashed) } int -hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, - const char *host, const char *ip, u_int options) +hostkeys_foreach_file(const char *path, FILE *f, hostkeys_foreach_fn *callback, + void *ctx, const char *host, const char *ip, u_int options, u_int note) { - FILE *f; char *line = NULL, ktype[128]; u_long linenum = 0; char *cp, *cp2; @@ -673,10 +761,7 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, memset(&lineinfo, 0, sizeof(lineinfo)); if (host == NULL && (options & HKF_WANT_MATCH) != 0) return SSH_ERR_INVALID_ARGUMENT; - if ((f = fopen(path, "r")) == NULL) - return SSH_ERR_SYSTEM_ERROR; - debug3("%s: reading file \"%s\"", __func__, path); while (getline(&line, &linesize, f) != -1) { linenum++; line[strcspn(line, "\n")] = '\0'; @@ -690,6 +775,7 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, lineinfo.marker = MRK_NONE; lineinfo.status = HKF_STATUS_OK; lineinfo.keytype = KEY_UNSPEC; + lineinfo.note = note; /* Skip any leading whitespace, comments and empty lines. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) @@ -704,8 +790,7 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, } if ((lineinfo.marker = check_markers(&cp)) == MRK_ERROR) { - verbose("%s: invalid marker at %s:%lu", - __func__, path, linenum); + verbose_f("invalid marker at %s:%lu", path, linenum); if ((options & HKF_WANT_MATCH) == 0) goto bad; continue; @@ -721,8 +806,8 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, if (host != NULL) { if ((s = match_maybe_hashed(host, lineinfo.hosts, &hashed)) == -1) { - debug2("%s: %s:%ld: bad host hash \"%.32s\"", - __func__, path, linenum, lineinfo.hosts); + debug2_f("%s:%ld: bad host hash \"%.32s\"", + path, linenum, lineinfo.hosts); goto bad; } if (s == 1) { @@ -734,9 +819,9 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, if (ip != NULL) { if ((s = match_maybe_hashed(ip, lineinfo.hosts, &hashed)) == -1) { - debug2("%s: %s:%ld: bad ip hash " - "\"%.32s\"", __func__, path, - linenum, lineinfo.hosts); + debug2_f("%s:%ld: bad ip hash " + "\"%.32s\"", path, linenum, + lineinfo.hosts); goto bad; } if (s == 1) { @@ -771,7 +856,7 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, * lines. */ if ((lineinfo.key = sshkey_new(KEY_UNSPEC)) == NULL) { - error("%s: sshkey_new failed", __func__); + error_f("sshkey_new failed"); r = SSH_ERR_ALLOC_FAIL; break; } @@ -827,6 +912,24 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, sshkey_free(lineinfo.key); free(lineinfo.line); free(line); - fclose(f); + return r; +} + +int +hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, + const char *host, const char *ip, u_int options, u_int note) +{ + FILE *f; + int r, oerrno; + + if ((f = fopen(path, "r")) == NULL) + return SSH_ERR_SYSTEM_ERROR; + + debug3_f("reading file \"%s\"", path); + r = hostkeys_foreach_file(path, f, callback, ctx, host, ip, + options, note); + oerrno = errno; + fclose(f); + errno = oerrno; return r; } diff --git a/hostfile.h b/hostfile.h index bd2104373..a24a4e329 100644 --- a/hostfile.h +++ b/hostfile.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hostfile.h,v 1.24 2015/02/16 22:08:57 djm Exp $ */ +/* $OpenBSD: hostfile.h,v 1.29 2021/01/26 00:51:30 djm Exp $ */ /* * Author: Tatu Ylonen @@ -28,17 +28,25 @@ struct hostkey_entry { u_long line; struct sshkey *key; HostkeyMarker marker; + u_int note; /* caller-specific note/flag */ +}; +struct hostkeys { + struct hostkey_entry *entries; + u_int num_entries; }; -struct hostkeys; struct hostkeys *init_hostkeys(void); -void load_hostkeys(struct hostkeys *, const char *, const char *); +void load_hostkeys(struct hostkeys *, const char *, + const char *, u_int); +void load_hostkeys_file(struct hostkeys *, const char *, + const char *, FILE *, u_int note); void free_hostkeys(struct hostkeys *); HostStatus check_key_in_hostkeys(struct hostkeys *, struct sshkey *, const struct hostkey_entry **); -int lookup_key_in_hostkeys_by_type(struct hostkeys *, int, +int lookup_key_in_hostkeys_by_type(struct hostkeys *, int, int, const struct hostkey_entry **); +int lookup_marker_in_hostkeys(struct hostkeys *, int); int hostfile_read_key(char **, u_int *, struct sshkey *); int add_host_to_hostfile(const char *, const char *, @@ -92,6 +100,7 @@ struct hostkey_foreach_line { int keytype; /* Type of key; KEY_UNSPEC for invalid/comment lines */ struct sshkey *key; /* Key, if parsed ok and HKF_WANT_MATCH_HOST set */ const char *comment; /* Any comment following the key */ + u_int note; /* caller-specified note copied from arguments */ }; /* @@ -102,7 +111,13 @@ struct hostkey_foreach_line { typedef int hostkeys_foreach_fn(struct hostkey_foreach_line *l, void *ctx); /* Iterate over a hostkeys file */ -int hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx, - const char *host, const char *ip, u_int options); +int hostkeys_foreach(const char *path, + hostkeys_foreach_fn *callback, void *ctx, + const char *host, const char *ip, u_int options, u_int note); +int hostkeys_foreach_file(const char *path, FILE *f, + hostkeys_foreach_fn *callback, void *ctx, + const char *host, const char *ip, u_int options, u_int note); + +void hostfile_create_user_ssh_dir(const char *, int); #endif diff --git a/int32_minmax.inc b/int32_minmax.inc new file mode 100644 index 000000000..e69de29bb diff --git a/kex.c b/kex.c index 49d701568..30425ab8a 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.155 2019/10/08 22:40:39 dtucker Exp $ */ +/* $OpenBSD: kex.c,v 1.167 2021/01/31 22:55:29 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -33,7 +33,9 @@ #include #include #include +#ifdef HAVE_POLL_H #include +#endif #ifdef WITH_OPENSSL #include @@ -108,8 +110,10 @@ static const struct kexalg kexalgs[] = { #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, +#ifdef USE_SNTRUP761X25519 + { KEX_SNTRUP761X25519_SHA512, KEX_KEM_SNTRUP761X25519_SHA512, 0, SSH_DIGEST_SHA512 }, +#endif #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ { NULL, 0, -1, -1}, }; @@ -245,7 +249,7 @@ kex_assemble_names(char **listp, const char *def, const char *all) list = tmp; } else if (*list == '-') { /* Remove names from default list */ - if ((*listp = match_filter_blacklist(def, list + 1)) == NULL) { + if ((*listp = match_filter_denylist(def, list + 1)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } @@ -282,7 +286,7 @@ kex_assemble_names(char **listp, const char *def, const char *all) goto fail; } free(matching); - if ((matching = match_filter_whitelist(all, cp)) == NULL) { + if ((matching = match_filter_allowlist(all, cp)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } @@ -358,14 +362,13 @@ kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp) goto out; } if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) { /* skip cookie */ - error("%s: consume cookie: %s", __func__, ssh_err(r)); + error_fr(r, "consume 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) { - error("%s: parse proposal %u: %s", __func__, - i, ssh_err(r)); + error_fr(r, "parse proposal %u", i); goto out; } debug2("%s: %s", proposal_names[i], proposal[i]); @@ -373,7 +376,7 @@ kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp) /* first kex follows / reserved */ if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */ (r = sshbuf_get_u32(b, &i)) != 0) { /* reserved */ - error("%s: parse: %s", __func__, ssh_err(r)); + error_fr(r, "parse"); goto out; } if (first_kex_follows != NULL) @@ -402,7 +405,7 @@ kex_prop_free(char **proposal) } /* ARGSUSED */ -static int +int kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh) { int r; @@ -437,7 +440,7 @@ kex_send_ext_info(struct ssh *ssh) (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || (r = sshpkt_put_cstring(ssh, algs)) != 0 || (r = sshpkt_send(ssh)) != 0) { - error("%s: compose: %s", __func__, ssh_err(r)); + error_fr(r, "compose"); goto out; } /* success */ @@ -489,14 +492,14 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh) 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); + error_f("nul byte in %s", name); return SSH_ERR_INVALID_FORMAT; } - debug("%s: %s=<%s>", __func__, name, val); + debug_f("%s=<%s>", name, val); kex->server_sig_algs = val; val = NULL; } else - debug("%s: %s (unrecognised)", __func__, name); + debug_f("%s (unrecognised)", name); free(name); free(val); } @@ -534,7 +537,7 @@ kex_send_kexinit(struct ssh *ssh) int r; if (kex == NULL) { - error("%s: no hex", __func__); + error_f("no kex"); return SSH_ERR_INTERNAL_ERROR; } if (kex->flags & KEX_INIT_SENT) @@ -543,12 +546,12 @@ kex_send_kexinit(struct ssh *ssh) /* generate a random cookie */ if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) { - error("%s: bad kex length: %zu < %d", __func__, + error_f("bad kex length: %zu < %d", sshbuf_len(kex->my), KEX_COOKIE_LEN); return SSH_ERR_INVALID_FORMAT; } if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) { - error("%s: buffer error", __func__); + error_f("buffer error"); return SSH_ERR_INTERNAL_ERROR; } arc4random_buf(cookie, KEX_COOKIE_LEN); @@ -556,7 +559,7 @@ kex_send_kexinit(struct ssh *ssh) if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 || (r = sshpkt_putb(ssh, kex->my)) != 0 || (r = sshpkt_send(ssh)) != 0) { - error("%s: compose reply: %s", __func__, ssh_err(r)); + error_fr(r, "compose reply"); return r; } debug("SSH2_MSG_KEXINIT sent"); @@ -576,7 +579,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) debug("SSH2_MSG_KEXINIT received"); if (kex == NULL) { - error("%s: no hex", __func__); + error_f("no kex"); return SSH_ERR_INTERNAL_ERROR; } ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL); @@ -587,13 +590,13 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) /* discard packet */ for (i = 0; i < KEX_COOKIE_LEN; i++) { if ((r = sshpkt_get_u8(ssh, NULL)) != 0) { - error("%s: discard cookie: %s", __func__, ssh_err(r)); + error_fr(r, "discard cookie"); return r; } } for (i = 0; i < PROPOSAL_MAX; i++) { if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) { - error("%s: discard proposal: %s", __func__, ssh_err(r)); + error_fr(r, "discard proposal"); return r; } } @@ -621,7 +624,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) return (kex->kex[kex->kex_type])(ssh); - error("%s: unknown kex type %u", __func__, kex->kex_type); + error_f("unknown kex type %u", kex->kex_type); return SSH_ERR_INTERNAL_ERROR; } @@ -634,7 +637,8 @@ kex_new(void) (kex->peer = sshbuf_new()) == NULL || (kex->my = sshbuf_new()) == NULL || (kex->client_version = sshbuf_new()) == NULL || - (kex->server_version = sshbuf_new()) == NULL) { + (kex->server_version = sshbuf_new()) == NULL || + (kex->session_id = sshbuf_new()) == NULL) { kex_free(kex); return NULL; } @@ -668,8 +672,7 @@ kex_free_newkeys(struct newkeys *newkeys) } free(newkeys->mac.name); explicit_bzero(&newkeys->mac, sizeof(newkeys->mac)); - explicit_bzero(newkeys, sizeof(*newkeys)); - free(newkeys); + freezero(newkeys, sizeof(*newkeys)); } void @@ -695,7 +698,7 @@ kex_free(struct kex *kex) sshbuf_free(kex->client_version); sshbuf_free(kex->server_version); sshbuf_free(kex->client_pub); - free(kex->session_id); + sshbuf_free(kex->session_id); free(kex->failed_choice); free(kex->hostkey_alg); free(kex->name); @@ -738,11 +741,11 @@ int kex_start_rekex(struct ssh *ssh) { if (ssh->kex == NULL) { - error("%s: no kex", __func__); + error_f("no kex"); return SSH_ERR_INTERNAL_ERROR; } if (ssh->kex->done == 0) { - error("%s: requested twice", __func__); + error_f("requested twice"); return SSH_ERR_INTERNAL_ERROR; } ssh->kex->done = 0; @@ -757,7 +760,7 @@ choose_enc(struct sshenc *enc, char *client, char *server) if (name == NULL) return SSH_ERR_NO_CIPHER_ALG_MATCH; if ((enc->cipher = cipher_by_name(name)) == NULL) { - error("%s: unsupported cipher %s", __func__, name); + error_f("unsupported cipher %s", name); free(name); return SSH_ERR_INTERNAL_ERROR; } @@ -779,7 +782,7 @@ choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server) if (name == NULL) return SSH_ERR_NO_MAC_ALG_MATCH; if (mac_setup(mac, name) < 0) { - error("%s: unsupported MAC %s", __func__, name); + error_f("unsupported MAC %s", name); free(name); return SSH_ERR_INTERNAL_ERROR; } @@ -796,14 +799,17 @@ choose_comp(struct sshcomp *comp, char *client, char *server) if (name == NULL) return SSH_ERR_NO_COMPRESS_ALG_MATCH; +#ifdef WITH_ZLIB if (strcmp(name, "zlib@openssh.com") == 0) { comp->type = COMP_DELAYED; } else if (strcmp(name, "zlib") == 0) { comp->type = COMP_ZLIB; - } else if (strcmp(name, "none") == 0) { + } else +#endif /* WITH_ZLIB */ + if (strcmp(name, "none") == 0) { comp->type = COMP_NONE; } else { - error("%s: unsupported compression scheme %s", __func__, name); + error_f("unsupported compression scheme %s", name); free(name); return SSH_ERR_INTERNAL_ERROR; } @@ -822,7 +828,7 @@ choose_kex(struct kex *k, char *client, char *server) if (k->name == NULL) return SSH_ERR_NO_KEX_ALG_MATCH; if ((kexalg = kex_alg_by_name(k->name)) == NULL) { - error("%s: unsupported KEX method %s", __func__, k->name); + error_f("unsupported KEX method %s", k->name); return SSH_ERR_INTERNAL_ERROR; } k->kex_type = kexalg->type; @@ -834,6 +840,7 @@ choose_kex(struct kex *k, char *client, char *server) static int choose_hostkeyalg(struct kex *k, char *client, char *server) { + free(k->hostkey_alg); k->hostkey_alg = match_list(client, server, NULL); debug("kex: host key algorithm: %s", @@ -842,8 +849,7 @@ choose_hostkeyalg(struct kex *k, char *client, char *server) return SSH_ERR_NO_HOSTKEY_ALG_MATCH; k->hostkey_type = sshkey_type_from_name(k->hostkey_alg); if (k->hostkey_type == KEY_UNSPEC) { - error("%s: unsupported hostkey algorithm %s", __func__, - k->hostkey_alg); + error_f("unsupported hostkey algorithm %s", k->hostkey_alg); return SSH_ERR_INTERNAL_ERROR; } k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg); @@ -1010,11 +1016,10 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, 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_update_buffer(hashctx, kex->session_id) != 0 || ssh_digest_final(hashctx, digest, mdsz) != 0) { r = SSH_ERR_LIBCRYPTO_ERROR; - error("%s: KEX hash failed", __func__); + error_f("KEX hash failed"); goto out; } ssh_digest_free(hashctx); @@ -1031,7 +1036,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, ssh_digest_update(hashctx, hash, hashlen) != 0 || ssh_digest_update(hashctx, digest, have) != 0 || ssh_digest_final(hashctx, digest + have, mdsz) != 0) { - error("%s: KDF failed", __func__); + error_f("KDF failed"); r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } @@ -1062,12 +1067,16 @@ kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen, 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); + if ((kex->flags & KEX_INITIAL) != 0) { + if (sshbuf_len(kex->session_id) != 0) { + error_f("already have session ID at kex"); + return SSH_ERR_INTERNAL_ERROR; + } + if ((r = sshbuf_put(kex->session_id, hash, hashlen)) != 0) + return r; + } else if (sshbuf_len(kex->session_id) == 0) { + error_f("no session ID in rekex"); + return SSH_ERR_INTERNAL_ERROR; } for (i = 0; i < NKEYS; i++) { if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen, @@ -1096,7 +1105,7 @@ kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp) *prvp = NULL; if (kex->load_host_public_key == NULL || kex->load_host_private_key == NULL) { - error("%s: missing hostkey loader", __func__); + error_f("missing hostkey loader"); return SSH_ERR_INVALID_ARGUMENT; } *pubp = kex->load_host_public_key(kex->hostkey_type, @@ -1114,7 +1123,7 @@ kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key) struct kex *kex = ssh->kex; if (kex->verify_host_key == NULL) { - error("%s: missing hostkey verifier", __func__); + error_f("missing hostkey verifier"); return SSH_ERR_INVALID_ARGUMENT; } if (server_host_key->type != kex->hostkey_type || @@ -1151,7 +1160,7 @@ send_error(struct ssh *ssh, char *msg) 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)); + error_f("write: %.100s", strerror(errno)); } /* @@ -1163,7 +1172,7 @@ int kex_exchange_identification(struct ssh *ssh, int timeout_ms, const char *version_addendum) { - int remote_major, remote_minor, mismatch; + int remote_major, remote_minor, mismatch, oerrno = 0; size_t len, i, n; int r, expect_nl; u_char c; @@ -1182,24 +1191,27 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, 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)); + oerrno = errno; + error_fr(r, "sshbuf_putf"); 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)); + oerrno = errno; + debug_f("write: %.100s", 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)); + oerrno = errno; + error_fr(r, "sshbuf_consume_end"); goto out; } our_version_string = sshbuf_dup_string(our_version); if (our_version_string == NULL) { - error("%s: sshbuf_dup_string failed", __func__); + error_f("sshbuf_dup_string failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } @@ -1210,8 +1222,8 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, 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); + error_f("No SSH version received in first %u lines " + "from server", SSH_MAX_PRE_BANNER_LINES); r = SSH_ERR_INVALID_FORMAT; goto out; } @@ -1229,8 +1241,8 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, r = SSH_ERR_CONN_TIMEOUT; goto out; } else if (r == -1) { - error("%s: %s", - __func__, strerror(errno)); + oerrno = errno; + error_f("%s", strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; goto out; } @@ -1239,13 +1251,12 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, len = atomicio(read, ssh_packet_get_connection_in(ssh), &c, 1); if (len != 1 && errno == EPIPE) { - error("%s: Connection closed by remote host", - __func__); + error_f("Connection closed by remote host"); r = SSH_ERR_CONN_CLOSED; goto out; } else if (len != 1) { - error("%s: read: %.100s", - __func__, strerror(errno)); + oerrno = errno; + error_f("read: %.100s", strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; goto out; } @@ -1256,17 +1267,17 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, if (c == '\n') break; if (c == '\0' || expect_nl) { - error("%s: banner line contains invalid " - "characters", __func__); + error_f("banner line contains invalid " + "characters"); goto invalid; } if ((r = sshbuf_put_u8(peer_version, c)) != 0) { - error("%s: sshbuf_put: %s", - __func__, ssh_err(r)); + oerrno = errno; + error_fr(r, "sshbuf_put"); goto out; } if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) { - error("%s: banner line too long", __func__); + error_f("banner line too long"); goto invalid; } } @@ -1276,26 +1287,26 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, 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__); + error_f("sshbuf_dup_string failed"); 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); + error_f("client sent invalid protocol identifier " + "\"%.256s\"", cp); free(cp); goto invalid; } - debug("%s: banner line %zu: %s", __func__, n, cp); + debug_f("banner line %zu: %s", n, cp); free(cp); } peer_version_string = sshbuf_dup_string(peer_version); if (peer_version_string == NULL) - error("%s: sshbuf_dup_string failed", __func__); + error_f("sshbuf_dup_string failed"); /* XXX must be same size for sscanf */ if ((remote_version = calloc(1, sshbuf_len(peer_version))) == NULL) { - error("%s: calloc failed", __func__); + error_f("calloc failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } @@ -1315,7 +1326,7 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, } debug("Remote protocol version %d.%d, remote software version %.100s", remote_major, remote_minor, remote_version); - ssh->compat = compat_datafellows(remote_version); + compat_banner(ssh, remote_version); mismatch = 0; switch (remote_major) { @@ -1361,6 +1372,8 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, free(our_version_string); free(peer_version_string); free(remote_version); + if (r == SSH_ERR_SYSTEM_ERROR) + errno = oerrno; return r; } diff --git a/kex.h b/kex.h index a5ae6ac05..9605ed528 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.109 2019/09/06 05:23:55 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.114 2021/01/31 22:55:29 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -62,7 +62,7 @@ #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 KEX_SNTRUP761X25519_SHA512 "sntrup761x25519-sha512@openssh.com" #define COMP_NONE 0 /* pre-auth compression (COMP_ZLIB) is only supported in the client */ @@ -101,7 +101,7 @@ enum kex_exchange { KEX_DH_GEX_SHA256, KEX_ECDH_SHA2, KEX_C25519_SHA256, - KEX_KEM_SNTRUP4591761X25519_SHA512, + KEX_KEM_SNTRUP761X25519_SHA512, KEX_MAX }; @@ -132,8 +132,6 @@ struct newkeys { 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; @@ -149,6 +147,7 @@ struct kex { struct sshbuf *peer; struct sshbuf *client_version; struct sshbuf *server_version; + struct sshbuf *session_id; sig_atomic_t done; u_int flags; int hash_alg; @@ -168,7 +167,7 @@ struct kex { const EC_GROUP *ec_group; /* ECDH */ 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 */ + u_char sntrup761_client_key[crypto_kem_sntrup761_SECRETKEYBYTES]; /* KEM */ struct sshbuf *client_pub; }; @@ -194,6 +193,7 @@ 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_protocol_error(int, u_int32_t, struct ssh *); int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *); int kex_send_newkeys(struct ssh *); int kex_start_rekex(struct ssh *); @@ -218,10 +218,10 @@ 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 *, +int kex_kem_sntrup761x25519_keypair(struct kex *); +int kex_kem_sntrup761x25519_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); -int kex_kem_sntrup4591761x25519_dec(struct kex *, const struct sshbuf *, +int kex_kem_sntrup761x25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **); int kex_dh_keygen(struct kex *); diff --git a/kexdh.c b/kexdh.c index 67133e339..001dd12db 100644 --- a/kexdh.c +++ b/kexdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdh.c,v 1.32 2019/01/21 10:40:11 djm Exp $ */ +/* $OpenBSD: kexdh.c,v 1.34 2020/12/04 02:29:25 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -42,6 +42,7 @@ #include "digest.h" #include "ssherr.h" #include "dh.h" +#include "log.h" int kex_dh_keygen(struct kex *kex) @@ -193,6 +194,7 @@ kex_dh_dec(struct kex *kex, const struct sshbuf *dh_blob, *shared_secretp = buf; buf = NULL; out: + BN_free(dh_pub); DH_free(kex->dh); kex->dh = NULL; sshbuf_free(buf); diff --git a/kexgen.c b/kexgen.c index bb996b504..35b83ccfb 100644 --- a/kexgen.c +++ b/kexgen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgen.c,v 1.3 2019/09/06 05:23:55 djm Exp $ */ +/* $OpenBSD: kexgen.c,v 1.6 2021/01/31 22:55:29 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -117,8 +117,8 @@ kex_gen_client(struct ssh *ssh) case KEX_C25519_SHA256: r = kex_c25519_keypair(kex); break; - case KEX_KEM_SNTRUP4591761X25519_SHA512: - r = kex_kem_sntrup4591761x25519_keypair(kex); + case KEX_KEM_SNTRUP761X25519_SHA512: + r = kex_kem_sntrup761x25519_keypair(kex); break; default: r = SSH_ERR_INVALID_ARGUMENT; @@ -148,6 +148,9 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh) size_t slen, hashlen; int r; + debug("SSH2_MSG_KEX_ECDH_REPLY received"); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &kex_protocol_error); + /* hostkey */ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) goto out; @@ -185,8 +188,8 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh) 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, + case KEX_KEM_SNTRUP761X25519_SHA512: + r = kex_kem_sntrup761x25519_dec(kex, server_blob, &shared_secret); break; default: @@ -212,7 +215,7 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh) goto out; if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen, - kex->hostkey_alg, ssh->compat)) != 0) + kex->hostkey_alg, ssh->compat, NULL)) != 0) goto out; if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) @@ -220,8 +223,8 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *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)); + explicit_bzero(kex->sntrup761_client_key, + sizeof(kex->sntrup761_client_key)); sshbuf_free(server_host_key_blob); free(signature); sshbuf_free(tmp); @@ -254,6 +257,9 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) size_t slen, hashlen; int r; + debug("SSH2_MSG_KEX_ECDH_INIT received"); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &kex_protocol_error); + if ((r = kex_load_hostkey(ssh, &server_host_private, &server_host_public)) != 0) goto out; @@ -282,8 +288,8 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) 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, + case KEX_KEM_SNTRUP761X25519_SHA512: + r = kex_kem_sntrup761x25519_enc(kex, client_pubkey, &server_pubkey, &shared_secret); break; default: diff --git a/kexgexc.c b/kexgexc.c index 1c65b8a18..4a2e741d8 100644 --- a/kexgexc.c +++ b/kexgexc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexc.c,v 1.34 2019/01/23 00:30:41 djm Exp $ */ +/* $OpenBSD: kexgexc.c,v 1.37 2021/01/31 22:55:29 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -68,7 +68,7 @@ kexgex_client(struct ssh *ssh) kex->min = DH_GRP_MIN; kex->max = DH_GRP_MAX; kex->nbits = nbits; - if (datafellows & SSH_BUG_DHGEX_LARGE) + if (ssh->compat & 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 || @@ -83,6 +83,7 @@ kexgex_client(struct ssh *ssh) fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n", kex->min, kex->nbits, kex->max); #endif + debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, &input_kex_dh_gex_group); r = 0; @@ -98,7 +99,8 @@ input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh) const BIGNUM *pub_key; int r, bits; - debug("got SSH2_MSG_KEX_DH_GEX_GROUP"); + debug("SSH2_MSG_KEX_DH_GEX_GROUP received"); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, &kex_protocol_error); if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 || (r = sshpkt_get_bignum2(ssh, &g)) != 0 || @@ -130,7 +132,7 @@ input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh) BN_print_fp(stderr, pub_key); fprintf(stderr, "\n"); #endif - ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, NULL); + debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY"); ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &input_kex_dh_gex_reply); r = 0; out: @@ -153,7 +155,9 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) size_t slen, hashlen; int r; - debug("got SSH2_MSG_KEX_DH_GEX_REPLY"); + debug("SSH2_MSG_KEX_DH_GEX_REPLY received"); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &kex_protocol_error); + /* key, cert */ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) goto out; @@ -199,7 +203,7 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh) goto out; if ((r = sshkey_verify(server_host_key, signature, slen, hash, - hashlen, kex->hostkey_alg, ssh->compat)) != 0) + hashlen, kex->hostkey_alg, ssh->compat, NULL)) != 0) goto out; if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) diff --git a/kexgexs.c b/kexgexs.c index 8ee3aaccb..f0fbcb912 100644 --- a/kexgexs.c +++ b/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.42 2019/01/23 00:30:41 djm Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.43 2021/01/31 22:55:29 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -77,6 +77,8 @@ input_kex_dh_gex_request(int type, u_int32_t seq, struct ssh *ssh) const BIGNUM *dh_p, *dh_g; debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST, &kex_protocol_error); + if ((r = sshpkt_get_u32(ssh, &min)) != 0 || (r = sshpkt_get_u32(ssh, &nbits)) != 0 || (r = sshpkt_get_u32(ssh, &max)) != 0 || @@ -136,6 +138,9 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh) size_t slen, hashlen; int r; + debug("SSH2_MSG_KEX_DH_GEX_INIT received"); + ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &kex_protocol_error); + if ((r = kex_load_hostkey(ssh, &server_host_private, &server_host_public)) != 0) goto out; diff --git a/kexsntrup4591761x25519.c b/kexsntrup761x25519.c similarity index 74% rename from kexsntrup4591761x25519.c rename to kexsntrup761x25519.c index 3b9b664f8..e3007fa29 100644 --- a/kexsntrup4591761x25519.c +++ b/kexsntrup761x25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexsntrup4591761x25519.c,v 1.3 2019/01/21 10:40:11 djm Exp $ */ +/* $OpenBSD: kexsntrup761x25519.c,v 1.1 2020/12/29 00:59:15 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -25,6 +25,8 @@ #include "includes.h" +#ifdef USE_SNTRUP761X25519 + #include #include @@ -38,7 +40,7 @@ #include "ssherr.h" int -kex_kem_sntrup4591761x25519_keypair(struct kex *kex) +kex_kem_sntrup761x25519_keypair(struct kex *kex) { struct sshbuf *buf = NULL; u_char *cp = NULL; @@ -47,15 +49,15 @@ kex_kem_sntrup4591761x25519_keypair(struct kex *kex) if ((buf = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE; + need = crypto_kem_sntrup761_PUBLICKEYBYTES + CURVE25519_SIZE; if ((r = sshbuf_reserve(buf, need, &cp)) != 0) goto out; - crypto_kem_sntrup4591761_keypair(cp, kex->sntrup4591761_client_key); + crypto_kem_sntrup761_keypair(cp, kex->sntrup761_client_key); #ifdef DEBUG_KEXECDH - dump_digest("client public key sntrup4591761:", cp, - crypto_kem_sntrup4591761_PUBLICKEYBYTES); + dump_digest("client public key sntrup761:", cp, + crypto_kem_sntrup761_PUBLICKEYBYTES); #endif - cp += crypto_kem_sntrup4591761_PUBLICKEYBYTES; + cp += crypto_kem_sntrup761_PUBLICKEYBYTES; kexc25519_keygen(kex->c25519_client_key, cp); #ifdef DEBUG_KEXECDH dump_digest("client public key c25519:", cp, CURVE25519_SIZE); @@ -68,7 +70,7 @@ kex_kem_sntrup4591761x25519_keypair(struct kex *kex) } int -kex_kem_sntrup4591761x25519_enc(struct kex *kex, +kex_kem_sntrup761x25519_enc(struct kex *kex, const struct sshbuf *client_blob, struct sshbuf **server_blobp, struct sshbuf **shared_secretp) { @@ -85,17 +87,17 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex, *shared_secretp = NULL; /* client_blob contains both KEM and ECDH client pubkeys */ - need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE; + need = crypto_kem_sntrup761_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 sntrup761:", client_pub, + crypto_kem_sntrup761_PUBLICKEYBYTES); dump_digest("client public key 25519:", - client_pub + crypto_kem_sntrup4591761_PUBLICKEYBYTES, + client_pub + crypto_kem_sntrup761_PUBLICKEYBYTES, CURVE25519_SIZE); #endif /* allocate buffer for concatenation of KEM key and ECDH shared key */ @@ -104,7 +106,7 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex, r = SSH_ERR_ALLOC_FAIL; goto out; } - if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES, + if ((r = sshbuf_reserve(buf, crypto_kem_sntrup761_BYTES, &kem_key)) != 0) goto out; /* allocate space for encrypted KEM key and ECDH pub key */ @@ -112,16 +114,16 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex, r = SSH_ERR_ALLOC_FAIL; goto out; } - need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE; + need = crypto_kem_sntrup761_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); + crypto_kem_sntrup761_enc(ciphertext, kem_key, client_pub); /* generate ECDH key pair, store server pubkey after ciphertext */ - server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES; + server_pub = ciphertext + crypto_kem_sntrup761_CIPHERTEXTBYTES; kexc25519_keygen(server_key, server_pub); /* append ECDH shared key */ - client_pub += crypto_kem_sntrup4591761_PUBLICKEYBYTES; + client_pub += crypto_kem_sntrup761_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) @@ -129,7 +131,7 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex, #ifdef DEBUG_KEXECDH dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE); dump_digest("server cipher text:", ciphertext, - crypto_kem_sntrup4591761_CIPHERTEXTBYTES); + crypto_kem_sntrup761_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)); @@ -155,7 +157,7 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex, } int -kex_kem_sntrup4591761x25519_dec(struct kex *kex, +kex_kem_sntrup761x25519_dec(struct kex *kex, const struct sshbuf *server_blob, struct sshbuf **shared_secretp) { struct sshbuf *buf = NULL; @@ -167,16 +169,16 @@ kex_kem_sntrup4591761x25519_dec(struct kex *kex, *shared_secretp = NULL; - need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE; + need = crypto_kem_sntrup761_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; + server_pub = ciphertext + crypto_kem_sntrup761_CIPHERTEXTBYTES; #ifdef DEBUG_KEXECDH dump_digest("server cipher text:", ciphertext, - crypto_kem_sntrup4591761_CIPHERTEXTBYTES); + crypto_kem_sntrup761_CIPHERTEXTBYTES); dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE); #endif /* hash concatenation of KEM key and ECDH shared key */ @@ -184,18 +186,18 @@ kex_kem_sntrup4591761x25519_dec(struct kex *kex, r = SSH_ERR_ALLOC_FAIL; goto out; } - if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES, + if ((r = sshbuf_reserve(buf, crypto_kem_sntrup761_BYTES, &kem_key)) != 0) goto out; - decoded = crypto_kem_sntrup4591761_dec(kem_key, ciphertext, - kex->sntrup4591761_client_key); + decoded = crypto_kem_sntrup761_dec(kem_key, ciphertext, + kex->sntrup761_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("client kem key:", kem_key, crypto_kem_sntrup761_BYTES); dump_digest("concatenation of KEM key and ECDH shared key:", sshbuf_ptr(buf), sshbuf_len(buf)); #endif @@ -217,3 +219,33 @@ kex_kem_sntrup4591761x25519_dec(struct kex *kex, sshbuf_free(buf); return r; } + +#else + +#include "ssherr.h" + +struct kex; +struct sshbuf; +struct sshkey; + +int +kex_kem_sntrup761x25519_keypair(struct kex *kex) +{ + return SSH_ERR_SIGN_ALG_UNSUPPORTED; +} + +int +kex_kem_sntrup761x25519_enc(struct kex *kex, + const struct sshbuf *client_blob, struct sshbuf **server_blobp, + struct sshbuf **shared_secretp) +{ + return SSH_ERR_SIGN_ALG_UNSUPPORTED; +} + +int +kex_kem_sntrup761x25519_dec(struct kex *kex, + const struct sshbuf *server_blob, struct sshbuf **shared_secretp) +{ + return SSH_ERR_SIGN_ALG_UNSUPPORTED; +} +#endif /* USE_SNTRUP761X25519 */ diff --git a/krl.c b/krl.c index a7f690955..5612e7742 100644 --- a/krl.c +++ b/krl.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: krl.c,v 1.44 2019/09/06 04:53:27 djm Exp $ */ +/* $OpenBSD: krl.c,v 1.52 2020/10/18 11:32:01 djm Exp $ */ #include "includes.h" @@ -38,12 +38,13 @@ #include "log.h" #include "digest.h" #include "bitmap.h" +#include "utf8.h" #include "krl.h" /* #define DEBUG_KRL */ #ifdef DEBUG_KRL -# define KRL_DBG(x) debug3 x +# define KRL_DBG(x) debug3_f x #else # define KRL_DBG(x) #endif @@ -240,8 +241,7 @@ revoked_certs_for_ca_key(struct ssh_krl *krl, const struct sshkey *ca_key, RB_INIT(&rc->revoked_serials); RB_INIT(&rc->revoked_key_ids); TAILQ_INSERT_TAIL(&krl->revoked_certs, rc, entry); - KRL_DBG(("%s: new CA %s", __func__, - ca_key == NULL ? "*" : sshkey_type(ca_key))); + KRL_DBG(("new CA %s", ca_key == NULL ? "*" : sshkey_type(ca_key))); *rcp = rc; return 0; } @@ -251,7 +251,7 @@ insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi) { struct revoked_serial rs, *ers, *crs, *irs; - KRL_DBG(("%s: insert %llu:%llu", __func__, lo, hi)); + KRL_DBG(("insert %llu:%llu", lo, hi)); memset(&rs, 0, sizeof(rs)); rs.lo = lo; rs.hi = hi; @@ -263,15 +263,14 @@ insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi) memcpy(irs, &rs, sizeof(*irs)); ers = RB_INSERT(revoked_serial_tree, rt, irs); if (ers != NULL) { - KRL_DBG(("%s: bad: ers != NULL", __func__)); + KRL_DBG(("bad: ers != NULL")); /* Shouldn't happen */ free(irs); return SSH_ERR_INTERNAL_ERROR; } ers = irs; } else { - KRL_DBG(("%s: overlap found %llu:%llu", __func__, - ers->lo, ers->hi)); + KRL_DBG(("overlap found %llu:%llu", ers->lo, ers->hi)); /* * The inserted entry overlaps an existing one. Grow the * existing entry. @@ -289,33 +288,31 @@ insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi) /* Check predecessors */ while ((crs = RB_PREV(revoked_serial_tree, rt, ers)) != NULL) { - KRL_DBG(("%s: pred %llu:%llu", __func__, crs->lo, crs->hi)); + KRL_DBG(("pred %llu:%llu", crs->lo, crs->hi)); if (ers->lo != 0 && crs->hi < ers->lo - 1) break; /* This entry overlaps. */ if (crs->lo < ers->lo) { ers->lo = crs->lo; - KRL_DBG(("%s: pred extend %llu:%llu", __func__, - ers->lo, ers->hi)); + KRL_DBG(("pred extend %llu:%llu", ers->lo, ers->hi)); } RB_REMOVE(revoked_serial_tree, rt, crs); free(crs); } /* Check successors */ while ((crs = RB_NEXT(revoked_serial_tree, rt, ers)) != NULL) { - KRL_DBG(("%s: succ %llu:%llu", __func__, crs->lo, crs->hi)); + KRL_DBG(("succ %llu:%llu", crs->lo, crs->hi)); if (ers->hi != (u_int64_t)-1 && crs->lo > ers->hi + 1) break; /* This entry overlaps. */ if (crs->hi > ers->hi) { ers->hi = crs->hi; - KRL_DBG(("%s: succ extend %llu:%llu", __func__, - ers->lo, ers->hi)); + KRL_DBG(("succ extend %llu:%llu", ers->lo, ers->hi)); } RB_REMOVE(revoked_serial_tree, rt, crs); free(crs); } - KRL_DBG(("%s: done, final %llu:%llu", __func__, ers->lo, ers->hi)); + KRL_DBG(("done, final %llu:%llu", ers->lo, ers->hi)); return 0; } @@ -351,7 +348,7 @@ ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const struct sshkey *ca_key, if ((r = revoked_certs_for_ca_key(krl, ca_key, &rc, 1)) != 0) return r; - KRL_DBG(("%s: revoke %s", __func__, key_id)); + KRL_DBG(("revoke %s", key_id)); if ((rki = calloc(1, sizeof(*rki))) == NULL || (rki->key_id = strdup(key_id)) == NULL) { free(rki); @@ -410,7 +407,7 @@ ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const struct sshkey *key) size_t len; int r; - debug3("%s: revoke type %s", __func__, sshkey_type(key)); + debug3_f("revoke type %s", sshkey_type(key)); if ((r = plain_key_blob(key, &blob, &len)) != 0) return r; return revoke_blob(&krl->revoked_keys, blob, len); @@ -436,7 +433,7 @@ revoke_by_hash(struct revoked_blob_tree *target, const u_char *p, size_t len) int ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const u_char *p, size_t len) { - debug3("%s: revoke by sha1", __func__); + debug3_f("revoke by sha1"); if (len != 20) return SSH_ERR_INVALID_FORMAT; return revoke_by_hash(&krl->revoked_sha1s, p, len); @@ -445,7 +442,7 @@ ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const u_char *p, size_t len) int ssh_krl_revoke_key_sha256(struct ssh_krl *krl, const u_char *p, size_t len) { - debug3("%s: revoke by sha256", __func__); + debug3_f("revoke by sha256"); if (len != 32) return SSH_ERR_INVALID_FORMAT; return revoke_by_hash(&krl->revoked_sha256s, p, len); @@ -541,9 +538,9 @@ choose_next_state(int current_state, u_int64_t contig, int final, *force_new_section = 1; cost = cost_bitmap_restart; } - KRL_DBG(("%s: contig %llu last_gap %llu next_gap %llu final %d, costs:" + KRL_DBG(("contig %llu last_gap %llu next_gap %llu final %d, costs:" "list %llu range %llu bitmap %llu new bitmap %llu, " - "selected 0x%02x%s", __func__, (long long unsigned)contig, + "selected 0x%02x%s", (long long unsigned)contig, (long long unsigned)last_gap, (long long unsigned)next_gap, final, (long long unsigned)cost_list, (long long unsigned)cost_range, (long long unsigned)cost_bitmap, @@ -601,7 +598,7 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf) for (rs = RB_MIN(revoked_serial_tree, &rc->revoked_serials); rs != NULL; rs = RB_NEXT(revoked_serial_tree, &rc->revoked_serials, rs)) { - KRL_DBG(("%s: serial %llu:%llu state 0x%02x", __func__, + KRL_DBG(("serial %llu:%llu state 0x%02x", (long long unsigned)rs->lo, (long long unsigned)rs->hi, state)); @@ -621,7 +618,7 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf) */ if (state != 0 && (force_new_sect || next_state != state || state == KRL_SECTION_CERT_SERIAL_RANGE)) { - KRL_DBG(("%s: finish state 0x%02x", __func__, state)); + KRL_DBG(("finish state 0x%02x", state)); switch (state) { case KRL_SECTION_CERT_SERIAL_LIST: case KRL_SECTION_CERT_SERIAL_RANGE: @@ -641,7 +638,7 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf) /* If we are starting a new section then prepare it now */ if (next_state != state || force_new_sect) { - KRL_DBG(("%s: start state 0x%02x", __func__, + KRL_DBG(("start state 0x%02x", next_state)); state = next_state; sshbuf_reset(sect); @@ -677,7 +674,7 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf) break; case KRL_SECTION_CERT_SERIAL_BITMAP: if (rs->lo - bitmap_start > INT_MAX) { - error("%s: insane bitmap gap", __func__); + error_f("insane bitmap gap"); goto out; } for (i = 0; i < contig; i++) { @@ -693,8 +690,7 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf) } /* Flush the remaining section, if any */ if (state != 0) { - KRL_DBG(("%s: serial final flush for state 0x%02x", - __func__, state)); + KRL_DBG(("serial final flush for state 0x%02x", state)); switch (state) { case KRL_SECTION_CERT_SERIAL_LIST: case KRL_SECTION_CERT_SERIAL_RANGE: @@ -710,12 +706,12 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf) (r = sshbuf_put_stringb(buf, sect)) != 0) goto out; } - KRL_DBG(("%s: serial done ", __func__)); + KRL_DBG(("serial done ")); /* Now output a section for any revocations by key ID */ sshbuf_reset(sect); RB_FOREACH(rki, revoked_key_id_tree, &rc->revoked_key_ids) { - KRL_DBG(("%s: key ID %s", __func__, rki->key_id)); + KRL_DBG(("key ID %s", rki->key_id)); if ((r = sshbuf_put_cstring(sect, rki->key_id)) != 0) goto out; } @@ -771,7 +767,7 @@ ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf, /* Finally, output sections for revocations by public key/hash */ sshbuf_reset(sect); RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) { - KRL_DBG(("%s: key len %zu ", __func__, rb->len)); + KRL_DBG(("key len %zu ", rb->len)); if ((r = sshbuf_put_string(sect, rb->blob, rb->len)) != 0) goto out; } @@ -782,7 +778,7 @@ ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf, } sshbuf_reset(sect); RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha1s) { - KRL_DBG(("%s: hash len %zu ", __func__, rb->len)); + KRL_DBG(("hash len %zu ", rb->len)); if ((r = sshbuf_put_string(sect, rb->blob, rb->len)) != 0) goto out; } @@ -794,7 +790,7 @@ ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf, } sshbuf_reset(sect); RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha256s) { - KRL_DBG(("%s: hash len %zu ", __func__, rb->len)); + KRL_DBG(("hash len %zu ", rb->len)); if ((r = sshbuf_put_string(sect, rb->blob, rb->len)) != 0) goto out; } @@ -806,16 +802,16 @@ ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf, } for (i = 0; i < nsign_keys; i++) { - KRL_DBG(("%s: signature key %s", __func__, - sshkey_ssh_name(sign_keys[i]))); + KRL_DBG(("sig key %s", sshkey_ssh_name(sign_keys[i]))); if ((r = sshbuf_put_u8(buf, KRL_SECTION_SIGNATURE)) != 0 || (r = sshkey_puts(sign_keys[i], buf)) != 0) goto out; - + /* XXX support sk-* keys */ if ((r = sshkey_sign(sign_keys[i], &sblob, &slen, - sshbuf_ptr(buf), sshbuf_len(buf), NULL, 0)) != 0) + sshbuf_ptr(buf), sshbuf_len(buf), NULL, NULL, + NULL, 0)) != 0) goto out; - KRL_DBG(("%s: signature sig len %zu", __func__, slen)); + KRL_DBG(("signature sig len %zu", slen)); if ((r = sshbuf_put_string(buf, sblob, slen)) != 0) goto out; } @@ -872,7 +868,7 @@ parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl) if ((r = sshbuf_get_u8(buf, &type)) != 0 || (r = sshbuf_froms(buf, &subsect)) != 0) goto out; - KRL_DBG(("%s: subsection type 0x%02x", __func__, type)); + KRL_DBG(("subsection type 0x%02x", type)); /* sshbuf_dump(subsect, stderr); */ switch (type) { @@ -909,7 +905,7 @@ parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl) nbits = bitmap_nbits(bitmap); for (serial = 0; serial < (u_int64_t)nbits; serial++) { if (serial > 0 && serial_lo + serial == 0) { - error("%s: bitmap wraps u64", __func__); + error_f("bitmap wraps u64"); r = SSH_ERR_INVALID_FORMAT; goto out; } @@ -968,7 +964,7 @@ blob_section(struct sshbuf *sect, struct revoked_blob_tree *target_tree, if ((r = sshbuf_get_string(sect, &rdata, &rlen)) != 0) return r; if (expected_len != 0 && rlen != expected_len) { - error("%s: bad length", __func__); + error_f("bad length"); free(rdata); return SSH_ERR_INVALID_FORMAT; } @@ -999,7 +995,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, *krlp = NULL; if (sshbuf_len(buf) < sizeof(KRL_MAGIC) - 1 || memcmp(sshbuf_ptr(buf), KRL_MAGIC, sizeof(KRL_MAGIC) - 1) != 0) { - debug3("%s: not a KRL", __func__); + debug3_f("not a KRL"); return SSH_ERR_KRL_BAD_MAGIC; } @@ -1012,7 +1008,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, goto out; if ((krl = ssh_krl_init()) == NULL) { - error("%s: alloc failed", __func__); + error_f("alloc failed"); goto out; } @@ -1049,7 +1045,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, if ((r = sshbuf_get_u8(copy, &type)) != 0 || (r = sshbuf_get_string_direct(copy, &blob, &blen)) != 0) goto out; - KRL_DBG(("%s: first pass, section 0x%02x", __func__, type)); + KRL_DBG(("first pass, section 0x%02x", type)); if (type != KRL_SECTION_SIGNATURE) { if (sig_seen) { error("KRL contains non-signature section " @@ -1079,7 +1075,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, } /* Check signature over entire KRL up to this point */ if ((r = sshkey_verify(key, blob, blen, - sshbuf_ptr(buf), sig_off, NULL, 0)) != 0) + sshbuf_ptr(buf), sig_off, NULL, 0, NULL)) != 0) goto out; /* Check if this key has already signed this KRL */ for (i = 0; i < nca_used; i++) { @@ -1125,7 +1121,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, if ((r = sshbuf_get_u8(copy, &type)) != 0 || (r = sshbuf_froms(copy, §)) != 0) goto out; - KRL_DBG(("%s: second pass, section 0x%02x", __func__, type)); + KRL_DBG(("second pass, section 0x%02x", type)); switch (type) { case KRL_SECTION_CERTIFICATES: @@ -1228,7 +1224,7 @@ is_cert_revoked(const struct sshkey *key, struct revoked_certs *rc) rki.key_id = key->cert->key_id; erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki); if (erki != NULL) { - KRL_DBG(("%s: revoked by key ID", __func__)); + KRL_DBG(("revoked by key ID")); return SSH_ERR_KEY_REVOKED; } @@ -1243,7 +1239,7 @@ is_cert_revoked(const struct sshkey *key, struct revoked_certs *rc) rs.lo = rs.hi = key->cert->serial; ers = RB_FIND(revoked_serial_tree, &rc->revoked_serials, &rs); if (ers != NULL) { - KRL_DBG(("%s: revoked serial %llu matched %llu:%llu", __func__, + KRL_DBG(("revoked serial %llu matched %llu:%llu", key->cert->serial, ers->lo, ers->hi)); return SSH_ERR_KEY_REVOKED; } @@ -1266,7 +1262,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); free(rb.blob); if (erb != NULL) { - KRL_DBG(("%s: revoked by key SHA1", __func__)); + KRL_DBG(("revoked by key SHA1")); return SSH_ERR_KEY_REVOKED; } memset(&rb, 0, sizeof(rb)); @@ -1276,7 +1272,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha256s, &rb); free(rb.blob); if (erb != NULL) { - KRL_DBG(("%s: revoked by key SHA256", __func__)); + KRL_DBG(("revoked by key SHA256")); return SSH_ERR_KEY_REVOKED; } @@ -1287,7 +1283,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb); free(rb.blob); if (erb != NULL) { - KRL_DBG(("%s: revoked by explicit key", __func__)); + KRL_DBG(("revoked by explicit key")); return SSH_ERR_KEY_REVOKED; } @@ -1310,7 +1306,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) return r; } - KRL_DBG(("%s: %llu no match", __func__, key->cert->serial)); + KRL_DBG(("%llu no match", key->cert->serial)); return 0; } @@ -1319,15 +1315,15 @@ ssh_krl_check_key(struct ssh_krl *krl, const struct sshkey *key) { int r; - KRL_DBG(("%s: checking key", __func__)); + KRL_DBG(("checking key")); if ((r = is_key_revoked(krl, key)) != 0) return r; if (sshkey_is_cert(key)) { - debug2("%s: checking CA key", __func__); + debug2_f("checking CA key"); if ((r = is_key_revoked(krl, key->cert->signature_key)) != 0) return r; } - KRL_DBG(("%s: key okay", __func__)); + KRL_DBG(("key okay")); return 0; } @@ -1336,32 +1332,116 @@ ssh_krl_file_contains_key(const char *path, const struct sshkey *key) { struct sshbuf *krlbuf = NULL; struct ssh_krl *krl = NULL; - int oerrno = 0, r, fd; + int oerrno = 0, r; if (path == NULL) return 0; - - if ((krlbuf = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((fd = open(path, O_RDONLY)) == -1) { - r = SSH_ERR_SYSTEM_ERROR; - oerrno = errno; - goto out; - } - if ((r = sshkey_load_file(fd, krlbuf)) != 0) { + if ((r = sshbuf_load_file(path, &krlbuf)) != 0) { oerrno = errno; goto out; } if ((r = ssh_krl_from_blob(krlbuf, &krl, NULL, 0)) != 0) goto out; - debug2("%s: checking KRL %s", __func__, path); + debug2_f("checking KRL %s", path); r = ssh_krl_check_key(krl, key); out: - if (fd != -1) - close(fd); sshbuf_free(krlbuf); ssh_krl_free(krl); if (r != 0) errno = oerrno; return r; } + +int +krl_dump(struct ssh_krl *krl, FILE *f) +{ + struct sshkey *key = NULL; + struct revoked_blob *rb; + struct revoked_certs *rc; + struct revoked_serial *rs; + struct revoked_key_id *rki; + int r, ret = 0; + char *fp, timestamp[64]; + + /* Try to print in a KRL spec-compatible format */ + format_timestamp(krl->generated_date, timestamp, sizeof(timestamp)); + fprintf(f, "# KRL version %llu\n", + (unsigned long long)krl->krl_version); + fprintf(f, "# Generated at %s\n", timestamp); + if (krl->comment != NULL && *krl->comment != '\0') { + r = INT_MAX; + asmprintf(&fp, INT_MAX, &r, "%s", krl->comment); + fprintf(f, "# Comment: %s\n", fp); + free(fp); + } + fputc('\n', f); + + RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) { + if ((r = sshkey_from_blob(rb->blob, rb->len, &key)) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + error_r(r, "parse KRL key"); + continue; + } + if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, + SSH_FP_DEFAULT)) == NULL) { + ret = SSH_ERR_INVALID_FORMAT; + error("sshkey_fingerprint failed"); + continue; + } + fprintf(f, "hash: SHA256:%s # %s\n", fp, sshkey_ssh_name(key)); + free(fp); + free(key); + } + RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha256s) { + fp = tohex(rb->blob, rb->len); + fprintf(f, "hash: SHA256:%s\n", fp); + free(fp); + } + RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha1s) { + /* + * There is not KRL spec keyword for raw SHA1 hashes, so + * print them as comments. + */ + fp = tohex(rb->blob, rb->len); + fprintf(f, "# hash SHA1:%s\n", fp); + free(fp); + } + + TAILQ_FOREACH(rc, &krl->revoked_certs, entry) { + fputc('\n', f); + if (rc->ca_key == NULL) + fprintf(f, "# Wildcard CA\n"); + else { + if ((fp = sshkey_fingerprint(rc->ca_key, + SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) { + ret = SSH_ERR_INVALID_FORMAT; + error("sshkey_fingerprint failed"); + continue; + } + fprintf(f, "# CA key %s %s\n", + sshkey_ssh_name(rc->ca_key), fp); + free(fp); + } + RB_FOREACH(rs, revoked_serial_tree, &rc->revoked_serials) { + if (rs->lo == rs->hi) { + fprintf(f, "serial: %llu\n", + (unsigned long long)rs->lo); + } else { + fprintf(f, "serial: %llu-%llu\n", + (unsigned long long)rs->lo, + (unsigned long long)rs->hi); + } + } + RB_FOREACH(rki, revoked_key_id_tree, &rc->revoked_key_ids) { + /* + * We don't want key IDs with embedded newlines to + * mess up the display. + */ + r = INT_MAX; + asmprintf(&fp, INT_MAX, &r, "%s", rki->key_id); + fprintf(f, "id: %s\n", fp); + free(fp); + } + } + return ret; +} diff --git a/krl.h b/krl.h index ce534a111..ca6d3f284 100644 --- a/krl.h +++ b/krl.h @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: krl.h,v 1.7 2019/06/21 04:21:04 djm Exp $ */ +/* $OpenBSD: krl.h,v 1.8 2020/04/03 02:26:56 djm Exp $ */ #ifndef _KRL_H #define _KRL_H @@ -61,6 +61,7 @@ int ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, const struct sshkey **sign_ca_keys, size_t nsign_ca_keys); int ssh_krl_check_key(struct ssh_krl *krl, const struct sshkey *key); int ssh_krl_file_contains_key(const char *path, const struct sshkey *key); +int krl_dump(struct ssh_krl *krl, FILE *f); #endif /* _KRL_H */ diff --git a/log.c b/log.c index d9c2d136c..4d786c2cf 100644 --- a/log.c +++ b/log.c @@ -1,4 +1,4 @@ -/* $OpenBSD: log.c,v 1.51 2018/07/27 12:03:17 markus Exp $ */ +/* $OpenBSD: log.c,v 1.56 2020/12/04 02:25:13 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -51,14 +51,17 @@ #endif #include "log.h" +#include "match.h" static LogLevel log_level = SYSLOG_LEVEL_INFO; static int log_on_stderr = 1; static int log_stderr_fd = STDERR_FILENO; static int log_facility = LOG_AUTH; -static char *argv0; +static const char *argv0; static log_handler_fn *log_handler; static void *log_handler_ctx; +static char **log_verbose; +static size_t nlog_verbose; extern char *__progname; @@ -157,96 +160,30 @@ log_level_name(LogLevel level) return NULL; } -/* Error messages that should be logged. */ - void -error(const char *fmt,...) +log_verbose_add(const char *s) { - va_list args; + char **tmp; - va_start(args, fmt); - do_log(SYSLOG_LEVEL_ERROR, fmt, args); - va_end(args); + /* Ignore failures here */ + if ((tmp = recallocarray(log_verbose, nlog_verbose, nlog_verbose + 1, + sizeof(*log_verbose))) != NULL) { + log_verbose = tmp; + if ((log_verbose[nlog_verbose] = strdup(s)) != NULL) + nlog_verbose++; + } } void -sigdie(const char *fmt,...) +log_verbose_reset(void) { -#ifdef DO_LOG_SAFE_IN_SIGHAND - va_list args; + size_t i; - va_start(args, fmt); - do_log(SYSLOG_LEVEL_FATAL, fmt, args); - va_end(args); -#endif - _exit(1); -} - -void -logdie(const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - do_log(SYSLOG_LEVEL_INFO, fmt, args); - va_end(args); - cleanup_exit(255); -} - -/* Log this message (information that usually should go to the log). */ - -void -logit(const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - do_log(SYSLOG_LEVEL_INFO, fmt, args); - va_end(args); -} - -/* More detailed messages (information that does not need to go to the log). */ - -void -verbose(const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - do_log(SYSLOG_LEVEL_VERBOSE, fmt, args); - va_end(args); -} - -/* Debugging messages that should not be logged during normal operation. */ - -void -debug(const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - do_log(SYSLOG_LEVEL_DEBUG1, fmt, args); - va_end(args); -} - -void -debug2(const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - do_log(SYSLOG_LEVEL_DEBUG2, fmt, args); - va_end(args); -} - -void -debug3(const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - do_log(SYSLOG_LEVEL_DEBUG3, fmt, args); - va_end(args); + for (i = 0; i < nlog_verbose; i++) + free(log_verbose[i]); + free(log_verbose); + log_verbose = NULL; + nlog_verbose = 0; } /* @@ -254,7 +191,8 @@ debug3(const char *fmt,...) */ void -log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr) +log_init(const char *av0, LogLevel level, SyslogFacility facility, + int on_stderr) { #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) struct syslog_data sdata = SYSLOG_DATA_INIT; @@ -370,6 +308,14 @@ log_redirect_stderr_to(const char *logfile) { int fd; + if (logfile == NULL) { + if (log_stderr_fd != STDERR_FILENO) { + close(log_stderr_fd); + log_stderr_fd = STDERR_FILENO; + } + return; + } + if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) { fprintf(stderr, "Couldn't open logfile %s: %s\n", logfile, strerror(errno)); @@ -387,18 +333,9 @@ set_log_handler(log_handler_fn *handler, void *ctx) log_handler_ctx = ctx; } -void -do_log2(LogLevel level, const char *fmt,...) -{ - va_list args; - - va_start(args, fmt); - do_log(level, fmt, args); - va_end(args); -} - -void -do_log(LogLevel level, const char *fmt, va_list args) +static void +do_log(const char *file, const char *func, int line, LogLevel level, + int force, const char *suffix, const char *fmt, va_list args) { #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) struct syslog_data sdata = SYSLOG_DATA_INIT; @@ -410,7 +347,7 @@ do_log(LogLevel level, const char *fmt, va_list args) int saved_errno = errno; log_handler_fn *tmp_handler; - if (level > log_level) + if (!force && level > log_level) return; switch (level) { @@ -453,13 +390,17 @@ do_log(LogLevel level, const char *fmt, va_list args) } else { vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); } + if (suffix != NULL) { + snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", msgbuf, suffix); + strlcpy(msgbuf, fmtbuf, sizeof(msgbuf)); + } strnvis(fmtbuf, msgbuf, sizeof(fmtbuf), log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS); if (log_handler != NULL) { /* Avoid recursion */ tmp_handler = log_handler; log_handler = NULL; - tmp_handler(level, fmtbuf, log_handler_ctx); + tmp_handler(file, func, line, level, fmtbuf, log_handler_ctx); log_handler = tmp_handler; } else if (log_on_stderr) { snprintf(msgbuf, sizeof msgbuf, "%.*s\r\n", @@ -478,3 +419,68 @@ do_log(LogLevel level, const char *fmt, va_list args) } errno = saved_errno; } + +void +sshlog(const char *file, const char *func, int line, int showfunc, + LogLevel level, const char *suffix, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + sshlogv(file, func, line, showfunc, level, suffix, fmt, args); + va_end(args); +} + +void +sshlogdie(const char *file, const char *func, int line, int showfunc, + LogLevel level, const char *suffix, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_INFO, + suffix, fmt, args); + va_end(args); + cleanup_exit(255); +} + +void +sshsigdie(const char *file, const char *func, int line, int showfunc, + LogLevel level, const char *suffix, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_FATAL, + suffix, fmt, args); + va_end(args); + _exit(1); +} + +void +sshlogv(const char *file, const char *func, int line, int showfunc, + LogLevel level, const char *suffix, const char *fmt, va_list args) +{ + char tag[128], fmt2[MSGBUFSIZ + 128]; + int forced = 0; + const char *cp; + size_t i; + + snprintf(tag, sizeof(tag), "%.48s:%.48s():%d", + (cp = strrchr(file, '/')) == NULL ? file : cp + 1, func, line); + for (i = 0; i < nlog_verbose; i++) { + if (match_pattern_list(tag, log_verbose[i], 0) == 1) { + forced = 1; + break; + } + } + + if (log_handler == NULL && forced) + snprintf(fmt2, sizeof(fmt2), "%s: %s", tag, fmt); + else if (showfunc) + snprintf(fmt2, sizeof(fmt2), "%s: %s", func, fmt); + else + strlcpy(fmt2, fmt, sizeof(fmt2)); + + do_log(file, func, line, level, forced, suffix, fmt2, args); +} diff --git a/log.h b/log.h index 78cda287d..5ec793cee 100644 --- a/log.h +++ b/log.h @@ -1,4 +1,4 @@ -/* $OpenBSD: log.h,v 1.24 2019/09/06 04:53:27 djm Exp $ */ +/* $OpenBSD: log.h,v 1.30 2020/12/04 02:25:13 djm Exp $ */ /* * Author: Tatu Ylonen @@ -16,6 +16,7 @@ #define SSH_LOG_H #include /* va_list */ +#include /* ssh_err() */ /* Supported syslog facilities and levels. */ typedef enum { @@ -48,36 +49,83 @@ typedef enum { SYSLOG_LEVEL_NOT_SET = -1 } LogLevel; -typedef void (log_handler_fn)(LogLevel, const char *, void *); +typedef void (log_handler_fn)(const char *, const char *, int, LogLevel, + const char *, void *); -void log_init(char *, LogLevel, SyslogFacility, int); +void log_init(const char *, LogLevel, SyslogFacility, int); LogLevel log_level_get(void); int log_change_level(LogLevel); int log_is_on_stderr(void); void log_redirect_stderr_to(const char *); +void log_verbose_add(const char *); +void log_verbose_reset(void); SyslogFacility log_facility_number(char *); const char * log_facility_name(SyslogFacility); LogLevel log_level_number(char *); const char * log_level_name(LogLevel); -void fatal(const char *, ...) __attribute__((noreturn)) - __attribute__((format(printf, 1, 2))); -void error(const char *, ...) __attribute__((format(printf, 1, 2))); -void sigdie(const char *, ...) __attribute__((noreturn)) - __attribute__((format(printf, 1, 2))); -void logdie(const char *, ...) __attribute__((noreturn)) - __attribute__((format(printf, 1, 2))); -void logit(const char *, ...) __attribute__((format(printf, 1, 2))); -void verbose(const char *, ...) __attribute__((format(printf, 1, 2))); -void debug(const char *, ...) __attribute__((format(printf, 1, 2))); -void debug2(const char *, ...) __attribute__((format(printf, 1, 2))); -void debug3(const char *, ...) __attribute__((format(printf, 1, 2))); - - void set_log_handler(log_handler_fn *, void *); -void do_log2(LogLevel, const char *, ...) - __attribute__((format(printf, 2, 3))); -void do_log(LogLevel, const char *, va_list); void cleanup_exit(int) __attribute__((noreturn)); + +void sshlog(const char *, const char *, int, int, + LogLevel, const char *, const char *, ...) + __attribute__((format(printf, 7, 8))); +void sshlogv(const char *, const char *, int, int, + LogLevel, const char *, const char *, va_list); +void sshsigdie(const char *, const char *, int, int, + LogLevel, const char *, const char *, ...) __attribute__((noreturn)) + __attribute__((format(printf, 7, 8))); +void sshlogdie(const char *, const char *, int, int, + LogLevel, const char *, const char *, ...) __attribute__((noreturn)) + __attribute__((format(printf, 7, 8))); +void sshfatal(const char *, const char *, int, int, + LogLevel, const char *, const char *, ...) __attribute__((noreturn)) + __attribute__((format(printf, 7, 8))); + +#define do_log2(level, ...) sshlog(__FILE__, __func__, __LINE__, 0, level, NULL, __VA_ARGS__) +#define debug3(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG3, NULL, __VA_ARGS__) +#define debug2(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG2, NULL, __VA_ARGS__) +#define debug(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG1, NULL, __VA_ARGS__) +#define verbose(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_VERBOSE, NULL, __VA_ARGS__) +#define logit(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_INFO, NULL, __VA_ARGS__) +#define error(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) +#define fatal(...) sshfatal(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_FATAL, NULL, __VA_ARGS__) +#define logdie(...) sshlogdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) +#define sigdie(...) sshsigdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) + +/* Variants that prepend the caller's function */ +#define do_log2_f(level, ...) sshlog(__FILE__, __func__, __LINE__, 1, level, NULL, __VA_ARGS__) +#define debug3_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG3, NULL, __VA_ARGS__) +#define debug2_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG2, NULL, __VA_ARGS__) +#define debug_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG1, NULL, __VA_ARGS__) +#define verbose_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_VERBOSE, NULL, __VA_ARGS__) +#define logit_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_INFO, NULL, __VA_ARGS__) +#define error_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) +#define fatal_f(...) sshfatal(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_FATAL, NULL, __VA_ARGS__) +#define logdie_f(...) sshlogdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) +#define sigdie_f(...) sshsigdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__) + +/* Variants that appends a ssh_err message */ +#define do_log2_r(r, level, ...) sshlog(__FILE__, __func__, __LINE__, 0, level, ssh_err(r), __VA_ARGS__) +#define debug3_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG3, ssh_err(r), __VA_ARGS__) +#define debug2_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG2, ssh_err(r), __VA_ARGS__) +#define debug_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG1, ssh_err(r), __VA_ARGS__) +#define verbose_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_VERBOSE, ssh_err(r), __VA_ARGS__) +#define logit_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_INFO, ssh_err(r), __VA_ARGS__) +#define error_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) +#define fatal_r(r, ...) sshfatal(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), __VA_ARGS__) +#define logdie_r(r, ...) sshlogdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) +#define sigdie_r(r, ...) sshsigdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) +#define do_log2_fr(r, level, ...) sshlog(__FILE__, __func__, __LINE__, 1, level, ssh_err(r), __VA_ARGS__) +#define debug3_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG3, ssh_err(r), __VA_ARGS__) +#define debug2_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG2, ssh_err(r), __VA_ARGS__) +#define debug_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG1, ssh_err(r), __VA_ARGS__) +#define verbose_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_VERBOSE, ssh_err(r), __VA_ARGS__) +#define logit_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_INFO, ssh_err(r), __VA_ARGS__) +#define error_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) +#define fatal_fr(r, ...) sshfatal(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), __VA_ARGS__) +#define logdie_fr(r, ...) sshlogdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) +#define sigdie_fr(r, ...) sshsigdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__) + #endif diff --git a/loginrec.c b/loginrec.c index e5289deb8..ea058fd6f 100644 --- a/loginrec.c +++ b/loginrec.c @@ -778,6 +778,9 @@ construct_utmpx(struct logininfo *li, struct utmpx *utx) strncpy(utx->ut_host, li->hostname, MIN_SIZEOF(utx->ut_host, li->hostname)); # endif +# ifdef HAVE_SS_IN_UTMPX + utx->ut_ss = li->hostaddr.sa_storage; +# endif # ifdef HAVE_ADDR_IN_UTMPX /* this is just a 32-bit IP address */ if (li->hostaddr.sa.sa_family == AF_INET) diff --git a/aclocal.m4 b/m4/openssh.m4 similarity index 90% rename from aclocal.m4 rename to m4/openssh.m4 index 25ecc49a2..4f9c3792d 100644 --- a/aclocal.m4 +++ b/m4/openssh.m4 @@ -15,12 +15,23 @@ AC_DEFUN([OSSH_CHECK_CFLAG_COMPILE], [{ #include #include int main(int argc, char **argv) { + (void)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); + /* + * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does + * not understand comments and we don't use the "fallthrough" attribute + * that it's looking for. + */ + switch(i){ + case 0: j += i; + /* FALLTHROUGH */ + default: j += k; + } exit(0); } ]])], @@ -52,6 +63,7 @@ AC_DEFUN([OSSH_CHECK_CFLAG_LINK], [{ #include #include int main(int argc, char **argv) { + (void)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; @@ -90,6 +102,7 @@ AC_DEFUN([OSSH_CHECK_LDFLAG_LINK], [{ #include #include int main(int argc, char **argv) { + (void)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; @@ -118,7 +131,7 @@ dnl OSSH_CHECK_HEADER_FOR_FIELD(field, header, symbol) dnl Does AC_EGREP_HEADER on 'header' for the string 'field' dnl If found, set 'symbol' to be defined. Cache the result. dnl TODO: This is not foolproof, better to compile and read from there -AC_DEFUN(OSSH_CHECK_HEADER_FOR_FIELD, [ +AC_DEFUN([OSSH_CHECK_HEADER_FOR_FIELD], [ # look for field '$1' in header '$2' dnl This strips characters illegal to m4 from the header filename ossh_safe=`echo "$2" | sed 'y%./+-%__p_%'` @@ -158,14 +171,15 @@ AC_DEFUN([TYPE_SOCKLEN_T], curl_cv_socklen_t_equiv= for arg2 in "struct sockaddr" void; do for t in int size_t unsigned long "unsigned long"; do - AC_TRY_COMPILE([ - #include - #include - - int getpeername (int, $arg2 *, $t *); - ],[ - $t len; - getpeername(0,0,&len); + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ + #include + #include + int getpeername (int, $arg2 *, $t *); + ]], [[ + $t len; + getpeername(0,0,&len); + ]]) ],[ curl_cv_socklen_t_equiv="$t" break diff --git a/match.c b/match.c index 0953af09d..13441e0e3 100644 --- a/match.c +++ b/match.c @@ -1,4 +1,4 @@ -/* $OpenBSD: match.c,v 1.40 2019/10/04 04:13:39 djm Exp $ */ +/* $OpenBSD: match.c,v 1.43 2020/11/03 22:53:12 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -42,6 +42,7 @@ #include #include #include +#include #include #include "xmalloc.h" @@ -52,7 +53,6 @@ * 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) { @@ -62,8 +62,9 @@ match_pattern(const char *s, const char *pattern) return !*s; if (*pattern == '*') { - /* Skip the asterisk. */ - pattern++; + /* Skip this and any consecutive asterisks. */ + while (*pattern == '*') + pattern++; /* If at end of pattern, accept immediately. */ if (!*pattern) @@ -186,7 +187,7 @@ match_usergroup_pattern_list(const char *string, const char *pattern) /* Windows usernames are case insensitive */ return match_pattern_list(string, pattern, 1); #else - /* Case insensitive match */ + /* Case sensitive match */ return match_pattern_list(string, pattern, 0); #endif } @@ -316,13 +317,13 @@ match_list(const char *client, const char *server, u_int *next) /* * Filter proposal using pattern-list filter. - * "blacklist" determines sense of filter: + * "denylist" 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) +filter_list(const char *proposal, const char *filter, int denylist) { size_t len = strlen(proposal) + 1; char *fix_prop = malloc(len); @@ -340,7 +341,7 @@ filter_list(const char *proposal, const char *filter, int blacklist) *fix_prop = '\0'; while ((cp = strsep(&tmp, ",")) != NULL) { r = match_pattern_list(cp, filter, 0); - if ((blacklist && r != 1) || (!blacklist && r == 1)) { + if ((denylist && r != 1) || (!denylist && r == 1)) { if (*fix_prop != '\0') strlcat(fix_prop, ",", len); strlcat(fix_prop, cp, len); @@ -355,7 +356,7 @@ filter_list(const char *proposal, const char *filter, int blacklist) * the 'filter' pattern list. Caller must free returned string. */ char * -match_filter_blacklist(const char *proposal, const char *filter) +match_filter_denylist(const char *proposal, const char *filter) { return filter_list(proposal, filter, 1); } @@ -365,7 +366,7 @@ match_filter_blacklist(const char *proposal, const char *filter) * the 'filter' pattern list. Caller must free returned string. */ char * -match_filter_whitelist(const char *proposal, const char *filter) +match_filter_allowlist(const char *proposal, const char *filter) { return filter_list(proposal, filter, 0); } diff --git a/match.h b/match.h index 3a8a6ecdc..312ca6e16 100644 --- a/match.h +++ b/match.h @@ -1,4 +1,4 @@ -/* $OpenBSD: match.h,v 1.19 2019/03/06 22:14:23 dtucker Exp $ */ +/* $OpenBSD: match.h,v 1.20 2020/07/05 23:59:45 djm Exp $ */ /* * Author: Tatu Ylonen @@ -21,8 +21,8 @@ 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 *); +char *match_filter_denylist(const char *, const char *); +char *match_filter_allowlist(const char *, const char *); /* addrmatch.c */ int addr_match_list(const char *, const char *); diff --git a/misc.c b/misc.c index 49ef7461c..4aa9c9881 100644 --- a/misc.c +++ b/misc.c @@ -1,29 +1,23 @@ -/* $OpenBSD: misc.c,v 1.142 2019/09/03 08:32:11 djm Exp $ */ +/* $OpenBSD: misc.c,v 1.162 2021/02/28 01:50:47 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. - * Copyright (c) 2005,2006 Damien Miller. All rights reserved. + * Copyright (c) 2005-2020 Damien Miller. All rights reserved. + * Copyright (c) 2004 Henning Brauer * - * 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. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * THIS SOFTWARE IS PROVIDED BY THE 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 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 @@ -38,7 +32,9 @@ #ifdef HAVE_LIBGEN_H # include #endif +#ifdef HAVE_POLL_H #include +#endif #include #include #include @@ -235,29 +231,83 @@ set_rdomain(int fd, const char *name) #endif } +int +get_sock_af(int fd) +{ + struct sockaddr_storage to; + socklen_t tolen = sizeof(to); + + memset(&to, 0, sizeof(to)); + if (getsockname(fd, (struct sockaddr *)&to, &tolen) == -1) + return -1; +#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; +} + +void +set_sock_tos(int fd, int tos) +{ +#ifndef IP_TOS_IS_BROKEN + int af; + + switch ((af = get_sock_af(fd))) { + case -1: + /* assume not a socket */ + break; + case AF_INET: +# ifdef IP_TOS + debug3_f("set socket %d IP_TOS 0x%02x", fd, tos); + if (setsockopt(fd, IPPROTO_IP, IP_TOS, + &tos, sizeof(tos)) == -1) { + error("setsockopt socket %d IP_TOS %d: %s:", + fd, tos, strerror(errno)); + } +# endif /* IP_TOS */ + break; + case AF_INET6: +# ifdef IPV6_TCLASS + debug3_f("set socket %d IPV6_TCLASS 0x%02x", fd, tos); + if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, + &tos, sizeof(tos)) == -1) { + error("setsockopt socket %d IPV6_TCLASS %d: %.100s:", + fd, tos, strerror(errno)); + } +# endif /* IPV6_TCLASS */ + break; + default: + debug2_f("unsupported socket family %d", af); + break; + } +#endif /* IP_TOS_IS_BROKEN */ +} + /* - * Wait up to *timeoutp milliseconds for fd to be readable. Updates + * Wait up to *timeoutp milliseconds for events on fd. Updates * *timeoutp with time remaining. * Returns 0 if fd ready or -1 on timeout or error (see errno). */ -int -waitrfd(int fd, int *timeoutp) +static int +waitfd(int fd, int *timeoutp, short events) { struct pollfd pfd; struct timeval t_start; int oerrno, r; - monotime_tv(&t_start); pfd.fd = fd; - pfd.events = POLLIN; + pfd.events = events; for (; *timeoutp >= 0;) { + monotime_tv(&t_start); 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) + else if (r == -1 && errno != EAGAIN && errno != EINTR) return -1; else if (r == 0) break; @@ -267,6 +317,16 @@ waitrfd(int fd, int *timeoutp) return -1; } +/* + * 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) { + return waitfd(fd, timeoutp, POLLIN); +} + /* * Attempt a non-blocking connect(2) to the specified address, waiting up to * *timeoutp milliseconds for the connection to complete. If the timeout is @@ -286,14 +346,19 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr, 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; + for (;;) { + if (connect(sockfd, serv_addr, addrlen) == 0) { + /* Succeeded already? */ + unset_nonblock(sockfd); + return 0; + } else if (errno == EINTR) + continue; + else if (errno != EINPROGRESS) + return -1; + break; + } - if (waitrfd(sockfd, timeoutp) == -1) + if (waitfd(sockfd, timeoutp, POLLIN | POLLOUT) == -1) return -1; /* Completed or failed */ @@ -479,10 +544,10 @@ a2tun(const char *s, int *remote) * * Return -1 if time string is invalid. */ -long +int convtime(const char *s) { - long total, secs, multiplier = 1; + long total, secs, multiplier; const char *p; char *endp; @@ -496,10 +561,11 @@ convtime(const char *s) while (*p) { secs = strtol(p, &endp, 10); if (p == endp || - (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) || + (errno == ERANGE && (secs == INT_MIN || secs == INT_MAX)) || secs < 0) return -1; + multiplier = 1; switch (*endp++) { case '\0': endp--; @@ -526,10 +592,10 @@ convtime(const char *s) default: return -1; } - if (secs >= LONG_MAX / multiplier) + if (secs > INT_MAX / multiplier) return -1; secs *= multiplier; - if (total >= LONG_MAX - secs) + if (total > INT_MAX - secs) return -1; total += secs; if (total < 0) @@ -540,6 +606,43 @@ convtime(const char *s) return total; } +#define TF_BUFS 8 +#define TF_LEN 9 + +const char * +fmt_timeframe(time_t t) +{ + char *buf; + static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ + static int idx = 0; + unsigned int sec, min, hrs, day; + unsigned long long week; + + buf = tfbuf[idx++]; + if (idx == TF_BUFS) + idx = 0; + + week = t; + + sec = week % 60; + week /= 60; + min = week % 60; + week /= 60; + hrs = week % 24; + week /= 24; + day = week % 7; + week /= 7; + + if (week > 0) + snprintf(buf, TF_LEN, "%02lluw%01ud%02uh", week, day, hrs); + else if (day > 0) + snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); + else + snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); + + return (buf); +} + /* * Returns a standardized host+port identifier string. * Caller must free returned string. @@ -1062,78 +1165,181 @@ tilde_expand_filename(const char *filename, uid_t uid) } /* - * 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. + * Expand a string with a set of %[char] escapes and/or ${ENVIRONMENT} + * substitutions. 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 which the caller must free. */ -char * -percent_expand(const char *string, ...) +static char * +vdollar_percent_expand(int *parseerror, int dollar, int percent, + const char *string, va_list ap) { #define EXPAND_MAX_KEYS 16 - u_int num_keys, i; + u_int num_keys = 0, i; struct { const char *key; const char *repl; } keys[EXPAND_MAX_KEYS]; struct sshbuf *buf; - va_list ap; - int r; - char *ret; + int r, missingvar = 0; + char *ret = NULL, *var, *varend, *val; + size_t len; if ((buf = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); + if (parseerror == NULL) + fatal_f("null parseerror arg"); + *parseerror = 1; - /* 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__); + /* Gather keys if we're doing percent expansion. */ + if (percent) { + 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_f("NULL replacement for token %s", + keys[num_keys].key); + } + } + if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL) + fatal_f("too many keys"); + if (num_keys == 0) + fatal_f("percent expansion without token list"); } - if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL) - fatal("%s: too many keys", __func__); - va_end(ap); /* Expand string */ for (i = 0; *string != '\0'; string++) { - if (*string != '%') { - append: - if ((r = sshbuf_put_u8(buf, *string)) != 0) { - fatal("%s: sshbuf_put_u8: %s", - __func__, ssh_err(r)); + /* Optionally process ${ENVIRONMENT} expansions. */ + if (dollar && string[0] == '$' && string[1] == '{') { + string += 2; /* skip over '${' */ + if ((varend = strchr(string, '}')) == NULL) { + error_f("environment variable '%s' missing " + "closing '}'", string); + goto out; } + len = varend - string; + if (len == 0) { + error_f("zero-length environment variable"); + goto out; + } + var = xmalloc(len + 1); + (void)strlcpy(var, string, len + 1); + if ((val = getenv(var)) == NULL) { + error_f("env var ${%s} has no value", var); + missingvar = 1; + } else { + debug3_f("expand ${%s} -> '%s'", var, val); + if ((r = sshbuf_put(buf, val, strlen(val))) !=0) + fatal_fr(r, "sshbuf_put ${}"); + } + free(var); + string += len; + continue; + } + + /* + * Process percent expansions if we have a list of TOKENs. + * If we're not doing percent expansion everything just gets + * appended here. + */ + if (*string != '%' || !percent) { + append: + if ((r = sshbuf_put_u8(buf, *string)) != 0) + fatal_fr(r, "sshbuf_put_u8 %%"); continue; } string++; /* %% case */ if (*string == '%') goto append; - if (*string == '\0') - fatal("%s: invalid format", __func__); + if (*string == '\0') { + error_f("invalid format"); + goto out; + } for (i = 0; i < num_keys; i++) { if (strchr(keys[i].key, *string) != NULL) { if ((r = sshbuf_put(buf, keys[i].repl, - strlen(keys[i].repl))) != 0) { - fatal("%s: sshbuf_put: %s", - __func__, ssh_err(r)); - } + strlen(keys[i].repl))) != 0) + fatal_fr(r, "sshbuf_put %%-repl"); break; } } - if (i >= num_keys) - fatal("%s: unknown key %%%c", __func__, *string); + if (i >= num_keys) { + error_f("unknown key %%%c", *string); + goto out; + } } - if ((ret = sshbuf_dup_string(buf)) == NULL) - fatal("%s: sshbuf_dup_string failed", __func__); + if (!missingvar && (ret = sshbuf_dup_string(buf)) == NULL) + fatal_f("sshbuf_dup_string failed"); + *parseerror = 0; + out: sshbuf_free(buf); - return ret; + return *parseerror ? NULL : ret; #undef EXPAND_MAX_KEYS } +/* + * Expand only environment variables. + * Note that although this function is variadic like the other similar + * functions, any such arguments will be unused. + */ + +char * +dollar_expand(int *parseerr, const char *string, ...) +{ + char *ret; + int err; + va_list ap; + + va_start(ap, string); + ret = vdollar_percent_expand(&err, 1, 0, string, ap); + va_end(ap); + if (parseerr != NULL) + *parseerr = err; + return ret; +} + +/* + * Returns expanded string or NULL if a specified environment variable is + * not defined, or calls fatal if the string is invalid. + */ +char * +percent_expand(const char *string, ...) +{ + char *ret; + int err; + va_list ap; + + va_start(ap, string); + ret = vdollar_percent_expand(&err, 0, 1, string, ap); + va_end(ap); + if (err) + fatal_f("failed"); + return ret; +} + +/* + * Returns expanded string or NULL if a specified environment variable is + * not defined, or calls fatal if the string is invalid. + */ +char * +percent_dollar_expand(const char *string, ...) +{ + char *ret; + int err; + va_list ap; + + va_start(ap, string); + ret = vdollar_percent_expand(&err, 1, 1, string, ap); + va_end(ap); + if (err) + fatal_f("failed"); + return ret; +} + int tun_open(int tun, int mode, char **ifname) { @@ -1163,16 +1369,16 @@ tun_open(int tun, int mode, char **ifname) break; } } else { - debug("%s: invalid tunnel %u", __func__, tun); + debug_f("invalid tunnel %u", tun); return -1; } if (fd == -1) { - debug("%s: %s open: %s", __func__, name, strerror(errno)); + debug_f("%s open: %s", name, strerror(errno)); return -1; } - debug("%s: %s mode %d fd %d", __func__, name, mode, fd); + debug_f("%s mode %d fd %d", name, mode, fd); /* Bring interface up if it is not already */ snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun); @@ -1180,16 +1386,16 @@ tun_open(int tun, int mode, char **ifname) goto failed; if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) { - debug("%s: get interface %s flags: %s", __func__, - ifr.ifr_name, strerror(errno)); + debug_f("get interface %s flags: %s", 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)); + debug_f("activate interface %s: %s", ifr.ifr_name, + strerror(errno)); goto failed; } } @@ -1254,6 +1460,33 @@ tohex(const void *vp, size_t l) return (r); } +/* + * Extend string *sp by the specified format. If *sp is not NULL (or empty), + * then the separator 'sep' will be prepended before the formatted arguments. + * Extended strings are heap allocated. + */ +void +xextendf(char **sp, const char *sep, const char *fmt, ...) +{ + va_list ap; + char *tmp1, *tmp2; + + va_start(ap, fmt); + xvasprintf(&tmp1, fmt, ap); + va_end(ap); + + if (*sp == NULL || **sp == '\0') { + free(*sp); + *sp = tmp1; + return; + } + xasprintf(&tmp2, "%s%s%s", *sp, sep == NULL ? "" : sep, tmp1); + free(tmp1); + free(*sp); + *sp = tmp2; +} + + u_int64_t get_u64(const void *vp) { @@ -1513,7 +1746,7 @@ mktemp_proto(char *s, size_t len) } r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX"); if (r < 0 || (size_t)r >= len) - fatal("%s: template string too short", __func__); + fatal_f("template string too short"); } static const struct { @@ -1542,6 +1775,7 @@ static const struct { { "cs6", IPTOS_DSCP_CS6 }, { "cs7", IPTOS_DSCP_CS7 }, { "ef", IPTOS_DSCP_EF }, + { "le", IPTOS_DSCP_LE }, { "lowdelay", IPTOS_LOWDELAY }, { "throughput", IPTOS_THROUGHPUT }, { "reliability", IPTOS_RELIABILITY }, @@ -1599,8 +1833,7 @@ unix_listener(const char *path, int backlog, int unlink_first) 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); + error_f("path \"%s\" too long for Unix domain socket", path); errno = ENAMETOOLONG; return -1; } @@ -1608,7 +1841,7 @@ unix_listener(const char *path, int backlog, int unlink_first) sock = socket(PF_UNIX, SOCK_STREAM, 0); if (sock == -1) { saved_errno = errno; - error("%s: socket: %.100s", __func__, strerror(errno)); + error_f("socket: %.100s", strerror(errno)); errno = saved_errno; return -1; } @@ -1618,16 +1851,14 @@ unix_listener(const char *path, int backlog, int unlink_first) } if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { saved_errno = errno; - error("%s: cannot bind to path %s: %s", - __func__, path, strerror(errno)); + error_f("cannot bind to path %s: %s", path, strerror(errno)); close(sock); errno = saved_errno; return -1; } if (listen(sock, backlog) == -1) { saved_errno = errno; - error("%s: cannot listen on path %s: %s", - __func__, path, strerror(errno)); + error_f("cannot listen on path %s: %s", path, strerror(errno)); close(sock); unlink(path); errno = saved_errno; @@ -1799,7 +2030,7 @@ argv_assemble(int argc, char **argv) struct sshbuf *buf, *arg; if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); for (i = 0; i < argc; i++) { ws = 0; @@ -1824,17 +2055,16 @@ argv_assemble(int argc, char **argv) break; } if (r != 0) - fatal("%s: sshbuf_put_u8: %s", - __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_put_u8"); } 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)); + fatal_fr(r, "assemble"); } if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL) - fatal("%s: malloc failed", __func__); + fatal_f("malloc failed"); memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf)); ret[sshbuf_len(buf)] = '\0'; sshbuf_free(buf); @@ -1850,7 +2080,7 @@ exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet) while (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) { - error("%s: waitpid: %s", tag, strerror(errno)); + error("%s waitpid: %s", tag, strerror(errno)); return -1; } } @@ -2243,3 +2473,275 @@ opt_match(const char **opts, const char *term) return 0; } +void +opt_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)++; +} + +void +opt_array_append(const char *file, const int line, const char *directive, + char ***array, u_int *lp, const char *s) +{ + opt_array_append2(file, line, directive, array, NULL, lp, s, 0); +} + +sshsig_t +ssh_signal(int signum, sshsig_t handler) +{ + struct sigaction sa, osa; + + /* mask all other signals while in handler */ + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = handler; + sigfillset(&sa.sa_mask); +#if defined(SA_RESTART) && !defined(NO_SA_RESTART) + if (signum != SIGALRM) + sa.sa_flags = SA_RESTART; +#endif + if (sigaction(signum, &sa, &osa) == -1) { + debug3("sigaction(%s): %s", strsignal(signum), strerror(errno)); + return SIG_ERR; + } + return osa.sa_handler; +} + +int +stdfd_devnull(int do_stdin, int do_stdout, int do_stderr) +{ + int devnull, ret = 0; + + if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { + error_f("open %s: %s", _PATH_DEVNULL, + strerror(errno)); + return -1; + } + if ((do_stdin && dup2(devnull, STDIN_FILENO) == -1) || + (do_stdout && dup2(devnull, STDOUT_FILENO) == -1) || + (do_stderr && dup2(devnull, STDERR_FILENO) == -1)) { + error_f("dup2: %s", strerror(errno)); + ret = -1; + } + if (devnull > STDERR_FILENO) + close(devnull); + return ret; +} + +/* + * 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, const char *command, + int ac, char **av, FILE **child, u_int flags, + struct passwd *pw, privdrop_fn *drop_privs, privrestore_fn *restore_privs) +{ + FILE *f = NULL; + struct stat st; + int fd, devnull, p[2], i; + pid_t pid; + char *cp, errmsg[512]; + u_int nenv = 0; + char **env = NULL; + + /* If dropping privs, then must specify user and restore function */ + if (drop_privs != NULL && (pw == NULL || restore_privs == NULL)) { + error("%s: inconsistent arguments", tag); /* XXX fatal? */ + return 0; + } + if (pw == NULL && (pw = getpwuid(getuid())) == NULL) { + error("%s: no user for current uid", tag); + return 0; + } + if (child != NULL) + *child = NULL; + + debug3_f("%s command \"%s\" running as %s (flags 0x%x)", + tag, command, pw->pw_name, flags); + + /* Check consistency */ + if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 && + (flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0) { + error_f("inconsistent flags"); + return 0; + } + if (((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0) != (child == NULL)) { + error_f("inconsistent flags/output"); + return 0; + } + + /* + * If executing an explicit binary, then verify the it exists + * and appears safe-ish to execute + */ + if (!path_absolute(av[0])) { + error("%s path is not absolute", tag); + return 0; + } + if (drop_privs != NULL) + drop_privs(pw); + if (stat(av[0], &st) == -1) { + error("Could not stat %s \"%s\": %s", tag, + av[0], strerror(errno)); + goto restore_return; + } + + if ((flags & SSH_SUBPROCESS_UNSAFE_PATH) == 0 && +#ifdef WINDOWS + (check_secure_file_permission(av[0], pw, 1) != 0)) { + error("Permissions on %s:\"%s\" are too open", tag, av[0]); +#else + safe_path(av[0], &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) { + error("Unsafe %s \"%s\": %s", tag, av[0], errmsg); +#endif + goto restore_return; + } + + /* Prepare to keep the child's stdout if requested */ + if (pipe(p) == -1) { + error("%s: pipe: %s", tag, strerror(errno)); + restore_return: + if (restore_privs != NULL) + restore_privs(); + return 0; + } + if (restore_privs != NULL) + restore_privs(); + +#ifdef FORK_NOT_SUPPORTED + { + posix_spawn_file_actions_t actions; + pid = -1; + + if (posix_spawn_file_actions_init(&actions) != 0 || + posix_spawn_file_actions_adddup2(&actions, p[1], STDOUT_FILENO) != 0) + fatal("posix_spawn initialization failed"); + else { +#ifdef WINDOWS + /* If the user's SID is the System SID and sshd is running as system, + * launch as a child process. + */ + if (IsWellKnownSid(get_sid(pw->pw_name), WinLocalSystemSid) && am_system()) { + debug("starting subprocess using posix_spawnp"); + if (posix_spawnp((pid_t*)&pid, av[0], &actions, NULL, av, NULL) != 0) + fatal("posix_spawnp: %s", strerror(errno)); + } + else +#endif + { + debug("starting subprocess as user using __posix_spawn_asuser"); + if (__posix_spawn_asuser((pid_t*)&pid, av[0], &actions, NULL, av, NULL, pw->pw_name) != 0) + fatal("posix_spawn_user: %s", strerror(errno)); + } + } + + posix_spawn_file_actions_destroy(&actions); + } +#else + 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. */ + if ((flags & SSH_SUBPROCESS_PRESERVE_ENV) == 0) { + nenv = 5; + env = xcalloc(sizeof(*env), nenv); + child_set_env(&env, &nenv, "PATH", _PATH_STDPATH); + child_set_env(&env, &nenv, "USER", pw->pw_name); + child_set_env(&env, &nenv, "LOGNAME", pw->pw_name); + child_set_env(&env, &nenv, "HOME", pw->pw_dir); + if ((cp = getenv("LANG")) != NULL) + child_set_env(&env, &nenv, "LANG", cp); + } + + for (i = 1; i < NSIG; i++) + ssh_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); + + if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) { + 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) == -1) { + 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); + } + if (env != NULL) + execve(av[0], av, env); + else + execv(av[0], av); + error("%s %s \"%s\": %s", tag, env == NULL ? "execv" : "execve", + command, strerror(errno)); + _exit(127); + default: /* parent */ + break; + } +#endif + 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_f("%s pid %ld", tag, (long)pid); + if (child != NULL) + *child = f; + return pid; +} diff --git a/misc.h b/misc.h index bcc34f980..2de7eb5bf 100644 --- a/misc.h +++ b/misc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.h,v 1.81 2019/09/03 08:32:11 djm Exp $ */ +/* $OpenBSD: misc.h,v 1.93 2021/02/15 20:36:35 markus Exp $ */ /* * Author: Tatu Ylonen @@ -53,6 +53,8 @@ void set_nodelay(int); int set_reuseaddr(int); char *get_rdomain(int); int set_rdomain(int, const char *); +int get_sock_af(int); +void set_sock_tos(int, int); int waitrfd(int, int *); int timeout_connect(int, const struct sockaddr *, socklen_t, int *); int a2port(const char *); @@ -65,10 +67,16 @@ 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 *); +int convtime(const char *); +const char *fmt_timeframe(time_t t); char *tilde_expand_filename(const char *, uid_t); + +char *dollar_expand(int *, const char *string, ...); char *percent_expand(const char *, ...) __attribute__((__sentinel__)); +char *percent_dollar_expand(const char *, ...) __attribute__((__sentinel__)); char *tohex(const void *, size_t); +void xextendf(char **s, const char *sep, const char *fmt, ...) + __attribute__((__format__ (printf, 3, 4))) __attribute__((__nonnull__ (3))); void sanitise_stdfd(void); void ms_subtract_diff(struct timeval *, int *); void ms_to_timeval(struct timeval *, int); @@ -84,12 +92,23 @@ 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 *); +int stdfd_devnull(int, int, int); void sock_set_v6only(int); struct passwd *pwcopy(struct passwd *); const char *ssh_gai_strerror(int); +typedef void privdrop_fn(struct passwd *); +typedef void privrestore_fn(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 */ +#define SSH_SUBPROCESS_UNSAFE_PATH (1<<3) /* Don't check for safe cmd */ +#define SSH_SUBPROCESS_PRESERVE_ENV (1<<4) /* Keep parent environment */ +pid_t subprocess(const char *, const char *, int, char **, FILE **, u_int, + struct passwd *, privdrop_fn *, privrestore_fn *); + typedef struct arglist arglist; struct arglist { char **list; @@ -171,6 +190,13 @@ int opt_flag(const char *opt, int allow_negate, const char **optsp); char *opt_dequote(const char **sp, const char **errstrp); int opt_match(const char **opts, const char *term); +/* readconf/servconf option lists */ +void opt_array_append(const char *file, const int line, + const char *directive, char ***array, u_int *lp, const char *s); +void opt_array_append2(const char *file, const int line, + const char *directive, char ***array, int **iarray, u_int *lp, + const char *s, int i); + /* readpass.c */ #define RP_ECHO 0x0001 @@ -178,11 +204,20 @@ int opt_match(const char **opts, const char *term); #define RP_ALLOW_EOF 0x0004 #define RP_USE_ASKPASS 0x0008 +struct notifier_ctx; + char *read_passphrase(const char *, int); int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2))); +struct notifier_ctx *notify_start(int, const char *, ...) + __attribute__((format(printf, 2, 3))); +void notify_complete(struct notifier_ctx *, const char *, ...) + __attribute__((format(printf, 2, 3))); #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)) +typedef void (*sshsig_t)(int); +sshsig_t ssh_signal(int, sshsig_t); + #endif /* _MISC_H */ diff --git a/moduli b/moduli index a6c13d8c2..6103e989c 100644 --- a/moduli +++ b/moduli @@ -1,452 +1,407 @@ -# $OpenBSD: moduli,v 1.24 2019/04/26 08:37:16 dtucker Exp $ +# $OpenBSD: moduli,v 1.28 2020/09/30 09:11:38 dtucker Exp $ # Time Type Tests Tries Size Generator Modulus -20181031113618 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE0BE8103 -20181031113634 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE0C7C3CF -20181031113642 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE0C8204B -20181031113722 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE0E7A6DB -20181031113747 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE0F5096B -20181031113822 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE11027BF -20181031113906 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE12EA013 -20181031113934 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE13F42E7 -20181031114007 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE15AA2C3 -20181031114101 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE18AB6BB -20181031114215 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE1C69837 -20181031114328 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE207143B -20181031114445 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE24E3977 -20181031114549 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE2843EE7 -20181031114559 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE285908B -20181031114647 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE2A7511B -20181031114706 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE2B08EBF -20181031114734 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE2C326CF -20181031114807 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE2E0BCBB -20181031114901 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE30D862B -20181031114935 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE32AADEF -20181031114949 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE32F8FDB -20181031115050 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE372E443 -20181031115213 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE3C3748F -20181031115339 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE4158847 -20181031115400 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE4262F2F -20181031115438 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE452029F -20181031115505 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE467FAEB -20181031115602 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE4A3A77B -20181031115728 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE4F4FEC3 -20181031115752 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE50404F3 -20181031115803 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE50889BB -20181031115940 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE57A3D23 -20181031120037 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE5CC4913 -20181031120051 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE5D944FB -20181031120113 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE5EF41F7 -20181031120225 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE646894F -20181031120258 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE670C3B7 -20181031120333 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE69AD617 -20181031120339 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE69AE223 -20181031120356 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE6ADE1B3 -20181031120414 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE6BD0ACF -20181031120712 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE7ACC18B -20181031120724 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE7B37CAB -20181031120737 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE7BF34CF -20181031120819 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE7F719A3 -20181031120825 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE7F7A70F -20181031120834 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE7FD3383 -20181031120841 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE7FF6C03 -20181031120850 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE806800F -20181031120856 2 6 100 2047 2 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE807F56B -20181031120905 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE80BD7DF -20181031120923 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE81F7F6F -20181031121031 2 6 100 2047 5 F13B549CC6FE8517551E48FAEBA8D93EAC29403838E22ED862927B8AC9A9ABBA96AB7E306F0A01B75C0E960AB9DEA0F8519BAA2F13E541E194604848CBC9DEC51165E7A45897104B4A9C54C7337270A8B1B7F53B9DC203744ED2C634889C879E713BEA519452AE800B390FFBABF40B992AF659947D3ED78AA04DDF51C84D7B0824978643683F2153C99F682E30A25683CE180948F62E2CC1EFA1513CB16E74117334356E4E365132BB37BA41B4B79F148F26842A61F12D42B149F3FAB0041CB7DF7F53742544FA4E956D314B140F49786E23A5446C1F5CD55CB59D845774C6D6EF1CE5B7426F351FE906C69D23720BCFC5E250DE2786ACEBEC823E1DE88D9BB7 -20181031121153 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD79F990A17 -20181031121230 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD79FC4B55B -20181031121305 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD79FF25EFF -20181031121338 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A0250433 -20181031121452 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A0A900D3 -20181031121515 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A0C7B767 -20181031121531 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A0DB38C3 -20181031121542 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A0E45E73 -20181031121642 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A13B7883 -20181031121702 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A155F0FF -20181031121739 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A19802C3 -20181031121744 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A198FC0B -20181031121802 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A1B38723 -20181031121819 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A1CBBC3F -20181031121927 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A24638B7 -20181031121954 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A26FE49F -20181031121959 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A272126F -20181031122023 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A2962B0B -20181031122035 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A2A69E27 -20181031122128 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A2F49F9B -20181031122137 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A2FC98C7 -20181031122211 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A32E8983 -20181031122217 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A332034B -20181031122230 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A341BC13 -20181031122415 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A3E82A8B -20181031122441 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A405F593 -20181031122523 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A44029BB -20181031122645 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A4A62F13 -20181031122739 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A4D96A23 -20181031122811 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A4F1B05B -20181031122853 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A5184683 -20181031122948 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A549FBCF -20181031123010 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A5593157 -20181031123029 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A5681F87 -20181031123056 2 6 100 2047 2 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A57EC4B3 -20181031123230 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A5DD04FF -20181031123244 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A5E3B3D7 -20181031123450 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A660A94F -20181031123530 2 6 100 2047 5 FAEA3B642004FC1DB17244B7DE6AE7EFEA5B3AB4D54A13674A0E4B460E9D0716E6313530F9BA5D9C959562FD4A1D23FC92D99F1060A3C1B374050C77152C461AEC19CBE7AD6818C48CC9568FF8F4E45367C1053D6DEBCF76BD4DE8E3BA808FA43A3649722202C83417ED96F423DCEA18BB3F99E4598C797D05E0D3E6D2E27A5EC0B10304BB7643AEA01DD989AE84AA4B08AC3AA5613C222C41F5CD46EAF191343F1D07664F2D6E7BC876BFC46CFEFBE50991EBC15664112F6DC8D58D6665B9BB9F974D7210AB8E04F963128E43D92B6D645A963121058BA29C668AC5DA81DF3CC17908D240E8771EB52E4396AB6DA2157F3EE55D0C0E20A52C560FD7A68FC267 -20181031125435 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11528E4B7 -20181031125919 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B115D90A53 -20181031130156 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B116301C17 -20181031130212 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11631DCAF -20181031130646 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B116E4CA3B -20181031130658 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B116E4E133 -20181031130803 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B117068663 -20181031130826 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B1170E270F -20181031131600 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B1184656D3 -20181031131740 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11883D577 -20181031131908 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B118B728DB -20181031131956 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B118D00F87 -20181031132017 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B118D567E7 -20181031132405 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B1196905F7 -20181031132450 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11980B233 -20181031132510 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B119877CCB -20181031132628 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B119B78FAF -20181031133030 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11A5CA257 -20181031133638 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11B5728B7 -20181031133714 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11B698D4F -20181031133816 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11B8BE2EF -20181031134152 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11C1D39BB -20181031134307 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11C4B4083 -20181031134804 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11D1356A7 -20181031135113 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11D93FB63 -20181031135414 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11E0CAEBB -20181031135744 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11E9CB9E3 -20181031140159 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11F4E4B63 -20181031140258 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11F72025B -20181031140622 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B11FFAA343 -20181031140654 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B120087713 -20181031140849 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B12052E023 -20181031141317 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B1210F24F7 -20181031141517 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B1215A8893 -20181031141539 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B12161A467 -20181031142722 2 6 100 3071 2 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B1234E3F83 -20181031143116 2 6 100 3071 5 DE6700153B27F195B230266F3E9064D8646E4E27111A6C5A013DE98A5CD7F11B31B1DC4C71DD72CBEC38DA508B1AD04CB69A372B8D01396C5AE7F5F99C3C3CBE1B2B3287C6AB5794E3AFD6C4E5C8E23B76E21A479765DD7D0D8D41A75DA966486E2C94030AA81314CFC104172048A82D95F402FA9B12E2CF3469AF6202F527BB5FADD82F7F5A67CF47EAA9F70FA02A55D45688EC65A26E8A8BCBD47BEA5C70721995434D0736F3396E9D1681BB08A336B0A9E3340AA24D1E9AC4B33103438C130B4BB87A22D3D85B8BC66B66679790AF7429D0B8F8CEE9BFA7F34239E0F109DABE5370196CB46C134B184178ED494D4703A681A18FFE9A4D6FF5EE71E141EBE11C6E3A6FEE7586F9D5B400EFDF06289783269BD86F1F38CABB0FBEAE666C0FE9EDAF7D1017DCCFBC4AEE1F1BE6FDA3EBD47C7E2BA2D54CC61B740E94B171E0FC2A0F93BF1B93FA4C1D6050106D20A69C11B16AC43EA17C6EE954444B05DCCAD5DAB6794A98FEE7256EA9B1F817E80D86C9242CFA02EED926E200C7B123D4E7B7 -20181031144633 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5BD211E4B -20181031144827 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5BD69A2F3 -20181031145126 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5BDE3D567 -20181031145403 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5BE4DA06B -20181031150010 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5BF499357 -20181031150458 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C00F4FE3 -20181031150931 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C0C7C2CF -20181031151259 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C159195F -20181031151525 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C1B99ABF -20181031152039 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C29330EB -20181031152155 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C2C100E7 -20181031152224 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C2CD60CF -20181031152510 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C33CEF4F -20181031152907 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C3E0892F -20181031153155 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C44E0077 -20181031153227 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C45D1D9F -20181031153350 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C493C143 -20181031153609 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C4EF9D0B -20181031153956 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C5898C03 -20181031154033 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C59B843B -20181031154104 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C5A94107 -20181031154333 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C60D5BBB -20181031154832 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C6DD0793 -20181031155320 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C7A1DB4B -20181031155718 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C842B8B7 -20181031160130 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C8EEDABB -20181031160435 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5C96EA9B7 -20181031161312 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CAE0E013 -20181031161424 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CB0BFEAB -20181031161443 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CB10BF07 -20181031161804 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CB9812B3 -20181031162300 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CC62B69B -20181031162439 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CC9EFAAB -20181031162719 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CD0A69F7 -20181031162832 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CD357E3F -20181031162924 2 6 100 3071 5 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CD51C05F -20181031162948 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CD5A0C83 -20181031163058 2 6 100 3071 2 D55876EAB302ADAA592F62BBE1E67B18C153FA6D93B6CF3C0D0E8989C13F29E1F6638AE58634C6A3C067754CA1241A8EDA45CB1306347BC6BA69D2CE5F515238C78CAFEB65D4FF05D52048EB048BE9B4C127C81EC60B978A372A5054B89BA7D8963DA343DB7F5B673B275E34D03A25C098FEE46063F963E47CAEB67A4915F413570C89224688F4598D25EEEE97DE581256261C0053CCBA12966E31849F31BF32BC506029A41F94356714EF0046FF68D5B75EC86ACB79708CD817C7752EA5E0D5E730245B06B91953434E2325B706C70492446CFC070C11F8E347AFDDB065B680A075BF287DEBFA9D59EE918B85D5D0157CD539A5E46888F39DB448D1D6BFAD57A3970C537387B556D801960276284F363287FE0230CA1950725B1B09A54DEDDF924BE8059E38A729A400582713F149E7E1005C8B0FB302ECA12D8949BA2B4FC645BE96B3F20384384626F1BA1F4E8E045442DDD6A124DECC49B8CDBD6D4217978F69FF8DE7B7F4B15908881391F81F43DF6FBD616398BE9225FE3AC5CD82F3D3 -20181031163809 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A1925064B -20181031164609 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A19BA1E2B -20181031170331 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A1B0331C7 -20181031174642 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A1E40577F -20181031175327 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A1EBA2BA3 -20181031190736 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A24551BC7 -20181031192252 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A256E6A8B -20181031193735 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A26848667 -20181031194031 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A26B3187F -20181031194403 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A26EC656B -20181031194833 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A273A8833 -20181031195443 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A27A959BF -20181031195836 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A27EBBC83 -20181031200940 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A28B88307 -20181031203106 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2A47E5BF -20181031203858 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2AD76CDB -20181031204443 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2B3F16FF -20181031205841 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2C416607 -20181031210215 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2C7C62CF -20181031211110 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2D1C8377 -20181031212747 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2E532EF7 -20181031214614 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A2FAEF903 -20181031215951 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A30A680FB -20181031222543 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A328D6FAB -20181031222846 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A32BD423F -20181031224038 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A339269AB -20181031225211 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A34692BDB -20181031225338 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A347B8EFF -20181031225926 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A34DFF2BB -20181031231202 2 6 100 4095 5 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A35C67F5F -20181031233350 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A3758AE93 -20181031233800 2 6 100 4095 2 FC69089A469473B9CF3F3CCD21123CCF3563811632E7FB6CDF9CDF7726AFA4691881289B3952D2347D7BA520E95016066B02888C7EA1E633B998E00EFE78E454EAF64D6462437E9DDB4A239DE998EC0756E7ED17B7A3499CCF2E3F33A54FD223BB6C485AECA2475E2C002C303F6A55530F2F83A98059699C59A43238468FC85CD137A1FC9B9674ED5D746B44848339A9CA772E802BCE56FED99E8B110C8CA365DFB9BFDD47CB2A33CA92469B3BCC6758B73A7A5685F3FB74B6D785ACFA15E462CA9E70453CD1E9D48D146F0951E4E10773A4FBC9C8E2948D2A091525F964FDE6B60BC3C7A175FF88D20A3758B2D6C35F253AF00B95697F32446EAAA00C7B8A3C4B9DC47EDF44BC4C35052CF7304ADE74A0A9C70575FA935961B07B908D9E58454662B0ED6D8148B79FC45B1F5EDD602B13C7285A75B901183C87CF0F6C060E40D48D9910BDB86C2A253C9894CCE7034DEB7707EF5256DE8E98570375845ADABAAF81893FF6D9E61E45FE9906E61CD2FB86F4A1ABC0D51527B56D3329192EBDFA78149C4652EA23463D6FEFC6F79F22154631CEB04692FB67B815FF791576AB9BA71B0A51009D4B2ECF0ED280745831B4B6B49D951479E5E6831F19CE717025AE212A3057D21832E86C847970CF0CEA82D19BC3D211A23EE2CB6B60ED499F1910A4AEC72FEE2BCA10E8BA9AC47ED2D953E1429B056CCEAD0ED2715D2A379DD5F3 -20181101001517 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C3B843C3 -20181101001909 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C3FC854F -20181101003052 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C4D5B923 -20181101003946 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C578D833 -20181101004718 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C60301F7 -20181101011451 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C80CD293 -20181101012546 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C8D7E023 -20181101013857 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C9CDF40F -20181101014111 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002C9EF64FB -20181101014518 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CA3777C7 -20181101014810 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CA6853C3 -20181101015518 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CAE81C2F -20181101022434 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CD0FC883 -20181101022626 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CD297D7B -20181101023305 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CDA00627 -20181101024528 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CE8651DF -20181101024730 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CEA46B8F -20181101025218 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002CEFBF913 -20181101030928 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D039AC1B -20181101031126 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D0557A5B -20181101032741 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D184F8BB -20181101033140 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D1C803A3 -20181101033414 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D1F094A7 -20181101033713 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D21F8203 -20181101034124 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D268646B -20181101035424 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D3556B5B -20181101042126 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D556768F -20181101043318 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D62CB7EF -20181101050055 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D835583B -20181101052304 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002D9D786F3 -20181101053022 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DA550ABB -20181101055828 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DC5EBE23 -20181101055855 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DC5EC45F -20181101061019 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DD2F3B53 -20181101061349 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DD68BE4B -20181101061523 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DD7D755B -20181101063404 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DED7E937 -20181101064144 2 6 100 4095 5 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DF60EDC7 -20181101064624 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002DFAC40E3 -20181101070243 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002E0D7FD93 -20181101070718 2 6 100 4095 2 CB00EACDC1EDB3E4111DB89DA6722A2D66156FC2F5B602DCE0510B47F36F6E94615D96D222BD22037AD407B782A888F534CE84C04E6B78FDF3F24C869960888D33F8396A58F34238B7E2F2BF3CE48263BE78474C422A073FCCF02C47218509E5A989208456CC7ECCB7004957802A413AA0AB3E51C29FB53A99886977A86B4C47A56C2F312D3BA2B2CC4D5CE637B13A77369D5D5CF478E9D38389969F5CF041863F1D5714F11BC66C0FEF500A6B3FEB18BDF575E9E0F066E0A42DEC284B5A23D1C31C628F672D94363CBCCEA7C81636D51D81337E7556B726B35185139FA7568978E684E511DB467D92F0B56B43ADF802E7ADC15107723068B06E024DD25340B228AE9674BC3FC58D6BD55FE67F01B197847B6F4FE8F2DF6BC8C72292067C6BEA73C1D8176926BDBB7A620C36CEC57230A89C9799416E68ECEB323425728DE2830C64979DDEC6355F2BB391FBDC705A5C1537EB03D2372650409D7084D6FF1B3913F9796109B40CAD99DC8B4EED4379A67E96FD1192BC87A5C60A410BB6996D1E0DA0D7E43CE2632B14714E6A25569B9F42D51F22C067F12E6E030DF1205FC91429E93214891F026089748772A64DD21C2F13EC3BEBC313187FB8936613D8E4A93F8569FFC6C6509D43F3939D4CFA5BF958D6E1E9E148DDD3E332728957413FA6084CDDC1263419C9C712F5DC3177F39F0EE5CB8B5F90EE60EEC4A002E12169CB -20181101074507 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AC509A2DF -20181101080039 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AC560A423 -20181101090537 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AC6F28D1F -20181101092350 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AC75F93C3 -20181101133727 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4ACDA5C3BF -20181101153921 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AD0A30BD7 -20181101171128 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AD2DFFEAB -20181101174632 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AD3B43EF3 -20181101182605 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AD4A147DB -20181101203006 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AD79B0197 -20181101204455 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AD7F055F3 -20181101205817 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AD837F15B -20181102024420 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AE097172B -20181102055827 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AE5403DDB -20181102071828 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AE71BA84B -20181102092836 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AEA2D28E3 -20181102103738 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AEBD11737 -20181102114713 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AED6CB613 -20181102115644 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AEDA11D23 -20181102121940 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AEE243617 -20181102130721 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AEF3698BF -20181102141842 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF0DFB873 -20181102154420 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF2D2C0A3 -20181102154806 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF2DFCAFB -20181102163042 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF3D211A3 -20181102165448 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF45675DB -20181102181017 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF614E323 -20181102193623 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF80E023F -20181102203258 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AF956439F -20181102221408 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AFBAC649B -20181102225455 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AFC958F53 -20181102232700 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AFD502EE3 -20181103011316 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4AFFC84A6B -20181103033644 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4B031123EB -20181103045613 2 6 100 6143 2 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4B04EC8B2B -20181103061743 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4B06C56A47 -20181103094430 2 6 100 6143 5 CAD8A4810C1ADC23A2317EA8BB2F93AD4198F948452AD65159BD3D71800456C339AFD34BC6D512D8FCD337463E3CDFBB4E81A9BE01A6FBA103051D50118610088400DEE2C8E51376B07593D50760832754D352737620CB3BD45CF6A0356209541D14FA9A356DB075DAC362617DF28B202B8FF5FE65A7A6106715796ECC5433DF29FDE1BA29D1D70BB0248EFEEE7DCB10B78EDE9F37078D39AEE37395927F97C2E8C8D80747496C5F4C7ED0A14193BDABE56665BE74475CBD49049F7BE47366B32A1E828B3155A7D48F1D06052DDAA3C0C24550772A69F0E3635794B1FC8BFF6274582092BE2CB3323269D3433FF6CC0294074B0BD8E5DF1A42A4A2A687FE9C4772994FA5EA75F099539D9A7761C687F3F2896D0517E73ABC64C8A330E740DB99537F30E9566497DE782C8F5A5A9E64111478A69BA4535C72B323CCCAFFD7E2C181009424D4CA391B0CED89411455E8CB00147E098716861AAB1B18EC5F295F22C8F687C9DBA534BDDF5F98D94E07F0DFFBB9D272AD71A7B1F657794E36EABA60A6D097F0AB4C405909F5D3D15B177496BCE74217892D701745D176AC5A6049C75F2C17C18FB00F09DFCF1934E69E64DC4C758C3353411503479EE07D7660B67DFDE76DD3FA26B2894DC3C6F5A87059657428324E613F7FE6AD25B09D73133AE16C0A5CA8E285BEF024DE79A27A3C363A70B80AAA1638EDEE29FCBD929D6AE23A5A064769F474D116DD11EACCA5B629EFAB4A95053BD9EBD5B21A3AC3CCD503EDF8CC659FBEAE8FC4EEB2B59CEB41438752AD130476F2DE793FB993BDE8057F1F31437F053B847653D379E2ED78491A0AF3F8ADFC4FF023DB11CC9087AFFC810FE16491CEE4E7CB8622C47E0F44479C0C6D915F4A68723B38FBE83DFDCEE4D5745CD316444BD98C951DAA9706795FE922754B80DB3AE924FBEC44AEF4C3D31EB9299175322FEF02A52E854377030F9BF09AB7CC1BF5327C8746BCAD1AA0A876B740FBCA2C914D45BA75292A2329078DF05ECDC8EA0C149D29E481AA1CA80DB2A13ADA476DE3D82D24136A5B92B7FCCC486A785706FF8ED0CD41F5DF4B0B7BA467 -20181103110754 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1949920F8B -20181103141747 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB194E3CB3E3 -20181103152440 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB194FD1CDE7 -20181103155517 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB195089F093 -20181103161259 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1950F052F7 -20181103173322 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1952DF5333 -20181103181221 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1953CC5B37 -20181103194325 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1955FDACA3 -20181103194542 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB195602AE57 -20181103205409 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1957A5593B -20181103221714 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1959A6D687 -20181104161809 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1973A572FF -20181104162823 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1973D9C983 -20181104163116 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1973E18163 -20181104164151 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB19741666EB -20181104183842 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1976CE68FB -20181104184621 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1976F40FA7 -20181104192058 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1977BCD9FB -20181104213223 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB197ACC31C7 -20181104215616 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB197B54F0A3 -20181104233753 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB197DA923D7 -20181104235806 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB197E18BC83 -20181105001724 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB197E83B0E7 -20181105010241 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB197F8509D7 -20181105022532 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB198168A38B -20181105042426 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB19842450D7 -20181105052112 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB19856CA53F -20181105052812 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB19858EBEEB -20181105053259 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB1985A24167 -20181105060205 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB19864B479F -20181105104043 2 6 100 6143 2 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB198B9EEEC3 -20181105111928 2 6 100 6143 5 F35161AADD9632E3575CDA92B32D0F28F2E75A457C95BE770E9A8E8122E71DDB31C63B86B67348319F52466B6F3FED41463FAADCA6CE2901FF62D867C09A3565BFC511A060AABAD5040F94C3066EFBFED3CA9BA71864EBBE9F616FCE8F9B0C9C463E2172BA6B1EEF222E310FEC9B70FDF42104292FE772CB350DB09040ED588DA44E0607286D1D66F155FFC5607EBEB4041F705839FEDB0C03FDA40F013BAE3D02EA1256B6DB4DB0F9ED423CD6DCFFD36AA0841BB1FDAF66A453A19EB967F0ECF045FB069302CCB0C6EB52834D1A8DBDE302530510349FC21AE0EE7D5F912D6FBFDEF8A19B8B4CEF2EEE0D05F67DB8F03E564FCD7CD2A344DD1A45A7079037A7629747BE1F183775275C93F52505BA701B27FB18035A0B8D707BF1A3B3BE453FD1A21B0B7FBA7CF90B3BB9665AA33EFB1FC04F858A33E8908397B976C03F972D6C50296DF33359E0BE9209C7D333A019937EC6A26BBB0EDD75DA06CF63A6333B1786B55DC0812AB74FD5D87EE581750E238EFCC75A1EF651502D3988C29C6C37504D90F8878D2FBE7F9131F273638A1BFFF96839557C5D1BA687DF78AFAF75E7FA7214B44C04BE0F3D160071146681C7CBE9B1DB1766C1D972E836DF71D0D4CD4E396D15EE25EF1A58FAC876E2ACCC2DE8EFA8B194694524C1F73D66B8D4D0B95C9896D18FE4061A68FB322BBC155D24E7EA516F740866BB32BB55E8FECAA7BC7F9D3D347024584F8BF4A40232D6AF32E3BB753718567698ABCA6440D68AF0B4317F343FA866ECCC64E895D780300BFA2FCAAAAFA4630C37EB8546025DFDD1E3FAB56F70CC95AA0CB7E3E8F11253D80B4C072ED04FE7068C4818B52831F77C11934F97AD153C44499AF0E6C99DE5741E41EB4C3DDEA3A7C7404AF7F154EAB7422598797E4E5106BFCF7390DE9AF5E9978A7000566FF8EE5737730108235AACBD38D8C337C71978FDC765243322C08F74B0F71B91E3C50BE3DAB7E58F0F8F187839AABB2991C1AB686975AEF90EECCBEAD74AE9C78F0A4DF2376A35A4E5894E8677A08788FEA19DEAE13C88D696C65A7426E620AA1492115E2BF0FB198C77AA37 -20181105162143 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416C2EDFD4B -20181106022607 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416CB3AFEA3 -20181106061722 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416CE37F7FB -20181106094748 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416D109F343 -20181106111032 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416D2224817 -20181106145715 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416D526B7D3 -20181106182511 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416D7F88093 -20181106185324 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416D85194CB -20181107004801 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416DD089B0F -20181107010004 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416DD2A3B6B -20181107033546 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416DF3A214F -20181107042839 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416DFE1C77F -20181107045255 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416E02B64E3 -20181107093859 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416E3F7C30F -20181107111504 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416E533987B -20181107115050 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416E5A3AA83 -20181107192529 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416EB936ECF -20181108001017 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416EF491CEF -20181108055511 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416F33826BF -20181108085903 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416F58E9E8B -20181108093954 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416F6069543 -20181108144923 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416F9FC5BCB -20181108194100 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B416FDB2EF23 -20181109005641 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B41701B64E6B -20181109074202 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B417064EC2FF -20181109125150 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4170A2F02DB -20181109160619 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4170C92055B -20181109161624 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4170CA966AF -20181109172619 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4170D7B99EB -20181110021145 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4171409B02B -20181110062711 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B417172F0403 -20181110153547 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4171D11BFBF -20181110171812 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4171E461903 -20181110193333 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4171FE2013B -20181111070228 2 6 100 7679 2 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4172812EAEB -20181111152029 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B4172BC07FE7 -20181111213014 2 6 100 7679 5 C988D06CCD826A9351D5CAE32A47B28ECC90FA4870D861CCC058CFA49419B0044A395E3F289A48C821B2EFE08D293B917B1DB2E2369564F5D066084F71A090706F84E101625CACAAECFFF3B2FE2A8C04FF9A14D43E9B316576F1571B0FDD51A119222601AE2BBFC3007FBC12D10A2D725AD9D8503A47B4B1977FAF4B0C8E244C372662A335C82380718ABAA9B522A03866EBFC6DD7DEE135A54FDCE58EAAF1996D2485E178888F361B01C2A5F5E21E65BAFFE3024C02210AF189975CADE7BFEAD4A90401D7E37D9B855FA8C8F0D2FBFF9357F8C05E3A2A14173E8F7555FD78B88ECEDC94E238639FA1F59C896F61501B2094199D7679805FB69026D4F13CDEB60CAA339BEB091D7D0C125C72028FDFEC35C5D6EE231B1A46C0619BF822F415121A975322001C4EDC29C5CAA430D1471D1013B67B90F5A7FAFB322B53A9C4D418763CB8A9DD068BF3B7702BA939B4FB0DA5253A999B5A8DFA664D2A9F94169F34E46D45D348E3A7E3424CF6019CFDFE1623940B3FC47A1064E601549C02020571FA10F63AEB0676213CD71D1A8A4140662D00471FE9BA88C269F8D217A978AE910A85CADCA772BD7023DC8D0C2ED524C7FEEFEDF408E4221F474A3783545E155118133FA9D65382F7261CF001701E46721021A1315780A53F4238C1AEEA41D38E1B3310D2EC9AE97C2677467157A0B74DA93A3CDF3E6CF898FA0F5CDF3F55CA572385698FD0F55E0E5C63B4BCB9F4A6EDB74C02C0150B057B1A903F7DD8EFC011EE822F2ECBB780914BCC43A11F7BF4A63BE31F06226881ADE9EA780A58C1A6D7183EE947611A03051A0EA817D6D26FC0C418607EEF57AE00494CDDA1CB518C3F910FD46C65F96E3553CEFFD72D13AC13904EFF4E66203B8D512BF7136251120F0BD28C1E781000BBF832A072DB3BBA7B2CFB5AB1F6DAA17FD6EA6C484BB764E5F01194A5445B1FD435977F916261FA1B5AAD6B7E83782C04EBF3CBD11DC7D929FFD8A16597E2D6A384F343D08E13CEA8232818D7F989BB4B0D7D7531AF0F4C6683356A109EAFD135D2E3319FFA6218053EC737FBD91D5886790D4FB1DB70F3D704148EFF2FAA0241F47F2902EA8286BD7647B615197B0E2A70F3638BDF46973518EA692DA5EE26E533F815FA5E5835C2080FAC1776A7CCFE2F49B1400A55F24C9FC465A766772EFB35756AABF0A42B58966E883AFE5E4000D863756225CDDA2F5AC06093173A1AFB5AD9A7B721A30820170A4AE35B3A2F09DE1B53B7D7A407E0F77F1CD4201337315E6677D30CA3E40F84A7AD707BE0FF99CE9334FAE40692F38135DBBC8CE8E7604C0F9C8AE1989C9FE2AC29C2800DC8876032B41730368927 -20181112101949 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4608E66C77 -20181112120627 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C460A539D5F -20181112155435 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C460D765A73 -20181112211414 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4611D8F2D7 -20181113033731 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C46170D027F -20181113122018 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C461E0FB427 -20181113122849 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C461E245A3F -20181113143304 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C461FC358AF -20181113155105 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4620C4118B -20181113165341 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4621936EAF -20181113171216 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4621C96C57 -20181114050208 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C462B2BBD5B -20181114141440 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4632523CCF -20181114160132 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4633A72497 -20181114185818 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4635EC630B -20181114200207 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4636B93337 -20181114220623 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C463844D7C3 -20181115101522 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4641A155C7 -20181115120812 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C46430AFEB3 -20181115125440 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C464390BAB3 -20181115150855 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C464535BB4B -20181115170837 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4646B220EF -20181115231105 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C464B3844E3 -20181116000709 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C464BE2332F -20181116053629 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C464EAB7A73 -20181116122404 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C46538BEADB -20181116141535 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4654E5E903 -20181116230159 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C465B551BBB -20181117015828 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C465D3CDE9F -20181117025015 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C465DD9203F -20181117031140 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C465E163313 -20181117071114 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C466102759F -20181117161936 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C4667A72DC3 -20181117215936 2 6 100 7679 5 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C466BB5F597 -20181118001148 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C466D436643 -20181118040056 2 6 100 7679 2 FB0D9422C2C18ABC70FF186A01FA8ED40D4950F804266E0B9661F1E2A6EC548235ADF6A86C277AC391995CF5C43940D264D81121AE69F224E949221EDC039AFE2DA6752F6C04E10159FE65D54CBE5EF34174D36E069C4FB18C8E6DBB80B2C6E0F0AD82E0B7281B9D675AE9E85F509B12746130BF725235E2AC495D268C383378FA130AFF2584962A8A3EDEC0B02504DF264F77980B8342713A28BD3219D83F6D70CC1393E10D5A4734BC029FECD3383FF41CB73AC61C29B54B50E439807BFA5663814B6DA5E81B9491217BE616F6B5F93728669FEF51C06D049586FA6584DFBECD526C5CAE6BBD17F104FA69D353A01CD7E39D5BEA60EB0491DCAE78F3A42BFBCC1F366C55FB23B649197B2D2493180963388FBC4A2AC804ECD042A97A07943D46F18EB6D6C24FC050E3DBD8EE2C84FA03E34814EA53197F1121232E239AA0DA133BD81D439AB595FC6F895AB27D0C6C8A5C3F468C9EF81A42BCB7676C2FF4D381063700AEE81FB7369463187413077048310A98D2DC034CCAB7001A28E288B4E6A8DB609974EC9FFC75F6DA91203429ACCEBA35B4CC03006BB069BD2A062A8CAF59E200A8E27B0CD48F896AE6236F0208AE3924EDF58F87557D05413C00CCAD3B95E6F659EC73FDC6933D6D1E21BE753670F6725F21721FDDC304E6178A3164A85F6757A508AFBD9AA4F1C7B181866F5AA306A25032E59C042ACA8EAEDE17B5136ACEC3B56D2E73284922162E614BE0B87654B7B12132D15E6F11F23B0FF2D0A898680B9A66BB908106A60FFC9A0FB43FF3ADCECDB128764764E1D429A0A194ABCD5AB41CE6B75CD025AC8A5FF2153A20E937354A27E361FB396D87924DCF91FE72203BCEA88303DF0A848EA5ADA9282C2C3C2B92542F721C58809178F36E2DA00D17C613FA5173BFC0F27F9502A1AE535BA9D373ABF83413A8F086FE904B0B45F449CCA9F0615028E1A4878463EA8EB424CA76949EA34A6A36C8DDE6EC4A4AE653A2F1F1009773BB92B8D20530A3313F388FA1AD70C3ECB716E5CA80A06C35CBA247D15D41795F8E083B27B4E227B616408863AFAE48F4C4AE68F1DA9A4B427F666DAD85035D1A499B25A09CC19548A5B9276FB082AA8B00879CCE17105CE7368033F4A18D68826780EB79162AD1B7C70879041BA08FB4A45B3071951DD05EFC9FD04AFCB99D57AEFD4EC51549EF9A166312E744CC7EEAEE9543C02D1B2D233A4B59B187D6E1DB64C843358E8B3C73765DDDC9D79D2D270FF493F56BB4F2F0DC4002605999644FF2A573CBA98492AC8577F5C1A822FD0FB709EAD85C786292DCB4FC8FAD924EEE898502BCD84ED4023C7D74A691A7A3A812685C467005CF4B -20181118070300 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211133D9A97 -20181118160610 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21119A92B8B -20181119005538 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2111FD14FAB -20181119071041 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211241066AB -20181119085941 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211254A0343 -20181119153022 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21129CA56FB -20181119193618 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2112C8E0D93 -20181119234643 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2112F6601C7 -20181120010634 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2113048398B -20181120045702 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21132D1168F -20181120121931 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21137C65BFB -20181121150916 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21149914247 -20181121230020 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2114EAE7D3B -20181121233310 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2114EFEE58B -20181122074348 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211542C97AF -20181122122936 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21157397D47 -20181122134740 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2115803DB63 -20181122213432 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2115CF3077F -20181122232736 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2115E1C6FCB -20181123013244 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2115F5E2D97 -20181123013752 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2115F623A23 -20181123032802 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211608810CB -20181123054205 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21161EAF243 -20181123185533 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2116A336C63 -20181124051353 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21170A23417 -20181124051939 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21170A81107 -20181124102146 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21173C1D793 -20181124105734 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2117416EF17 -20181124114011 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211747D7B4B -20181124162540 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2117764D6CF -20181124195401 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21179863787 -20181124221336 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2117AE70AF7 -20181125005223 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2117C7CCCA7 -20181125060115 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2117F8262DB -20181125063720 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C2117FD8EA63 -20181125071430 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211803251C3 -20181125172444 2 6 100 8191 2 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C21185F9BDF3 -20181126120755 2 6 100 8191 5 D72A51FC8A019CA61D28C85021CE881FBDCA1D9E2773A50343C390408ABF52C024F0268B5D4F74AA0722F8FA78F966B7AE411C57015CC9E0DB7E56B27A1D078D951747F90F8F663552B12F9BE26809481BD6D62C8EE018E2944DCF0EC7D31FFE3F7DD2F11F3C8311F1C2E2038613E541F53BA05FD92A540D11BB3267E80CCC5DEC74FD67AE473FAD56EFE2CF04457BB7B3121F93AC8F00A5DBE46E460B9B97823F937CF18722D4EE6373EF369D26A7602491493497C1EFDA3F7509772853CF84CD64A06A54FE32817B39B98CE3CE4477616CF232B04D0B2098D5A4E575939C63B26B72BE87B2BEF58F2F6DB4B2A0E00634E02637DF471D6519C22BA9494F225CA01A1A96886C6F02CE0D11EDE3370180E6E6F5CA54B44A8B66BF16ECD52193B7483700AA4051AF775F80818F3331AD80BB25A0FC8775B7821C32EAFDBEF75B3BFCB2F1A4BBDF5340B20AC9E185B0770CE6AAB120CFC4C8C88CA381946F48C0478DC07E5CF3CFB805A1BA8DB905A6D2ABFCFD765990CA4699D9F9B6922FECA4FF861362B4525FF0934E679109AB8F00909945FE897E927380F72416231AAE1A717D47BD129D5549F60C2EA377744B8807AA2432D1925D02C4C205715231DFAD86AC6B5253DE58E3E3F65484A0014CC1EFFBABC6EE912A925C08C8BB68E5FD7A13AED0116863EFA7E69A33D28A1FA853B7E0B84A5F78EFC44CDC39C4148C4B1B3D17E7371E51F96CFAAEBE15D67E82B590B9BB0567BC161AFF012F7571E514BCA7157A8C1521BD7147E83EE57721A77895722390D9C1B7C3BEEEF316E313F5A2DFBA0A5E3509F5F2CEB90C07E1177D3C8AA6CD56F5C5C614656D155350AAFD556890247AE6EDEE2236583A6DA347679C69A9B518FA9BD882F5B9850762C987F727CFEE68421A2D4F363EC45EDABAD574CC4C5AB7654F1C7E0CD84E708CD7C3ED66F369EC1E0E193346FE4747709F6A6DC969E3D2394758E807F4370E2C5A64B5190C5E9D3983CF5778076667B3E41AA28A868B9EA72C45A9234A2C92F0627512AC815CDC1418C676E66B474C071C65DF4EB7AA109ED189B30F49C9A7310CDD5504A0155E5A37FB41548B78049F3FF57EF682D04EFF6B43E5390B07019C555CB55D477552EC778C5BBF00830D1D2B233CB9B5C5A1817F96F395A527458625740A6B2FEFDF160F003D72086FAD44EA24CC669E710A965052D997E63144FD5F32271D0CF75D24DCCF5F4A8E7FD0381E03F0E9DB6F63BA5A59790788D48161E0C292436F79120C9057EBC7B1CA430E5D060836CEE57945DF5557EE2036588A902A1BD163F4DA436602B4BEF61A20D52B15877BFF9973366F242A6D2564BF32E2251C0E07DB2C98A31E82B63F6513FD4CC37D040653E3A68C6B2DB43B569FB070120ADEE89042BF0AC0E9103164E5F8BC57847A1F109ABF35E6E5DE0258C211914B6C57 -20181126180517 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA20E92F77 -20181127132421 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA2E7C1F6B -20181127185312 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA32237C3F -20181127232536 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA353F763B -20181127233956 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA355F350B -20181128191837 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA4281917F -20181128221658 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA44764C13 -20181129071050 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA4A5411D3 -20181129083522 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA4B386FC3 -20181129195812 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA5262DD0F -20181129230915 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA547B23C3 -20181129232739 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA54A6C53B -20181130011847 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA55D16287 -20181130055628 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA58CB384B -20181130162040 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA5F85360B -20181201010704 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA652B1403 -20181201012529 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA6552017F -20181201070700 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA68F8AE73 -20181201120437 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA6C1C6B53 -20181201153708 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA6E492B5B -20181201212404 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA71E3AEBB -20181201213749 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA71FF6D23 -20181202153927 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA7D41FB5F -20181203042444 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA852BE5A7 -20181203093150 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA88559E07 -20181203160725 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA8C5B7A9F -20181203195346 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA8EA11AB7 -20181203212839 2 6 100 8191 2 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA8F91F893 -20181203214143 2 6 100 8191 5 EA2361A4ABC2DDA42ADD74B38CE837D05B00192233F16571DAB16B15049BA7606BA9A6DC1588738A9949D68815E7F9DB7FEB2C81C1284F976E38376817186BB7725E05B3DA281A887F71DADA27911625597D376826592E156211FF30844F8A1C47DF9320AE8E9C9171181EE3F7D5EB1B56F79D7DCC39FC5C20A23EF716809E2035466B7E7A43DF588D73637DC89192E5EC392C917AD498C66E229EDBEFAEBD449773973E04F812B55466A3F2E321FA8A3AD1B6AF8A95178F4EF001004EAA4D83EC362F1B966137C811AE2B52B5815ED28F7CEB16DE55E7C64E5D34BE122EED25B5E9DAC04AE9EBB4C0EEBA6D447B435262EDF18CD616E396C80DCAF8547DED8A9817BB70FEDEA734E5A7005F8C7C2CB53366827824E2666DE1F1AC109A41576BC37B3BD1536D79CAB6F6BD7A2D9863EF0F6FEA547A990EF5DF931632F203682D34462025E053CEE1D25EEB0508CBE0A50F7D687A5AE6038F3BE219992B7796E1181D06AA9072D5419E50046F40D5985CB8EBE8C5232EE75AB3C03F113C5EC4669C072D5C514EFA0778062DDD9FF90BB75DDBA4AE2E2100559A35273D202E93B17FFABBC976DB516DA4FC9433322FE6517E5B39021A4564AFB6E1A15B1EB5981B952A8161C688C461CD1CC8E67882CAAFD6FDFA2BA7EBFC40D16D39F4DA16879D230375833741E1B3C49D1630E10C5E6CD1C11AEB2C356C3A0A4EAD805B9330199AC8BC1BB1ECF2E3F84839B5A444FB06959505AF97019C695D6A14990A1E2C678A6EC187C90F6989DA0E977767F2110D8C9289C6E85CC87C7141B11B284A4DCE2ACA6414F5AEB560E11E44699973E4BC4B28526C2D1C68B81A51ACC9E490B6F28129100FC3888C85ABB9E0B3808F00753F76C908E8E71B08EDD87C9359F716324183EE3D89389839F0E741246400D1BEC8F5592F4D66ED0205A90F6A153D3D0751662BB95FA3CBF1543D35E2B9E02497FA24173FC8387B36EE320007E4DC8D3400DC69D361FE071D1C015F87F4FD8E942E5D92D7197279F02513839ABC5D11098DF80A4D3817B7AFC4F7A93BA8469D89DB503284B6D2B7E90F2B52ED2E6F65F0E90A3D13564725FF563772C5356E2C50AFED4301BBE029DEFB252B1598847FAB4136B69110942DE842A9186D391E8CB2AD210B1D9B9473676222F6EA1F445E24290B6F1845243B33250224C0F316E18C52180220C2549D093D9F3974980F95DA8F1A49E36D142A3957A1F7DE6E492578544D17C856BEEC0F40FAFBFB8140945D6B13AB23BE8D1ABDC3E4A92E051CD180C5F2FE288C96F831DD5F34CA679E618D160B21F1697870F8F3B3A7318D0A558C4EADF16D0A76079D148F7404AC163852513ECE66374A9F5A8BC4C87F36CB2AE52ADBC034DEAE51FD60DC071284F8CAC9346E6D60F97D6CFE41C605B2C4D8D0C8BA41DB0DB3A2BD01B037D8CA8FAACDB7 +20200603013151 2 6 100 2047 5 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B598E0A26F +20200603013238 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B5992253EB +20200603013253 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59936A07B +20200603013341 2 6 100 2047 5 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59979324F +20200603013412 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B5999ADA8B +20200603013518 2 6 100 2047 5 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59A02A39F +20200603013530 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59A123243 +20200603013735 2 6 100 2047 5 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59AD6F947 +20200603013748 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59AE8D8E3 +20200603013933 2 6 100 2047 5 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59B86B667 +20200603014014 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59BBA6DEB +20200603014054 2 6 100 2047 5 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59C01B8A7 +20200603014128 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59C29951B +20200603014140 2 6 100 2047 5 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59C375247 +20200603014240 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59C962533 +20200603014320 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59CC3D1B3 +20200603014419 2 6 100 2047 5 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59D1CF107 +20200603014455 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59D5BEF33 +20200603014535 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59D8CD76B +20200603014539 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59D8CEC9B +20200603014547 2 6 100 2047 5 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59D94AC97 +20200603014600 2 6 100 2047 5 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59DA41237 +20200603014618 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59DAD23B3 +20200603014629 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59DB9A6AB +20200603014640 2 6 100 2047 5 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59DC72D17 +20200603014646 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59DCA93E3 +20200603014713 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59DE24DDB +20200603014735 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59E04C08B +20200603014834 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59E5D24E3 +20200603015049 2 6 100 2047 5 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59F359287 +20200603015117 2 6 100 2047 5 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59F4EB0D7 +20200603015124 2 6 100 2047 5 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59F547E4F +20200603015250 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B59FDE260B +20200603015443 2 6 100 2047 5 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B5A088C767 +20200603015517 2 6 100 2047 2 C1B5AE12216BF36E172F949757150831C974F0D9589CAA6E6639754A321243ED9FF7846C2BEE736D420BB5A049A0E14EEB8A578C79B5482963D405610BF6F23FBEE7E4BFBF1FDA04EBC69CAEFB767366C057B2F1ECFAD374E5D7079EC99B1FDFB19177920DDFA0991354FF3603E184A05E7756025E7A856B5B80E5252036E8048180264DE4BD9D96C318332F7C20CE30CFBFEDE1CE02874FA4D05AE76F4767EA65999BCBE0BF7C46924671B181917E80B035EBE5DEF7263447CC0546B9CE0D38198C4A5B73DD6C82DB4DF902167166C05486FBE4EAA8A8096CC0465EC0A061D9C8DAB0B24AE58C5AD652A31233832E0FF90385BD62FBFE7D558B18B5A0ADBCE3 +20200603015616 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC1F54FE3 +20200603015632 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC20D92BB +20200603015714 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC2466F63 +20200603015737 2 6 100 2047 5 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC26D42FF +20200603015759 2 6 100 2047 5 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC290CFC7 +20200603015826 2 6 100 2047 5 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC2A9F777 +20200603015926 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC302E2AB +20200603020047 2 6 100 2047 5 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC385317F +20200603020153 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC3ED4683 +20200603020330 2 6 100 2047 5 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC47C42DF +20200603020424 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC4C763EB +20200603020516 2 6 100 2047 5 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC51127D7 +20200603020716 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC5C96ADB +20200603020724 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC5D27F33 +20200603020757 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC608698B +20200603020857 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC662C493 +20200603021019 2 6 100 2047 5 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC6CD731F +20200603021029 2 6 100 2047 5 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC6D98B37 +20200603021126 2 6 100 2047 5 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC72C56AF +20200603021137 2 6 100 2047 5 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC73B2487 +20200603021230 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC783A09B +20200603021237 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC78AB273 +20200603021248 2 6 100 2047 5 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC79749E7 +20200603021336 2 6 100 2047 5 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC7D6F6C7 +20200603021349 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC7E7DE83 +20200603021433 2 6 100 2047 5 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC81FC717 +20200603021555 2 6 100 2047 5 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC8A2E197 +20200603021648 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC8EF5243 +20200603021748 2 6 100 2047 5 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC9466C5F +20200603021817 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC962284B +20200603021848 2 6 100 2047 2 CC80BBBF39CE11FCF95392238D15C8FDD1707D9F1DE408CF64661BD7C14D5BABD6A9D01F7EB2182781ADFB99C4DBBFB0071D129521E454B9C6921F5FBAE54B10342C246AFB288D93AF265CC213E0416C1E0CCBC279DD84AE7B6F56A6FA1D243A8719334B6D625C30012E2115114A40C2244B1AF7051B2FFB3BE46E7A291F49CE0B67C92F544BBC5DAEDA5DBABDA8CBDDE03AFEDFEF63D06B4787A4FB4A4666147A5A9469F7F37387493C7E64E75ABBB5CF94966E091EC529CAEB18481C109BC28003E779DABD1973006D2929B4A6DAA6AA14B1606D42C02AFB6357D16FE7F74109E6D15D47A7F135D11523698F648B28E8B4504711D7BA60096A6A7DC99760E3 +20200603024052 2 6 100 3071 5 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A91FDFFF9AF +20200603024236 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A91FE2CF7AB +20200603030816 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A9201780DFB +20200603031241 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A9202073643 +20200603031336 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A92021B4CD3 +20200603031841 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A9202BDA763 +20200603032328 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A9203510ECB +20200603032520 2 6 100 3071 5 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920388C3E7 +20200603032842 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A9203F56F83 +20200603033217 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920460103B +20200603033521 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A9204BFC103 +20200603033736 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920502CC63 +20200603034230 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A92059BD8AB +20200603034313 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A9205A947E3 +20200603034452 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A9205DD15C3 +20200603034648 2 6 100 3071 5 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920616CA47 +20200603035115 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A92069C9C2B +20200603035225 2 6 100 3071 5 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A9206BB9E4F +20200603035500 2 6 100 3071 5 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A92070DE93F +20200603035636 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920737396B +20200603040133 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A9207D5E89B +20200603040227 2 6 100 3071 5 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A9207EC8EE7 +20200603040625 2 6 100 3071 5 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A9208640D27 +20200603041338 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920945B5AB +20200603041419 2 6 100 3071 5 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920951AE07 +20200603041640 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920999446B +20200603043156 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920B8735AB +20200603043319 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920BA8BB73 +20200603043430 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920BC8D263 +20200603044252 2 6 100 3071 5 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920CD96A5F +20200603044815 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920D7CF1BB +20200603045034 2 6 100 3071 5 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920DC0D2E7 +20200603045100 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920DC9043B +20200603045746 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920EA22D0B +20200603045832 2 6 100 3071 2 ECFB72C76B880DAD52A24F83637D85C1B8B3093B51B9031D7890D582E25F700EB8ED2D3640F376A0F6A76FFD283EF55B9747F37C049BEF03F1D1B0B4FAD2B989D4FF02BD1A64AA734DF85A8AD94CC8D74BA8010B989416D2F169AF55EF984E592EA0D449DAF774A2536519623C079164FF5B703A0F429AEC32A42755E28B36E5F5848D14696A8491AF3784AA6945F73498FE2E6443ADE4E65909A863587DF150B5E9D960D9EEFBAF7BFCC768EBED9B2F79D3A1A365DAB065909A97132FC7354B446CCF9AA3A1BED03606C8D0F4DDDC4A862CA839E98754273191313F7BE1B5966F271FCFBEE91EEEAA83AE69A4D42D3B3FF57991AC9FE1B815F6CC366B5793E5CFFA9116FEC3C4D9B79F68D4B16B7945942B20B6AFE011B8687820BF257CB551B6591D84D4087C191907DE481D14C0815954416F98D3C677A2FDEDE4BB1C2DA18DA3BD1DC34958168F9C9336B805ECC25136246264FAE1B92540573F4DA8FC26D03DC3456ABCB5F289A8D3F81D1BD2510CB8035D1DB5C9C13F428A920EAFE143 +20200603050921 2 6 100 3071 5 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17EECACD1F +20200603052247 2 6 100 3071 5 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F081C487 +20200603053129 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F1987E43 +20200603053245 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F1BC8503 +20200603053449 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F1F91A73 +20200603053857 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F27C8A43 +20200603053957 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F2955523 +20200603054803 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F394838B +20200603055727 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F4BF9BE3 +20200603060437 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F5A887B3 +20200603060919 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F63DC10B +20200603061739 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F74CFFCB +20200603062124 2 6 100 3071 5 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F7BE3FD7 +20200603062244 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F7E219A3 +20200603062352 2 6 100 3071 5 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F800A877 +20200603062854 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F8A5CD2B +20200603063441 2 6 100 3071 5 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F957937F +20200603063639 2 6 100 3071 5 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17F98ED287 +20200603064225 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17FA46F36B +20200603064300 2 6 100 3071 5 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17FA53E86F +20200603064723 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17FAD9840B +20200603065325 2 6 100 3071 5 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17FB991D57 +20200603065827 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17FC383623 +20200603065922 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17FC4B78A3 +20200603070014 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17FC5D3D33 +20200603070257 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17FCB2934B +20200603070528 2 6 100 3071 5 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17FCF8C26F +20200603070954 2 6 100 3071 5 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17FD83D0B7 +20200603071417 2 6 100 3071 5 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17FE089B4F +20200603071755 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED17FE7F6E9B +20200603073423 2 6 100 3071 2 E1D5789FC337053CEECF601ABA6CD8DC9625FAF3A8CBAFF40FB3C7B27FD61854C1E1D3D8D577F0FD466C911CA0550678F15A839C419F026ECE2B2C51828108F687DEEABF39748763AA1964D7F2D251756B10ECBDD78A1020B8E08AF0590A2E83661E53931ABD6A5193EB154051DE3B4329969AE835D7AB44C4E202C70FD202372384D4F3464ED486C85F1A3660B881923AC9B9C10733703F2BC7B76A04251E399D26EBA2AF41C76AD9FDA0C0BC63B0442E1A91239660B1B2A91885C7329A07E5EAA0B4727A793A0B2794F62E18FC3F563E89E91EA38FE55B0A9BF74FF6065CA7DFBAAC535384BCD7A19530B62ECC61979EB332C0677C600F128ECE2C38921814358AADFF5ECCE38761713D0537CAC626FF0D6DE6A58094451AE1ED53802170837EF38FA63FF3F3AF9989089B990D047E95A5AE436FBB00AD85D6B235B66FE21C8B19C2AAD7FEFC3132361210FDA9EEBABD0507CD95AF6079E29435626299064E793BCF766CD007C6442E67E035B779D7F2A756A02C6209C014A8ED180093BC73 +20200603081916 2 6 100 4095 5 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBB2D4D797 +20200603083145 2 6 100 4095 5 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBB388F177 +20200603083521 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBB3B5C34B +20200603084043 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBB40162F3 +20200603084749 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBB4655173 +20200603092034 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBB64D516B +20200603095055 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBB8176DB3 +20200603095144 2 6 100 4095 5 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBB81A12B7 +20200603095539 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBB84BE7E3 +20200603095824 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBB86B8F43 +20200603101512 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBB960938B +20200603104916 2 6 100 4095 5 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBBB5FE757 +20200603105710 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBBBCCBA53 +20200603105827 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBBBD8F413 +20200603105917 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBBBDBA9EB +20200603110729 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBBC4E8FFB +20200603111137 2 6 100 4095 5 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBBC861FF7 +20200603111642 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBBCC73993 +20200603111836 2 6 100 4095 5 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBBCDAA5EF +20200603113326 2 6 100 4095 5 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBBDB5695F +20200603115340 2 6 100 4095 5 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBBEDE1F7F +20200603120124 2 6 100 4095 5 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBBF484387 +20200603120350 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBBF66044B +20200603122542 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBC0A9B2D3 +20200603123932 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBC1727CEB +20200603130016 2 6 100 4095 5 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBC2A4BC9F +20200603133721 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBC4C82B83 +20200603134150 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBC50278E3 +20200603134315 2 6 100 4095 5 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBC50E06EF +20200603135758 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBC5E92E73 +20200603140431 2 6 100 4095 5 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBC641B467 +20200603141500 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBC6D1EF0B +20200603142240 2 6 100 4095 5 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBC73D85CF +20200603144519 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBC88AA813 +20200603152458 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBCAB4342B +20200603154356 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBCBB51E33 +20200603155251 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBCC2FFA63 +20200603160553 2 6 100 4095 5 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBCCE8D70F +20200603160829 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBCD05EF5B +20200603164544 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBCF2AA323 +20200603164741 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBCF3E737B +20200603170255 2 6 100 4095 2 FADB8928A550514C5D83CCCD98141A2A1EBC81D9B298AE4FB11CA19942682C2D72B29897BF77CA0A39B85130EAEB705C59BCBCB677FC6B08B7048FCFF55BFB6F1C6C44984002438FE3763B9342588649D2A79048975FCAF9C5BE658A3B73BA732768977A10565B597A1F3F58503384637A525369A00A4E50986780C66C8007D76523914FE52F7E4C479D86466A266317B8607665F49BE434643A528D177B57409ACBD387BCF8ED3609F8770933921F873F620771034774F41DDB33C3334747497F146529034F71563360B6778FD98614A67C6605D1D0540F10843516A3AF6E8F7DC81EE9EA3D61E8A6A54866E25EB6BEFAD1FEB08BBE2D3AF023471C249A6CE5112F3862F18A1DD3816298EAD7B9F064E243C01736866D06B1103C3FED190799DF25569F419019C98195D771DFF5FD82C01DB7883C3840B784F635F66B285116E4F84207930F0FCD05D8F07AAA3FAC67DAAE83B38F7AC1BDB719CBB1BAB1A735B567784BC7A3DD5A84C27C4F9443071AD03E4887A9354F2A4DDE965F4AF4325184857DC74A398AE4284777086CE88A7D0D20D2F23DB1CF4AD9D74A45719DC3162D50D27824283DAB31E7D58967E9F575F46F235733501200986AA4D0A94735F15330198EB804B39577F43E4F34D31385BA1D5B96A769BBA1616923421B8B277E26DEF215090EDB1174D99AAA7D3D1A2443D28EB5BF6E90A6C4E24BFBD016BC53 +20200603174159 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DDF71B183 +20200603175329 2 6 100 4095 5 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DE0166EB7 +20200603175916 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DE062F643 +20200603184324 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DE2FC12A3 +20200603184429 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DE3055C0B +20200603185842 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DE3D8A083 +20200603192814 2 6 100 4095 5 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DE58A7357 +20200603193254 2 6 100 4095 5 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DE5CB2ABF +20200603193621 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DE5F55FC3 +20200603200025 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DE75DAE53 +20200603201138 2 6 100 4095 5 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DE7FDB23F +20200603202852 2 6 100 4095 5 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DE8FADA4F +20200603203058 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DE914E293 +20200603203547 2 6 100 4095 5 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DE955F197 +20200603204018 2 6 100 4095 5 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DE990327F +20200603214442 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DED4B6E1B +20200603220036 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DEE2C08C3 +20200603222135 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DEF66B02B +20200603222250 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DEF70AB3B +20200603223212 2 6 100 4095 5 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DEFF51C3F +20200603230927 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DF211A5D3 +20200603231319 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DF2433C9B +20200603231528 2 6 100 4095 5 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DF25BCB27 +20200603231746 2 6 100 4095 5 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DF276CF2F +20200603232250 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DF2BD6513 +20200603233720 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DF38497EB +20200603235438 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DF47D8963 +20200604001143 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DF570FF3B +20200604002250 2 6 100 4095 5 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DF60F878F +20200604002438 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DF620B41B +20200604055558 2 6 100 4095 5 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DFA633BBF +20200604061051 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DFB397083 +20200604061554 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DFB7C2FDB +20200604063226 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DFC65DF23 +20200604065024 2 6 100 4095 2 C313DC332CA881BD902A99A7D1BD21F3A30E3F7AB0CDFB5621C8040C10FCAE7B7CB62418B22FFE72A2010022D54C0D961ED8388D6B951A77F65CC83436C94D13AA701404ACAC2D205529444489AF0F6DBFD3BF9DFEE48ED180447017A5ED1BFA553B9307D6D8A7C5B9CEA439A293469433B5E42265D19DB8ABFD8C5A210ED8D0356FE9EBCEE90BE901A4485A621A5E76DE1D97A2F96E4BFF6BFC5A2E6D35F9294B1E9AD8A03EF4DE74B4474D7427F6D22D1D92D4308000D7D710A87C6005886BB5E09D8B5C6617C46BF3676B95DE7BBD8B4E9F600CF3D0D0692341FA0807451215C57AF94A0871D73564FEAAEF46B0B11440BE867734C7909523C48C31EB72BFFE4B4FBFDCAF6AE67E8D5EF5CC0FD343C3C7BA2058F666A9911C499EBAA19676D0911CC8ED919265EFB99ED650F88834EE52FE3FAB09D92F5B9B7A5B3C0B7682B9339416344913BE9851681E5941E92DC93AEF7D777C9A066D1B58EFC7D83573BC9030BDAC0C4FE2D6DD6C46CB53FC0790E198B62853DBE0DA046475292D627C2D71E8B0067F537EF9AD5BEA0070F873F840BD6ACD9BED642FB47C43A268C1E57EB16F7AA1DD6392025180C94606D6C2E5D9479DCE96DD90563A8897A237514953596B1319493BEBFD62F6F7FE94B0F1427A38B777ED1F98973740141F5E524F462BF20D7BF3B5F802FA1C071A5FD5E3FD6A35CFACF6D4351E4BF41DFD6980B3 +20200604082734 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB31F961E9F +20200604084249 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB31FDC7AF3 +20200604091259 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB3206DC3DF +20200604101647 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB321ACC813 +20200604103215 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB321F009F7 +20200604111534 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB322C70503 +20200604125038 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB324A52B33 +20200604170714 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB329B0AADF +20200604201954 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB32D7E3A0F +20200604225914 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB330A536DF +20200604235825 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB331C4B13B +20200605002513 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB3324381DF +20200605020140 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB33424AE3F +20200605174721 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB33BBFFA77 +20200605181350 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB33C39E413 +20200605211751 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB33FBA22CF +20200605220744 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB340A69BAB +20200605222038 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB340DC3917 +20200605224624 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB3414FBDF7 +20200606004552 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB343904617 +20200606010539 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB343E728E3 +20200606041215 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB34773F577 +20200606043519 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB347DDC483 +20200606060158 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB349792CCF +20200606061048 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB349995E23 +20200606072525 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB34AFC43A3 +20200606110034 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB34EE5592B +20200606132049 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB351770B4B +20200606143556 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB352D19757 +20200606155651 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB3543BDFC7 +20200606165831 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB3554B535B +20200606212229 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB359FD9073 +20200606220136 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB35AA7E8EB +20200606223830 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB35B464AFF +20200607002602 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB35D27674B +20200607041439 2 6 100 6143 5 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB3612F4687 +20200607090802 2 6 100 6143 2 C023C230380A2DADB3604BF16B0820515CAC3A56D4C81478C7A7F2C2A9447DA4CBF5D0322D1BAF511FBB97BDB4B548B1D011DF098DA0129BD4600767F8B691D569A167CA70FE65DEEC95923C9E4749103769BE8A03C021153D1A90E65F5B48A480E10733DEDD1A122ED26636D60F553090AB3DBE65D5E8D8ABCAC5E55E84F2FA8440847DC1F5B01EAE345E50CCF88FC765BF392F2C296980BD89AB34F9A7347DDFEBAFB710CF9264B9E0E2DB8EB44B525028C595136E87E45947096BA64053B2FE9E3415FE32DF3068467044BB9DC36A70846D7659D153403F5B3B57DFABF4D0459A9CEA5BD3BFDEEC00714A9F333F016B425338C68CD639E2215D40C98CEFB3790F1ED1696A6FF63D656759678ABEED75227423A4DECB18CAD41253D73EAC54E5F078CF31B195E1E7277A8EF677EE41786B2CFF84C95964F830546808222AF588561556C214853836C8B6818BEE0D1934C38F5A01030F98F57A3FB9C951F752E04045B7ADDF367A6C173624A6F42FEB27FE01E932D2E02DF7C46E1B664EE05A531BCD219CF734A26D10F98BCC313F58CA03B97E78E6F6B8F51CB7A563244E22318CF371383E5B20C36831097C00BBDA9440AA528090B1AE9D3A49DDCEA29B458CF63E22307125205538629FCBBCF7166881C7C238869629DD1D153E429D2D6A77E1E8599D26F9EF7DA4C499256FFCB32E8D7E488038A00737C6896D16C50C243AACC6AF29D1BD2F86C56C5A5DA77CF2676AA5ACF2223529DAA33BC137E65D943C263FA98788481E82D58281A7681E6A9E2F645EF229A7FA7407F31E459CF96AF1AFDAE863FDBA1C0072BB970CFF30491816DBD8D54B2A7683C3BA968B49812611BC4A0DC437EA791BF202E030355D1C52466171CBEDDB06ECA66E891D6A6417F4E33D7F586FC6043F92A8C9C526270F0552F08CA46374AED948437216B84F474FE2A8869FC4121DAA099BEDE62BE7A234617132FB6C22E6ACF13C6E0AFEB18AB556682B5331ED7B280985B38A3FFF7DFCDEC7535887CB2F9042298EB5D1B18841282A4552EF9292A58011644619D72C294FA4AA3E4930FDC32DCDB3666D9ED3 +20200607105240 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C4651481AC9A3 +20200607133637 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46514B532A43 +20200607163856 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46514EDA94F3 +20200607192855 2 6 100 6143 5 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C465152143C87 +20200607195432 2 6 100 6143 5 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46515283AF8F +20200607230617 2 6 100 6143 5 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46515617BC0F +20200608012123 2 6 100 6143 5 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46515893FD67 +20200608021859 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C4651599AB89B +20200608035721 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46515B642983 +20200608044119 2 6 100 6143 5 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46515C305197 +20200608063659 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46515E6DD31B +20200608082941 2 6 100 6143 5 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C4651609244BF +20200608110527 2 6 100 6143 5 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46516389D057 +20200608121159 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C465164C740DB +20200608180046 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46516B604DCB +20200608181840 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46516BAD8D9B +20200608185332 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46516C4C7C13 +20200608191623 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46516CB2720B +20200608222523 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C4651703AD573 +20200609002530 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46517274C703 +20200609024353 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C4651750D2B73 +20200609030451 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C465175677013 +20200609033613 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C465175F369F3 +20200609040050 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C465176620273 +20200609062156 2 6 100 6143 5 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C465178F038AF +20200609070757 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C465179BF4683 +20200609094557 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46517C97C613 +20200609143727 2 6 100 6143 5 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C465181B85657 +20200609145622 2 6 100 6143 5 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46518205D68F +20200609150740 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46518231FE23 +20200609230217 2 6 100 6143 5 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46518A94E1BF +20200610010357 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46518CBBC813 +20200610013612 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46518D487AA3 +20200610014250 2 6 100 6143 2 C57F2CBC0C6147F572B0F48F4F8E26DABE9C61EB3DC99B6753A587B3C215984DAF3F996960C81C4B0DE94FA300D19F5373E4067CFDA4A885C57A30F412A1872ECC06BF86E74FA687836333C5A5C8AE8A0540D031EB84E11DEF9F08138D6D82321531829463B35F627979753D085580082D86C7B37C1AB72EA78333609505F508BE0C50347DF9E30D97FDFB6D9F6EC81174AD46695E913FED9AF505529ADB913FEA5795ED206275B356BB3718FC479DE36048F49619ED7ED09C1D43F1B74B7DA182B5D771987A5A0C5244B8379F966E3BF7E2053FF2055B67A4F42E8A4E16908DB847F5B9CF8801BB7031B03FC7041F67242E69D91C12BB5ED64C2FE5786D4A5F71E2DAC5A1E4860EC08D6D0769A26E6D6B03515DF82827C2BB6AD32A1B6F27AC7A3F8ECF39F4BA2B52A93E2606C31151B49E7B1830748B57C3E0B0CB5EB3F3AC15E13CFF02CFB10D75D37EA636BEA0924500879404F70628BD2950239996F409AD1F56F16443437184250D9C8BE3BC41B61407EE724BFE36D1B8C0D295B128AC3B279C2022B52CDFB6D24900789161048DC6123C21E5C1678F4B3B8D22CB4056CB1EF88C6CD8077BC19CEA36347DA42BC9442642A9227C06D3C2C8151F1DD501C50F4653131826C83F7220C15B5D0D967102DA6F9F565E6AA82E6086BDEF70A910646A90625E941CFD28B9ACF5CB9146A8E9ED55567A0037B5836AB354505357A0DE604A21ACC65A69C1FB52493F520F8CE8E307213DC83E72E1C996A8A2131EE08B863A31AA5E2431CE5D2051B3D3C713B76CAB9A396C885335422EDD2C7056AC91060EABCD70620BE7717C4C977C419D2B07A9D6D41E2FB5D698CCFD8B932E4748AC0120E35467BC774660CE678F04C64D59CAEF3112E7E1B766A2CF49D6B6C841131BBC42755899F5EB96BCB33AD4593B7EFD0E41A4B9517667F1305B9D9A84C9C9E9A4F1EA70CCC7649D63C2E611954F5A9DE6AA4C176FAF32044E268FC664B5378D314BC510D16B41A81C1342F902F295E68B7B16E3BB22CBEB3D59391EBEC058FCA8C9FB62D1E4FB9445706362C54EB804B89646A1A46C46518D5EFC23 +20200610044251 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A654DB7CCF +20200610045738 2 6 100 7679 2 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A654FA9813 +20200610071715 2 6 100 7679 2 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A6567C3163 +20200610215424 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A65FFF83B7 +20200610224823 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A6608D79FF +20200617060930 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A663CE8807 +20200617091256 2 6 100 7679 2 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A665DBFE4B +20200617113153 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A6676B33F7 +20200617170511 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A66B179027 +20200617224324 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A66EDBCFA7 +20200618013140 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A670B46447 +20200618133142 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A678A89E8F +20200619002228 2 6 100 7679 2 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A67FC1FBF3 +20200619052551 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A6830B759F +20200620020539 2 6 100 7679 2 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A68A981AF3 +20200620090325 2 6 100 7679 2 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A68EFF0E13 +20200620190400 2 6 100 7679 2 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A6955464D3 +20200620192646 2 6 100 7679 2 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A69585D693 +20200620194126 2 6 100 7679 2 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A695A1BFA3 +20200620235757 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A698313E5F +20200621064953 2 6 100 7679 2 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A69C626CE3 +20200623073839 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A6B44F5CDF +20200623133511 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A6B7E45A07 +20200623163036 2 6 100 7679 2 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A6B9949D03 +20200623171631 2 6 100 7679 2 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A6BA0088F3 +20200623190013 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A6BAFE9BB7 +20200623200819 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A6BBA63F8F +20200623233346 2 6 100 7679 2 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A6BDAF193B +20200624020817 2 6 100 7679 5 D9BDD28997D5CC2F34E75DB842230C8FEC671AF277140D4FA40FAC7618EA985F1F139D1D841B2D700173C78CDA1C4E7F8DAC16978D221EBA202B0B031CE0A66DA50EB015F8043028E99D4FA6D28D0C19E13822826DC669C1EC83F1B1BEDEDB0BDE18C99679C0A5658D1AF3A45349B0FBB68032242B11A530B532EA98BCA093E5ABFABB04BCB9B54E69C998C8145DEA14B5C0DBFB954F729B7C773C31C66E16649B14CDAEF76F64D1CC85E820B0015E4BDAD3F88E7FEBD64B153B8C2F5B580E60F94DDC3D9B8651A7847DF8AC0A458187265B86B7C363FD98671688956EDCB44EA5972C041DA42D04E8EF460744576DBB25BFC5F14D4C657055D59E1A22942D700E3A29B23730FC475C595DCA4F83DC7106F2C9D290F78C5CA26700B6D39CB0B27C60A1F4B6F0F7E6AAF4E0B02F567652313BD5BE594972364E158C1FF57F2081257DFC04E9D3365906355495A2D1AD063D14FA7F6F374ACF8336F055F47140FEAC995957A776CE16573C53932E9D537A9AD4419F94C1A53912452D761D0652FCB9580CFBBD293A7EFC80FEF3632F850DBF631C61CFE1A473E0B708513267764F5621BBB1AEB8AB055324CA910996469161108AC348ABBF9A22C61B1F42DE07DE8DA6E1B906D73FD71CBC5CBF006F72067044E7FF625C28AFD2F77AB0B991E7B4331A7B8E88C9B917F0BB167BCBC7BD1F0A84327BEAB988D818FC3A35B32BBC92E3D61347D76729AA98B6A51D24DADF6580A28629935D2057912C805BA7B55F76A064DA257F6E6EEE21BD919F17EB1B8BBB1D640C0B38E436AADD8DCB72080F9A837363E59ED252BB522AD98D9AE6E2F074D2D3719A49E1026E1B096B0CF974DEDC462997394C03FE11C766EB09C37AC37034C8A05568EFD9D6099DAB338551B320B103488F3757ECEEED3331402335444099535E4E06893C020D2096CF2DEC75EB3978B052179E495B573A032A5201BEFFB843463DEF35E06BDD1A9E00AD49C20B5B4DB9926DBA60DBF7F48FF63BC08C176CB384A10D9EFF2E3F6F912516B902B60F857DAF600A2E8ADE99254456790D270ECB95FB2E8CF7967F94B2C34B24472EC1E56789D17529D907DF57874652E2FA223DB8656570973E6239222E5FDB3B949D559679F938F622090FF0C97091959E93013F51C00E1AE31E0466E0A21C4B1CA98A18343E5386077FFC276AB3FD37C511D2C978C01B62E5F2FFE460515CD7B271AFB8244667AFBF26C09E6F6C7F9719F973A65E3FC3354A0FCC49336361BFAB9E0EB276FA1B5215E9C5C60CDE67DDB9CD6D2ED5A829CDEB8713A6962C1F781770EDE447C23A0AF1768BCFB2FF84B4B96F0662714772D79BB660A6BF306ADF +20200624120025 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9A48268CB +20200624212659 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9AAFA0B53 +20200625054216 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9B08B8B4B +20200625123632 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9B52A385B +20200625172019 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9B8463B1B +20200626052613 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9C027DE2B +20200626101643 2 6 100 7679 5 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9C11E420F +20200626115032 2 6 100 7679 5 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9C21BE90F +20200626121646 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9C259D8AB +20200626221832 2 6 100 7679 5 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9C8D6C58F +20200627003443 2 6 100 7679 5 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9CA48A947 +20200627072751 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9CEBA2483 +20200627132611 2 6 100 7679 5 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9D172E21F +20200628074151 2 6 100 7679 5 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9DCE587D7 +20200628192017 2 6 100 7679 5 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9E443C567 +20200628211535 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9E564FA5B +20200629022616 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9E87B2F13 +20200629030222 2 6 100 7679 5 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9E8D05DBF +20200629054955 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9EA889CF3 +20200629085314 2 6 100 7679 5 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9EC71DF2F +20200629090539 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9EC8B1483 +20200629125524 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9EEE0A61B +20200629171748 2 6 100 7679 5 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9F18A7977 +20200630033559 2 6 100 7679 5 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189C9F7F90DBF +20200701005327 2 6 100 7679 5 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189CA052CA8BF +20200701141753 2 6 100 7679 5 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189CA0D5D91DF +20200701180117 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189CA0F982473 +20200701222250 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189CA12381BA3 +20200702010052 2 6 100 7679 5 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189CA13C5E40F +20200702020447 2 6 100 7679 2 F33B0F0818B623E831020BF1F21033CEDB49A00241324323E0D768AF68E1C989D401A834784F31ED3A332581A0589712AA215602B2811B35F6916664586EF5797ACF114313A4CF6E5A4AFB4307CD4C119AC0A1D2E6861E5A7E3D16BEA5ED82BB1801A68F2E77E9C5964D9E7CDEBAE4D292CCB458B9D2CE312149EE34B485835EC5A071C5AFF9FA8134D562FDA0381B03F987BB226F9CF647EB496096630362D97E165EB47D874F921EFDB408D88B132E10D99F5920C718DE8A5EECD228D030C7FC3EC712243C4C75E13299300C165962724C4B1CBA811B9158CB01402DCEADDD6849FEE51DEEC74A065EF226A2E41D4F6075C6C4C4466AAB2CFD00E8B7CD3EA75656D7F316F13E924FA133370CFBF59BCE94C2CA0F5F4595E4B3C9CBA040733AAAA53BCC2E2F30BF3A59D25613EC1DD0C373B9F256BA110FD7DDE5DE1697E79AE46956B2EB064E48C63EBA205AB1DBE65F39511F33DC0A7111B03B50AC1921A3EB1A321297BCFC28C6848F55597AFD510A0A2551D3275CB84EABA8624909CB135A2F25EC7352646B0C60DECAAB24C1B95C4E91BC1390E4BD6B420413B3909F8B5593CED45D91A1D462ECCFFC29D4BF9F23928E76672D6EE93148916DDB24C440DFAB01AA2942B4A249BB731C169A76A107D7F6A66F624D7507671E2C9507DA1819A6EBA212B13CC233EDE2BB7883441394A12A95A61BF6876061766913191B33597F1E8BF85AB5A26471C021B5029B34485E7B2D18186638F18EE0B85E72D4A9A866FF634C0652CF1F6BCA9C35669345E983D641A8C6FC6516D8772EC78622F950E175BC8577E99257D009FD8374EEC65507FA9034CCB7376858DDF91A97E5E826A563CB4F11A8C83DC92842F397FDC9861404BDFFFBFFD16ADDB85820123296EA52184C82D062EF68D37A6857473B0A93DFB48DF6CB19938945509F29E88D7C3BF6381AB154F5182E41C58E97341925F6CB545A86C15E4E04F155641BB12169E12B4800F89059746557C8432D08A8E2928EFB9EFA7A8CCB9BD1E55A85E0BDB872703626A89206DA36D5EE99E9BE711E20562150F9B35C0C7F262970F60C7CA5668D7FEEEEF31D6C9360830C656BBC72012DA0E9DE5D364F17EDAA261AC0489B2D39D7F9F54500583BA348CBF28875054017621F795EF7F0B20AE88C50768D981AB9EDFFD6A2B9C144CC815BDB01133138E7FE93D6B5167B164366B76783B68B7A383DC0856F29F35308AB5A6E092CCD238553E9ADF130706488FA95441D367BEFF42B90E590157E31C5D14BE574F674328EB835C8DF1C84A4CD39E31B545843F885B1F68D2F7C769FB67E3AF89ED0728D2F8C49DB7B5A079EC189CA14610AFB +20200702141056 2 6 100 8191 5 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B8092131717 +20200702144742 2 6 100 8191 5 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B8092635E07 +20200704195421 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80A98AA7BB +20200705044459 2 6 100 8191 5 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80AE337807 +20200709044115 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80B1103903 +20200709111031 2 6 100 8191 5 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80B4BB063F +20200709122228 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80B560D2AB +20200709231042 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80BB820B4B +20200710011425 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80BCA15883 +20200710070834 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80BFE94DD3 +20200711010355 2 6 100 8191 5 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80C9C858F7 +20200711154230 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80D1BFF01B +20200711210958 2 6 100 8191 5 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80D49EC027 +20200711221130 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80D51FBF5B +20200712012057 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80D6C56D7B +20200712025849 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80D79C8BD3 +20200712085111 2 6 100 8191 5 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80DAB1DE77 +20200712111154 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80DBE208A3 +20200712170032 2 6 100 8191 5 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80DEF05C2F +20200712205950 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80E0F0E3AB +20200713042732 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80E4A95523 +20200713054611 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80E54D52DB +20200713111019 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80E80C304B +20200713231114 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80EE498EEB +20200713232228 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80EE59CF2B +20200714023100 2 6 100 8191 5 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80EFF07CC7 +20200714031313 2 6 100 8191 5 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80F044017F +20200714041520 2 6 100 8191 5 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80F0C471DF +20200714043639 2 6 100 8191 5 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80F0EA175F +20200714065444 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80F21223F3 +20200714133000 2 6 100 8191 5 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80F56A8F2F +20200715042829 2 6 100 8191 5 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B80FD035EBF +20200715170628 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B81000F34CB +20200716042653 2 6 100 8191 2 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B8105A24213 +20200716044620 2 6 100 8191 5 FE8395C9AE4A595356F452E45DF7D762D3A014FEB24E19186365D2BB8740C384EE385601E524A910DC320C4B96D1FAECE8367AE226290C6484B2F9297F185D266063904ED73A257DC9A653750213D524AF0C46B2C13D51A95088B225BAED46BF3C451B9666D7371264E07A9269ED050B75DF602699A41083DA7B55E29B9A4D97DEB07F3731C7D56EBB26A8E4A980F1D085772A9779DF0B0C6D70D84A9422B4DA7118418C649B1CB4427D2BB1EE67710ECEFD41D0C4F5E4A7D87DEB4D5CA502DD56E1FE22F0BA53C3420566C7862D4A7E969958B3E935B73A323DDF7FC4839BD89AB696FEDD5299631C1DC15E849B753829A99CBA301A8DB3601203862059E33B1256D233E830BC2E4441B1458027BA97D0218B4B31D3EA350F550E328E5C32B8C36BE6F1E7F18B13F55BC42C54F6A5530255E206CC6CFC52CFC521B9B3355C9705BD66355310F89A4B70D44317E67C4B06D60001849E965E38F1F9C58AF177DFE3EB6048A54D02AD99E203C004714E97BFAF0163215DBAA9B1A262183B7109B60C975135D8DC02F6F48839EE2588BBBAD9D7C2126837B1C50019A721FD3D498979F10472BBC28FECA5AFF0560AECCE5249D809514B707DC9A57B358ACFAEB5A393E28AB752FE583DED0FCB40119702BD1E7CEFEC11980F64D034612B050919CA3121B2A9F1C4F66530EED3658CEEB0A7822A72DE37123AFD94BE8D7B6A9C2941AE9917697BA07B45815D0662491AF90222880878101792A8CB31926D9F66E6560B7E8273F213EA79311CE9261EBB9483E6FB8582650F69B834E792A614DB7D9ADEAA6E88368B8E72DB948E302420480E3F5B574F16CFA0F336555B649BFF5A3596D887DBAC229791FE5B194D95635709062C457261264B7B559D644D63CE12EA4FF7708D9B087453B318B57BC537E6FF3B8BBC408A5CD8DE6F3C628A0ECB5B9A020FB99A009C127861D54949B3BC068E2FCE802FFD69A8FBA34B474880532B88033B0F63D98F6BA5B455861FFE031A66427891E1492E999CB77C05F66E7458B5643DC43DAABDAA6A8BB4119A7C11B9B155820D5BE8CD91AD052769D73391D2FCE46F0BEADD6B62312C64ECD4613E5D1423F0EC56435BBFE0C43366BF60C361381AB1D8CAEC44D13C9DABE6937EF0018D689EE3F791CB1956CA46C32D293BD901BE4C95F4895525298C4D9D7EDA0E4840F81F458F520A0779CF09F45AE156C83195ECC82D85D4E71E535C6EF8933912A6459782923F2A7927919EDC80F5469DB628DE323D72881757FCF9BCC81D3E121A1BBF593A7B2EF10A2766FCF735FC993CF1303ADFE78D914A66CEDC64F606FD326B2DC501984CE64FE82DD4353AB1F7A3A2F556E73982D19CBF504E0901547D7F4B4E41B58E3F537774799DF4423B8376FE8D7760E3DBBD73E1D5DCB1499789711A90BE26D0DB48AA89E72B8105C3235F +20200717004114 2 6 100 8191 2 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E2563B2FF3 +20200717235130 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E25DEE6EFF +20200718065353 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E261E56D0F +20200719061659 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E26EE97997 +20200719174532 2 6 100 8191 2 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E2753B7F7B +20200719233549 2 6 100 8191 2 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E278465B13 +20200720193256 2 6 100 8191 2 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E27EAF2603 +20200720221223 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E28016951F +20200720225043 2 6 100 8191 2 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E280684433 +20200721051511 2 6 100 8191 2 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E283E5442B +20200721202027 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E28BF7EF47 +20200722031754 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E28FA5D78F +20200722033316 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E28FBF971F +20200722065544 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E2917E7E8F +20200722082838 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E292454C9F +20200722174034 2 6 100 8191 2 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E297121163 +20200723025424 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E29BB02057 +20200723041739 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E29C6C06E7 +20200723052236 2 6 100 8191 2 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E29CFC7C53 +20200723065956 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E29DD62887 +20200723141158 2 6 100 8191 2 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E2A1DEDC7B +20200723143438 2 6 100 8191 2 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E2A20B359B +20200723180649 2 6 100 8191 2 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E2A3FDE2C3 +20200723182158 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E2A41A0857 +20200724142608 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E2AF0F839F +20200724163612 2 6 100 8191 2 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E2B034D293 +20200726001643 2 6 100 8191 2 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E2C133FD8B +20200726175941 2 6 100 8191 2 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E2CA996EAB +20200726180625 2 6 100 8191 2 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E2CA9DE833 +20200727032532 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E2CF5B2087 +20200727053855 2 6 100 8191 5 F80E15DF775E74500D293272136D58EC8D062AB4FCF79FE676D1E7C31466BBF53DB66029B5AA4C527F0D59D3D00BEE81CF126FD0F8CC2FB19017E9F6B02D75BE094347756941901536C84FF90D5E14953AABD9D6A660404C8164C9EFE33B0BD6B2CAC083F7EDD115393E43A2DD6CCE66037ACC14D987EB1F6B23A77BC2EBC3621B160C2561DCDED8E51CCDC7B2C6ABA4ED99F686218D9B925231626619CB61452D83FD6A0AD8CC12698777BD28762038D45399B1D0E06930D87444D4DD3EFE94287F34557D021077ED3E8F61E9FE6138F1BA7335198FE5D06373E5FFDAB4058E3697BC4A013C91F8B1DD1C9409A5A7D9A3707B958DF6E83052881C36724D98E8FA98C83FD8FBBFCD8B0C09B31ECDFE9D7884DCCD6F7E192A8B6F0DE93CB12891872DF631E1C4E5DF3C9B5A7FB773F9165236D776CCE0E80E61AC842D6B01AAA82856DA6E4581D542709C702FCBC2FE8C28B546BB21F42AF475076BAF67B21F92BB70703A0941962EE5D9DFDFC620DA16DEB0EBC166DB869E956AF4EAAF008BD2B78AA77474A481AFED15AB98751F3431A815C4B606F6A34423A0DA4236FB1339177FD9FB3AFBC8166E313FD8C02C12D8DE0184F3E6CEE043685B8372E14B84100A7BB3536460E3FF851F73E2ED904953F6481D33D7B4BD8A9C829F92911FDFAD6CA31EBC1B70E4CD3D964E7A922BFAD0A828959F3AAD1708E742F68FD8B5DA90558D9F8222DFC1765B835DBF7FF5785F0645D04B56EE67A76EEAF04243A1E4EE47787328EFAA880A463D064B203CB70CDEFF554D281A6E161D3EB55967763DD09F5A68FC23B8D3660C8EFB705706B699F9A9FED5F16E77E060220F5572F11564B7D5F27BCCA81A1052A9745A4C7C37B776BAA4CEE950513577300A0CBBF9C555DBD0D83BB49E51EBE66405A404B19A5CC18577A2ED5DE05AA2F459CB78A92845F4A4C0CC8559B8E0338425D7988E1FA4572D67BBD9B9AD3B7156FD8C079E18C1285DF894426BD702804C4C468726420EAAB61C82E33BAC8613D541DA5B767B0877C5C8607BE72B5EA322EC00A4575606E959051CC658322287D255786C5C21E9799E7B8E5F0C93BCF0A267CB4C48C8F4271DF0A34ED2BB9C2FD8091375FD1B3E61D7A3F2F71F4D33226331DF2B7F22E48D2D831C2EA0383D8A7481191780DADD0ED5AFC6F28ADC8796B8B558A1DA2FCB838BC167A0A0377A7ACCF0E30B87111F9DB1760F3C0D16F097DDD3330D6A9369E8A6E57CAE4E5EB290A3370E55202C08EBA5A4D06C01996BDC06BBE027EBF746DF1579F82BF3A3A2765EA4AA989B56F82D4812539182AFFC8F5A8CAC826D2A7720CC2327521075CC8C7084B2CCA30DF574CAC8C44148DF989B7B1E940CBFFE47EB3892147920C3D93AE764B769F2A71AC2A2A2C4E05C60C887151CE4B8947FBA7C756D6F69F5394A3106F3E2D07FAFE7 diff --git a/moduli.c b/moduli.c index 4f6f8da8d..8dd36b1cf 100644 --- a/moduli.c +++ b/moduli.c @@ -1,4 +1,4 @@ -/* $OpenBSD: moduli.c,v 1.36 2019/10/04 03:26:58 dtucker Exp $ */ +/* $OpenBSD: moduli.c,v 1.37 2019/11/15 06:00:20 djm Exp $ */ /* * Copyright 1994 Phil Karn * Copyright 1996-1998, 2003 William Allen Simpson @@ -578,7 +578,6 @@ 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; @@ -602,8 +601,6 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted, 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); @@ -753,7 +750,7 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted, * that p is also prime. A single pass will weed out the * vast majority of composite q's. */ - is_prime = BN_is_prime_ex(q, 1, ctx, NULL); + is_prime = BN_is_prime_ex(q, 1, NULL, NULL); if (is_prime < 0) fatal("BN_is_prime_ex failed"); if (is_prime == 0) { @@ -769,7 +766,7 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted, * will show up on the first Rabin-Miller iteration so it * doesn't hurt to specify a high iteration count. */ - is_prime = BN_is_prime_ex(p, trials, ctx, NULL); + is_prime = BN_is_prime_ex(p, trials, NULL, NULL); if (is_prime < 0) fatal("BN_is_prime_ex failed"); if (is_prime == 0) { @@ -779,7 +776,7 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted, debug("%10u: p is almost certainly prime", count_in); /* recheck q more rigorously */ - is_prime = BN_is_prime_ex(q, trials - 1, ctx, NULL); + is_prime = BN_is_prime_ex(q, trials - 1, NULL, NULL); if (is_prime < 0) fatal("BN_is_prime_ex failed"); if (is_prime == 0) { @@ -802,7 +799,6 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted, free(lp); BN_free(p); BN_free(q); - BN_CTX_free(ctx); if (checkpoint_file != NULL) unlink(checkpoint_file); diff --git a/monitor.c b/monitor.c index a4755e89a..98df45c27 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.199 2019/10/07 23:10:38 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.223 2021/01/27 10:05:28 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -95,6 +95,7 @@ #include "authfd.h" #include "match.h" #include "ssherr.h" +#include "sk-api.h" #ifdef GSSAPI static Gssctxt *gsscontext = NULL; @@ -103,7 +104,6 @@ static Gssctxt *gsscontext = NULL; /* 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? */ @@ -308,8 +308,7 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) if (authenticated && !auth2_update_methods_lists(authctxt, auth_method, auth_submethod)) { - debug3("%s: method %s: partial", __func__, - auth_method); + debug3_f("method %s: partial", auth_method); authenticated = 0; partial = 1; } @@ -317,8 +316,8 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) if (authenticated) { if (!(ent->flags & MON_AUTHDECIDE)) - fatal("%s: unexpected authentication from %d", - __func__, ent->type); + fatal_f("unexpected authentication from %d", + ent->type); if (authctxt->pw->pw_uid == 0 && !auth_root_allowed(ssh, auth_method)) authenticated = 0; @@ -351,12 +350,11 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) } if (!authctxt->valid) - fatal("%s: authenticated invalid user", __func__); + fatal_f("authenticated invalid user"); if (strcmp(auth_method, "unknown") == 0) - fatal("%s: authentication method name unknown", __func__); + fatal_f("authentication method name unknown"); - debug("%s: %s has been authenticated by privileged process", - __func__, authctxt->user); + debug_f("user %s authenticated by privileged process", authctxt->user); ssh->authctxt = NULL; ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); @@ -392,11 +390,11 @@ monitor_child_postauth(struct ssh *ssh, struct monitor *pmonitor) 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); + ssh_signal(SIGHUP, &monitor_child_handler); + ssh_signal(SIGTERM, &monitor_child_handler); + ssh_signal(SIGINT, &monitor_child_handler); #ifdef SIGXFSZ - signal(SIGXFSZ, SIG_IGN); + ssh_signal(SIGXFSZ, SIG_IGN); #endif mon_dispatch = mon_dispatch_postauth20; @@ -419,49 +417,53 @@ static int monitor_read_log(struct monitor *pmonitor) { struct sshbuf *logmsg; - u_int len, level; - char *msg; + u_int len, level, line; + char *msg, *file, *func; u_char *p; int r; if ((logmsg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); /* Read length */ if ((r = sshbuf_reserve(logmsg, 4, &p)) != 0) - fatal("%s: reserve: %s", __func__, ssh_err(r)); + fatal_fr(r, "reserve len"); if (atomicio(read, pmonitor->m_log_recvfd, p, 4) != 4) { if (errno == EPIPE) { sshbuf_free(logmsg); - debug("%s: child log fd closed", __func__); + debug_f("child log fd closed"); close(pmonitor->m_log_recvfd); pmonitor->m_log_recvfd = -1; return -1; } - fatal("%s: log fd read: %s", __func__, strerror(errno)); + fatal_f("log fd read: %s", strerror(errno)); } if ((r = sshbuf_get_u32(logmsg, &len)) != 0) - fatal("%s: get len: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse len"); if (len <= 4 || len > 8192) - fatal("%s: invalid log message length %u", __func__, len); + fatal_f("invalid log message length %u", len); /* Read severity, message */ sshbuf_reset(logmsg); if ((r = sshbuf_reserve(logmsg, len, &p)) != 0) - fatal("%s: reserve: %s", __func__, ssh_err(r)); + fatal_fr(r, "reserve msg"); 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 || + fatal_f("log fd read: %s", strerror(errno)); + if ((r = sshbuf_get_cstring(logmsg, &file, NULL)) != 0 || + (r = sshbuf_get_cstring(logmsg, &func, NULL)) != 0 || + (r = sshbuf_get_u32(logmsg, &line)) != 0 || + (r = sshbuf_get_u32(logmsg, &level)) != 0 || (r = sshbuf_get_cstring(logmsg, &msg, NULL)) != 0) - fatal("%s: decode: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); /* Log it */ if (log_level_name(level) == NULL) - fatal("%s: invalid log level %u (corrupted message?)", - __func__, level); - do_log2(level, "%s [preauth]", msg); + fatal_f("invalid log level %u (corrupted message?)", level); + sshlog(file, func, line, 0, level, NULL, "%s [preauth]", msg); sshbuf_free(logmsg); + free(file); + free(func); free(msg); return 0; @@ -485,7 +487,7 @@ monitor_read(struct ssh *ssh, struct monitor *pmonitor, struct mon_table *ent, if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) { if (errno == EINTR || errno == EAGAIN) continue; - fatal("%s: poll: %s", __func__, strerror(errno)); + fatal_f("poll: %s", strerror(errno)); } if (pfd[1].revents) { /* @@ -500,13 +502,13 @@ monitor_read(struct ssh *ssh, struct monitor *pmonitor, struct mon_table *ent, } if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); mm_request_receive(pmonitor->m_sendfd, m); if ((r = sshbuf_get_u8(m, &type)) != 0) - fatal("%s: decode: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse type"); - debug3("%s: checking request %d", __func__, type); + debug3_f("checking request %d", type); while (ent->f != NULL) { if (ent->type == type) @@ -516,15 +518,13 @@ monitor_read(struct ssh *ssh, struct monitor *pmonitor, struct mon_table *ent, if (ent->f != NULL) { if (!(ent->flags & MON_PERMIT)) - fatal("%s: unpermitted request %d", __func__, - type); + fatal_f("unpermitted request %d", type); 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); + debug2_f("%d used once, disabling now", type); ent->flags &= ~MON_PERMIT; } @@ -534,7 +534,7 @@ monitor_read(struct ssh *ssh, struct monitor *pmonitor, struct mon_table *ent, return ret; } - fatal("%s: unsupported request: %d", __func__, type); + fatal_f("unsupported request: %d", type); /* NOTREACHED */ return (-1); @@ -542,7 +542,7 @@ monitor_read(struct ssh *ssh, struct monitor *pmonitor, struct mon_table *ent, /* allowed key state */ static int -monitor_allowed_key(u_char *blob, u_int bloblen) +monitor_allowed_key(const u_char *blob, u_int bloblen) { /* make sure key is allowed */ if (key_blob == NULL || key_bloblen != bloblen || @@ -579,21 +579,19 @@ mm_answer_moduli(struct ssh *ssh, int sock, struct sshbuf *m) 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)); + fatal_fr(r, "parse"); - debug3("%s: got parameters: %d %d %d", - __func__, min, want, max); + debug3_f("got parameters: %d %d %d", 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); + fatal_f("bad parameters: %d %d %d", 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)); + fatal_fr(r, "assemble empty"); return (0); } else { /* Send first bignum */ @@ -601,7 +599,7 @@ mm_answer_moduli(struct ssh *ssh, int sock, struct sshbuf *m) 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)); + fatal_fr(r, "assemble"); DH_free(dh); } @@ -623,15 +621,15 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m) u_int keyid, compat; const char proof_req[] = "hostkeys-prove-00@openssh.com"; - debug3("%s", __func__); + debug3_f("entering"); 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)); + fatal_fr(r, "parse"); if (keyid > INT_MAX) - fatal("%s: invalid key ID", __func__); + fatal_f("invalid key ID"); /* * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), @@ -650,21 +648,20 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m) * the client sent us. */ if (session_id2_len == 0) /* hostkeys is never first */ - fatal("%s: bad data length: %zu", __func__, datlen); + fatal_f("bad data length: %zu", datlen); if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL) - fatal("%s: no hostkey for index %d", __func__, keyid); + fatal_f("no hostkey for index %d", keyid); if ((sigbuf = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); 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)); + fatal_fr(r, "assemble private key proof"); 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)); + fatal_f("bad data length: %zu, hostkey proof len %zu", + datlen, sshbuf_len(sigbuf)); sshbuf_free(sigbuf); is_proof = 1; } @@ -678,25 +675,22 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m) 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)); + options.sk_provider, NULL, compat)) != 0) + fatal_fr(r, "sign"); } 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)); - } + p, datlen, alg, compat)) != 0) + fatal_fr(r, "agent sign"); } else - fatal("%s: no hostkey from index %d", __func__, keyid); + fatal_f("no hostkey from index %d", keyid); - debug3("%s: %s signature %p(%zu)", __func__, - is_proof ? "hostkey proof" : "KEX", signature, siglen); + debug3_f("%s signature %p(%zu)", is_proof ? "hostkey proof" : "KEX", + signature, siglen); sshbuf_reset(m); if ((r = sshbuf_put_string(m, signature, siglen)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); free(alg); free(p); @@ -710,8 +704,14 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m) return (0); } -/* Retrieves the password entry and also checks if the user is permitted */ +#define PUTPW(b, id) \ + do { \ + if ((r = sshbuf_put_string(b, \ + &pwent->id, sizeof(pwent->id))) != 0) \ + fatal_fr(r, "assemble %s", #id); \ + } while (0) +/* Retrieves the password entry and also checks if the user is permitted */ int mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m) { @@ -720,13 +720,13 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m) int r, allowed = 0; u_int i; - debug3("%s", __func__); + debug3_f("entering"); if (authctxt->attempt++ != 0) - fatal("%s: multiple attempts for getpwnam", __func__); + fatal_f("multiple attempts for getpwnam"); if ((r = sshbuf_get_cstring(m, &username, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); pwent = getpwnamallow(ssh, username); @@ -738,7 +738,7 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m) if (pwent == NULL) { if ((r = sshbuf_put_u8(m, 0)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble fakepw"); authctxt->pw = fakepw(); goto out; } @@ -747,10 +747,18 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m) 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 || + /* XXX send fake class/dir/shell, etc. */ + if ((r = sshbuf_put_u8(m, 1)) != 0) + fatal_fr(r, "assemble ok"); + PUTPW(m, pw_uid); + PUTPW(m, pw_gid); +#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE + PUTPW(m, pw_change); +#endif +#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE + PUTPW(m, pw_expire); +#endif + if ((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 || @@ -760,26 +768,23 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m) #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)); + fatal_fr(r, "assemble pw"); 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)); + fatal_fr(r, "assemble options"); #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)); \ - } \ + if (options.x != NULL && \ + (r = sshbuf_put_cstring(m, options.x)) != 0) \ + fatal_fr(r, "assemble %s", #x); \ } 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)); \ + fatal_fr(r, "assemble %s", #x); \ } \ } while (0) /* See comment in servconf.h */ @@ -794,10 +799,10 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m) * run to it's packet_disconnect(), but it must not allow any * authentication to succeed. */ - debug("%s: no valid authentication method lists", __func__); + debug_f("no valid authentication method lists"); } - debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed); + debug3_f("sending MONITOR_ANS_PWNAM: %d", allowed); mm_request_send(sock, MONITOR_ANS_PWNAM, m); /* Allow service/style information on the auth context */ @@ -820,7 +825,7 @@ int mm_answer_auth2_read_banner(struct ssh *ssh, int sock, struct sshbuf *m) 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)); + fatal_fr(r, "assemble"); mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m); free(banner); @@ -836,9 +841,8 @@ mm_answer_authserv(struct ssh *ssh, int sock, struct sshbuf *m) 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); + fatal_fr(r, "parse"); + debug3_f("service=%s, style=%s", authctxt->service, authctxt->style); if (strlen(authctxt->style) == 0) { free(authctxt->style); @@ -886,24 +890,24 @@ mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m) size_t plen; if (!options.password_authentication) - fatal("%s: password authentication not enabled", __func__); + fatal_f("password authentication not enabled"); if ((r = sshbuf_get_cstring(m, &passwd, &plen)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); /* Only authenticate if the context is valid */ authenticated = options.password_authentication && auth_password(ssh, passwd); - explicit_bzero(passwd, plen); - free(passwd); + freezero(passwd, plen); sshbuf_reset(m); if ((r = sshbuf_put_u32(m, authenticated)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); #ifdef USE_PAM if ((r = sshbuf_put_u32(m, sshpam_get_maxtries_reached())) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble PAM"); #endif debug3("%s: sending result %d", __func__, authenticated); + debug3_f("sending result %d", authenticated); mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m); call_count++; @@ -926,19 +930,19 @@ mm_answer_bsdauthquery(struct ssh *ssh, int sock, struct sshbuf *m) int r; if (!options.kbd_interactive_authentication) - fatal("%s: kbd-int authentication not enabled", __func__); + fatal_f("kbd-int authentication not enabled"); 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)); + fatal_fr(r, "assemble"); if (success) { if ((r = sshbuf_put_cstring(m, prompts[0])) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble prompt"); } - debug3("%s: sending challenge success: %u", __func__, success); + debug3_f("sending challenge success: %u", success); mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m); if (success) { @@ -958,23 +962,23 @@ mm_answer_bsdauthrespond(struct ssh *ssh, int sock, struct sshbuf *m) int r, authok; if (!options.kbd_interactive_authentication) - fatal("%s: kbd-int authentication not enabled", __func__); + fatal_f("kbd-int authentication not enabled"); if (authctxt->as == NULL) - fatal("%s: no bsd auth session", __func__); + fatal_f("no bsd auth session"); if ((r = sshbuf_get_cstring(m, &response, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); authok = options.challenge_response_authentication && auth_userresponse(authctxt->as, response, 0); authctxt->as = NULL; - debug3("%s: <%s> = <%d>", __func__, response, authok); + debug3_f("<%s> = <%d>", response, authok); free(response); sshbuf_reset(m); if ((r = sshbuf_put_u32(m, authok)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); - debug3("%s: sending authenticated: %d", __func__, authok); + debug3_f("sending authenticated: %d", authok); mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); auth_method = "keyboard-interactive"; @@ -1157,21 +1161,21 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m) int r, allowed = 0; struct sshauthopt *opts = NULL; - debug3("%s entering", __func__); - if ((r = sshbuf_get_u32(m, &(u_int32_t)type)) != 0 || + debug3_f("entering"); + 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)); + fatal_fr(r, "parse"); - debug3("%s: key_from_blob: %p", __func__, key); + debug3_f("key_from_blob: %p", 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__); + (ssh->compat & SSH_BUG_RSASIGMD5) != 0) + fatal_f("passed a SSH_BUG_RSASIGMD5 key"); switch (type) { case MM_USERKEY: @@ -1181,7 +1185,7 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m) if (auth2_key_already_used(authctxt, key)) break; if (!key_base_type_match(auth_method, key, - options.pubkey_key_types)) + options.pubkey_accepted_algos)) break; allowed = user_key_allowed(ssh, authctxt->pw, key, pubkey_auth_attempt, &opts); @@ -1193,7 +1197,7 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m) if (auth2_key_already_used(authctxt, key)) break; if (!key_base_type_match(auth_method, key, - options.hostbased_key_types)) + options.hostbased_accepted_algos)) break; allowed = hostbased_key_allowed(ssh, authctxt->pw, cuser, chost, key); @@ -1202,13 +1206,13 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m) cuser, chost); break; default: - fatal("%s: unknown key type %d", __func__, type); + fatal_f("unknown key type %d", type); break; } } - debug3("%s: %s authentication%s: %s key is %s", __func__, - auth_method, pubkey_auth_attempt ? "" : " test", + debug3_f("%s authentication%s: %s key is %s", auth_method, + pubkey_auth_attempt ? "" : " test", (key == NULL || !authctxt->valid) ? "invalid" : sshkey_type(key), allowed ? "allowed" : "not allowed"); @@ -1220,7 +1224,7 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m) 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)); + fatal_fr(r, "sshkey_to_blob"); key_blobtype = type; key_opts = opts; hostbased_cuser = cuser; @@ -1235,9 +1239,9 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m) sshbuf_reset(m); if ((r = sshbuf_put_u32(m, allowed)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); if (opts != NULL && (r = sshauthopt_serialise(opts, m, 1)) != 0) - fatal("%s: sshauthopt_serialise: %s", __func__, ssh_err(r)); + fatal_fr(r, "sshauthopt_serialise"); mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m); if (!allowed) @@ -1247,7 +1251,7 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m) } static int -monitor_valid_userblob(u_char *data, u_int datalen) +monitor_valid_userblob(struct ssh *ssh, const u_char *data, u_int datalen) { struct sshbuf *b; const u_char *p; @@ -1256,12 +1260,10 @@ monitor_valid_userblob(u_char *data, u_int datalen) 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 ((b = sshbuf_from(data, datalen)) == NULL) + fatal_f("sshbuf_from"); - if (datafellows & SSH_OLD_SESSIONID) { + if (ssh->compat & SSH_OLD_SESSIONID) { p = sshbuf_ptr(b); len = sshbuf_len(b); if ((session_id2 == NULL) || @@ -1269,21 +1271,21 @@ monitor_valid_userblob(u_char *data, u_int datalen) (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)); + fatal_fr(r, "consume"); } else { if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse sessionid"); 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)); + fatal_fr(r, "parse type"); 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)); + fatal_fr(r, "parse userstyle"); xasprintf(&userstyle, "%s%s%s", authctxt->user, authctxt->style ? ":" : "", authctxt->style ? authctxt->style : ""); @@ -1296,17 +1298,17 @@ monitor_valid_userblob(u_char *data, u_int datalen) 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)); + fatal_fr(r, "parse method"); 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)); + fatal_fr(r, "parse pktype"); 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)); + fatal_fr(r, "parse pk"); if (sshbuf_len(b) != 0) fail++; sshbuf_free(b); @@ -1314,8 +1316,8 @@ monitor_valid_userblob(u_char *data, u_int datalen) } static int -monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, - char *chost) +monitor_valid_hostbasedblob(const u_char *data, u_int datalen, + const char *cuser, const char *chost) { struct sshbuf *b; const u_char *p; @@ -1324,11 +1326,10 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, 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 ((b = sshbuf_from(data, datalen)) == NULL) + fatal_f("sshbuf_new"); + if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) + fatal_fr(r, "parse sessionid"); if ((session_id2 == NULL) || (len != session_id2_len) || @@ -1336,11 +1337,11 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, fail++; if ((r = sshbuf_get_u8(b, &type)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse type"); 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)); + fatal_fr(r, "parse userstyle"); xasprintf(&userstyle, "%s%s%s", authctxt->user, authctxt->style ? ":" : "", authctxt->style ? authctxt->style : ""); @@ -1353,17 +1354,17 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, 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)); + fatal_fr(r, "parse method"); 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)); + fatal_fr(r, "parse pk"); /* 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)); + fatal_fr(r, "parse host"); if (((len = strlen(cp)) > 0) && cp[len - 1] == '.') cp[len - 1] = '\0'; if (strcmp(cp, chost) != 0) @@ -1372,7 +1373,7 @@ monitor_valid_hostbasedblob(u_char *data, u_int datalen, char *cuser, /* verify client user */ if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse ruser"); if (strcmp(cp, cuser) != 0) fail++; free(cp); @@ -1387,20 +1388,22 @@ int mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) { struct sshkey *key; - u_char *signature, *data, *blob; - char *sigalg; + const u_char *signature, *data, *blob; + char *sigalg = NULL, *fp = NULL; size_t signaturelen, datalen, bloblen; - int r, ret, valid_data = 0, encoded_ret; + int r, ret, req_presence = 0, req_verify = 0, valid_data = 0; + int encoded_ret; + struct sshkey_sig_details *sig_details = NULL; - 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 || + if ((r = sshbuf_get_string_direct(m, &blob, &bloblen)) != 0 || + (r = sshbuf_get_string_direct(m, &signature, &signaturelen)) != 0 || + (r = sshbuf_get_string_direct(m, &data, &datalen)) != 0 || (r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); if (hostbased_cuser == NULL || hostbased_chost == NULL || !monitor_allowed_key(blob, bloblen)) - fatal("%s: bad key, not previously allowed", __func__); + fatal_f("bad key, not previously allowed"); /* Empty signature algorithm means NULL. */ if (*sigalg == '\0') { @@ -1410,11 +1413,11 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) /* 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)); + fatal_fr(r, "parse key"); switch (key_blobtype) { case MM_USERKEY: - valid_data = monitor_valid_userblob(data, datalen); + valid_data = monitor_valid_userblob(ssh, data, datalen); auth_method = "publickey"; break; case MM_HOSTKEY: @@ -1427,32 +1430,73 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) break; } if (!valid_data) - fatal("%s: bad signature data blob", __func__); + fatal_f("bad %s signature data blob", + key_blobtype == MM_USERKEY ? "userkey" : + (key_blobtype == MM_HOSTKEY ? "hostkey" : "unknown")); + + if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) + fatal_f("sshkey_fingerprint failed"); ret = sshkey_verify(key, signature, signaturelen, data, datalen, - sigalg, ssh->compat); - debug3("%s: %s %p signature %s", __func__, auth_method, key, - (ret == 0) ? "verified" : "unverified"); - auth2_record_key(authctxt, ret == 0, key); + sigalg, ssh->compat, &sig_details); + debug3_f("%s %p signature %s%s%s", auth_method, key, + (ret == 0) ? "verified" : "unverified", + (ret != 0) ? ": " : "", (ret != 0) ? ssh_err(ret) : ""); - free(blob); - free(signature); - free(data); - free(sigalg); + if (ret == 0 && key_blobtype == MM_USERKEY && sig_details != NULL) { + req_presence = (options.pubkey_auth_options & + PUBKEYAUTH_TOUCH_REQUIRED) || + !key_opts->no_require_user_presence; + if (req_presence && + (sig_details->sk_flags & SSH_SK_USER_PRESENCE_REQD) == 0) { + error("public key %s %s signature for %s%s from %.128s " + "port %d rejected: user presence " + "(authenticator touch) requirement not met ", + sshkey_type(key), fp, + authctxt->valid ? "" : "invalid user ", + authctxt->user, ssh_remote_ipaddr(ssh), + ssh_remote_port(ssh)); + ret = SSH_ERR_SIGNATURE_INVALID; + } + req_verify = (options.pubkey_auth_options & + PUBKEYAUTH_VERIFY_REQUIRED) || key_opts->require_verify; + if (req_verify && + (sig_details->sk_flags & SSH_SK_USER_VERIFICATION_REQD) == 0) { + error("public key %s %s signature for %s%s from %.128s " + "port %d rejected: user verification requirement " + "not met ", sshkey_type(key), fp, + authctxt->valid ? "" : "invalid user ", + authctxt->user, ssh_remote_ipaddr(ssh), + ssh_remote_port(ssh)); + ret = SSH_ERR_SIGNATURE_INVALID; + } + } + auth2_record_key(authctxt, ret == 0, key); 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)); + if ((r = sshbuf_put_u32(m, encoded_ret)) != 0 || + (r = sshbuf_put_u8(m, sig_details != NULL)) != 0) + fatal_fr(r, "assemble"); + if (sig_details != NULL) { + if ((r = sshbuf_put_u32(m, sig_details->sk_counter)) != 0 || + (r = sshbuf_put_u8(m, sig_details->sk_flags)) != 0) + fatal_fr(r, "assemble sk"); + } + sshkey_sig_details_free(sig_details); mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m); + free(sigalg); + free(fp); + sshkey_free(key); + return ret == 0; } @@ -1484,9 +1528,9 @@ mm_record_login(struct ssh *ssh, Session *s, struct passwd *pw) static void mm_session_close(Session *s) { - debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid); + debug3_f("session %d pid %ld", s->self, (long)s->pid); if (s->ttyfd != -1) { - debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); + debug3_f("tty %s ptyfd %d", s->tty, s->ptyfd); session_pty_cleanup2(s); } session_unused(s->self); @@ -1499,7 +1543,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m) Session *s; int r, res, fd0; - debug3("%s entering", __func__); + debug3_f("entering"); sshbuf_reset(m); s = session_new(); @@ -1515,11 +1559,11 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m) 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)); + fatal_fr(r, "assemble"); /* We need to trick ttyslot */ if (dup2(s->ttyfd, 0) == -1) - fatal("%s: dup2", __func__); + fatal_f("dup2"); mm_record_login(ssh, s, authctxt->pw); @@ -1528,28 +1572,28 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m) /* send messages generated by record_login */ if ((r = sshbuf_put_stringb(m, loginmsg)) != 0) - fatal("%s: put login message: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble loginmsg"); 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__); + fatal_f("send fds failed"); /* make sure nothing uses fd 0 */ if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) == -1) - fatal("%s: open(/dev/null): %s", __func__, strerror(errno)); + fatal_f("open(/dev/null): %s", strerror(errno)); if (fd0 != 0) - error("%s: fd0 %d != 0", __func__, fd0); + error_f("fd0 %d != 0", fd0); - /* slave is not needed */ + /* slave side of pty 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); + debug3_f("tty %s ptyfd %d", s->tty, s->ttyfd); return (0); @@ -1557,7 +1601,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m) if (s != NULL) mm_session_close(s); if ((r = sshbuf_put_u32(m, 0)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble 0"); mm_request_send(sock, MONITOR_ANS_PTY, m); return (0); } @@ -1569,10 +1613,10 @@ mm_answer_pty_cleanup(struct ssh *ssh, int sock, struct sshbuf *m) char *tty; int r; - debug3("%s entering", __func__); + debug3_f("entering"); if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse tty"); if ((s = session_by_tty(tty)) != NULL) mm_session_close(s); sshbuf_reset(m); @@ -1586,7 +1630,7 @@ mm_answer_term(struct ssh *ssh, int sock, struct sshbuf *req) extern struct monitor *pmonitor; int res, status; - debug3("%s: tearing down sessions", __func__); + debug3_f("tearing down sessions"); /* The child is terminating */ session_destroy_all(ssh, &mm_session_close); @@ -1756,47 +1800,53 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) struct kex *kex; int r; - debug3("%s: packet_set_state", __func__); + debug3_f("packet_set_state"); if ((r = ssh_packet_set_state(ssh, child_state)) != 0) - fatal("%s: packet_set_state: %s", __func__, ssh_err(r)); + fatal_fr(r, "packet_set_state"); sshbuf_free(child_state); child_state = NULL; - - if ((kex = ssh->kex) != NULL) { - /* XXX set callbacks */ + if ((kex = ssh->kex) == NULL) + fatal_f("internal error: ssh->kex == NULL"); + if (session_id2_len != sshbuf_len(ssh->kex->session_id)) { + fatal_f("incorrect session id length %zu (expected %u)", + sshbuf_len(ssh->kex->session_id), session_id2_len); + } + if (memcmp(sshbuf_ptr(ssh->kex->session_id), session_id2, + session_id2_len) != 0) + fatal_f("session ID mismatch"); + /* XXX set callbacks */ #ifdef WITH_OPENSSL - 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; + 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] = kex_gen_server; + kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif #endif /* WITH_OPENSSL */ - kex->kex[KEX_C25519_SHA256] = kex_gen_server; - kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; - kex->load_host_public_key=&get_hostkey_public_by_type; - kex->load_host_private_key=&get_hostkey_private_by_type; - kex->host_key_index=&get_hostkey_index; - kex->sign = sshd_hostkey_sign; - } + kex->kex[KEX_C25519_SHA256] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP761X25519_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 */ +/* This function requires careful sanity checking */ void mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) { - debug3("%s: Waiting for new keys", __func__); + debug3_f("Waiting for new keys"); if ((child_state = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, child_state); - debug3("%s: GOT new keys", __func__); + debug3_f("GOT new keys"); } @@ -1816,7 +1866,7 @@ monitor_openfds(struct monitor *mon, int do_logfds) #endif if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) - fatal("%s: socketpair: %s", __func__, strerror(errno)); + fatal_f("socketpair: %s", strerror(errno)); #ifdef SO_ZEROIZE if (setsockopt(pair[0], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) == -1) error("setsockopt SO_ZEROIZE(0): %.100s", strerror(errno)); @@ -1830,7 +1880,7 @@ monitor_openfds(struct monitor *mon, int do_logfds) if (do_logfds) { if (pipe(pair) == -1) - fatal("%s: pipe: %s", __func__, strerror(errno)); + fatal_f("pipe: %s", strerror(errno)); FD_CLOSEONEXEC(pair[0]); FD_CLOSEONEXEC(pair[1]); mon->m_log_recvfd = pair[0]; @@ -1869,10 +1919,10 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m) int r; if (!options.gss_authentication) - fatal("%s: GSSAPI authentication not enabled", __func__); + fatal_f("GSSAPI authentication not enabled"); if ((r = sshbuf_get_string(m, &p, &len)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); goid.elements = p; goid.length = len; @@ -1882,7 +1932,7 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m) sshbuf_reset(m); if ((r = sshbuf_put_u32(m, major)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); mm_request_send(sock, MONITOR_ANS_GSSSETUP, m); @@ -1902,10 +1952,10 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) int r; if (!options.gss_authentication) - fatal("%s: GSSAPI authentication not enabled", __func__); + fatal_f("GSSAPI authentication not enabled"); if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "ssh_gssapi_get_buffer_desc"); major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); free(in.value); @@ -1913,7 +1963,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *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)); + fatal_fr(r, "assemble"); mm_request_send(sock, MONITOR_ANS_GSSSTEP, m); gss_release_buffer(&minor, &out); @@ -1934,11 +1984,11 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) int r; if (!options.gss_authentication) - fatal("%s: GSSAPI authentication not enabled", __func__); + fatal_f("GSSAPI authentication not enabled"); 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)); + fatal_fr(r, "ssh_gssapi_get_buffer_desc"); ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic); @@ -1947,7 +1997,7 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) sshbuf_reset(m); if ((r = sshbuf_put_u32(m, ret)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m); @@ -1964,15 +2014,15 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) const char *displayname; if (!options.gss_authentication) - fatal("%s: GSSAPI authentication not enabled", __func__); + fatal_f("GSSAPI authentication not enabled"); 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)); + fatal_fr(r, "assemble"); - debug3("%s: sending result %d", __func__, authenticated); + debug3_f("sending result %d", authenticated); mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); auth_method = "gssapi-with-mic"; @@ -1985,4 +2035,4 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) } #endif /* GSSAPI */ - + diff --git a/monitor_fdpass.c b/monitor_fdpass.c index d766edcf1..a07727a8e 100644 --- a/monitor_fdpass.c +++ b/monitor_fdpass.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_fdpass.c,v 1.21 2016/02/29 20:22:36 jca Exp $ */ +/* $OpenBSD: monitor_fdpass.c,v 1.22 2020/10/18 11:32:01 djm Exp $ */ /* * Copyright 2001 Niels Provos * All rights reserved. @@ -89,17 +89,16 @@ mm_send_fd(int sock, int fd) pfd.events = POLLOUT; while ((n = sendmsg(sock, &msg, 0)) == -1 && (errno == EAGAIN || errno == EINTR)) { - debug3("%s: sendmsg(%d): %s", __func__, fd, strerror(errno)); + debug3_f("sendmsg(%d): %s", fd, strerror(errno)); (void)poll(&pfd, 1, -1); } if (n == -1) { - error("%s: sendmsg(%d): %s", __func__, fd, - strerror(errno)); + error_f("sendmsg(%d): %s", fd, strerror(errno)); return -1; } if (n != 1) { - error("%s: sendmsg: expected sent 1 got %zd", __func__, n); + error_f("sendmsg: expected sent 1 got %zd", n); return -1; } return 0; @@ -145,35 +144,34 @@ mm_receive_fd(int sock) pfd.events = POLLIN; while ((n = recvmsg(sock, &msg, 0)) == -1 && (errno == EAGAIN || errno == EINTR)) { - debug3("%s: recvmsg: %s", __func__, strerror(errno)); + debug3_f("recvmsg: %s", strerror(errno)); (void)poll(&pfd, 1, -1); } if (n == -1) { - error("%s: recvmsg: %s", __func__, strerror(errno)); + error_f("recvmsg: %s", strerror(errno)); return -1; } if (n != 1) { - error("%s: recvmsg: expected received 1 got %zd", __func__, n); + error_f("recvmsg: expected received 1 got %zd", n); return -1; } #ifdef HAVE_ACCRIGHTS_IN_MSGHDR if (msg.msg_accrightslen != sizeof(fd)) { - error("%s: no fd", __func__); + error_f("no fd"); return -1; } #else cmsg = CMSG_FIRSTHDR(&msg); if (cmsg == NULL) { - error("%s: no message header", __func__); + error_f("no message header"); return -1; } #ifndef BROKEN_CMSG_TYPE if (cmsg->cmsg_type != SCM_RIGHTS) { - error("%s: expected type %d got %d", __func__, - SCM_RIGHTS, cmsg->cmsg_type); + error_f("expected %d got %d", SCM_RIGHTS, cmsg->cmsg_type); return -1; } #endif @@ -181,7 +179,7 @@ mm_receive_fd(int sock) #endif return fd; #else - error("%s: file descriptor passing not supported", __func__); + error_f("file descriptor passing not supported"); return -1; #endif } diff --git a/monitor_wrap.c b/monitor_wrap.c index 4169b7604..1226dfd0e 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.113 2019/06/28 13:35:04 deraadt Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.122 2020/11/27 00:37:10 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -82,7 +82,8 @@ extern struct sshbuf *loginmsg; extern ServerOptions options; void -mm_log_handler(LogLevel level, const char *msg, void *ctx) +mm_log_handler(const char *file, const char *func, int line, + LogLevel level, const char *msg, void *ctx) { struct sshbuf *log_msg; struct monitor *mon = (struct monitor *)ctx; @@ -90,21 +91,24 @@ mm_log_handler(LogLevel level, const char *msg, void *ctx) size_t len; if (mon->m_log_sendfd == -1) - fatal("%s: no log channel", __func__); + fatal_f("no log channel"); if ((log_msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u32(log_msg, 0)) != 0 || /* length; filled below */ + (r = sshbuf_put_cstring(log_msg, file)) != 0 || + (r = sshbuf_put_cstring(log_msg, func)) != 0 || + (r = sshbuf_put_u32(log_msg, (u_int)line)) != 0 || (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)); + fatal_fr(r, "assemble"); if ((len = sshbuf_len(log_msg)) < 4 || len > 0xffffffff) - fatal("%s: bad length %zu", __func__, len); + fatal_f("bad length %zu", 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)); + fatal_f("write: %s", strerror(errno)); sshbuf_free(log_msg); } @@ -124,16 +128,16 @@ 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); + debug3_f("entering, type %d", type); if (mlen >= 0xffffffff) - fatal("%s: bad length %zu", __func__, mlen); + fatal_f("bad length %zu", 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)); + fatal_f("write: %s", strerror(errno)); if (atomicio(vwrite, sock, sshbuf_mutable_ptr(m), mlen) != mlen) - fatal("%s: write: %s", __func__, strerror(errno)); + fatal_f("write: %s", strerror(errno)); } void @@ -143,21 +147,21 @@ mm_request_receive(int sock, struct sshbuf *m) u_int msg_len; int r; - debug3("%s entering", __func__); + debug3_f("entering"); if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) { if (errno == EPIPE) cleanup_exit(255); - fatal("%s: read: %s", __func__, strerror(errno)); + fatal_f("read: %s", strerror(errno)); } msg_len = PEEK_U32(buf); if (msg_len > 256 * 1024) - fatal("%s: read: bad msg_len %d", __func__, msg_len); + fatal_f("read: bad msg_len %d", msg_len); sshbuf_reset(m); if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "reserve"); if (atomicio(read, sock, p, msg_len) != msg_len) - fatal("%s: read: %s", __func__, strerror(errno)); + fatal_f("read: %s", strerror(errno)); } void @@ -166,14 +170,13 @@ 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); + debug3_f("entering, type %d", type); mm_request_receive(sock, m); if ((r = sshbuf_get_u8(m, &rtype)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); if (rtype != type) - fatal("%s: read: rtype %d != type %d", __func__, - rtype, type); + fatal_f("read: rtype %d != type %d", rtype, type); } #ifdef WITH_OPENSSL @@ -186,27 +189,27 @@ mm_choose_dh(int min, int nbits, int max) struct sshbuf *m; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, m); - debug3("%s: waiting for MONITOR_ANS_MODULI", __func__); + debug3_f("waiting for MONITOR_ANS_MODULI"); 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)); + fatal_fr(r, "parse success"); if (success == 0) - fatal("%s: MONITOR_ANS_MODULI failed", __func__); + fatal_f("MONITOR_ANS_MODULI failed"); if ((r = sshbuf_get_bignum2(m, &p)) != 0 || (r = sshbuf_get_bignum2(m, &g)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse group"); - debug3("%s: remaining %zu", __func__, sshbuf_len(m)); + debug3_f("remaining %zu", sshbuf_len(m)); sshbuf_free(m); return (dh_new_group(g, p)); @@ -215,34 +218,43 @@ mm_choose_dh(int min, int nbits, int max) int 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) + const u_char *data, size_t datalen, const char *hostkey_alg, + const char *sk_provider, const char *sk_pin, u_int compat) { struct kex *kex = *pmonitor->m_pkex; struct sshbuf *m; u_int ndx = kex->host_key_index(key, 0, ssh); int r; - debug3("%s entering", __func__); - + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, m); - debug3("%s: waiting for MONITOR_ANS_SIGN", __func__); + debug3_f("waiting for MONITOR_ANS_SIGN"); 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)); + fatal_fr(r, "parse"); sshbuf_free(m); return (0); } +#define GETPW(b, id) \ + do { \ + if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) \ + fatal_fr(r, "parse pw %s", #id); \ + if (len != sizeof(pw->id)) \ + fatal_fr(r, "bad length for %s", #id); \ + memcpy(&pw->id, p, len); \ + } while (0) + struct passwd * mm_getpwnamallow(struct ssh *ssh, const char *username) { @@ -255,20 +267,20 @@ mm_getpwnamallow(struct ssh *ssh, const char *username) u_char ok; const u_char *p; - debug3("%s entering", __func__); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, username)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, m); - debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__); + debug3_f("waiting for MONITOR_ANS_PWNAM"); 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)); + fatal_fr(r, "parse success"); if (ok == 0) { pw = NULL; goto out; @@ -276,12 +288,14 @@ mm_getpwnamallow(struct ssh *ssh, const char *username) /* 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)); - + GETPW(m, pw_uid); + GETPW(m, pw_gid); +#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE + GETPW(m, pw_change); +#endif +#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE + GETPW(m, pw_expire); +#endif 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 @@ -292,24 +306,21 @@ mm_getpwnamallow(struct ssh *ssh, const char *username) #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)); + fatal_fr(r, "parse pw"); 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)); + fatal_fr(r, "parse opts"); if (len != sizeof(*newopts)) - fatal("%s: option block size mismatch", __func__); + fatal_f("option block size mismatch"); 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)); \ - } \ + if (newopts->x != NULL && \ + (r = sshbuf_get_cstring(m, &newopts->x, NULL)) != 0) \ + fatal_fr(r, "parse %s", #x); \ } while (0) #define M_CP_STRARRAYOPT(x, nx) do { \ newopts->x = newopts->nx == 0 ? \ @@ -317,8 +328,7 @@ out: 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)); \ + fatal_fr(r, "parse %s", #x); \ } \ } while (0) /* See comment in servconf.h */ @@ -328,6 +338,9 @@ out: copy_set_server_options(&options, newopts, 1); log_change_level(options.log_level); + log_verbose_reset(); + for (i = 0; i < options.num_log_verbose; i++) + log_verbose_add(options.log_verbose[i]); process_permitopen(ssh, &options); free(newopts); @@ -343,17 +356,17 @@ mm_auth2_read_banner(void) char *banner; int r; - debug3("%s entering", __func__); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "parse"); sshbuf_free(m); /* treat empty banner as missing banner */ @@ -372,13 +385,13 @@ mm_inform_authserv(char *service, char *style) struct sshbuf *m; int r; - debug3("%s entering", __func__); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m); @@ -395,32 +408,31 @@ mm_auth_password(struct ssh *ssh, char *password) u_int maxtries = 0; #endif - debug3("%s entering", __func__); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, password)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, m); - debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__); + debug3_f("waiting for MONITOR_ANS_AUTHPASSWORD"); 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)); + fatal_fr(r, "parse"); #ifdef USE_PAM if ((r = sshbuf_get_u32(m, &maxtries)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse PAM"); if (maxtries > INT_MAX) - fatal("%s: bad maxtries %u", __func__, maxtries); + fatal_fr(r, "bad maxtries"); sshpam_set_maxtries_reached(maxtries); #endif sshbuf_free(m); - debug3("%s: user %sauthenticated", - __func__, authenticated ? "" : "not "); + debug3_f("user %sauthenticated", authenticated ? "" : "not "); return (authenticated); } @@ -447,33 +459,31 @@ mm_key_allowed(enum mm_keytype type, const char *user, const char *host, int r, allowed = 0; struct sshauthopt *opts = NULL; - debug3("%s entering", __func__); + debug3_f("entering"); if (authoptp != NULL) *authoptp = NULL; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, m); - debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__); + debug3_f("waiting for MONITOR_ANS_KEYALLOWED"); 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)); - } + fatal_fr(r, "parse"); + if (allowed && type == MM_USERKEY && + (r = sshauthopt_deserialise(m, &opts)) != 0) + fatal_fr(r, "sshauthopt_deserialise"); sshbuf_free(m); if (authoptp != NULL) { @@ -493,31 +503,46 @@ mm_key_allowed(enum mm_keytype type, const char *user, const char *host, 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) + const u_char *data, size_t datalen, const char *sigalg, u_int compat, + struct sshkey_sig_details **sig_detailsp) { struct sshbuf *m; u_int encoded_ret = 0; int r; + u_char sig_details_present, flags; + u_int counter; - debug3("%s entering", __func__); - + debug3_f("entering"); + if (sig_detailsp != NULL) + *sig_detailsp = NULL; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, m); - debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__); + debug3_f("waiting for MONITOR_ANS_KEYVERIFY"); 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)); + if ((r = sshbuf_get_u32(m, &encoded_ret)) != 0 || + (r = sshbuf_get_u8(m, &sig_details_present)) != 0) + fatal_fr(r, "parse"); + if (sig_details_present && encoded_ret == 0) { + if ((r = sshbuf_get_u32(m, &counter)) != 0 || + (r = sshbuf_get_u8(m, &flags)) != 0) + fatal_fr(r, "parse sig_details"); + if (sig_detailsp != NULL) { + *sig_detailsp = xcalloc(1, sizeof(**sig_detailsp)); + (*sig_detailsp)->sk_counter = counter; + (*sig_detailsp)->sk_flags = flags; + } + } sshbuf_free(m); @@ -533,12 +558,11 @@ mm_send_keystate(struct ssh *ssh, struct monitor *monitor) int r; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = ssh_packet_get_state(ssh, m)) != 0) - fatal("%s: get_state failed: %s", - __func__, ssh_err(r)); + fatal_fr(r, "ssh_packet_get_state"); mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m); - debug3("%s: Finished sending state", __func__); + debug3_f("Finished sending state"); sshbuf_free(m); } @@ -552,7 +576,7 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen) /* 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__); + error_f("cannot allocate fds for pty"); if (tmp1 > 0) close(tmp1); if (tmp2 > 0) @@ -563,34 +587,34 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen) close(tmp2); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, m); - debug3("%s: waiting for MONITOR_ANS_PTY", __func__); + debug3_f("waiting for MONITOR_ANS_PTY"); 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)); + fatal_fr(r, "parse success"); if (success == 0) { - debug3("%s: pty alloc failed", __func__); + debug3_f("pty alloc failed"); 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)); + fatal_fr(r, "parse"); 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)); + fatal_fr(r, "put loginmsg"); 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__); + fatal_f("receive fds failed"); /* Success */ return (1); @@ -605,9 +629,9 @@ mm_session_pty_cleanup2(Session *s) if (s->ttyfd == -1) return; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, s->tty)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assmble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, m); sshbuf_free(m); @@ -780,7 +804,7 @@ mm_terminate(void) struct sshbuf *m; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, m); sshbuf_free(m); } @@ -806,31 +830,31 @@ mm_bsdauth_query(void *ctx, char **name, char **infotxt, char *challenge; int r; - debug3("%s: entering", __func__); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "parse success"); if (success == 0) { - debug3("%s: no challenge", __func__); + debug3_f("no challenge"); 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)); + fatal_fr(r, "parse challenge"); sshbuf_free(m); mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); (*prompts)[0] = challenge; - debug3("%s: received challenge: %s", __func__, challenge); + debug3_f("received challenge: %s", challenge); return (0); } @@ -841,21 +865,21 @@ mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses) struct sshbuf *m; int r, authok; - debug3("%s: entering", __func__); + debug3_f("entering"); if (numresponses != 1) return (-1); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, responses[0])) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); 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)); + fatal_fr(r, "parse"); sshbuf_free(m); return ((authok == 0) ? -1 : 0); @@ -909,15 +933,15 @@ mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid) *ctx = NULL; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_string(m, goid->elements, goid->length)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); 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)); + fatal_fr(r, "parse"); sshbuf_free(m); return (major); @@ -933,19 +957,19 @@ mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in, int r; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_string(m, in->value, in->length)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "assemble"); 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)); + fatal_fr(r, "parse"); if (flagsp != NULL) { if ((r = sshbuf_get_u32(m, &flags)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse flags"); *flagsp = flags; } @@ -962,17 +986,17 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) int r; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "assemble"); 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)); + fatal_fr(r, "parse"); sshbuf_free(m); return(major); } @@ -984,17 +1008,17 @@ mm_ssh_gssapi_userok(char *user) int r, authenticated = 0; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "parse"); sshbuf_free(m); - debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); + debug3_f("user %sauthenticated", authenticated ? "" : "not "); return (authenticated); } #endif /* GSSAPI */ diff --git a/monitor_wrap.h b/monitor_wrap.h index 191277f3a..8507f1c11 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.h,v 1.42 2019/09/06 05:23:55 djm Exp $ */ +/* $OpenBSD: monitor_wrap.h,v 1.46 2020/10/16 13:24:45 djm Exp $ */ /* * Copyright 2002 Niels Provos @@ -38,14 +38,17 @@ struct monitor; struct Authctxt; struct sshkey; struct sshauthopt; +struct sshkey_sig_details; -void mm_log_handler(LogLevel, const char *, void *); +void mm_log_handler(const char *, const char *, int, LogLevel, + const char *, void *); int mm_is_monitor(void); #ifdef WITH_OPENSSL DH *mm_choose_dh(int, int, int); #endif int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *, - const u_char *, size_t, const char *, u_int compat); + const u_char *, size_t, const char *, const char *, + const char *, u_int compat); void mm_inform_authserv(char *, char *); struct passwd *mm_getpwnamallow(struct ssh *, const char *); char *mm_auth2_read_banner(void); @@ -57,7 +60,7 @@ int mm_user_key_allowed(struct ssh *, struct passwd *, struct sshkey *, int, 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); + const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); #ifdef GSSAPI OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); diff --git a/msg.c b/msg.c index 1bd20f3d3..d22c4e477 100644 --- a/msg.c +++ b/msg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: msg.c,v 1.17 2018/07/09 21:59:10 markus Exp $ */ +/* $OpenBSD: msg.c,v 1.20 2020/10/18 11:32:01 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * @@ -47,16 +47,16 @@ ssh_msg_send(int fd, u_char type, struct sshbuf *m) u_char buf[5]; u_int mlen = sshbuf_len(m); - debug3("ssh_msg_send: type %u", (unsigned int)type & 0xff); + debug3_f("type %u", (unsigned int)type & 0xff); put_u32(buf, mlen + 1); buf[4] = type; /* 1st byte of payload is mesg-type */ if (atomicio(vwrite, fd, buf, sizeof(buf)) != sizeof(buf)) { - error("ssh_msg_send: write"); + error_f("write: %s", strerror(errno)); return (-1); } if (atomicio(vwrite, fd, sshbuf_mutable_ptr(m), mlen) != mlen) { - error("ssh_msg_send: write"); + error_f("write: %s", strerror(errno)); return (-1); } return (0); @@ -73,21 +73,21 @@ ssh_msg_recv(int fd, struct sshbuf *m) if (atomicio(read, fd, buf, sizeof(buf)) != sizeof(buf)) { if (errno != EPIPE) - error("ssh_msg_recv: read: header"); + error_f("read header: %s", strerror(errno)); return (-1); } msg_len = get_u32(buf); - if (msg_len > 256 * 1024) { - error("ssh_msg_recv: read: bad msg_len %u", msg_len); + if (msg_len > sshbuf_max_size(m)) { + error_f("read: bad msg_len %u", msg_len); return (-1); } sshbuf_reset(m); if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) { - error("%s: buffer error: %s", __func__, ssh_err(r)); + error_fr(r, "reserve"); return -1; } if (atomicio(read, fd, p, msg_len) != msg_len) { - error("ssh_msg_recv: read: %s", strerror(errno)); + error_f("read: %s", strerror(errno)); return (-1); } return (0); diff --git a/mux.c b/mux.c index f3ea11cdc..d0f066a77 100644 --- a/mux.c +++ b/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.80 2019/06/28 13:35:04 deraadt Exp $ */ +/* $OpenBSD: mux.c,v 1.86 2020/10/29 02:52:43 djm Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -187,20 +187,20 @@ static const struct { { 0, NULL } }; -/* Cleanup callback fired on closure of mux slave _session_ channel */ +/* Cleanup callback fired on closure of mux client _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); + debug3_f("entering for channel %d", cid); if (c == NULL) - fatal("%s: channel_by_id(%i) == NULL", __func__, cid); + fatal_f("channel_by_id(%i) == NULL", 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); + fatal_f("channel %d missing control channel %d", + c->self, c->ctl_chan); c->ctl_chan = -1; cc->remote_id = 0; cc->have_remote_id = 0; @@ -209,26 +209,26 @@ mux_master_session_cleanup_cb(struct ssh *ssh, int cid, void *unused) channel_cancel_cleanup(ssh, c->self); } -/* Cleanup callback fired on closure of mux slave _control_ channel */ +/* Cleanup callback fired on closure of mux client _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); + debug3_f("entering for channel %d", cid); if (c == NULL) - fatal("%s: channel_by_id(%i) == NULL", __func__, cid); + fatal_f("channel_by_id(%i) == NULL", 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); + fatal_f("channel %d missing session channel %u", + 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); + debug2_f("channel %d: not open", sc->self); chan_mark_dead(ssh, sc); } else { if (sc->istate == CHAN_INPUT_OPEN) @@ -251,7 +251,7 @@ env_permitted(char *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); + error_f("name '%.100s...' too long", env); return 0; } @@ -273,21 +273,21 @@ mux_master_process_hello(struct ssh *ssh, u_int rid, int r; if (state == NULL) - fatal("%s: channel %d: c->mux_ctx == NULL", __func__, c->self); + fatal_f("channel %d: c->mux_ctx == NULL", c->self); if (state->hello_rcvd) { - error("%s: HELLO received twice", __func__); + error_f("HELLO received twice"); return -1; } if ((r = sshbuf_get_u32(m, &ver)) != 0) { - error("%s: malformed message: %s", __func__, ssh_err(r)); + error_fr(r, "parse"); return -1; } if (ver != SSHMUX_VER) { - error("%s: unsupported multiplexing protocol version %u " - "(expected %u)", __func__, ver, SSHMUX_VER); + error_f("unsupported multiplexing protocol version %u " + "(expected %u)", ver, SSHMUX_VER); return -1; } - debug2("%s: channel %d slave version %u", __func__, c->self, ver); + debug2_f("channel %d client version %u", c->self, ver); /* No extensions are presently defined */ while (sshbuf_len(m) > 0) { @@ -296,12 +296,11 @@ mux_master_process_hello(struct ssh *ssh, u_int rid, 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)); + error_fr(r, "parse extension"); return -1; } - debug2("%s: Unrecognised extension \"%s\" length %zu", - __func__, name, value_len); + debug2_f("Unrecognised extension \"%s\" length %zu", + name, value_len); free(name); } state->hello_rcvd = 1; @@ -316,7 +315,7 @@ reply_ok(struct sshbuf *reply, u_int rid) 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)); + fatal_fr(r, "reply"); } /* Enqueue an error response to the reply buffer */ @@ -328,7 +327,7 @@ reply_error(struct sshbuf *reply, u_int type, u_int rid, const char *msg) 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)); + fatal_fr(r, "reply"); } static int @@ -363,7 +362,7 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid, free(cctx->env); free(cctx->term); free(cctx); - error("%s: malformed message", __func__); + error_f("malformed message"); return -1; } @@ -380,29 +379,28 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid, 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); + error_f(">%d environment variables received, " + "ignoring additional", 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, + debug2_f("channel %d: request tty %d, X %d, agent %d, subsys %d, " + "term \"%s\", cmd \"%s\", env %u", 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__); + fatal_f("sshbuf_new"); if ((r = sshbuf_put(cctx->cmd, cmd, strlen(cmd))) != 0) - fatal("%s: sshbuf_put: %s", __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_put"); 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); + error_f("failed to receive fd %d from client", i); for (j = 0; j < i; j++) close(new_fd[j]); for (j = 0; j < env_len; j++) @@ -417,12 +415,12 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid, } } - debug3("%s: got fds stdin %d, stdout %d, stderr %d", __func__, + debug3_f("got fds stdin %d, stdout %d, stderr %d", 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__); + debug2_f("session already open"); reply_error(reply, MUX_S_FAILURE, rid, "Multiple sessions not supported"); cleanup: @@ -443,7 +441,7 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid, 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__); + debug2_f("session refused by user"); reply_error(reply, MUX_S_PERMISSION_DENIED, rid, "Permission denied"); goto cleanup; @@ -452,7 +450,7 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid, /* 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)); + error_f("tcgetattr: %s", strerror(errno)); /* enable nonblocking unless tty */ if (!isatty(new_fd[0])) @@ -474,7 +472,7 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid, 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->remote_id = nc->self; /* link control -> session channel */ c->have_remote_id = 1; if (cctx->want_tty && escape_char != 0xffffffff) { @@ -484,8 +482,8 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid, client_new_escape_filter_ctx((int)escape_char)); } - debug2("%s: channel_new: %d linked to control channel %d", - __func__, nc->self, nc->ctl_chan); + debug2_f("channel_new: %d linked to control channel %d", + nc->self, nc->ctl_chan); channel_send_open(ssh, nc->self); channel_register_open_confirm(ssh, nc->self, mux_session_confirm, cctx); @@ -503,13 +501,13 @@ mux_master_process_alive_check(struct ssh *ssh, u_int rid, { int r; - debug2("%s: channel %d: alive check", __func__, c->self); + debug2_f("channel %d: alive check", 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)); + fatal_fr(r, "reply"); return 0; } @@ -518,13 +516,13 @@ 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); + debug2_f("channel %d: terminate request", 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__); + debug2_f("termination refused by user"); reply_error(reply, MUX_S_PERMISSION_DENIED, rid, "Permission denied"); return 0; @@ -568,7 +566,7 @@ format_forward(u_int ftype, struct Forward *fwd) fwd->connect_host, fwd->connect_port); break; default: - fatal("%s: unknown forward type %u", __func__, ftype); + fatal_f("unknown forward type %u", ftype); } return ret; } @@ -615,11 +613,11 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) if ((c = channel_by_id(ssh, fctx->cid)) == NULL) { /* no channel for reply */ - error("%s: unknown channel", __func__); + error_f("unknown channel"); return; } if ((out = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); if (fctx->fid >= options.num_remote_forwards || (options.remote_forwards[fctx->fid].connect_path == NULL && options.remote_forwards[fctx->fid].connect_host == NULL)) { @@ -627,15 +625,14 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) goto fail; } rfwd = &options.remote_forwards[fctx->fid]; - debug("%s: %s for: listen %d, connect %s:%d", __func__, + debug_f("%s for: listen %d, connect %s:%d", 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) { if ((r = sshpkt_get_u32(ssh, &port)) != 0) - fatal("%s: packet error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "parse port"); if (port > 65535) { fatal("Invalid allocated port %u for " "mux remote forward to %s:%d", port, @@ -650,7 +647,7 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) (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)); + fatal_fr(r, "reply"); channel_update_permission(ssh, rfwd->handle, rfwd->allocated_port); } else { @@ -667,8 +664,8 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) 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, + debug2_f("clearing registered forwarding for listen %d, " + "connect %s:%d", rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path : rfwd->connect_host, rfwd->connect_port); @@ -679,15 +676,15 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) memset(rfwd, 0, sizeof(*rfwd)); } fail: - error("%s: %s", __func__, failmsg); + error_f("%s", 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)); + fatal_fr(r, "enqueue"); sshbuf_free(out); if (c->mux_pause <= 0) - fatal("%s: mux_pause %d", __func__, c->mux_pause); + fatal_f("mux_pause %d", c->mux_pause); c->mux_pause = 0; /* start processing messages again */ } @@ -712,7 +709,7 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid, (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__); + error_f("malformed message"); ret = -1; goto out; } @@ -737,12 +734,12 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid, else fwd.connect_host = connect_addr; - debug2("%s: channel %d: request %s", __func__, c->self, + debug2_f("channel %d: request %s", 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); + logit_f("invalid forwarding type %u", ftype); invalid: free(listen_addr); free(connect_addr); @@ -751,26 +748,25 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid, return 0; } if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) { - logit("%s: streamlocal and dynamic forwards " - "are mutually exclusive", __func__); + logit_f("streamlocal and dynamic forwards " + "are mutually exclusive"); goto invalid; } if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) { - logit("%s: invalid listen port %u", __func__, - fwd.listen_port); + logit_f("invalid listen port %u", 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__, + logit_f("invalid connect port %u", fwd.connect_port); goto invalid; } if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) { - logit("%s: missing connect host", __func__); + logit_f("missing connect host"); goto invalid; } @@ -782,8 +778,7 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid, if (compare_forward(&fwd, options.local_forwards + i)) { exists: - debug2("%s: found existing forwarding", - __func__); + debug2_f("found existing forwarding"); reply_ok(reply, rid); goto out; } @@ -795,13 +790,13 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid, continue; if (fwd.listen_port != 0) goto exists; - debug2("%s: found allocated port", __func__); + debug2_f("found allocated port"); 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)); + fatal_fr(r, "reply FWD_REMOTE"); goto out; } break; @@ -810,7 +805,7 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid, 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__); + debug2_f("forwarding refused by user"); reply_error(reply, MUX_S_PERMISSION_DENIED, rid, "Permission denied"); goto out; @@ -821,7 +816,7 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid, if (!channel_setup_local_fwd_listener(ssh, &fwd, &options.fwd_opts)) { fail: - logit("%s: requested %s failed", __func__, fwd_desc); + logit_f("requested %s failed", fwd_desc); reply_error(reply, MUX_S_FAILURE, rid, "Port forwarding failed"); goto out; @@ -879,7 +874,7 @@ mux_master_process_close_fwd(struct ssh *ssh, u_int rid, (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__); + error_f("malformed message"); ret = -1; goto out; } @@ -905,7 +900,7 @@ mux_master_process_close_fwd(struct ssh *ssh, u_int rid, else fwd.connect_host = connect_addr; - debug2("%s: channel %d: request cancel %s", __func__, c->self, + debug2_f("channel %d: request cancel %s", c->self, (fwd_desc = format_forward(ftype, &fwd))); /* make sure this has been requested */ @@ -984,18 +979,16 @@ mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid, (r = sshbuf_get_cstring(m, &chost, NULL)) != 0 || (r = sshbuf_get_u32(m, &cport)) != 0) { free(chost); - error("%s: malformed message", __func__); + error_f("malformed message"); return -1; } - debug2("%s: channel %d: request stdio fwd to %s:%u", - __func__, c->self, chost, cport); + debug2_f("channel %d: stdio fwd to %s:%u", 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); + error_f("failed to receive fd %d from client", i); for (j = 0; j < i; j++) close(new_fd[j]); free(chost); @@ -1007,12 +1000,11 @@ mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid, } } - debug3("%s: got fds stdin %d, stdout %d", __func__, - new_fd[0], new_fd[1]); + debug3_f("got fds stdin %d, stdout %d", new_fd[0], new_fd[1]); /* XXX support multiple child sessions in future */ if (c->have_remote_id) { - debug2("%s: session already open", __func__); + debug2_f("session already open"); reply_error(reply, MUX_S_FAILURE, rid, "Multiple sessions not supported"); cleanup: @@ -1026,7 +1018,7 @@ mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid, 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__); + debug2_f("stdio fwd refused by user"); reply_error(reply, MUX_S_PERMISSION_DENIED, rid, "Permission denied"); goto cleanup; @@ -1043,11 +1035,10 @@ mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid, free(chost); nc->ctl_chan = c->self; /* link session -> control channel */ - c->remote_id = nc->self; /* link control -> session 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); + debug2_f("channel_new: %d control %d", nc->self, nc->ctl_chan); channel_register_cleanup(ssh, nc->self, mux_master_session_cleanup_cb, 1); @@ -1071,38 +1062,38 @@ mux_stdio_confirm(struct ssh *ssh, int id, int success, void *arg) int r; if (cctx == NULL) - fatal("%s: cctx == NULL", __func__); + fatal_f("cctx == NULL"); if ((c = channel_by_id(ssh, id)) == NULL) - fatal("%s: no channel for id %d", __func__, id); + fatal_f("no channel for id %d", id); if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) - fatal("%s: channel %d lacks control channel %d", __func__, + fatal_f("channel %d lacks control channel %d", id, c->ctl_chan); if ((reply = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); if (!success) { - debug3("%s: sending failure reply", __func__); + debug3_f("sending failure reply"); reply_error(reply, MUX_S_FAILURE, cctx->rid, "Session open refused by peer"); /* prepare reply */ goto done; } - debug3("%s: sending success reply", __func__); + debug3_f("sending success reply"); /* 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)); + fatal_fr(r, "reply"); done: /* Send reply */ if ((r = sshbuf_put_stringb(cc->output, reply)) != 0) - fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r)); + fatal_fr(r, "enqueue"); sshbuf_free(reply); if (cc->mux_pause <= 0) - fatal("%s: mux_pause %d", __func__, cc->mux_pause); + fatal_f("mux_pause %d", cc->mux_pause); cc->mux_pause = 0; /* start processing messages again */ c->open_confirm_ctx = NULL; free(cctx); @@ -1112,13 +1103,13 @@ 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); + debug_f("channel %d: stop listening", 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__); + debug2_f("stop listen refused by user"); reply_error(reply, MUX_S_PERMISSION_DENIED, rid, "Permission denied"); return 0; @@ -1144,17 +1135,17 @@ mux_master_process_proxy(struct ssh *ssh, u_int rid, { int r; - debug("%s: channel %d: proxy request", __func__, c->self); + debug_f("channel %d: proxy request", 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)); + fatal_fr(r, "reply"); return 0; } -/* Channel callbacks fired on read/write from mux slave fd */ +/* Channel callbacks fired on read/write from mux client fd */ static int mux_master_read_cb(struct ssh *ssh, Channel *c) { @@ -1164,7 +1155,7 @@ mux_master_read_cb(struct ssh *ssh, Channel *c) int r, ret = -1; if ((out = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); /* Setup ctx and */ if (c->mux_ctx == NULL) { @@ -1176,12 +1167,11 @@ mux_master_read_cb(struct ssh *ssh, Channel *c) /* 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)); + fatal_fr(r, "reply"); /* 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); + fatal_fr(r, "enqueue"); + debug3_f("channel %d: hello sent", c->self); ret = 0; goto out; } @@ -1189,21 +1179,21 @@ mux_master_read_cb(struct ssh *ssh, Channel *c) /* Channel code ensures that we receive whole packets */ if ((r = sshbuf_froms(c->input, &in)) != 0) { malf: - error("%s: malformed message", __func__); + error_f("malformed message"); 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)); + debug3_f("channel %d packet type 0x%08x len %zu", 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); + error_f("expected MUX_MSG_HELLO(0x%08x), " + "received 0x%08x", MUX_MSG_HELLO, type); goto out; } if ((r = sshbuf_get_u32(in, &rid)) != 0) @@ -1218,16 +1208,14 @@ mux_master_read_cb(struct ssh *ssh, Channel *c) } } if (mux_master_handlers[i].handler == NULL) { - error("%s: unsupported mux message 0x%08x", __func__, type); + error_f("unsupported mux message 0x%08x", 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)); - } + if (sshbuf_len(out) != 0 && + (r = sshbuf_put_stringb(c->output, out)) != 0) + fatal_fr(r, "enqueue"); out: sshbuf_free(in); sshbuf_free(out); @@ -1241,21 +1229,19 @@ mux_exit_message(struct ssh *ssh, Channel *c, int exitval) Channel *mux_chan; int r; - debug3("%s: channel %d: exit message, exitval %d", __func__, c->self, - exitval); + debug3_f("channel %d: exit message, exitval %d", 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); + fatal_f("channel %d missing mux %d", c->self, c->ctl_chan); /* Append exit message packet to control socket output queue */ if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); 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)); + fatal_fr(r, "reply"); sshbuf_free(m); } @@ -1266,19 +1252,18 @@ mux_tty_alloc_failed(struct ssh *ssh, Channel *c) Channel *mux_chan; int r; - debug3("%s: channel %d: TTY alloc failed", __func__, c->self); + debug3_f("channel %d: TTY alloc failed", 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); + fatal_f("channel %d missing mux %d", c->self, c->ctl_chan); /* Append exit message packet to control socket output queue */ if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); 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)); + fatal_fr(r, "reply"); sshbuf_free(m); } @@ -1313,7 +1298,7 @@ muxserver_listen(struct ssh *ssh) 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); + debug3_f("temporary control path %s", options.control_path); old_umask = umask(0177); muxserver_sock = unix_listener(options.control_path, 64, 0); @@ -1342,7 +1327,7 @@ muxserver_listen(struct ssh *ssh) /* 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__, + fatal_f("link mux listener %s => %s: %s", options.control_path, orig_control_path, strerror(errno)); } @@ -1362,7 +1347,7 @@ muxserver_listen(struct ssh *ssh) 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__, + debug3_f("mux listener channel %d fd %d", mux_listener_channel->self, mux_listener_channel->sock); } @@ -1377,17 +1362,17 @@ mux_session_confirm(struct ssh *ssh, int id, int success, void *arg) struct sshbuf *reply; if (cctx == NULL) - fatal("%s: cctx == NULL", __func__); + fatal_f("cctx == NULL"); if ((c = channel_by_id(ssh, id)) == NULL) - fatal("%s: no channel for id %d", __func__, id); + fatal_f("no channel for id %d", id); if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) - fatal("%s: channel %d lacks control channel %d", __func__, + fatal_f("channel %d lacks control channel %d", id, c->ctl_chan); if ((reply = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); if (!success) { - debug3("%s: sending failure reply", __func__); + debug3_f("sending failure reply"); reply_error(reply, MUX_S_FAILURE, cctx->rid, "Session open refused by peer"); goto done; @@ -1416,27 +1401,27 @@ mux_session_confirm(struct ssh *ssh, int id, int success, void *arg) debug("Requesting authentication agent forwarding."); channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0); if ((r = sshpkt_send(ssh)) != 0) - fatal("%s: packet error: %s", __func__, ssh_err(r)); + fatal_fr(r, "send"); } 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__); + debug3_f("sending success reply"); /* 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)); + fatal_fr(r, "reply"); done: /* Send reply */ if ((r = sshbuf_put_stringb(cc->output, reply)) != 0) - fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r)); + fatal_fr(r, "enqueue"); sshbuf_free(reply); if (cc->mux_pause <= 0) - fatal("%s: mux_pause %d", __func__, cc->mux_pause); + fatal_f("mux_pause %d", cc->mux_pause); cc->mux_pause = 0; /* start processing messages again */ c->open_confirm_ctx = NULL; sshbuf_free(cctx->cmd); @@ -1485,7 +1470,7 @@ mux_client_read(int fd, struct sshbuf *b, size_t need) pfd.fd = fd; pfd.events = POLLIN; if ((r = sshbuf_reserve(b, need, &p)) != 0) - fatal("%s: reserve: %s", __func__, ssh_err(r)); + fatal_fr(r, "reserve"); for (have = 0; have < need; ) { if (muxclient_terminate) { errno = EINTR; @@ -1527,9 +1512,9 @@ mux_client_write_packet(int fd, struct sshbuf *m) pfd.fd = fd; pfd.events = POLLOUT; if ((queue = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); if ((r = sshbuf_put_stringb(queue, m)) != 0) - fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r)); + fatal_fr(r, "enqueue"); need = sshbuf_len(queue); ptr = sshbuf_ptr(queue); @@ -1578,10 +1563,10 @@ mux_client_read_packet(int fd, struct sshbuf *m) int r, oerrno; if ((queue = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); if (mux_client_read(fd, queue, 4) != 0) { if ((oerrno = errno) == EPIPE) - debug3("%s: read header failed: %s", __func__, + debug3_f("read header failed: %s", strerror(errno)); sshbuf_free(queue); errno = oerrno; @@ -1590,14 +1575,14 @@ mux_client_read_packet(int fd, struct sshbuf *m) 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)); + debug3_f("read body failed: %s", 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)); + fatal_fr(r, "dequeue"); sshbuf_free(queue); return 0; } @@ -1610,14 +1595,14 @@ mux_client_hello_exchange(int fd) int r, ret = -1; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); 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)); + fatal_fr(r, "assemble hello"); /* no extensions */ if (mux_client_write_packet(fd, m) != 0) { - debug("%s: write packet: %s", __func__, strerror(errno)); + debug_f("write packet: %s", strerror(errno)); goto out; } @@ -1625,33 +1610,31 @@ mux_client_hello_exchange(int fd) /* Read their HELLO */ if (mux_client_read_packet(fd, m) != 0) { - debug("%s: read packet failed", __func__); + debug_f("read packet failed"); goto out; } if ((r = sshbuf_get_u32(m, &type)) != 0) - fatal("%s: decode type: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse type"); if (type != MUX_MSG_HELLO) { - error("%s: expected HELLO (%u) received %u", - __func__, MUX_MSG_HELLO, type); + error_f("expected HELLO (%u) got %u", MUX_MSG_HELLO, type); goto out; } if ((r = sshbuf_get_u32(m, &ver)) != 0) - fatal("%s: decode version: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse version"); if (ver != SSHMUX_VER) { error("Unsupported multiplexing protocol version %d " "(expected %d)", ver, SSHMUX_VER); goto out; } - debug2("%s: master version %u", __func__, ver); + debug2_f("master version %u", 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)); + error_fr(r, "parse extension"); goto out; } debug2("Unrecognised master extension \"%s\"", name); @@ -1672,16 +1655,16 @@ mux_client_request_alive(int fd) u_int pid, type, rid; int r; - debug3("%s: entering", __func__); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); 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)); + fatal_fr(r, "assemble"); if (mux_client_write_packet(fd, m) != 0) - fatal("%s: write packet: %s", __func__, strerror(errno)); + fatal_f("write packet: %s", strerror(errno)); sshbuf_reset(m); @@ -1692,23 +1675,23 @@ mux_client_request_alive(int fd) } if ((r = sshbuf_get_u32(m, &type)) != 0) - fatal("%s: decode type: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse type"); 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); + fatal_fr(r, "parse error message"); + fatal_f("master returned error: %s", e); } if ((r = sshbuf_get_u32(m, &rid)) != 0) - fatal("%s: decode remote ID: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse remote ID"); if (rid != muxclient_request_id) - fatal("%s: out of sequence reply: my id %u theirs %u", - __func__, muxclient_request_id, rid); + fatal_f("out of sequence reply: my id %u theirs %u", + muxclient_request_id, rid); if ((r = sshbuf_get_u32(m, &pid)) != 0) - fatal("%s: decode PID: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse PID"); sshbuf_free(m); - debug3("%s: done pid = %u", __func__, pid); + debug3_f("done pid = %u", pid); muxclient_request_id++; @@ -1723,16 +1706,16 @@ mux_client_request_terminate(int fd) u_int type, rid; int r; - debug3("%s: entering", __func__); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); 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)); + fatal_fr(r, "request"); if (mux_client_write_packet(fd, m) != 0) - fatal("%s: write packet: %s", __func__, strerror(errno)); + fatal_f("write packet: %s", strerror(errno)); sshbuf_reset(m); @@ -1743,30 +1726,28 @@ mux_client_request_terminate(int fd) sshbuf_free(m); return; } - fatal("%s: read from master failed: %s", - __func__, strerror(errno)); + fatal_f("read from master failed: %s", 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)); + fatal_fr(r, "parse"); if (rid != muxclient_request_id) - fatal("%s: out of sequence reply: my id %u theirs %u", - __func__, muxclient_request_id, rid); + fatal_f("out of sequence reply: my id %u theirs %u", + 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_fr(r, "parse error message"); 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); + fatal_fr(r, "parse error message"); + fatal_f("termination request failed: %s", e); default: - fatal("%s: unexpected response from master 0x%08x", - __func__, type); + fatal_f("unexpected response from master 0x%08x", type); } sshbuf_free(m); muxclient_request_id++; @@ -1804,7 +1785,7 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd) chost = fwd->connect_host; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); if ((r = sshbuf_put_u32(m, type)) != 0 || (r = sshbuf_put_u32(m, muxclient_request_id)) != 0 || (r = sshbuf_put_u32(m, ftype)) != 0 || @@ -1812,10 +1793,10 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd) (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)); + fatal_fr(r, "request"); if (mux_client_write_packet(fd, m) != 0) - fatal("%s: write packet: %s", __func__, strerror(errno)); + fatal_f("write packet: %s", strerror(errno)); sshbuf_reset(m); @@ -1827,19 +1808,19 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd) if ((r = sshbuf_get_u32(m, &type)) != 0 || (r = sshbuf_get_u32(m, &rid)) != 0) - fatal("%s: decode: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); if (rid != muxclient_request_id) - fatal("%s: out of sequence reply: my id %u theirs %u", - __func__, muxclient_request_id, rid); + fatal_f("out of sequence reply: my id %u theirs %u", + 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__); + fatal_f("got MUX_S_REMOTE_PORT for cancel"); if ((r = sshbuf_get_u32(m, &fwd->allocated_port)) != 0) - fatal("%s: decode port: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse port"); verbose("Allocated port %u for remote forward to %s:%d", fwd->allocated_port, fwd->connect_host ? fwd->connect_host : "", @@ -1849,19 +1830,18 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd) 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_fr(r, "parse error message"); 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)); + fatal_fr(r, "parse error message"); sshbuf_free(m); - error("%s: forwarding request failed: %s", __func__, e); + error_f("forwarding request failed: %s", e); return -1; default: - fatal("%s: unexpected response from master 0x%08x", - __func__, type); + fatal_f("unexpected response from master 0x%08x", type); } sshbuf_free(m); @@ -1874,7 +1854,7 @@ mux_client_forwards(int fd, int cancel_flag) { int i, ret = 0; - debug3("%s: %s forwardings: %d local, %d remote", __func__, + debug3_f("%s forwardings: %d local, %d remote", cancel_flag ? "cancel" : "request", options.num_local_forwards, options.num_remote_forwards); @@ -1902,25 +1882,19 @@ mux_client_request_session(int fd) const char *term; u_int echar, rid, sid, esid, exitval, type, exitval_seen; extern char **environ; - int r, i, devnull, rawmode; + int r, i, rawmode; - debug3("%s: entering", __func__); + debug3_f("entering"); if ((muxserver_pid = mux_client_request_alive(fd)) == 0) { - error("%s: master alive request failed", __func__); + error_f("master alive request failed"); return -1; } - signal(SIGPIPE, SIG_IGN); + ssh_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 (stdin_null_flag && stdfd_devnull(1, 0, 0) == -1) + fatal_f("stdfd_devnull failed"); if ((term = getenv("TERM")) == NULL) term = ""; @@ -1929,7 +1903,7 @@ mux_client_request_session(int fd) echar = (u_int)options.escape_char; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); 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 */ @@ -1940,7 +1914,7 @@ mux_client_request_session(int fd) (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)); + fatal_fr(r, "request"); /* Pass environment */ if (options.num_send_env > 0 && environ != NULL) { @@ -1948,74 +1922,73 @@ mux_client_request_session(int fd) if (!env_permitted(environ[i])) continue; if ((r = sshbuf_put_cstring(m, environ[i])) != 0) - fatal("%s: request: %s", __func__, ssh_err(r)); + fatal_fr(r, "request sendenv"); } } 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)); + fatal_fr(r, "request setenv"); } if (mux_client_write_packet(fd, m) != 0) - fatal("%s: write packet: %s", __func__, strerror(errno)); + fatal_f("write packet: %s", 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__); + fatal_f("send fds failed"); - debug3("%s: session request sent", __func__); + debug3_f("session request sent"); /* Read their reply */ sshbuf_reset(m); if (mux_client_read_packet(fd, m) != 0) { - error("%s: read from master failed: %s", - __func__, strerror(errno)); + error_f("read from master failed: %s", 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)); + fatal_fr(r, "parse"); if (rid != muxclient_request_id) - fatal("%s: out of sequence reply: my id %u theirs %u", - __func__, muxclient_request_id, rid); + fatal_f("out of sequence reply: my id %u theirs %u", + 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)); + fatal_fr(r, "parse session ID"); + debug_f("master session id: %u", 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)); + fatal_fr(r, "parse error message"); 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); + fatal_fr(r, "parse error message"); + error_f("session request failed: %s", e); sshbuf_free(m); return -1; default: sshbuf_free(m); - error("%s: unexpected response from master 0x%08x", - __func__, type); + error_f("unexpected response from master 0x%08x", type); return -1; } muxclient_request_id++; if (pledge("stdio proc tty", NULL) == -1) - fatal("%s pledge(): %s", __func__, strerror(errno)); + fatal_f("pledge(): %s", 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); + ssh_signal(SIGHUP, control_client_sighandler); + ssh_signal(SIGINT, control_client_sighandler); + ssh_signal(SIGTERM, control_client_sighandler); + ssh_signal(SIGWINCH, control_client_sigrelay); rawmode = tty_flag; if (tty_flag) @@ -2033,40 +2006,34 @@ mux_client_request_session(int fd) 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)); + fatal_fr(r, "parse type"); 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)); + fatal_fr(r, "parse session ID"); if (esid != sid) - fatal("%s: tty alloc fail on unknown session: " - "my id %u theirs %u", - __func__, sid, esid); + fatal_f("tty alloc fail on unknown session: " + "my id %u theirs %u", 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)); + fatal_fr(r, "parse session ID"); if (esid != sid) - fatal("%s: exit on unknown session: " - "my id %u theirs %u", - __func__, sid, esid); + fatal_f("exit on unknown session: " + "my id %u theirs %u", sid, esid); if (exitval_seen) - fatal("%s: exitval sent twice", __func__); + fatal_f("exitval sent twice"); if ((r = sshbuf_get_u32(m, &exitval)) != 0) - fatal("%s: decode exit value: %s", - __func__, ssh_err(r)); + fatal_fr(r, "parse exitval"); 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); + fatal_fr(r, "parse error message"); + fatal_f("master returned error: %s", e); } } @@ -2098,12 +2065,12 @@ mux_client_proxy(int fd) int r; if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); 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)); + fatal_fr(r, "request"); if (mux_client_write_packet(fd, m) != 0) - fatal("%s: write packet: %s", __func__, strerror(errno)); + fatal_f("write packet: %s", strerror(errno)); sshbuf_reset(m); @@ -2114,18 +2081,18 @@ mux_client_proxy(int fd) } if ((r = sshbuf_get_u32(m, &type)) != 0 || (r = sshbuf_get_u32(m, &rid)) != 0) - fatal("%s: decode: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); if (rid != muxclient_request_id) - fatal("%s: out of sequence reply: my id %u theirs %u", - __func__, muxclient_request_id, rid); + fatal_f("out of sequence reply: my id %u theirs %u", + 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); + fatal_fr(r, "parse error message"); + fatal_f("master returned error: %s", e); } sshbuf_free(m); - debug3("%s: done", __func__); + debug3_f("done"); muxclient_request_id++; return 0; } @@ -2136,93 +2103,85 @@ mux_client_request_stdio_fwd(int fd) struct sshbuf *m; char *e; u_int type, rid, sid; - int r, devnull; + int r; - debug3("%s: entering", __func__); + debug3_f("entering"); if ((muxserver_pid = mux_client_request_alive(fd)) == 0) { - error("%s: master alive request failed", __func__); + error_f("master alive request failed"); return -1; } - signal(SIGPIPE, SIG_IGN); + ssh_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 (stdin_null_flag && stdfd_devnull(1, 0, 0) == -1) + fatal_f("stdfd_devnull failed"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); 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)); + fatal_fr(r, "request"); if (mux_client_write_packet(fd, m) != 0) - fatal("%s: write packet: %s", __func__, strerror(errno)); + fatal_f("write packet: %s", 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__); + fatal_f("send fds failed"); if (pledge("stdio proc tty", NULL) == -1) - fatal("%s pledge(): %s", __func__, strerror(errno)); + fatal_f("pledge(): %s", strerror(errno)); platform_pledge_mux(); - debug3("%s: stdio forward request sent", __func__); + debug3_f("stdio forward request sent"); /* Read their reply */ sshbuf_reset(m); if (mux_client_read_packet(fd, m) != 0) { - error("%s: read from master failed: %s", - __func__, strerror(errno)); + error_f("read from master failed: %s", 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)); + fatal_fr(r, "parse"); if (rid != muxclient_request_id) - fatal("%s: out of sequence reply: my id %u theirs %u", - __func__, muxclient_request_id, rid); + fatal_f("out of sequence reply: my id %u theirs %u", + 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); + fatal_fr(r, "parse session ID"); + debug_f("master session id: %u", 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)); + fatal_fr(r, "parse error message"); 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)); + fatal_fr(r, "parse error message"); sshbuf_free(m); fatal("Stdio forwarding request failed: %s", e); default: sshbuf_free(m); - error("%s: unexpected response from master 0x%08x", - __func__, type); + error_f("unexpected response from master 0x%08x", 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); + ssh_signal(SIGHUP, control_client_sighandler); + ssh_signal(SIGINT, control_client_sighandler); + ssh_signal(SIGTERM, control_client_sighandler); + ssh_signal(SIGWINCH, control_client_sigrelay); /* * Stick around until the controlee closes the client_fd. @@ -2232,10 +2191,9 @@ mux_client_request_stdio_fwd(int fd) if (errno == EPIPE || (errno == EINTR && muxclient_terminate != 0)) return 0; - fatal("%s: mux_client_read_packet: %s", - __func__, strerror(errno)); + fatal_f("mux_client_read_packet: %s", strerror(errno)); } - fatal("%s: master returned unexpected message %u", __func__, type); + fatal_f("master returned unexpected message %u", type); } static void @@ -2246,45 +2204,43 @@ mux_client_request_stop_listening(int fd) u_int type, rid; int r; - debug3("%s: entering", __func__); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); 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)); + fatal_fr(r, "request"); if (mux_client_write_packet(fd, m) != 0) - fatal("%s: write packet: %s", __func__, strerror(errno)); + fatal_f("write packet: %s", 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)); + fatal_f("read from master failed: %s", 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)); + fatal_fr(r, "parse"); if (rid != muxclient_request_id) - fatal("%s: out of sequence reply: my id %u theirs %u", - __func__, muxclient_request_id, rid); + fatal_f("out of sequence reply: my id %u theirs %u", + 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_fr(r, "parse error message"); 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); + fatal_fr(r, "parse error message"); + fatal_f("stop listening request failed: %s", e); default: - fatal("%s: unexpected response from master 0x%08x", - __func__, type); + fatal_f("unexpected response from master 0x%08x", type); } sshbuf_free(m); muxclient_request_id++; @@ -2325,7 +2281,7 @@ muxclient(const char *path) (unsigned int)sizeof(addr.sun_path)); if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) - fatal("%s socket(): %s", __func__, strerror(errno)); + fatal_f("socket(): %s", strerror(errno)); if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { switch (muxclient_command) { @@ -2352,7 +2308,7 @@ muxclient(const char *path) set_nonblock(sock); if (mux_client_hello_exchange(sock) != 0) { - error("%s: master hello exchange failed", __func__); + error_f("master hello exchange failed"); close(sock); return -1; } @@ -2360,7 +2316,7 @@ muxclient(const char *path) switch (muxclient_command) { case SSHMUX_COMMAND_ALIVE_CHECK: if ((pid = mux_client_request_alive(sock)) == 0) - fatal("%s: master alive check failed", __func__); + fatal_f("master alive check failed"); fprintf(stderr, "Master running (pid=%u)\r\n", pid); exit(0); case SSHMUX_COMMAND_TERMINATE: @@ -2370,11 +2326,11 @@ muxclient(const char *path) exit(0); case SSHMUX_COMMAND_FORWARD: if (mux_client_forwards(sock, 0) != 0) - fatal("%s: master forward request failed", __func__); + fatal_f("master forward request failed"); exit(0); case SSHMUX_COMMAND_OPEN: if (mux_client_forwards(sock, 0) != 0) { - error("%s: master forward request failed", __func__); + error_f("master forward request failed"); return -1; } mux_client_request_session(sock); @@ -2389,8 +2345,7 @@ muxclient(const char *path) exit(0); case SSHMUX_COMMAND_CANCEL_FWD: if (mux_client_forwards(sock, 1) != 0) - error("%s: master cancel forward request failed", - __func__); + error_f("master cancel forward request failed"); exit(0); case SSHMUX_COMMAND_PROXY: mux_client_proxy(sock); diff --git a/myproposal.h b/myproposal.h index 34bd10c9f..f03b7dfd0 100644 --- a/myproposal.h +++ b/myproposal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: myproposal.h,v 1.58 2019/02/23 08:20:43 djm Exp $ */ +/* $OpenBSD: myproposal.h,v 1.68 2020/10/03 04:15:06 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -24,103 +24,47 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include - -/* conditional algorithm support */ - -#ifdef OPENSSL_HAS_ECC -#ifdef OPENSSL_HAS_NISTP521 -# define KEX_ECDH_METHODS \ +#define KEX_SERVER_KEX \ + "curve25519-sha256," \ + "curve25519-sha256@libssh.org," \ "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 \ + "ecdh-sha2-nistp521," \ "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_SERVER_KEX \ - KEX_CURVE25519_METHODS \ - KEX_ECDH_METHODS \ - KEX_SHA2_METHODS \ - KEX_SHA2_GROUP14 \ - "diffie-hellman-group14-sha1" + "diffie-hellman-group18-sha512," \ + "diffie-hellman-group14-sha256" #define KEX_CLIENT_KEX KEX_SERVER_KEX #define KEX_DEFAULT_PK_ALG \ - HOSTKEY_ECDSA_CERT_METHODS \ "ssh-ed25519-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," \ + "sk-ssh-ed25519-cert-v01@openssh.com," \ + "sk-ecdsa-sha2-nistp256-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," \ + "ecdsa-sha2-nistp256," \ + "ecdsa-sha2-nistp384," \ + "ecdsa-sha2-nistp521," \ + "sk-ssh-ed25519@openssh.com," \ + "sk-ecdsa-sha2-nistp256@openssh.com," \ "rsa-sha2-512," \ "rsa-sha2-256," \ "ssh-rsa" -/* the actual algorithms */ - -#define KEX_SERVER_ENCRYPT \ +#define KEX_SERVER_ENCRYPT \ "chacha20-poly1305@openssh.com," \ - "aes128-ctr,aes192-ctr,aes256-ctr" \ - AESGCM_CIPHER_MODES + "aes128-ctr,aes192-ctr,aes256-ctr," \ + "aes128-gcm@openssh.com,aes256-gcm@openssh.com" #define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT -#define KEX_SERVER_MAC \ +#define KEX_SERVER_MAC \ "umac-64-etm@openssh.com," \ "umac-128-etm@openssh.com," \ "hmac-sha2-256-etm@openssh.com," \ @@ -136,42 +80,14 @@ /* Not a KEX value, but here so all the algorithm defaults are together */ #define SSH_ALLOWED_CA_SIGALGS \ - HOSTKEY_ECDSA_METHODS \ "ssh-ed25519," \ + "ecdsa-sha2-nistp256," \ + "ecdsa-sha2-nistp384," \ + "ecdsa-sha2-nistp521," \ + "sk-ssh-ed25519@openssh.com," \ + "sk-ecdsa-sha2-nistp256@openssh.com," \ "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 */ + "rsa-sha2-256" #define KEX_DEFAULT_COMP "none,zlib@openssh.com" #define KEX_DEFAULT_LANG "" @@ -199,4 +115,3 @@ KEX_DEFAULT_COMP, \ KEX_DEFAULT_LANG, \ KEX_DEFAULT_LANG - diff --git a/nchan.c b/nchan.c index 1e96eb641..4a4494b86 100644 --- a/nchan.c +++ b/nchan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nchan.c,v 1.70 2019/06/28 13:35:04 deraadt Exp $ */ +/* $OpenBSD: nchan.c,v 1.72 2021/01/27 09:26:54 djm Exp $ */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * @@ -185,12 +185,11 @@ chan_send_eof2(struct ssh *ssh, Channel *c) switch (c->istate) { case CHAN_INPUT_WAIT_DRAIN: if (!c->have_remote_id) - fatal("%s: channel %d: no remote_id", - __func__, c->self); + fatal_f("channel %d: no remote_id", c->self); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EOF)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); + fatal_fr(r, "send CHANNEL_EOF"); c->flags |= CHAN_EOF_SENT; break; default: @@ -214,12 +213,11 @@ chan_send_close2(struct ssh *ssh, Channel *c) error("channel %d: already sent close", c->self); } else { if (!c->have_remote_id) - fatal("%s: channel %d: no remote_id", - __func__, c->self); + fatal_f("channel %d: no remote_id", c->self); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_CLOSE)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); + fatal_fr(r, "send CHANNEL_EOF"); c->flags |= CHAN_CLOSE_SENT; } } @@ -235,16 +233,16 @@ chan_send_eow2(struct ssh *ssh, Channel *c) c->self); return; } - if (!(datafellows & SSH_NEW_OPENSSH)) + if (!(ssh->compat & SSH_NEW_OPENSSH)) return; if (!c->have_remote_id) - fatal("%s: channel %d: no remote_id", __func__, c->self); + fatal_f("channel %d: no remote_id", c->self); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_cstring(ssh, "eow@openssh.com")) != 0 || (r = sshpkt_put_u8(ssh, 0)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); + fatal_fr(r, "send CHANNEL_EOF"); } /* shared */ @@ -336,7 +334,7 @@ chan_is_dead(struct ssh *ssh, Channel *c, int do_send) } if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED) return 0; - if ((datafellows & SSH_BUG_EXTEOF) && + if ((ssh->compat & SSH_BUG_EXTEOF) && c->extended_usage == CHAN_EXTENDED_WRITE && c->efd != -1 && sshbuf_len(c->extended) > 0) { @@ -376,22 +374,20 @@ chan_shutdown_write(struct ssh *ssh, Channel *c) if (c->type == SSH_CHANNEL_LARVAL) return; /* shutdown failure is allowed if write failed already */ - debug2("channel %d: %s (i%d o%d sock %d wfd %d efd %d [%s])", - c->self, __func__, c->istate, c->ostate, c->sock, c->wfd, c->efd, + debug2_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])", + c->self, c->istate, c->ostate, c->sock, c->wfd, c->efd, channel_format_extended_usage(c)); if (c->sock != -1) { if (shutdown(c->sock, SHUT_WR) == -1) { - debug2("channel %d: %s: shutdown() failed for " - "fd %d [i%d o%d]: %.100s", c->self, __func__, - c->sock, c->istate, c->ostate, - strerror(errno)); + debug2_f("channel %d: shutdown() failed for " + "fd %d [i%d o%d]: %.100s", c->self, c->sock, + c->istate, c->ostate, strerror(errno)); } } else { if (channel_close_fd(ssh, &c->wfd) < 0) { - logit("channel %d: %s: close() failed for " - "fd %d [i%d o%d]: %.100s", - c->self, __func__, c->wfd, c->istate, c->ostate, - strerror(errno)); + logit_f("channel %d: close() failed for " + "fd %d [i%d o%d]: %.100s", c->self, c->wfd, + c->istate, c->ostate, strerror(errno)); } } } @@ -401,8 +397,8 @@ chan_shutdown_read(struct ssh *ssh, Channel *c) { if (c->type == SSH_CHANNEL_LARVAL) return; - debug2("channel %d: %s (i%d o%d sock %d wfd %d efd %d [%s])", - c->self, __func__, c->istate, c->ostate, c->sock, c->rfd, c->efd, + debug2_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])", + c->self, c->istate, c->ostate, c->sock, c->rfd, c->efd, channel_format_extended_usage(c)); if (c->sock != -1) { /* @@ -411,17 +407,15 @@ chan_shutdown_read(struct ssh *ssh, Channel *c) * HP-UX may return ENOTCONN also. */ if (shutdown(c->sock, SHUT_RD) == -1 && errno != ENOTCONN) { - error("channel %d: %s: shutdown() failed for " - "fd %d [i%d o%d]: %.100s", - c->self, __func__, c->sock, c->istate, c->ostate, - strerror(errno)); + error_f("channel %d: shutdown() failed for " + "fd %d [i%d o%d]: %.100s", c->self, c->sock, + c->istate, c->ostate, strerror(errno)); } } else { if (channel_close_fd(ssh, &c->rfd) < 0) { - logit("channel %d: %s: close() failed for " - "fd %d [i%d o%d]: %.100s", - c->self, __func__, c->rfd, c->istate, c->ostate, - strerror(errno)); + logit_f("channel %d: close() failed for " + "fd %d [i%d o%d]: %.100s", c->self, c->rfd, + c->istate, c->ostate, strerror(errno)); } } } @@ -434,13 +428,12 @@ chan_shutdown_extended_read(struct ssh *ssh, Channel *c) if (c->extended_usage != CHAN_EXTENDED_READ && c->extended_usage != CHAN_EXTENDED_IGNORE) return; - debug2("channel %d: %s (i%d o%d sock %d wfd %d efd %d [%s])", - c->self, __func__, c->istate, c->ostate, c->sock, c->rfd, c->efd, + debug_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])", + c->self, c->istate, c->ostate, c->sock, c->rfd, c->efd, channel_format_extended_usage(c)); if (channel_close_fd(ssh, &c->efd) < 0) { - logit("channel %d: %s: close() failed for " - "extended fd %d [i%d o%d]: %.100s", - c->self, __func__, c->efd, c->istate, c->ostate, - strerror(errno)); + logit_f("channel %d: close() failed for " + "extended fd %d [i%d o%d]: %.100s", c->self, c->efd, + c->istate, c->ostate, strerror(errno)); } } diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in index 1162dc550..3eb188f0b 100644 --- a/openbsd-compat/Makefile.in +++ b/openbsd-compat/Makefile.in @@ -7,12 +7,15 @@ VPATH=@srcdir@ CC=@CC@ LD=@LD@ CFLAGS=@CFLAGS@ +CFLAGS_NOPIE=@CFLAGS_NOPIE@ CPPFLAGS=-I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ +PICFLAG=@PICFLAG@ LIBS=@LIBS@ AR=@AR@ RANLIB=@RANLIB@ INSTALL=@INSTALL@ LDFLAGS=-L. @LDFLAGS@ +LDFLAGS_NOPIE=-L. -Lopenbsd-compat/ @LDFLAGS_NOPIE@ OPENBSD=base64.o \ basename.o \ @@ -25,6 +28,7 @@ OPENBSD=base64.o \ explicit_bzero.o \ fmt_scaled.o \ freezero.o \ + fnmatch.o \ getcwd.o \ getgrouplist.o \ getopt_long.o \ @@ -40,7 +44,6 @@ OPENBSD=base64.o \ readpassphrase.o \ reallocarray.o \ recallocarray.o \ - rmd160.o \ rresvport.o \ setenv.o \ setproctitle.o \ @@ -96,7 +99,7 @@ PORTS= port-aix.o \ port-uw.o .c.o: - $(CC) $(CFLAGS) $(CPPFLAGS) -c $< + $(CC) $(CFLAGS_NOPIE) $(PICFLAG) $(CPPFLAGS) -c $< all: libopenbsd-compat.a diff --git a/openbsd-compat/bcrypt_pbkdf.c b/openbsd-compat/bcrypt_pbkdf.c index 785234563..62728d38f 100644 --- a/openbsd-compat/bcrypt_pbkdf.c +++ b/openbsd-compat/bcrypt_pbkdf.c @@ -15,6 +15,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +/* OPENBSD ORIGINAL: lib/libutil/bcrypt_pbkdf.c */ + #include "includes.h" #ifndef HAVE_BCRYPT_PBKDF @@ -91,7 +93,7 @@ bcrypt_hash(u_int8_t *sha2pass, u_int8_t *sha2salt, u_int8_t *out) cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext), &j); for (i = 0; i < 64; i++) - blf_enc(&state, cdata, sizeof(cdata) / sizeof(uint64_t)); + blf_enc(&state, cdata, sizeof(cdata) / (sizeof(uint64_t))); /* copy out */ for (i = 0; i < BCRYPT_WORDS; i++) { diff --git a/openbsd-compat/bsd-misc.c b/openbsd-compat/bsd-misc.c index 7a26ee40c..059b6d3b3 100644 --- a/openbsd-compat/bsd-misc.c +++ b/openbsd-compat/bsd-misc.c @@ -129,7 +129,9 @@ utimensat(int fd, const char *path, const struct timespec times[2], int flag) { struct timeval tv[2]; +# ifdef HAVE_FUTIMES int ret, oflags = O_WRONLY; +# endif tv[0].tv_sec = times[0].tv_sec; tv[0].tv_usec = times[0].tv_nsec / 1000; @@ -426,3 +428,13 @@ int _ssh_compat_fflush(FILE *f) return fflush(f); } #endif + +#ifndef HAVE_LOCALTIME_R +struct tm * +localtime_r(const time_t *timep, struct tm *result) +{ + struct tm *tm = localtime(timep); + *result = *tm; + return result; +} +#endif diff --git a/openbsd-compat/bsd-misc.h b/openbsd-compat/bsd-misc.h index cb158cd5c..3a7dd6f4c 100644 --- a/openbsd-compat/bsd-misc.h +++ b/openbsd-compat/bsd-misc.h @@ -64,14 +64,6 @@ 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 @@ -88,16 +80,27 @@ int fchownat(int, const char *, uid_t, gid_t, int); 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 +#endif /* !HAVE_STRUCT_TIMESPEC */ + +#if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) +# include int nanosleep(const struct timespec *, struct timespec *); #endif +#ifndef HAVE_UTIMENSAT +# include +/* 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 /* !HAVE_UTIMENSAT */ + #ifndef HAVE_USLEEP int usleep(unsigned int useconds); #endif @@ -177,4 +180,12 @@ int flock(int, int); # define fflush(x) (_ssh_compat_fflush(x)) #endif +#ifndef HAVE_LOCALTIME_R +struct tm *localtime_r(const time_t *, struct tm *); +#endif + +#ifndef HAVE_REALPATH +#define realpath(x, y) (sftp_realpath((x), (y))) +#endif + #endif /* _BSD_MISC_H */ diff --git a/openbsd-compat/bsd-openpty.c b/openbsd-compat/bsd-openpty.c index 123a9be56..1ab41f42b 100644 --- a/openbsd-compat/bsd-openpty.c +++ b/openbsd-compat/bsd-openpty.c @@ -65,6 +65,8 @@ #include #include +#include "misc.h" + #ifndef O_NOCTTY #define O_NOCTTY 0 #endif @@ -97,16 +99,16 @@ openpty(int *amaster, int *aslave, char *name, struct termios *termp, */ int ptm; char *pts; - mysig_t old_signal; + sshsig_t old_signal; if ((ptm = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) return (-1); /* XXX: need to close ptm on error? */ - old_signal = signal(SIGCHLD, SIG_DFL); + old_signal = ssh_signal(SIGCHLD, SIG_DFL); if (grantpt(ptm) < 0) return (-1); - signal(SIGCHLD, old_signal); + ssh_signal(SIGCHLD, old_signal); if (unlockpt(ptm) < 0) return (-1); diff --git a/openbsd-compat/bsd-signal.c b/openbsd-compat/bsd-signal.c index 0b816a3a6..38d5e972e 100644 --- a/openbsd-compat/bsd-signal.c +++ b/openbsd-compat/bsd-signal.c @@ -23,34 +23,6 @@ #include "openbsd-compat/bsd-signal.h" -#undef signal - -mysig_t -mysignal(int sig, mysig_t act) -{ -#ifdef HAVE_SIGACTION - struct sigaction sa, osa; - - if (sigaction(sig, NULL, &osa) == -1) - return (mysig_t) -1; - if (osa.sa_handler != act) { - memset(&sa, 0, sizeof(sa)); - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; -#ifdef SA_INTERRUPT - if (sig == SIGALRM) - sa.sa_flags |= SA_INTERRUPT; -#endif - sa.sa_handler = act; - if (sigaction(sig, &sa, NULL) == -1) - return (mysig_t) -1; - } - return (osa.sa_handler); -#else - return (signal(sig, act)); -#endif -} - #if !defined(HAVE_STRSIGNAL) char *strsignal(int sig) { diff --git a/openbsd-compat/bsd-signal.h b/openbsd-compat/bsd-signal.h index 4cb8cb7a0..8d8c44419 100644 --- a/openbsd-compat/bsd-signal.h +++ b/openbsd-compat/bsd-signal.h @@ -19,6 +19,8 @@ #include "includes.h" +#include + #ifndef _NSIG # ifdef NSIG # define _NSIG NSIG @@ -27,11 +29,6 @@ # endif #endif -/* wrapper for signal interface */ -typedef void (*mysig_t)(int); -mysig_t mysignal(int sig, mysig_t act); -#define signal(a,b) mysignal(a,b) - #if !defined(HAVE_STRSIGNAL) char *strsignal(int); #endif diff --git a/openbsd-compat/bsd-snprintf.c b/openbsd-compat/bsd-snprintf.c index f27b9d808..f041121fd 100644 --- a/openbsd-compat/bsd-snprintf.c +++ b/openbsd-compat/bsd-snprintf.c @@ -73,7 +73,7 @@ * Fix incorrect zpadlen handling in fmtfp. * Thanks to Ollie Oldham for spotting it. * few mods to make it easier to compile the tests. - * addedd the "Ollie" test to the floating point ones. + * added the "Ollie" test to the floating point ones. * * Martin Pool (mbp@samba.org) April 2003 * Remove NO_CONFIG_H so that the test case can be built within a source diff --git a/openbsd-compat/bsd-statvfs.c b/openbsd-compat/bsd-statvfs.c index e3bd87d98..10d876439 100644 --- a/openbsd-compat/bsd-statvfs.c +++ b/openbsd-compat/bsd-statvfs.c @@ -29,6 +29,11 @@ # define MNAMELEN 32 #endif +#ifdef HAVE_STRUCT_STATFS_F_FILES +# define HAVE_STRUCT_STATFS +#endif + +#ifdef HAVE_STRUCT_STATFS static void copy_statfs_to_statvfs(struct statvfs *to, struct statfs *from) { @@ -48,11 +53,12 @@ copy_statfs_to_statvfs(struct statvfs *to, struct statfs *from) #endif to->f_namemax = MNAMELEN; } +#endif # ifndef HAVE_STATVFS int statvfs(const char *path, struct statvfs *buf) { -# ifdef HAVE_STATFS +# if defined(HAVE_STATFS) && defined(HAVE_STRUCT_STATFS) struct statfs fs; memset(&fs, 0, sizeof(fs)); @@ -70,7 +76,7 @@ int statvfs(const char *path, struct statvfs *buf) # ifndef HAVE_FSTATVFS int fstatvfs(int fd, struct statvfs *buf) { -# ifdef HAVE_FSTATFS +# if defined(HAVE_FSTATFS) && defined(HAVE_STRUCT_STATFS) struct statfs fs; memset(&fs, 0, sizeof(fs)); diff --git a/openbsd-compat/explicit_bzero.c b/openbsd-compat/explicit_bzero.c index 6ef9825a9..68cd2c10b 100644 --- a/openbsd-compat/explicit_bzero.c +++ b/openbsd-compat/explicit_bzero.c @@ -15,7 +15,15 @@ #ifndef HAVE_EXPLICIT_BZERO -#ifdef HAVE_MEMSET_S +#ifdef HAVE_EXPLICIT_MEMSET + +void +explicit_bzero(void *p, size_t n) +{ + (void)explicit_memset(p, 0, n); +} + +#elif defined(HAVE_MEMSET_S) void explicit_bzero(void *p, size_t n) diff --git a/openbsd-compat/fnmatch.c b/openbsd-compat/fnmatch.c new file mode 100644 index 000000000..b5641a091 --- /dev/null +++ b/openbsd-compat/fnmatch.c @@ -0,0 +1,495 @@ +/* $OpenBSD: fnmatch.c,v 1.22 2020/03/13 03:25:45 djm Exp $ */ + +/* Copyright (c) 2011, VMware, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the VMware, Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. 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) 2008, 2016 Todd C. 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. + */ + +/* Authored by William A. Rowe Jr. , April 2011 + * + * Derived from The Open Group Base Specifications Issue 7, IEEE Std 1003.1-2008 + * as described in; + * http://pubs.opengroup.org/onlinepubs/9699919799/functions/fnmatch.html + * + * Filename pattern matches defined in section 2.13, "Pattern Matching Notation" + * from chapter 2. "Shell Command Language" + * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13 + * where; 1. A bracket expression starting with an unquoted '^' + * character CONTINUES to specify a non-matching list; 2. an explicit '.' + * in a bracket expression matching list, e.g. "[.abc]" does NOT match a leading + * in a filename; 3. a '[' which does not introduce + * a valid bracket expression is treated as an ordinary character; 4. a differing + * number of consecutive slashes within pattern and string will NOT match; + * 5. a trailing '\' in FNM_ESCAPE mode is treated as an ordinary '\' character. + * + * Bracket expansion defined in section 9.3.5, "RE Bracket Expression", + * from chapter 9, "Regular Expressions" + * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05 + * with no support for collating symbols, equivalence class expressions or + * character class expressions. A partial range expression with a leading + * hyphen following a valid range expression will match only the ordinary + * and the ending character (e.g. "[a-m-z]" will match characters + * 'a' through 'm', a '-', or a 'z'). + * + * Supports BSD extensions FNM_LEADING_DIR to match pattern to the end of one + * path segment of string, and FNM_CASEFOLD to ignore alpha case. + * + * NOTE: Only POSIX/C single byte locales are correctly supported at this time. + * Notably, non-POSIX locales with FNM_CASEFOLD produce undefined results, + * particularly in ranges of mixed case (e.g. "[A-z]") or spanning alpha and + * nonalpha characters within a range. + * + * XXX comments below indicate porting required for multi-byte character sets + * and non-POSIX locale collation orders; requires mbr* APIs to track shift + * state of pattern and string (rewinding pattern and string repeatedly). + * + * Certain parts of the code assume 0x00-0x3F are unique with any MBCS (e.g. + * UTF-8, SHIFT-JIS, etc). Any implementation allowing '\' as an alternate + * path delimiter must be aware that 0x5C is NOT unique within SHIFT-JIS. + */ + +/* OPENBSD ORIGINAL: lib/libc/gen/fnmatch.c */ + +#include "includes.h" +#ifndef HAVE_FNMATCH + +#include +#include +#include + +#include "charclass.h" + +#define RANGE_MATCH 1 +#define RANGE_NOMATCH 0 +#define RANGE_ERROR (-1) + +static int +classmatch(const char *pattern, char test, int foldcase, const char **ep) +{ + const char * const mismatch = pattern; + const char *colon; + struct cclass *cc; + int rval = RANGE_NOMATCH; + size_t len; + + if (pattern[0] != '[' || pattern[1] != ':') { + *ep = mismatch; + return RANGE_ERROR; + } + pattern += 2; + + if ((colon = strchr(pattern, ':')) == NULL || colon[1] != ']') { + *ep = mismatch; + return RANGE_ERROR; + } + *ep = colon + 2; + len = (size_t)(colon - pattern); + + if (foldcase && strncmp(pattern, "upper:]", 7) == 0) + pattern = "lower:]"; + for (cc = cclasses; cc->name != NULL; cc++) { + if (!strncmp(pattern, cc->name, len) && cc->name[len] == '\0') { + if (cc->isctype((unsigned char)test)) + rval = RANGE_MATCH; + break; + } + } + if (cc->name == NULL) { + /* invalid character class, treat as normal text */ + *ep = mismatch; + rval = RANGE_ERROR; + } + return rval; +} + +/* Most MBCS/collation/case issues handled here. Wildcard '*' is not handled. + * EOS '\0' and the FNM_PATHNAME '/' delimiters are not advanced over, + * however the "\/" sequence is advanced to '/'. + * + * Both pattern and string are **char to support pointer increment of arbitrary + * multibyte characters for the given locale, in a later iteration of this code + */ +static int fnmatch_ch(const char **pattern, const char **string, int flags) +{ + const char * const mismatch = *pattern; + const int nocase = !!(flags & FNM_CASEFOLD); + const int escape = !(flags & FNM_NOESCAPE); + const int slash = !!(flags & FNM_PATHNAME); + int result = FNM_NOMATCH; + const char *startch; + int negate; + + if (**pattern == '[') { + ++*pattern; + + /* Handle negation, either leading ! or ^ operators */ + negate = (**pattern == '!') || (**pattern == '^'); + if (negate) + ++*pattern; + + /* ']' is an ordinary char at the start of the range pattern */ + if (**pattern == ']') + goto leadingclosebrace; + + while (**pattern) { + if (**pattern == ']') { + ++*pattern; + /* XXX: Fix for MBCS character width */ + ++*string; + return (result ^ negate); + } + + if (escape && (**pattern == '\\')) { + ++*pattern; + + /* Patterns must terminate with ']', not EOS */ + if (!**pattern) + break; + } + + /* Patterns must terminate with ']' not '/' */ + if (slash && (**pattern == '/')) + break; + + /* Match character classes. */ + switch (classmatch(*pattern, **string, nocase, pattern)) { + case RANGE_MATCH: + result = 0; + continue; + case RANGE_NOMATCH: + /* Valid character class but no match. */ + continue; + default: + /* Not a valid character class. */ + break; + } + if (!**pattern) + break; + +leadingclosebrace: + /* Look at only well-formed range patterns; + * "x-]" is not allowed unless escaped ("x-\]") + * XXX: Fix for locale/MBCS character width + */ + if (((*pattern)[1] == '-') && ((*pattern)[2] != ']')) { + startch = *pattern; + *pattern += (escape && ((*pattern)[2] == '\\')) ? 3 : 2; + + /* + * NOT a properly balanced [expr] pattern, EOS + * terminated or ranges containing a slash in + * FNM_PATHNAME mode pattern fall out to to the + * rewind and test '[' literal code path. + */ + if (!**pattern || (slash && (**pattern == '/'))) + break; + + /* XXX: handle locale/MBCS comparison, advance by MBCS char width */ + if ((**string >= *startch) && (**string <= **pattern)) + result = 0; + else if (nocase && + (isupper((unsigned char)**string) || + isupper((unsigned char)*startch) || + isupper((unsigned char)**pattern)) && + (tolower((unsigned char)**string) >= + tolower((unsigned char)*startch)) && + (tolower((unsigned char)**string) <= + tolower((unsigned char)**pattern))) + result = 0; + + ++*pattern; + continue; + } + + /* XXX: handle locale/MBCS comparison, advance by MBCS char width */ + if ((**string == **pattern)) + result = 0; + else if (nocase && (isupper((unsigned char)**string) || + isupper((unsigned char)**pattern)) && + (tolower((unsigned char)**string) == + tolower((unsigned char)**pattern))) + result = 0; + + ++*pattern; + } + /* + * NOT a properly balanced [expr] pattern; + * Rewind and reset result to test '[' literal + */ + *pattern = mismatch; + result = FNM_NOMATCH; + } else if (**pattern == '?') { + /* Optimize '?' match before unescaping **pattern */ + if (!**string || (slash && (**string == '/'))) + return FNM_NOMATCH; + result = 0; + goto fnmatch_ch_success; + } else if (escape && (**pattern == '\\') && (*pattern)[1]) { + ++*pattern; + } + + /* XXX: handle locale/MBCS comparison, advance by the MBCS char width */ + if (**string == **pattern) + result = 0; + else if (nocase && (isupper((unsigned char)**string) || + isupper((unsigned char)**pattern)) && + (tolower((unsigned char)**string) == + tolower((unsigned char)**pattern))) + result = 0; + + /* Refuse to advance over trailing slash or NULs */ + if (**string == '\0' || **pattern == '\0' || + (slash && ((**string == '/') || (**pattern == '/')))) + return result; + +fnmatch_ch_success: + ++*pattern; + ++*string; + return result; +} + + +int fnmatch(const char *pattern, const char *string, int flags) +{ + static const char dummystring[2] = {' ', 0}; + const int escape = !(flags & FNM_NOESCAPE); + const int slash = !!(flags & FNM_PATHNAME); + const int leading_dir = !!(flags & FNM_LEADING_DIR); + const char *dummyptr, *matchptr, *strendseg; + int wild; + /* For '*' wild processing only; suppress 'used before initialization' + * warnings with dummy initialization values; + */ + const char *strstartseg = NULL; + const char *mismatch = NULL; + int matchlen = 0; + + if (*pattern == '*') + goto firstsegment; + + while (*pattern && *string) { + /* + * Pre-decode "\/" which has no special significance, and + * match balanced slashes, starting a new segment pattern. + */ + if (slash && escape && (*pattern == '\\') && (pattern[1] == '/')) + ++pattern; + if (slash && (*pattern == '/') && (*string == '/')) { + ++pattern; + ++string; + } + +firstsegment: + /* + * At the beginning of each segment, validate leading period + * behavior. + */ + if ((flags & FNM_PERIOD) && (*string == '.')) { + if (*pattern == '.') + ++pattern; + else if (escape && (*pattern == '\\') && (pattern[1] == '.')) + pattern += 2; + else + return FNM_NOMATCH; + ++string; + } + + /* + * Determine the end of string segment. Presumes '/' + * character is unique, not composite in any MBCS encoding + */ + if (slash) { + strendseg = strchr(string, '/'); + if (!strendseg) + strendseg = strchr(string, '\0'); + } else { + strendseg = strchr(string, '\0'); + } + + /* + * Allow pattern '*' to be consumed even with no remaining + * string to match. + */ + while (*pattern) { + if ((string > strendseg) || + ((string == strendseg) && (*pattern != '*'))) + break; + + if (slash && ((*pattern == '/') || + (escape && (*pattern == '\\') && (pattern[1] == '/')))) + break; + + /* + * Reduce groups of '*' and '?' to n '?' matches + * followed by one '*' test for simplicity. + */ + for (wild = 0; (*pattern == '*') || (*pattern == '?'); ++pattern) { + if (*pattern == '*') { + wild = 1; + } else if (string < strendseg) { /* && (*pattern == '?') */ + /* XXX: Advance 1 char for MBCS locale */ + ++string; + } + else { /* (string >= strendseg) && (*pattern == '?') */ + return FNM_NOMATCH; + } + } + + if (wild) { + strstartseg = string; + mismatch = pattern; + + /* + * Count fixed (non '*') char matches remaining + * in pattern * excluding '/' (or "\/") and '*'. + */ + for (matchptr = pattern, matchlen = 0; 1; ++matchlen) { + if ((*matchptr == '\0') || + (slash && ((*matchptr == '/') || + (escape && (*matchptr == '\\') && + (matchptr[1] == '/'))))) { + /* Compare precisely this many + * trailing string chars, the + * resulting match needs no + * wildcard loop. + */ + /* XXX: Adjust for MBCS */ + if (string + matchlen > strendseg) + return FNM_NOMATCH; + + string = strendseg - matchlen; + wild = 0; + break; + } + + if (*matchptr == '*') { + /* + * Ensure at least this many + * trailing string chars remain + * for the first comparison. + */ + /* XXX: Adjust for MBCS */ + if (string + matchlen > strendseg) + return FNM_NOMATCH; + + /* + * Begin first wild comparison + * at the current position. + */ + break; + } + + /* + * Skip forward in pattern by a single + * character match Use a dummy + * fnmatch_ch() test to count one + * "[range]" escape. + */ + /* XXX: Adjust for MBCS */ + if (escape && (*matchptr == '\\') && + matchptr[1]) { + matchptr += 2; + } else if (*matchptr == '[') { + dummyptr = dummystring; + fnmatch_ch(&matchptr, &dummyptr, + flags); + } else { + ++matchptr; + } + } + } + + /* Incrementally match string against the pattern. */ + while (*pattern && (string < strendseg)) { + /* Success; begin a new wild pattern search. */ + if (*pattern == '*') + break; + + if (slash && ((*string == '/') || + (*pattern == '/') || (escape && + (*pattern == '\\') && (pattern[1] == '/')))) + break; + + /* + * Compare ch's (the pattern is advanced over + * "\/" to the '/', but slashes will mismatch, + * and are not consumed). + */ + if (!fnmatch_ch(&pattern, &string, flags)) + continue; + + /* + * Failed to match, loop against next char + * offset of string segment until not enough + * string chars remain to match the fixed + * pattern. + */ + if (wild) { + /* XXX: Advance 1 char for MBCS locale */ + string = ++strstartseg; + if (string + matchlen > strendseg) + return FNM_NOMATCH; + + pattern = mismatch; + continue; + } else + return FNM_NOMATCH; + } + } + + if (*string && !((slash || leading_dir) && (*string == '/'))) + return FNM_NOMATCH; + + if (*pattern && !(slash && ((*pattern == '/') || + (escape && (*pattern == '\\') && (pattern[1] == '/'))))) + return FNM_NOMATCH; + + if (leading_dir && !*pattern && *string == '/') + return 0; + } + + /* Where both pattern and string are at EOS, declare success. */ + if (!*string && !*pattern) + return 0; + + /* Pattern didn't match to the end of string. */ + return FNM_NOMATCH; +} +#endif /* HAVE_FNMATCH */ diff --git a/openbsd-compat/fnmatch.h b/openbsd-compat/fnmatch.h new file mode 100644 index 000000000..d3bc4a863 --- /dev/null +++ b/openbsd-compat/fnmatch.h @@ -0,0 +1,66 @@ +/* $OpenBSD: fnmatch.h,v 1.8 2005/12/13 00:35:22 millert Exp $ */ +/* $NetBSD: fnmatch.h,v 1.5 1994/10/26 00:55:53 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 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. + * + * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93 + */ + +/* OPENBSD ORIGINAL: include/fnmatch.h */ + +#ifndef HAVE_FNMATCH_H +/* Ensure we define FNM_CASEFOLD */ +#define __BSD_VISIBLE 1 + +#ifndef _FNMATCH_H_ +#define _FNMATCH_H_ + +#ifdef HAVE_SYS_CDEFS_H +#include +#endif + +#define FNM_NOMATCH 1 /* Match failed. */ +#define FNM_NOSYS 2 /* Function not supported (unused). */ + +#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ +#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ +#define FNM_PERIOD 0x04 /* Period must be matched by period. */ +#if __BSD_VISIBLE +#define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ +#define FNM_CASEFOLD 0x10 /* Case insensitive search. */ +#define FNM_IGNORECASE FNM_CASEFOLD +#define FNM_FILE_NAME FNM_PATHNAME +#endif + +/* __BEGIN_DECLS */ +int fnmatch(const char *, const char *, int); +/* __END_DECLS */ + +#endif /* !_FNMATCH_H_ */ +#endif /* ! HAVE_FNMATCH_H */ diff --git a/openbsd-compat/glob.c b/openbsd-compat/glob.c index 7c97e67f5..e89151789 100644 --- a/openbsd-compat/glob.c +++ b/openbsd-compat/glob.c @@ -1,4 +1,4 @@ -/* $OpenBSD: glob.c,v 1.38 2011/09/22 06:27:29 djm Exp $ */ +/* $OpenBSD: glob.c,v 1.49 2020/04/21 08:25:22 dtucker Exp $ */ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -70,6 +70,9 @@ #include #include #include +#ifdef HAVE_STDINT_H +#include +#endif #include #include @@ -80,6 +83,10 @@ #include "charclass.h" +#ifdef TILDE +# undef TILDE +#endif + #define DOLLAR '$' #define DOT '.' #define EOS '\0' @@ -131,12 +138,9 @@ typedef char Char; #define ismeta(c) (((c)&M_QUOTE) != 0) #define GLOB_LIMIT_MALLOC 65536 -#define GLOB_LIMIT_STAT 128 +#define GLOB_LIMIT_STAT 2048 #define GLOB_LIMIT_READDIR 16384 -/* Limit of recursion during matching attempts. */ -#define GLOB_LIMIT_RECUR 64 - struct glob_lim { size_t glim_malloc; size_t glim_stat; @@ -150,7 +154,7 @@ struct glob_path_stat { static int compare(const void *, const void *); static int compare_gps(const void *, const void *); -static int g_Ctoc(const Char *, char *, u_int); +static int g_Ctoc(const Char *, char *, size_t); static int g_lstat(Char *, struct stat *, glob_t *); static DIR *g_opendir(Char *, glob_t *); static Char *g_strchr(const Char *, int); @@ -169,7 +173,7 @@ static const Char * static int globexp1(const Char *, glob_t *, struct glob_lim *); static int globexp2(const Char *, const Char *, glob_t *, struct glob_lim *); -static int match(Char *, Char *, Char *, int); +static int match(Char *, Char *, Char *); #ifdef DEBUG static void qprintf(const char *, Char *); #endif @@ -180,12 +184,9 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), { const u_char *patnext; int c; - Char *bufnext, *bufend, patbuf[MAXPATHLEN]; + Char *bufnext, *bufend, patbuf[PATH_MAX]; struct glob_lim limit = { 0, 0, 0 }; - if (strnlen(pattern, PATH_MAX) == PATH_MAX) - return(GLOB_NOMATCH); - patnext = (u_char *) pattern; if (!(flags & GLOB_APPEND)) { pglob->gl_pathc = 0; @@ -198,13 +199,15 @@ glob(const char *pattern, int flags, int (*errfunc)(const char *, int), pglob->gl_errfunc = errfunc; pglob->gl_matchc = 0; - if (pglob->gl_offs < 0 || pglob->gl_pathc < 0 || - pglob->gl_offs >= INT_MAX || pglob->gl_pathc >= INT_MAX || - pglob->gl_pathc >= INT_MAX - pglob->gl_offs - 1) + if (strnlen(pattern, PATH_MAX) == PATH_MAX) + return(GLOB_NOMATCH); + + if (pglob->gl_offs >= SSIZE_MAX || pglob->gl_pathc >= SSIZE_MAX || + pglob->gl_pathc >= SSIZE_MAX - pglob->gl_offs - 1) return GLOB_NOSPACE; bufnext = patbuf; - bufend = bufnext + MAXPATHLEN - 1; + bufend = bufnext + PATH_MAX - 1; if (flags & GLOB_NOESCAPE) while (bufnext < bufend && (c = *patnext++) != EOS) *bufnext++ = c; @@ -261,7 +264,7 @@ globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int i, rv; Char *lm, *ls; const Char *pe, *pm, *pl; - Char patbuf[MAXPATHLEN]; + Char patbuf[PATH_MAX]; /* copy part up to the brace */ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) @@ -472,10 +475,11 @@ static int glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) { const Char *qpatnext; - int c, err, oldpathc; - Char *bufnext, patbuf[MAXPATHLEN]; + int c, err; + size_t oldpathc; + Char *bufnext, patbuf[PATH_MAX]; - qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob); + qpatnext = globtilde(pattern, patbuf, PATH_MAX, pglob); oldpathc = pglob->gl_pathc; bufnext = patbuf; @@ -545,7 +549,7 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) qprintf("glob0:", patbuf); #endif - if ((err = glob1(patbuf, patbuf+MAXPATHLEN-1, pglob, limitp)) != 0) + if ((err = glob1(patbuf, patbuf+PATH_MAX-1, pglob, limitp)) != 0) return(err); /* @@ -566,9 +570,9 @@ glob0(const Char *pattern, glob_t *pglob, struct glob_lim *limitp) if ((pglob->gl_flags & GLOB_KEEPSTAT)) { /* Keep the paths and stat info synced during sort */ struct glob_path_stat *path_stat; - int i; - int n = pglob->gl_pathc - oldpathc; - int o = pglob->gl_offs + oldpathc; + size_t i; + size_t n = pglob->gl_pathc - oldpathc; + size_t o = pglob->gl_offs + oldpathc; if ((path_stat = calloc(n, sizeof(*path_stat))) == NULL) return GLOB_NOSPACE; @@ -609,13 +613,13 @@ compare_gps(const void *_p, const void *_q) static int glob1(Char *pattern, Char *pattern_last, glob_t *pglob, struct glob_lim *limitp) { - Char pathbuf[MAXPATHLEN]; + Char pathbuf[PATH_MAX]; /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ if (*pattern == EOS) return(0); - return(glob2(pathbuf, pathbuf+MAXPATHLEN-1, - pathbuf, pathbuf+MAXPATHLEN-1, + return(glob2(pathbuf, pathbuf+PATH_MAX-1, + pathbuf, pathbuf+PATH_MAX-1, pattern, pattern_last, pglob, limitp)); } @@ -639,8 +643,6 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, for (anymeta = 0;;) { if (*pattern == EOS) { /* End of pattern? */ *pathend = EOS; - if (g_lstat(pathbuf, &sb, pglob)) - return(0); if ((pglob->gl_flags & GLOB_LIMIT) && limitp->glim_stat++ >= GLOB_LIMIT_STAT) { @@ -649,6 +651,8 @@ glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, *pathend = EOS; return(GLOB_NOSPACE); } + if (g_lstat(pathbuf, &sb, pglob)) + return(0); if (((pglob->gl_flags & GLOB_MARK) && pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) || @@ -700,7 +704,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, struct dirent *dp; DIR *dirp; int err; - char buf[MAXPATHLEN]; + char buf[PATH_MAX]; /* * The readdirfunc declaration can't be prototyped, because it is @@ -760,7 +764,7 @@ glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, break; } - if (!match(pathend, pattern, restpattern, GLOB_LIMIT_RECUR)) { + if (!match(pathend, pattern, restpattern)) { *pathend = EOS; continue; } @@ -797,56 +801,51 @@ globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, struct stat *sb) { char **pathv; - ssize_t i; - size_t newn, len; + size_t i, newn, len; char *copy = NULL; const Char *p; struct stat **statv; newn = 2 + pglob->gl_pathc + pglob->gl_offs; - if (pglob->gl_offs >= INT_MAX || - pglob->gl_pathc >= INT_MAX || - newn >= INT_MAX || + if (pglob->gl_offs >= SSIZE_MAX || + pglob->gl_pathc >= SSIZE_MAX || + newn >= SSIZE_MAX || SIZE_MAX / sizeof(*pathv) <= newn || SIZE_MAX / sizeof(*statv) <= newn) { nospace: - for (i = pglob->gl_offs; i < (ssize_t)(newn - 2); i++) { + for (i = pglob->gl_offs; i < newn - 2; i++) { if (pglob->gl_pathv && pglob->gl_pathv[i]) free(pglob->gl_pathv[i]); if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0 && pglob->gl_pathv && pglob->gl_pathv[i]) free(pglob->gl_statv[i]); } - if (pglob->gl_pathv) { - free(pglob->gl_pathv); - pglob->gl_pathv = NULL; - } - if (pglob->gl_statv) { - free(pglob->gl_statv); - pglob->gl_statv = NULL; - } + free(pglob->gl_pathv); + pglob->gl_pathv = NULL; + free(pglob->gl_statv); + pglob->gl_statv = NULL; return(GLOB_NOSPACE); } - pathv = realloc(pglob->gl_pathv, newn * sizeof(*pathv)); + pathv = reallocarray(pglob->gl_pathv, newn, sizeof(*pathv)); if (pathv == NULL) goto nospace; if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { /* first time around -- clear initial gl_offs items */ pathv += pglob->gl_offs; - for (i = pglob->gl_offs; --i >= 0; ) + for (i = pglob->gl_offs; i > 0; i--) *--pathv = NULL; } pglob->gl_pathv = pathv; if ((pglob->gl_flags & GLOB_KEEPSTAT) != 0) { - statv = realloc(pglob->gl_statv, newn * sizeof(*statv)); + statv = reallocarray(pglob->gl_statv, newn, sizeof(*statv)); if (statv == NULL) goto nospace; if (pglob->gl_statv == NULL && pglob->gl_offs > 0) { /* first time around -- clear initial gl_offs items */ statv += pglob->gl_offs; - for (i = pglob->gl_offs; --i >= 0; ) + for (i = pglob->gl_offs; i > 0; i--) *--statv = NULL; } pglob->gl_statv = statv; @@ -894,17 +893,24 @@ globextend(const Char *path, glob_t *pglob, struct glob_lim *limitp, /* * pattern matching function for filenames. Each occurrence of the * - * pattern causes a recursion level. + * pattern causes an iteration. + * + * Note, this function differs from the original as per the discussion + * here: https://research.swtch.com/glob + * + * Basically we removed the recursion and made it use the algorithm + * from Russ Cox to not go quadratic on cases like a file called + * ("a" x 100) . "x" matched against a pattern like "a*a*a*a*a*a*a*y". */ static int -match(Char *name, Char *pat, Char *patend, int recur) +match(Char *name, Char *pat, Char *patend) { int ok, negate_range; Char c, k; + Char *nextp = NULL; + Char *nextn = NULL; - if (recur-- == 0) - return(GLOB_NOSPACE); - +loop: while (pat < patend) { c = *pat++; switch (c & M_MASK) { @@ -913,19 +919,19 @@ match(Char *name, Char *pat, Char *patend, int recur) pat++; /* eat consecutive '*' */ if (pat == patend) return(1); - do { - if (match(name, pat, patend, recur)) - return(1); - } while (*name++ != EOS); - return(0); + if (*name == EOS) + return(0); + nextn = name + 1; + nextp = pat - 1; + break; case M_ONE: if (*name++ == EOS) - return(0); + goto fail; break; case M_SET: ok = 0; if ((k = *name++) == EOS) - return(0); + goto fail; if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) ++pat; while (((c = *pat++) & M_MASK) != M_END) { @@ -944,36 +950,43 @@ match(Char *name, Char *pat, Char *patend, int recur) ok = 1; } if (ok == negate_range) - return(0); + goto fail; break; default: if (*name++ != c) - return(0); + goto fail; break; } } - return(*name == EOS); + if (*name == EOS) + return(1); + +fail: + if (nextn) { + pat = nextp; + name = nextn; + goto loop; + } + return(0); } /* Free allocated data belonging to a glob_t structure. */ void globfree(glob_t *pglob) { - int i; + size_t i; char **pp; if (pglob->gl_pathv != NULL) { pp = pglob->gl_pathv + pglob->gl_offs; for (i = pglob->gl_pathc; i--; ++pp) - if (*pp) - free(*pp); + free(*pp); free(pglob->gl_pathv); pglob->gl_pathv = NULL; } if (pglob->gl_statv != NULL) { for (i = 0; i < pglob->gl_pathc; i++) { - if (pglob->gl_statv[i] != NULL) - free(pglob->gl_statv[i]); + free(pglob->gl_statv[i]); } free(pglob->gl_statv); pglob->gl_statv = NULL; @@ -983,7 +996,7 @@ globfree(glob_t *pglob) static DIR * g_opendir(Char *str, glob_t *pglob) { - char buf[MAXPATHLEN]; + char buf[PATH_MAX]; if (!*str) strlcpy(buf, ".", sizeof buf); @@ -1001,7 +1014,7 @@ g_opendir(Char *str, glob_t *pglob) static int g_lstat(Char *fn, struct stat *sb, glob_t *pglob) { - char buf[MAXPATHLEN]; + char buf[PATH_MAX]; if (g_Ctoc(fn, buf, sizeof(buf))) return(-1); @@ -1013,7 +1026,7 @@ g_lstat(Char *fn, struct stat *sb, glob_t *pglob) static int g_stat(Char *fn, struct stat *sb, glob_t *pglob) { - char buf[MAXPATHLEN]; + char buf[PATH_MAX]; if (g_Ctoc(fn, buf, sizeof(buf))) return(-1); @@ -1033,7 +1046,7 @@ g_strchr(const Char *str, int ch) } static int -g_Ctoc(const Char *str, char *buf, u_int len) +g_Ctoc(const Char *str, char *buf, size_t len) { while (len--) { diff --git a/openbsd-compat/glob.h b/openbsd-compat/glob.h index f069a05dc..1692d36cc 100644 --- a/openbsd-compat/glob.h +++ b/openbsd-compat/glob.h @@ -1,4 +1,4 @@ -/* $OpenBSD: glob.h,v 1.11 2010/09/24 13:32:55 djm Exp $ */ +/* $OpenBSD: glob.h,v 1.14 2019/02/04 16:45:40 millert Exp $ */ /* $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $ */ /* @@ -46,6 +46,7 @@ #define _COMPAT_GLOB_H_ #include +#include # define glob_t _ssh_compat_glob_t # define glob(a, b, c, d) _ssh__compat_glob(a, b, c, d) @@ -53,9 +54,9 @@ struct stat; typedef struct { - int gl_pathc; /* Count of total paths so far. */ - int gl_matchc; /* Count of paths matching pattern. */ - int gl_offs; /* Reserved at beginning of gl_pathv. */ + size_t gl_pathc; /* Count of total paths so far. */ + size_t gl_matchc; /* Count of paths matching pattern. */ + size_t gl_offs; /* Reserved at beginning of gl_pathv. */ int gl_flags; /* Copy of flags parameter to glob. */ char **gl_pathv; /* List of paths matching pattern. */ struct stat **gl_statv; /* Stat entries corresponding to gl_pathv */ diff --git a/openbsd-compat/memmem.c b/openbsd-compat/memmem.c index 3e5e6b5e6..ac1243eb0 100644 --- a/openbsd-compat/memmem.c +++ b/openbsd-compat/memmem.c @@ -1,30 +1,26 @@ -/* $OpenBSD: memmem.c,v 1.4 2015/08/31 02:53:57 guenther Exp $ */ -/*- - * Copyright (c) 2005 Pascal Gloor +/* $OpenBSD: memmem.c,v 1.5 2020/04/16 12:39:28 claudio Exp $ */ + +/* + * Copyright (c) 2005-2020 Rich Felker, et al. * - * 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. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: * - * 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. + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * 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 AUTHORS OR 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. */ #include "includes.h" @@ -32,38 +28,164 @@ #ifndef HAVE_MEMMEM #include +#ifdef HAVE_STDINT_H +#include +#endif + +static char * +twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) +{ + uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1]; + for (h+=2, k-=2; k; k--, hw = hw<<8 | *h++) + if (hw == nw) return (char *)h-2; + return hw == nw ? (char *)h-2 : 0; +} + +static char * +threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) +{ + uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8; + uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8; + for (h+=3, k-=3; k; k--, hw = (hw|*h++)<<8) + if (hw == nw) return (char *)h-3; + return hw == nw ? (char *)h-3 : 0; +} + +static char * +fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) +{ + uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3]; + uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3]; + for (h+=4, k-=4; k; k--, hw = hw<<8 | *h++) + if (hw == nw) return (char *)h-4; + return hw == nw ? (char *)h-4 : 0; +} + +#define MAX(a,b) ((a)>(b)?(a):(b)) +#define MIN(a,b) ((a)<(b)?(a):(b)) + +#define BITOP(a,b,op) \ + ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a)))) /* - * Find the first occurrence of the byte string s in byte string l. + * Maxime Crochemore and Dominique Perrin, Two-way string-matching, + * Journal of the ACM, 38(3):651-675, July 1991. */ +static char * +twoway_memmem(const unsigned char *h, const unsigned char *z, + const unsigned char *n, size_t l) +{ + size_t i, ip, jp, k, p, ms, p0, mem, mem0; + size_t byteset[32 / sizeof(size_t)] = { 0 }; + size_t shift[256]; + + /* Computing length of needle and fill shift table */ + for (i=0; i n[jp+k]) { + jp += k; + k = 1; + p = jp - ip; + } else { + ip = jp++; + k = p = 1; + } + } + ms = ip; + p0 = p; + + /* And with the opposite comparison */ + ip = -1; jp = 0; k = p = 1; + while (jp+k ms+1) ms = ip; + else p = p0; + + /* Periodic needle? */ + if (memcmp(n, n+p, ms+1)) { + mem0 = 0; + p = MAX(ms, l-ms-1) + 1; + } else mem0 = l-p; + mem = 0; + + /* Search loop */ + for (;;) { + /* If remainder of haystack is shorter than needle, done */ + if (z-h < l) return 0; + + /* Check last byte first; advance by shift on mismatch */ + if (BITOP(byteset, h[l-1], &)) { + k = l-shift[h[l-1]]; + if (k) { + if (k < mem) k = mem; + h += k; + mem = 0; + continue; + } + } else { + h += l; + mem = 0; + continue; + } + + /* Compare right half */ + for (k=MAX(ms+1,mem); kmem && n[k-1] == h[k-1]; k--); + if (k <= mem) return (char *)h; + h += p; + mem = mem0; + } +} void * -memmem(const void *l, size_t l_len, const void *s, size_t s_len) +memmem(const void *h0, size_t k, const void *n0, size_t l) { - const char *cur, *last; - const char *cl = l; - const char *cs = s; + const unsigned char *h = h0, *n = n0; - /* a zero length needle should just return the haystack */ - if (s_len == 0) - return (void *)cl; + /* Return immediately on empty needle */ + if (!l) return (void *)h; - /* "s" must be smaller or equal to "l" */ - if (l_len < s_len) - return NULL; + /* Return immediately when needle is longer than haystack */ + if (k #include -#if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP) +#if !defined(HAVE_MKDTEMP) #define MKTEMP_NAME 0 #define MKTEMP_FILE 1 @@ -138,4 +138,4 @@ mkdtemp(char *path) return(error ? NULL : path); } -#endif /* !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP) */ +#endif /* !defined(HAVE_MKDTEMP) */ diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h index 610db5508..e7b205710 100644 --- a/openbsd-compat/openbsd-compat.h +++ b/openbsd-compat/openbsd-compat.h @@ -44,9 +44,13 @@ #include "getrrsetbyname.h" #include "sha1.h" #include "sha2.h" -#include "rmd160.h" #include "md5.h" #include "blf.h" +#include "fnmatch.h" + +#if defined(HAVE_LOGIN_CAP) && !defined(HAVE_LOGIN_GETPWCLASS) +# define login_getpwclass(pw) login_getclass(pw->pw_class) +#endif #ifndef HAVE_BASENAME char *basename(const char *path); @@ -73,7 +77,7 @@ int getpagesize(void); char *getcwd(char *pt, size_t size); #endif -#ifndef HAVE_MEMMEM +#if defined(HAVE_DECL_MEMMEM) && HAVE_DECL_MEMMEM == 0 void *memmem(const void *, size_t, const void *, size_t); #endif @@ -122,7 +126,7 @@ void strmode(int mode, char *p); char *strptime(const char *buf, const char *fmt, struct tm *tm); #endif -#if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP) +#if !defined(HAVE_MKDTEMP) int mkstemps(char *path, int slen); int mkstemp(char *path); char *mkdtemp(char *path); @@ -197,7 +201,7 @@ int writev(int, struct iovec *, int); #include "bsd-waitpid.h" #include "bsd-poll.h" -#ifndef HAVE_GETPEEREID +#if defined(HAVE_DECL_GETPEEREID) && HAVE_DECL_GETPEEREID == 0 int getpeereid(int , uid_t *, gid_t *); #endif @@ -325,6 +329,10 @@ void explicit_bzero(void *p, size_t n); void freezero(void *, size_t); #endif +#ifndef HAVE_LOCALTIME_R +struct tm *localtime_r(const time_t *, struct tm *); +#endif + char *xcrypt(const char *password, const char *salt); char *shadow_pw(struct passwd *pw); diff --git a/openbsd-compat/openssl-compat.h b/openbsd-compat/openssl-compat.h index 917bc6f7c..8ca50b5ac 100644 --- a/openbsd-compat/openssl-compat.h +++ b/openbsd-compat/openssl-compat.h @@ -62,6 +62,12 @@ void ssh_libcrypto_init(void); # define OPENSSL_DSA_MAX_MODULUS_BITS 10000 #endif +#ifdef LIBRESSL_VERSION_NUMBER +# if LIBRESSL_VERSION_NUMBER < 0x3010000fL +# define HAVE_BROKEN_CHACHA20 +# endif +#endif + #ifndef OPENSSL_HAVE_EVPCTR # define EVP_aes_128_ctr evp_aes_128_ctr # define EVP_aes_192_ctr evp_aes_128_ctr @@ -87,12 +93,6 @@ void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t); # endif #endif -#if defined(HAVE_EVP_RIPEMD160) -# if defined(OPENSSL_NO_RIPEMD) || defined(OPENSSL_NO_RMD160) -# undef HAVE_EVP_RIPEMD160 -# endif -#endif - /* LibreSSL/OpenSSL 1.1x API compat */ #ifndef HAVE_DSA_GET0_PQG void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, @@ -113,8 +113,12 @@ int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key); #endif /* HAVE_DSA_SET0_KEY */ #ifndef HAVE_EVP_CIPHER_CTX_GET_IV +# ifdef HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV +# define EVP_CIPHER_CTX_get_iv EVP_CIPHER_CTX_get_updated_iv +# else /* HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV */ int EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx, unsigned char *iv, size_t len); +# endif /* HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV */ #endif /* HAVE_EVP_CIPHER_CTX_GET_IV */ #ifndef HAVE_EVP_CIPHER_CTX_SET_IV diff --git a/openbsd-compat/port-aix.c b/openbsd-compat/port-aix.c index fc80dc39f..e0d3eba51 100644 --- a/openbsd-compat/port-aix.c +++ b/openbsd-compat/port-aix.c @@ -26,6 +26,8 @@ */ #include "includes.h" +#ifdef _AIX + #include "xmalloc.h" #include "sshbuf.h" #include "ssherr.h" @@ -36,8 +38,6 @@ #include "ssh_api.h" #include "log.h" -#ifdef _AIX - #include #if defined(HAVE_NETDB_H) # include @@ -383,12 +383,13 @@ aix_restoreauthdb(void) # 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. + * 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) +aix_krb5_get_principal_name(const char *const_pw_name) { + char *pw_name = (char *)const_pw_name; char *authname = NULL, *authdomain = NULL, *principal = NULL; setuserdb(S_READ); @@ -398,7 +399,8 @@ aix_krb5_get_principal_name(char *pw_name) debug("AIX getuserattr S_AUTHNAME: %s", strerror(errno)); if (authdomain != NULL) - xasprintf(&principal, "%s@%s", authname ? authname : pw_name, authdomain); + xasprintf(&principal, "%s@%s", authname ? authname : pw_name, + authdomain); else if (authname != NULL) principal = xstrdup(authname); enduserdb(); diff --git a/openbsd-compat/port-aix.h b/openbsd-compat/port-aix.h index 904de3096..0ee366140 100644 --- a/openbsd-compat/port-aix.h +++ b/openbsd-compat/port-aix.h @@ -97,7 +97,7 @@ 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 *); +char *aix_krb5_get_principal_name(const char *); # endif #endif diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c index 622988822..77cb8213a 100644 --- a/openbsd-compat/port-linux.c +++ b/openbsd-compat/port-linux.c @@ -55,11 +55,10 @@ ssh_selinux_enabled(void) } /* Return the default security context for the given username */ -static security_context_t +static char * ssh_selinux_getctxbyname(char *pwname) { - security_context_t sc = NULL; - char *sename = NULL, *lvl = NULL; + char *sc = NULL, *sename = NULL, *lvl = NULL; int r; #ifdef HAVE_GETSEUSERBYNAME @@ -105,7 +104,7 @@ ssh_selinux_getctxbyname(char *pwname) void ssh_selinux_setup_exec_context(char *pwname) { - security_context_t user_ctx = NULL; + char *user_ctx = NULL; if (!ssh_selinux_enabled()) return; @@ -136,9 +135,7 @@ ssh_selinux_setup_exec_context(char *pwname) void ssh_selinux_setup_pty(char *pwname, const char *tty) { - security_context_t new_tty_ctx = NULL; - security_context_t user_ctx = NULL; - security_context_t old_tty_ctx = NULL; + char *new_tty_ctx = NULL, *user_ctx = NULL, *old_tty_ctx = NULL; security_class_t chrclass; if (!ssh_selinux_enabled()) @@ -182,18 +179,18 @@ ssh_selinux_change_context(const char *newname) { int len, newlen; char *oldctx, *newctx, *cx; - void (*switchlog) (const char *fmt,...) = logit; + LogLevel log_level = SYSLOG_LEVEL_INFO; if (!ssh_selinux_enabled()) return; - if (getcon((security_context_t *)&oldctx) < 0) { + if (getcon(&oldctx) < 0) { logit("%s: getcon failed with %s", __func__, strerror(errno)); return; } if ((cx = index(oldctx, ':')) == NULL || (cx = index(cx + 1, ':')) == NULL) { - logit ("%s: unparseable context %s", __func__, oldctx); + logit("%s: unparsable context %s", __func__, oldctx); return; } @@ -203,7 +200,7 @@ ssh_selinux_change_context(const char *newname) */ if (strncmp(cx, SSH_SELINUX_UNCONFINED_TYPE, sizeof(SSH_SELINUX_UNCONFINED_TYPE) - 1) == 0) - switchlog = debug3; + log_level = SYSLOG_LEVEL_DEBUG3; newlen = strlen(oldctx) + strlen(newname) + 1; newctx = xmalloc(newlen); @@ -215,8 +212,8 @@ ssh_selinux_change_context(const char *newname) debug3("%s: setting context from '%s' to '%s'", __func__, oldctx, newctx); if (setcon(newctx) < 0) - switchlog("%s: setcon %s from %s failed with %s", __func__, - newctx, oldctx, strerror(errno)); + do_log2(log_level, "%s: setcon %s from %s failed with %s", + __func__, newctx, oldctx, strerror(errno)); free(oldctx); free(newctx); } @@ -224,7 +221,7 @@ ssh_selinux_change_context(const char *newname) void ssh_selinux_setfscreatecon(const char *path) { - security_context_t context; + char *context; if (!ssh_selinux_enabled()) return; diff --git a/openbsd-compat/port-net.c b/openbsd-compat/port-net.c index bb535626f..da6d44678 100644 --- a/openbsd-compat/port-net.c +++ b/openbsd-compat/port-net.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -137,6 +138,7 @@ sys_set_process_rdomain(const char *name) #if defined(SSH_TUN_LINUX) #include +#define TUN_CTRL_DEV "/dev/net/tun" int sys_tun_open(int tun, int mode, char **ifname) @@ -147,10 +149,9 @@ sys_tun_open(int tun, int mode, char **ifname) if (ifname != NULL) *ifname = NULL; - - if ((fd = open("/dev/net/tun", O_RDWR)) == -1) { - debug("%s: failed to open tunnel control interface: %s", - __func__, strerror(errno)); + if ((fd = open(TUN_CTRL_DEV, O_RDWR)) == -1) { + debug("%s: failed to open tunnel control device \"%s\": %s", + __func__, TUN_CTRL_DEV, strerror(errno)); return (-1); } @@ -209,8 +210,11 @@ sys_tun_open(int tun, int mode, char **ifname) { struct ifreq ifr; char name[100]; - int fd = -1, sock, flag; + int fd = -1, sock; const char *tunbase = "tun"; +#if defined(TUNSIFHEAD) && !defined(SSH_TUN_PREPEND_AF) + int flag; +#endif if (ifname != NULL) *ifname = NULL; @@ -247,8 +251,8 @@ sys_tun_open(int tun, int mode, char **ifname) } /* Turn on tunnel headers */ - flag = 1; #if defined(TUNSIFHEAD) && !defined(SSH_TUN_PREPEND_AF) + flag = 1; if (mode != SSH_TUNMODE_ETHERNET && ioctl(fd, TUNSIFHEAD, &flag) == -1) { debug("%s: ioctl(%d, TUNSIFHEAD, 1): %s", __func__, fd, diff --git a/openbsd-compat/rmd160.c b/openbsd-compat/rmd160.c deleted file mode 100644 index e915141a5..000000000 --- a/openbsd-compat/rmd160.c +++ /dev/null @@ -1,378 +0,0 @@ -/* - * 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. - */ -/* - * Preneel, Bosselaers, Dobbertin, "The Cryptographic Hash Function RIPEMD-160", - * RSA Laboratories, CryptoBytes, Volume 3, Number 2, Autumn 1997, - * ftp://ftp.rsasecurity.com/pub/cryptobytes/crypto3n2.pdf - */ - -#include "includes.h" - -#ifndef WITH_OPENSSL - -#include -#ifdef HAVE_ENDIAN_H -#include -#endif -#include -#include - -#define PUT_64BIT_LE(cp, value) do { \ - (cp)[7] = (value) >> 56; \ - (cp)[6] = (value) >> 48; \ - (cp)[5] = (value) >> 40; \ - (cp)[4] = (value) >> 32; \ - (cp)[3] = (value) >> 24; \ - (cp)[2] = (value) >> 16; \ - (cp)[1] = (value) >> 8; \ - (cp)[0] = (value); } while (0) - -#define PUT_32BIT_LE(cp, value) do { \ - (cp)[3] = (value) >> 24; \ - (cp)[2] = (value) >> 16; \ - (cp)[1] = (value) >> 8; \ - (cp)[0] = (value); } while (0) - -#define H0 0x67452301U -#define H1 0xEFCDAB89U -#define H2 0x98BADCFEU -#define H3 0x10325476U -#define H4 0xC3D2E1F0U - -#define K0 0x00000000U -#define K1 0x5A827999U -#define K2 0x6ED9EBA1U -#define K3 0x8F1BBCDCU -#define K4 0xA953FD4EU - -#define KK0 0x50A28BE6U -#define KK1 0x5C4DD124U -#define KK2 0x6D703EF3U -#define KK3 0x7A6D76E9U -#define KK4 0x00000000U - -/* rotate x left n bits. */ -#define ROL(n, x) (((x) << (n)) | ((x) >> (32-(n)))) - -#define F0(x, y, z) ((x) ^ (y) ^ (z)) -#define F1(x, y, z) (((x) & (y)) | ((~x) & (z))) -#define F2(x, y, z) (((x) | (~y)) ^ (z)) -#define F3(x, y, z) (((x) & (z)) | ((y) & (~z))) -#define F4(x, y, z) ((x) ^ ((y) | (~z))) - -#define R(a, b, c, d, e, Fj, Kj, sj, rj) \ - do { \ - a = ROL(sj, a + Fj(b,c,d) + X(rj) + Kj) + e; \ - c = ROL(10, c); \ - } while(0) - -#define X(i) x[i] - -static u_int8_t PADDING[RMD160_BLOCK_LENGTH] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -void -RMD160Init(RMD160_CTX *ctx) -{ - ctx->count = 0; - ctx->state[0] = H0; - ctx->state[1] = H1; - ctx->state[2] = H2; - ctx->state[3] = H3; - ctx->state[4] = H4; -} - -void -RMD160Update(RMD160_CTX *ctx, const u_int8_t *input, size_t len) -{ - size_t have, off, need; - - have = (ctx->count / 8) % RMD160_BLOCK_LENGTH; - need = RMD160_BLOCK_LENGTH - have; - ctx->count += 8 * len; - off = 0; - - if (len >= need) { - if (have) { - memcpy(ctx->buffer + have, input, need); - RMD160Transform(ctx->state, ctx->buffer); - off = need; - have = 0; - } - /* now the buffer is empty */ - while (off + RMD160_BLOCK_LENGTH <= len) { - RMD160Transform(ctx->state, input+off); - off += RMD160_BLOCK_LENGTH; - } - } - if (off < len) - memcpy(ctx->buffer + have, input+off, len-off); -} - -void -RMD160Pad(RMD160_CTX *ctx) -{ - u_int8_t size[8]; - size_t padlen; - - PUT_64BIT_LE(size, ctx->count); - - /* - * pad to RMD160_BLOCK_LENGTH byte blocks, at least one byte from - * PADDING plus 8 bytes for the size - */ - padlen = RMD160_BLOCK_LENGTH - ((ctx->count / 8) % RMD160_BLOCK_LENGTH); - if (padlen < 1 + 8) - padlen += RMD160_BLOCK_LENGTH; - RMD160Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ - RMD160Update(ctx, size, 8); -} - -void -RMD160Final(u_int8_t digest[RMD160_DIGEST_LENGTH], RMD160_CTX *ctx) -{ - int i; - - RMD160Pad(ctx); - for (i = 0; i < 5; i++) - PUT_32BIT_LE(digest + i*4, ctx->state[i]); - memset(ctx, 0, sizeof (*ctx)); -} - -void -RMD160Transform(u_int32_t state[5], const u_int8_t block[RMD160_BLOCK_LENGTH]) -{ - u_int32_t a, b, c, d, e, aa, bb, cc, dd, ee, t, x[16]; - -#if BYTE_ORDER == LITTLE_ENDIAN - memcpy(x, block, RMD160_BLOCK_LENGTH); -#else - int i; - - for (i = 0; i < 16; i++) - x[i] = (u_int32_t)( - (u_int32_t)(block[i*4 + 0]) | - (u_int32_t)(block[i*4 + 1]) << 8 | - (u_int32_t)(block[i*4 + 2]) << 16 | - (u_int32_t)(block[i*4 + 3]) << 24); -#endif - - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - - /* Round 1 */ - R(a, b, c, d, e, F0, K0, 11, 0); - R(e, a, b, c, d, F0, K0, 14, 1); - R(d, e, a, b, c, F0, K0, 15, 2); - R(c, d, e, a, b, F0, K0, 12, 3); - R(b, c, d, e, a, F0, K0, 5, 4); - R(a, b, c, d, e, F0, K0, 8, 5); - R(e, a, b, c, d, F0, K0, 7, 6); - R(d, e, a, b, c, F0, K0, 9, 7); - R(c, d, e, a, b, F0, K0, 11, 8); - R(b, c, d, e, a, F0, K0, 13, 9); - R(a, b, c, d, e, F0, K0, 14, 10); - R(e, a, b, c, d, F0, K0, 15, 11); - R(d, e, a, b, c, F0, K0, 6, 12); - R(c, d, e, a, b, F0, K0, 7, 13); - R(b, c, d, e, a, F0, K0, 9, 14); - R(a, b, c, d, e, F0, K0, 8, 15); /* #15 */ - /* Round 2 */ - R(e, a, b, c, d, F1, K1, 7, 7); - R(d, e, a, b, c, F1, K1, 6, 4); - R(c, d, e, a, b, F1, K1, 8, 13); - R(b, c, d, e, a, F1, K1, 13, 1); - R(a, b, c, d, e, F1, K1, 11, 10); - R(e, a, b, c, d, F1, K1, 9, 6); - R(d, e, a, b, c, F1, K1, 7, 15); - R(c, d, e, a, b, F1, K1, 15, 3); - R(b, c, d, e, a, F1, K1, 7, 12); - R(a, b, c, d, e, F1, K1, 12, 0); - R(e, a, b, c, d, F1, K1, 15, 9); - R(d, e, a, b, c, F1, K1, 9, 5); - R(c, d, e, a, b, F1, K1, 11, 2); - R(b, c, d, e, a, F1, K1, 7, 14); - R(a, b, c, d, e, F1, K1, 13, 11); - R(e, a, b, c, d, F1, K1, 12, 8); /* #31 */ - /* Round 3 */ - R(d, e, a, b, c, F2, K2, 11, 3); - R(c, d, e, a, b, F2, K2, 13, 10); - R(b, c, d, e, a, F2, K2, 6, 14); - R(a, b, c, d, e, F2, K2, 7, 4); - R(e, a, b, c, d, F2, K2, 14, 9); - R(d, e, a, b, c, F2, K2, 9, 15); - R(c, d, e, a, b, F2, K2, 13, 8); - R(b, c, d, e, a, F2, K2, 15, 1); - R(a, b, c, d, e, F2, K2, 14, 2); - R(e, a, b, c, d, F2, K2, 8, 7); - R(d, e, a, b, c, F2, K2, 13, 0); - R(c, d, e, a, b, F2, K2, 6, 6); - R(b, c, d, e, a, F2, K2, 5, 13); - R(a, b, c, d, e, F2, K2, 12, 11); - R(e, a, b, c, d, F2, K2, 7, 5); - R(d, e, a, b, c, F2, K2, 5, 12); /* #47 */ - /* Round 4 */ - R(c, d, e, a, b, F3, K3, 11, 1); - R(b, c, d, e, a, F3, K3, 12, 9); - R(a, b, c, d, e, F3, K3, 14, 11); - R(e, a, b, c, d, F3, K3, 15, 10); - R(d, e, a, b, c, F3, K3, 14, 0); - R(c, d, e, a, b, F3, K3, 15, 8); - R(b, c, d, e, a, F3, K3, 9, 12); - R(a, b, c, d, e, F3, K3, 8, 4); - R(e, a, b, c, d, F3, K3, 9, 13); - R(d, e, a, b, c, F3, K3, 14, 3); - R(c, d, e, a, b, F3, K3, 5, 7); - R(b, c, d, e, a, F3, K3, 6, 15); - R(a, b, c, d, e, F3, K3, 8, 14); - R(e, a, b, c, d, F3, K3, 6, 5); - R(d, e, a, b, c, F3, K3, 5, 6); - R(c, d, e, a, b, F3, K3, 12, 2); /* #63 */ - /* Round 5 */ - R(b, c, d, e, a, F4, K4, 9, 4); - R(a, b, c, d, e, F4, K4, 15, 0); - R(e, a, b, c, d, F4, K4, 5, 5); - R(d, e, a, b, c, F4, K4, 11, 9); - R(c, d, e, a, b, F4, K4, 6, 7); - R(b, c, d, e, a, F4, K4, 8, 12); - R(a, b, c, d, e, F4, K4, 13, 2); - R(e, a, b, c, d, F4, K4, 12, 10); - R(d, e, a, b, c, F4, K4, 5, 14); - R(c, d, e, a, b, F4, K4, 12, 1); - R(b, c, d, e, a, F4, K4, 13, 3); - R(a, b, c, d, e, F4, K4, 14, 8); - R(e, a, b, c, d, F4, K4, 11, 11); - R(d, e, a, b, c, F4, K4, 8, 6); - R(c, d, e, a, b, F4, K4, 5, 15); - R(b, c, d, e, a, F4, K4, 6, 13); /* #79 */ - - aa = a ; bb = b; cc = c; dd = d; ee = e; - - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - - /* Parallel round 1 */ - R(a, b, c, d, e, F4, KK0, 8, 5); - R(e, a, b, c, d, F4, KK0, 9, 14); - R(d, e, a, b, c, F4, KK0, 9, 7); - R(c, d, e, a, b, F4, KK0, 11, 0); - R(b, c, d, e, a, F4, KK0, 13, 9); - R(a, b, c, d, e, F4, KK0, 15, 2); - R(e, a, b, c, d, F4, KK0, 15, 11); - R(d, e, a, b, c, F4, KK0, 5, 4); - R(c, d, e, a, b, F4, KK0, 7, 13); - R(b, c, d, e, a, F4, KK0, 7, 6); - R(a, b, c, d, e, F4, KK0, 8, 15); - R(e, a, b, c, d, F4, KK0, 11, 8); - R(d, e, a, b, c, F4, KK0, 14, 1); - R(c, d, e, a, b, F4, KK0, 14, 10); - R(b, c, d, e, a, F4, KK0, 12, 3); - R(a, b, c, d, e, F4, KK0, 6, 12); /* #15 */ - /* Parallel round 2 */ - R(e, a, b, c, d, F3, KK1, 9, 6); - R(d, e, a, b, c, F3, KK1, 13, 11); - R(c, d, e, a, b, F3, KK1, 15, 3); - R(b, c, d, e, a, F3, KK1, 7, 7); - R(a, b, c, d, e, F3, KK1, 12, 0); - R(e, a, b, c, d, F3, KK1, 8, 13); - R(d, e, a, b, c, F3, KK1, 9, 5); - R(c, d, e, a, b, F3, KK1, 11, 10); - R(b, c, d, e, a, F3, KK1, 7, 14); - R(a, b, c, d, e, F3, KK1, 7, 15); - R(e, a, b, c, d, F3, KK1, 12, 8); - R(d, e, a, b, c, F3, KK1, 7, 12); - R(c, d, e, a, b, F3, KK1, 6, 4); - R(b, c, d, e, a, F3, KK1, 15, 9); - R(a, b, c, d, e, F3, KK1, 13, 1); - R(e, a, b, c, d, F3, KK1, 11, 2); /* #31 */ - /* Parallel round 3 */ - R(d, e, a, b, c, F2, KK2, 9, 15); - R(c, d, e, a, b, F2, KK2, 7, 5); - R(b, c, d, e, a, F2, KK2, 15, 1); - R(a, b, c, d, e, F2, KK2, 11, 3); - R(e, a, b, c, d, F2, KK2, 8, 7); - R(d, e, a, b, c, F2, KK2, 6, 14); - R(c, d, e, a, b, F2, KK2, 6, 6); - R(b, c, d, e, a, F2, KK2, 14, 9); - R(a, b, c, d, e, F2, KK2, 12, 11); - R(e, a, b, c, d, F2, KK2, 13, 8); - R(d, e, a, b, c, F2, KK2, 5, 12); - R(c, d, e, a, b, F2, KK2, 14, 2); - R(b, c, d, e, a, F2, KK2, 13, 10); - R(a, b, c, d, e, F2, KK2, 13, 0); - R(e, a, b, c, d, F2, KK2, 7, 4); - R(d, e, a, b, c, F2, KK2, 5, 13); /* #47 */ - /* Parallel round 4 */ - R(c, d, e, a, b, F1, KK3, 15, 8); - R(b, c, d, e, a, F1, KK3, 5, 6); - R(a, b, c, d, e, F1, KK3, 8, 4); - R(e, a, b, c, d, F1, KK3, 11, 1); - R(d, e, a, b, c, F1, KK3, 14, 3); - R(c, d, e, a, b, F1, KK3, 14, 11); - R(b, c, d, e, a, F1, KK3, 6, 15); - R(a, b, c, d, e, F1, KK3, 14, 0); - R(e, a, b, c, d, F1, KK3, 6, 5); - R(d, e, a, b, c, F1, KK3, 9, 12); - R(c, d, e, a, b, F1, KK3, 12, 2); - R(b, c, d, e, a, F1, KK3, 9, 13); - R(a, b, c, d, e, F1, KK3, 12, 9); - R(e, a, b, c, d, F1, KK3, 5, 7); - R(d, e, a, b, c, F1, KK3, 15, 10); - R(c, d, e, a, b, F1, KK3, 8, 14); /* #63 */ - /* Parallel round 5 */ - R(b, c, d, e, a, F0, KK4, 8, 12); - R(a, b, c, d, e, F0, KK4, 5, 15); - R(e, a, b, c, d, F0, KK4, 12, 10); - R(d, e, a, b, c, F0, KK4, 9, 4); - R(c, d, e, a, b, F0, KK4, 12, 1); - R(b, c, d, e, a, F0, KK4, 5, 5); - R(a, b, c, d, e, F0, KK4, 14, 8); - R(e, a, b, c, d, F0, KK4, 6, 7); - R(d, e, a, b, c, F0, KK4, 8, 6); - R(c, d, e, a, b, F0, KK4, 13, 2); - R(b, c, d, e, a, F0, KK4, 6, 13); - R(a, b, c, d, e, F0, KK4, 5, 14); - R(e, a, b, c, d, F0, KK4, 15, 0); - R(d, e, a, b, c, F0, KK4, 13, 3); - R(c, d, e, a, b, F0, KK4, 11, 9); - R(b, c, d, e, a, F0, KK4, 11, 11); /* #79 */ - - t = state[1] + cc + d; - state[1] = state[2] + dd + e; - state[2] = state[3] + ee + a; - state[3] = state[4] + aa + b; - state[4] = state[0] + bb + c; - state[0] = t; -} - -#endif /* !WITH_OPENSSL */ diff --git a/openbsd-compat/rmd160.h b/openbsd-compat/rmd160.h deleted file mode 100644 index 99c1dcdc0..000000000 --- a/openbsd-compat/rmd160.h +++ /dev/null @@ -1,61 +0,0 @@ -/* $OpenBSD: rmd160.h,v 1.17 2012/12/05 23:19:57 deraadt 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. - */ -#ifndef _RMD160_H -#define _RMD160_H - -#ifndef WITH_OPENSSL - -#define RMD160_BLOCK_LENGTH 64 -#define RMD160_DIGEST_LENGTH 20 -#define RMD160_DIGEST_STRING_LENGTH (RMD160_DIGEST_LENGTH * 2 + 1) - -/* RMD160 context. */ -typedef struct RMD160Context { - u_int32_t state[5]; /* state */ - u_int64_t count; /* number of bits, mod 2^64 */ - u_int8_t buffer[RMD160_BLOCK_LENGTH]; /* input buffer */ -} RMD160_CTX; - -void RMD160Init(RMD160_CTX *); -void RMD160Transform(u_int32_t [5], const u_int8_t [RMD160_BLOCK_LENGTH]) - __attribute__((__bounded__(__minbytes__,1,5))) - __attribute__((__bounded__(__minbytes__,2,RMD160_BLOCK_LENGTH))); -void RMD160Update(RMD160_CTX *, const u_int8_t *, size_t) - __attribute__((__bounded__(__string__,2,3))); -void RMD160Pad(RMD160_CTX *); -void RMD160Final(u_int8_t [RMD160_DIGEST_LENGTH], RMD160_CTX *) - __attribute__((__bounded__(__minbytes__,1,RMD160_DIGEST_LENGTH))); -char *RMD160End(RMD160_CTX *, char *) - __attribute__((__bounded__(__minbytes__,2,RMD160_DIGEST_STRING_LENGTH))); -char *RMD160File(const char *, char *) - __attribute__((__bounded__(__minbytes__,2,RMD160_DIGEST_STRING_LENGTH))); -char *RMD160FileChunk(const char *, char *, off_t, off_t) - __attribute__((__bounded__(__minbytes__,2,RMD160_DIGEST_STRING_LENGTH))); -char *RMD160Data(const u_int8_t *, size_t, char *) - __attribute__((__bounded__(__string__,1,2))) - __attribute__((__bounded__(__minbytes__,3,RMD160_DIGEST_STRING_LENGTH))); - -#endif /* !WITH_OPENSSL */ -#endif /* _RMD160_H */ diff --git a/openbsd-compat/sha2.c b/openbsd-compat/sha2.c index e63324c99..ce936e262 100644 --- a/openbsd-compat/sha2.c +++ b/openbsd-compat/sha2.c @@ -42,10 +42,10 @@ !defined(HAVE_SHA512UPDATE) /* no-op out, similar to DEF_WEAK but only needed here */ -#define MAKE_CLONE(x, y) void __ssh_compat_make_clone_##x_##y(void); +#define MAKE_CLONE(x, y) void __ssh_compat_make_clone_##x_##y(void) #include -#include +#include "openbsd-compat/sha2.h" /* * UNROLLED TRANSFORM LOOP NOTE: diff --git a/openbsd-compat/sys-queue.h b/openbsd-compat/sys-queue.h index 5108f394c..816c15cd4 100644 --- a/openbsd-compat/sys-queue.h +++ b/openbsd-compat/sys-queue.h @@ -1,4 +1,4 @@ -/* $OpenBSD: queue.h,v 1.36 2012/04/11 13:29:14 naddy Exp $ */ +/* $OpenBSD: queue.h,v 1.45 2018/07/12 14:22:54 sashan Exp $ */ /* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ /* @@ -41,94 +41,97 @@ * Require for OS/X and other platforms that have old/broken/incomplete * . */ -#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_EMPTY +#undef CIRCLEQ_END #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_HEAD +#undef CIRCLEQ_HEAD_INITIALIZER #undef CIRCLEQ_INIT #undef CIRCLEQ_INSERT_AFTER #undef CIRCLEQ_INSERT_BEFORE #undef CIRCLEQ_INSERT_HEAD #undef CIRCLEQ_INSERT_TAIL +#undef CIRCLEQ_LAST +#undef CIRCLEQ_NEXT +#undef CIRCLEQ_PREV #undef CIRCLEQ_REMOVE #undef CIRCLEQ_REPLACE +#undef LIST_EMPTY +#undef LIST_END +#undef LIST_ENTRY +#undef LIST_FIRST +#undef LIST_FOREACH +#undef LIST_FOREACH_SAFE +#undef LIST_HEAD +#undef LIST_HEAD_INITIALIZER +#undef LIST_INIT +#undef LIST_INSERT_AFTER +#undef LIST_INSERT_BEFORE +#undef LIST_INSERT_HEAD +#undef LIST_NEXT +#undef LIST_REMOVE +#undef LIST_REPLACE +#undef SIMPLEQ_CONCAT +#undef SIMPLEQ_EMPTY +#undef SIMPLEQ_END +#undef SIMPLEQ_ENTRY +#undef SIMPLEQ_FIRST +#undef SIMPLEQ_FOREACH +#undef SIMPLEQ_FOREACH_SAFE +#undef SIMPLEQ_HEAD +#undef SIMPLEQ_HEAD_INITIALIZER +#undef SIMPLEQ_INIT +#undef SIMPLEQ_INSERT_AFTER +#undef SIMPLEQ_INSERT_HEAD +#undef SIMPLEQ_INSERT_TAIL +#undef SIMPLEQ_NEXT +#undef SIMPLEQ_REMOVE_AFTER +#undef SIMPLEQ_REMOVE_HEAD +#undef SLIST_EMPTY +#undef SLIST_END +#undef SLIST_ENTRY +#undef SLIST_FIRST +#undef SLIST_FOREACH +#undef SLIST_FOREACH_PREVPTR +#undef SLIST_FOREACH_SAFE +#undef SLIST_HEAD +#undef SLIST_HEAD_INITIALIZER +#undef SLIST_INIT +#undef SLIST_INSERT_AFTER +#undef SLIST_INSERT_HEAD +#undef SLIST_NEXT +#undef SLIST_REMOVE +#undef SLIST_REMOVE_AFTER +#undef SLIST_REMOVE_HEAD +#undef SLIST_REMOVE_NEXT +#undef TAILQ_CONCAT +#undef TAILQ_EMPTY +#undef TAILQ_END +#undef TAILQ_ENTRY +#undef TAILQ_FIRST +#undef TAILQ_FOREACH +#undef TAILQ_FOREACH_REVERSE +#undef TAILQ_FOREACH_REVERSE_SAFE +#undef TAILQ_FOREACH_SAFE +#undef TAILQ_HEAD +#undef TAILQ_HEAD_INITIALIZER +#undef TAILQ_INIT +#undef TAILQ_INSERT_AFTER +#undef TAILQ_INSERT_BEFORE +#undef TAILQ_INSERT_HEAD +#undef TAILQ_INSERT_TAIL +#undef TAILQ_LAST +#undef TAILQ_NEXT +#undef TAILQ_PREV +#undef TAILQ_REMOVE +#undef TAILQ_REPLACE /* - * This file defines five types of data structures: singly-linked lists, - * lists, simple queues, tail queues, and circular queues. + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues and XOR simple queues. * * * A singly-linked list is headed by a single forward pointer. The elements @@ -148,7 +151,7 @@ * 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 + * A simple 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 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 @@ -162,19 +165,17 @@ * 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. + * An XOR simple queue is used in the same way as a regular simple queue. + * The difference is that the head structure also includes a "cookie" that + * is XOR'd with the queue pointer (first, last or next) to generate the + * real pointer value. * * 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) +#define _Q_INVALID ((void *)-1) +#define _Q_INVALIDATE(a) (a) = _Q_INVALID #else #define _Q_INVALIDATE(a) #endif @@ -186,15 +187,15 @@ 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. */ @@ -248,8 +249,8 @@ struct { \ curelm = curelm->field.sle_next; \ curelm->field.sle_next = \ curelm->field.sle_next->field.sle_next; \ - _Q_INVALIDATE((elm)->field.sle_next); \ } \ + _Q_INVALIDATE((elm)->field.sle_next); \ } while (0) /* @@ -270,7 +271,7 @@ struct { \ } /* - * List access methods + * List access methods. */ #define LIST_FIRST(head) ((head)->lh_first) #define LIST_END(head) NULL @@ -407,6 +408,94 @@ struct { \ (head)->sqh_last = &(elm)->field.sqe_next; \ } while (0) +#define SIMPLEQ_CONCAT(head1, head2) do { \ + if (!SIMPLEQ_EMPTY((head2))) { \ + *(head1)->sqh_last = (head2)->sqh_first; \ + (head1)->sqh_last = (head2)->sqh_last; \ + SIMPLEQ_INIT((head2)); \ + } \ +} while (0) + +/* + * XOR Simple queue definitions. + */ +#define XSIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqx_first; /* first element */ \ + struct type **sqx_last; /* addr of last next element */ \ + unsigned long sqx_cookie; \ +} + +#define XSIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqx_next; /* next element */ \ +} + +/* + * XOR Simple queue access methods. + */ +#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \ + (unsigned long)(ptr))) +#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first)) +#define XSIMPLEQ_END(head) NULL +#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head)) +#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next)) + + +#define XSIMPLEQ_FOREACH(var, head, field) \ + for ((var) = XSIMPLEQ_FIRST(head); \ + (var) != XSIMPLEQ_END(head); \ + (var) = XSIMPLEQ_NEXT(head, var, field)) + +#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = XSIMPLEQ_FIRST(head); \ + (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \ + (var) = (tvar)) + +/* + * XOR Simple queue functions. + */ +#define XSIMPLEQ_INIT(head) do { \ + arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \ + (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ +} while (0) + +#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqx_next = (head)->sqx_first) == \ + XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ + (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \ +} while (0) + +#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \ + *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ +} while (0) + +#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \ + XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ + (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \ +} while (0) + +#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqx_first = XSIMPLEQ_XOR(head, \ + (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ +} while (0) + +#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ + if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \ + (elm)->field.sqx_next)->field.sqx_next) \ + == XSIMPLEQ_XOR(head, NULL)) \ + (head)->sqx_last = \ + XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ +} while (0) + + /* * Tail queue definitions. */ @@ -425,8 +514,8 @@ struct { \ struct type **tqe_prev; /* address of previous next element */ \ } -/* - * tail queue access methods +/* + * Tail queue access methods. */ #define TAILQ_FIRST(head) ((head)->tqh_first) #define TAILQ_END(head) NULL @@ -527,133 +616,13 @@ struct { \ _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); \ +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + } \ } 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_ */ +#endif /* !_SYS_QUEUE_H_ */ diff --git a/packet.c b/packet.c index 817da43b5..4bd8b4ec9 100644 --- a/packet.c +++ b/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.286 2019/06/28 13:35:04 deraadt Exp $ */ +/* $OpenBSD: packet.c,v 1.299 2021/01/27 10:05:28 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -58,7 +58,9 @@ #include #include #include +#ifdef HAVE_POLL_H #include +#endif #include #include @@ -74,7 +76,9 @@ # endif #endif +#ifdef WITH_ZLIB #include +#endif #include "xmalloc.h" #include "compat.h" @@ -148,9 +152,11 @@ struct session_state { /* Scratch buffer for packet compression/decompression. */ struct sshbuf *compression_buffer; +#ifdef WITH_ZLIB /* Incoming/outgoing compression dictionaries */ z_stream compression_in_stream; z_stream compression_out_stream; +#endif int compression_in_started; int compression_out_started; int compression_in_failures; @@ -276,7 +282,8 @@ ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx) int ssh_packet_is_rekeying(struct ssh *ssh) { - return ssh->state->rekeying || ssh->kex->done == 0; + return ssh->state->rekeying || + (ssh->kex != NULL && ssh->kex->done == 0); } /* @@ -290,13 +297,13 @@ ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out) int r; if (none == NULL) { - error("%s: cannot load cipher 'none'", __func__); + error_f("cannot load cipher 'none'"); return NULL; } if (ssh == NULL) ssh = ssh_alloc_session_state(); if (ssh == NULL) { - error("%s: could not allocate state", __func__); + error_f("could not allocate state"); return NULL; } state = ssh->state; @@ -306,7 +313,7 @@ ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out) (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)); + error_fr(r, "cipher_init failed"); free(ssh); /* XXX need ssh_free_session_state? */ return NULL; } @@ -339,6 +346,8 @@ ssh_packet_set_mux(struct ssh *ssh) { ssh->state->mux = 1; ssh->state->rekeying = 0; + kex_free(ssh->kex); + ssh->kex = NULL; } int @@ -466,19 +475,7 @@ ssh_packet_get_bytes(struct ssh *ssh, u_int64_t *ibytes, u_int64_t *obytes) 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) == -1) - 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; + return get_sock_af(ssh->state->connection_out); } /* Sets the connection into non-blocking mode. */ @@ -528,9 +525,9 @@ ssh_remote_ipaddr(struct ssh *ssh) ssh->local_ipaddr = get_local_ipaddr(sock); ssh->local_port = get_local_port(sock); } else { - ssh->remote_ipaddr = strdup("UNKNOWN"); + ssh->remote_ipaddr = xstrdup("UNKNOWN"); ssh->remote_port = 65535; - ssh->local_ipaddr = strdup("UNKNOWN"); + ssh->local_ipaddr = xstrdup("UNKNOWN"); ssh->local_port = 65535; } } @@ -607,6 +604,7 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) state->newkeys[mode] = NULL; ssh_clear_newkeys(ssh, mode); /* next keys */ } +#ifdef WITH_ZLIB /* compression state is in shared mem, so we can only release it once */ if (do_close && state->compression_buffer) { sshbuf_free(state->compression_buffer); @@ -633,6 +631,7 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) inflateEnd(stream); } } +#endif /* WITH_ZLIB */ cipher_free(state->send_context); cipher_free(state->receive_context); state->send_context = state->receive_context = NULL; @@ -643,6 +642,8 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) ssh->remote_ipaddr = NULL; free(ssh->state); ssh->state = NULL; + kex_free(ssh->kex); + ssh->kex = NULL; } } @@ -688,6 +689,7 @@ ssh_packet_init_compression(struct ssh *ssh) return 0; } +#ifdef WITH_ZLIB static int start_compression_out(struct ssh *ssh, int level) { @@ -819,6 +821,33 @@ uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) /* NOTREACHED */ } +#else /* WITH_ZLIB */ + +static int +start_compression_out(struct ssh *ssh, int level) +{ + return SSH_ERR_INTERNAL_ERROR; +} + +static int +start_compression_in(struct ssh *ssh) +{ + return SSH_ERR_INTERNAL_ERROR; +} + +static int +compress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) +{ + return SSH_ERR_INTERNAL_ERROR; +} + +static int +uncompress_buffer(struct ssh *ssh, struct sshbuf *in, struct sshbuf *out) +{ + return SSH_ERR_INTERNAL_ERROR; +} +#endif /* WITH_ZLIB */ + void ssh_clear_newkeys(struct ssh *ssh, int mode) { @@ -856,8 +885,8 @@ ssh_set_newkeys(struct ssh *ssh, int mode) max_blocks = &state->max_blocks_in; } if (state->newkeys[mode] != NULL) { - debug("%s: rekeying %s, input %llu bytes %llu blocks, " - "output %llu bytes %llu blocks", __func__, dir, + debug_f("rekeying %s, input %llu bytes %llu blocks, " + "output %llu bytes %llu blocks", dir, (unsigned long long)state->p_read.bytes, (unsigned long long)state->p_read.blocks, (unsigned long long)state->p_send.bytes, @@ -879,7 +908,7 @@ ssh_set_newkeys(struct ssh *ssh, int mode) return r; } mac->enabled = 1; - DBG(debug("%s: cipher_init_context: %s", __func__, dir)); + DBG(debug_f("cipher_init_context: %s", dir)); cipher_free(*ccp); *ccp = NULL; if ((r = cipher_init(ccp, enc->cipher, enc->key, enc->key_len, @@ -1102,8 +1131,8 @@ ssh_packet_send2_wrapped(struct ssh *ssh) 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)); + DBG(debug3_f("adding %d (len %d padlen %d extra_pad %d)", + pad, len, padlen, state->extra_pad)); tmp = padlen; padlen += pad; /* Check whether padlen calculation overflowed */ @@ -1218,7 +1247,7 @@ ssh_packet_send2(struct ssh *ssh) */ if ((need_rekey || state->rekeying) && !ssh_packet_type_is_kex(type)) { if (need_rekey) - debug3("%s: rekex triggered", __func__); + debug3_f("rekex triggered"); debug("enqueue packet: %u", type); p = calloc(1, sizeof(*p)); if (p == NULL) @@ -1260,8 +1289,7 @@ ssh_packet_send2(struct ssh *ssh) */ if (ssh_packet_need_rekeying(ssh, sshbuf_len(p->payload))) { - debug3("%s: queued packet triggered rekex", - __func__); + debug3_f("queued packet triggered rekex"); return kex_start_rekex(ssh); } debug("dequeue packet: %u", type); @@ -1329,7 +1357,7 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) } /* Wait for some data to arrive. */ for (;;) { - if (state->packet_timeout_ms != -1) { + if (state->packet_timeout_ms > 0) { ms_to_timeval(&timeout, ms_remain); monotime_tv(&start); } @@ -1341,7 +1369,7 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) r = SSH_ERR_SYSTEM_ERROR; goto out; } - if (state->packet_timeout_ms == -1) + if (state->packet_timeout_ms <= 0) continue; ms_subtract_diff(&start, &ms_remain); if (ms_remain <= 0) { @@ -1380,7 +1408,7 @@ ssh_packet_read(struct ssh *ssh) int r; if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "read"); return type; } @@ -1438,7 +1466,7 @@ ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) (r = sshbuf_get_u8(state->incoming_packet, typep)) != 0) return r; if (ssh_packet_log_type(*typep)) - debug3("%s: type %u", __func__, *typep); + debug3_f("type %u", *typep); /* sshbuf_dump(state->incoming_packet, stderr); */ /* reset for next packet */ state->packlen = 0; @@ -1669,7 +1697,7 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) /* do we need to rekey? */ if (ssh_packet_need_rekeying(ssh, 0)) { - debug3("%s: rekex triggered", __func__); + debug3_f("rekex triggered"); if ((r = kex_start_rekex(ssh)) != 0) return r; } @@ -1795,7 +1823,7 @@ ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...) (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)); + fatal_fr(r, "send DEBUG"); } void @@ -1814,6 +1842,7 @@ static void sshpkt_vfatal(struct ssh *ssh, int r, const char *fmt, va_list ap) { char *tag = NULL, remote_id[512]; + int oerrno = errno; sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); @@ -1841,6 +1870,7 @@ sshpkt_vfatal(struct ssh *ssh, int r, const char *fmt, va_list ap) case SSH_ERR_NO_HOSTKEY_ALG_MATCH: if (ssh && ssh->kex && ssh->kex->failed_choice) { ssh_packet_clear_keys(ssh); + errno = oerrno; logdie("Unable to negotiate with %s: %s. " "Their offer: %s", remote_id, ssh_err(r), ssh->kex->failed_choice); @@ -1849,14 +1879,13 @@ sshpkt_vfatal(struct ssh *ssh, int r, const char *fmt, va_list ap) default: if (vasprintf(&tag, fmt, ap) == -1) { ssh_packet_clear_keys(ssh); - logdie("%s: could not allocate failure message", - __func__); + logdie_f("could not allocate failure message"); } ssh_packet_clear_keys(ssh); - logdie("%s%sConnection %s %s: %s", + errno = oerrno; + logdie_r(r, "%s%sConnection %s %s", tag != NULL ? tag : "", tag != NULL ? ": " : "", - ssh->state->server_side ? "from" : "to", - remote_id, ssh_err(r)); + ssh->state->server_side ? "from" : "to", remote_id); } } @@ -1869,7 +1898,7 @@ sshpkt_fatal(struct ssh *ssh, int r, const char *fmt, ...) sshpkt_vfatal(ssh, r, fmt, ap); /* NOTREACHED */ va_end(ap); - logdie("%s: should have exited", __func__); + logdie_f("should have exited"); } /* @@ -1975,7 +2004,7 @@ ssh_packet_write_wait(struct ssh *ssh) timeoutp = &timeout; } for (;;) { - if (state->packet_timeout_ms != -1) { + if (state->packet_timeout_ms > 0) { ms_to_timeval(&timeout, ms_remain); monotime_tv(&start); } @@ -1985,7 +2014,7 @@ ssh_packet_write_wait(struct ssh *ssh) if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) break; - if (state->packet_timeout_ms == -1) + if (state->packet_timeout_ms <= 0) continue; ms_subtract_diff(&start, &ms_remain); if (ms_remain <= 0) { @@ -2028,30 +2057,9 @@ ssh_packet_not_very_much_data_to_write(struct ssh *ssh) 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)) == -1) - 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)) == -1) - error("setsockopt IPV6_TCLASS %d: %.100s:", - tos, strerror(errno)); - break; -# endif /* IPV6_TCLASS */ - } -#endif /* IP_TOS_IS_BROKEN */ + set_sock_tos(ssh->state->connection_in, tos); } /* Informs that the current session is interactive. Sets IP flags for that. */ @@ -2072,8 +2080,7 @@ ssh_packet_set_interactive(struct ssh *ssh, int interactive, int qos_interactive if (!ssh_packet_connection_is_on_socket(ssh)) return; set_nodelay(state->connection_in); - ssh_packet_set_tos(ssh, interactive ? qos_interactive : - qos_bulk); + ssh_packet_set_tos(ssh, interactive ? qos_interactive : qos_bulk); } /* Returns true if the current connection is interactive. */ @@ -2172,7 +2179,7 @@ ssh_packet_set_postauth(struct ssh *ssh) { int r; - debug("%s: called", __func__); + debug_f("called"); /* This was set in net child, but is not visible in user child */ ssh->state->after_authentication = 1; ssh->state->rekeying = 0; @@ -2189,9 +2196,7 @@ 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 || + if ((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 || @@ -2200,6 +2205,7 @@ kex_to_blob(struct sshbuf *m, struct kex *kex) (r = sshbuf_put_stringb(m, kex->peer)) != 0 || (r = sshbuf_put_stringb(m, kex->client_version)) != 0 || (r = sshbuf_put_stringb(m, kex->server_version)) != 0 || + (r = sshbuf_put_stringb(m, kex->session_id)) != 0 || (r = sshbuf_put_u32(m, kex->flags)) != 0) return r; return 0; @@ -2352,8 +2358,7 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp) 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 || + if ((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 || @@ -2362,6 +2367,7 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp) (r = sshbuf_get_stringb(m, kex->peer)) != 0 || (r = sshbuf_get_stringb(m, kex->client_version)) != 0 || (r = sshbuf_get_stringb(m, kex->server_version)) != 0 || + (r = sshbuf_get_stringb(m, kex->session_id)) != 0 || (r = sshbuf_get_u32(m, &kex->flags)) != 0) goto out; kex->server = 1; @@ -2406,7 +2412,7 @@ ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m) (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 + * We set the time here so that in post-auth privsep child we * count from the completion of the authentication. */ state->rekey_time = monotime(); @@ -2428,7 +2434,7 @@ ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m) if (sshbuf_len(m)) return SSH_ERR_INVALID_FORMAT; - debug3("%s: done", __func__); + debug3_f("done"); return 0; } @@ -2619,7 +2625,7 @@ ssh_packet_send_mux(struct ssh *ssh) cp = sshbuf_mutable_ptr(state->outgoing_packet); type = cp[5]; if (ssh_packet_log_type(type)) - debug3("%s: type %u", __func__, type); + debug3_f("type %u", type); /* drop everything, but the connection protocol */ if (type >= SSH2_MSG_CONNECTION_MIN && type <= SSH2_MSG_CONNECTION_MAX) { diff --git a/packet.h b/packet.h index 8ccfd2e05..c2544bd96 100644 --- a/packet.h +++ b/packet.h @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.h,v 1.91 2019/09/06 05:23:55 djm Exp $ */ +/* $OpenBSD: packet.h,v 1.92 2020/03/06 18:11:10 markus Exp $ */ /* * Author: Tatu Ylonen @@ -177,7 +177,8 @@ 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, int r, const char *fmt, ...) - __attribute__((format(printf, 3, 4))); + __attribute__((format(printf, 3, 4))) + __attribute__((noreturn)); int sshpkt_msg_ignore(struct ssh *, u_int); int sshpkt_put(struct ssh *ssh, const void *v, size_t len); diff --git a/pathnames.h b/pathnames.h index cb44caa4d..f7ca5a75a 100644 --- a/pathnames.h +++ b/pathnames.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pathnames.h,v 1.28 2018/02/23 15:58:37 markus Exp $ */ +/* $OpenBSD: pathnames.h,v 1.31 2019/11/12 19:33:08 markus Exp $ */ /* * Author: Tatu Ylonen @@ -77,6 +77,8 @@ #define _PATH_SSH_CLIENT_ID_RSA _PATH_SSH_USER_DIR "/id_rsa" #define _PATH_SSH_CLIENT_ID_ED25519 _PATH_SSH_USER_DIR "/id_ed25519" #define _PATH_SSH_CLIENT_ID_XMSS _PATH_SSH_USER_DIR "/id_xmss" +#define _PATH_SSH_CLIENT_ID_ECDSA_SK _PATH_SSH_USER_DIR "/id_ecdsa_sk" +#define _PATH_SSH_CLIENT_ID_ED25519_SK _PATH_SSH_USER_DIR "/id_ed25519_sk" /* * Configuration file in user's home directory. This file need not be @@ -132,6 +134,11 @@ #define _PATH_SSH_PKCS11_HELPER "/usr/libexec/ssh-pkcs11-helper" #endif +/* Location of ssh-sk-helper to support keys in security keys */ +#ifndef _PATH_SSH_SK_HELPER +#define _PATH_SSH_SK_HELPER "/usr/libexec/ssh-sk-helper" +#endif + /* xauth for X11 forwarding */ #ifndef _PATH_XAUTH #define _PATH_XAUTH "/usr/X11R6/bin/xauth" diff --git a/progressmeter.c b/progressmeter.c index 8f0c20092..c73d45897 100644 --- a/progressmeter.c +++ b/progressmeter.c @@ -1,4 +1,4 @@ -/* $OpenBSD: progressmeter.c,v 1.48 2019/05/03 06:06:30 dtucker Exp $ */ +/* $OpenBSD: progressmeter.c,v 1.50 2020/01/23 07:10:22 dtucker Exp $ */ /* * Copyright (c) 2003 Nils Nordman. All rights reserved. * @@ -238,7 +238,6 @@ refresh_progress_meter(int force_update) static void sig_alarm(int ignore) { - signal(SIGALRM, sig_alarm); alarm_fired = 1; alarm(UPDATE_INTERVAL); } @@ -258,8 +257,8 @@ start_progress_meter(const char *f, off_t filesize, off_t *ctr) setscreensize(); refresh_progress_meter(1); - signal(SIGALRM, sig_alarm); - signal(SIGWINCH, sig_winch); + ssh_signal(SIGALRM, sig_alarm); + ssh_signal(SIGWINCH, sig_winch); alarm(UPDATE_INTERVAL); } @@ -282,7 +281,6 @@ stop_progress_meter(void) static void sig_winch(int sig) { - signal(SIGWINCH, sig_winch); win_resized = 1; } diff --git a/readconf.c b/readconf.c index a5aaf821e..96a5596be 100644 --- a/readconf.c +++ b/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.309 2019/09/06 14:45:34 naddy Exp $ */ +/* $OpenBSD: readconf.c,v 1.352 2021/02/24 01:18:08 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -35,9 +35,9 @@ #endif #include #include -#include #include #include +#include #include #include #ifdef USE_SYSTEM_GLOB @@ -122,8 +122,6 @@ ForwardAgent no ForwardX11 no PasswordAuthentication yes - RSAAuthentication yes - RhostsRSAAuthentication yes StrictHostKeyChecking yes TcpKeepAlive no IdentityFile ~/.ssh/identity @@ -147,15 +145,16 @@ typedef enum { oHost, oMatch, oInclude, oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, oGatewayPorts, oExitOnForwardFailure, - oPasswordAuthentication, oRSAAuthentication, + oPasswordAuthentication, oChallengeResponseAuthentication, oXAuthLocation, - oIdentityFile, oHostname, oPort, oCipher, oRemoteForward, oLocalForward, + oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward, + oPermitRemoteOpen, oCertificateFile, oAddKeysToAgent, oIdentityAgent, - oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand, + oUser, oEscapeChar, oProxyCommand, oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, - oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts, - oUsePrivilegedPort, oLogFacility, oLogLevel, oCiphers, oMacs, + oTCPKeepAlive, oNumberOfPasswordPrompts, + oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs, oPubkeyAuthentication, oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, @@ -173,8 +172,9 @@ typedef enum { oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, - oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes, - oPubkeyAcceptedKeyTypes, oCASignatureAlgorithms, oProxyJump, + oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms, + oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump, + oSecurityKeyProvider, oKnownHostsCommand, oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported } OpCodes; @@ -199,6 +199,9 @@ static struct { { "afstokenpassing", oUnsupported }, { "kerberosauthentication", oUnsupported }, { "kerberostgtpassing", oUnsupported }, + { "rsaauthentication", oUnsupported }, + { "rhostsrsaauthentication", oUnsupported }, + { "compressionlevel", oUnsupported }, /* Sometimes-unsupported options */ #if defined(GSSAPI) @@ -215,9 +218,6 @@ static struct { { "smartcarddevice", oUnsupported }, { "pkcs11provider", oUnsupported }, #endif - { "rsaauthentication", oUnsupported }, - { "rhostsrsaauthentication", oUnsupported }, - { "compressionlevel", oUnsupported }, { "forwardagent", oForwardAgent }, { "forwardx11", oForwardX11 }, @@ -249,6 +249,7 @@ static struct { { "macs", oMacs }, { "remoteforward", oRemoteForward }, { "localforward", oLocalForward }, + { "permitremoteopen", oPermitRemoteOpen }, { "user", oUser }, { "host", oHost }, { "match", oMatch }, @@ -265,6 +266,7 @@ static struct { { "numberofpasswordprompts", oNumberOfPasswordPrompts }, { "syslogfacility", oLogFacility }, { "loglevel", oLogLevel }, + { "logverbose", oLogVerbose }, { "dynamicforward", oDynamicForward }, { "preferredauthentications", oPreferredAuthentications }, { "hostkeyalgorithms", oHostKeyAlgorithms }, @@ -307,14 +309,53 @@ static struct { { "revokedhostkeys", oRevokedHostKeys }, { "fingerprinthash", oFingerprintHash }, { "updatehostkeys", oUpdateHostkeys }, - { "hostbasedkeytypes", oHostbasedKeyTypes }, - { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes }, + { "hostbasedalgorithms", oHostbasedAcceptedAlgorithms }, + { "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */ + { "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms }, + { "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */ { "ignoreunknown", oIgnoreUnknown }, { "proxyjump", oProxyJump }, + { "securitykeyprovider", oSecurityKeyProvider }, + { "knownhostscommand", oKnownHostsCommand }, { NULL, oBadOption } }; +static const char *lookup_opcode_name(OpCodes code); + +const char * +kex_default_pk_alg(void) +{ + static char *pkalgs; + + if (pkalgs == NULL) { + char *all_key; + + all_key = sshkey_alg_list(0, 0, 1, ','); + pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); + free(all_key); + } + return pkalgs; +} + +char * +ssh_connection_hash(const char *thishost, const char *host, const char *portstr, + const char *user) +{ + struct ssh_digest_ctx *md; + u_char conn_hash[SSH_DIGEST_MAX_LENGTH]; + + 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, user, strlen(user)) < 0 || + ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0) + fatal_f("mux digest failed"); + ssh_digest_free(md); + return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1)); +} + /* * Adds a local TCP/IP port forward to options. Never returns if there is an * error. @@ -418,7 +459,7 @@ add_certificate_file(Options *options, const char *path, int userprovided) 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); + debug2_f("ignoring duplicate key %s", path); return; } } @@ -449,7 +490,7 @@ add_identity_file(Options *options, const char *dir, const char *filename, 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); + debug2_f("ignoring duplicate key %s", path); free(path); return; } @@ -482,7 +523,7 @@ execute_in_shell(const char *cmd) { char *shell; pid_t pid; - int devnull, status; + int status; #ifdef WINDOWS return system(cmd); @@ -496,23 +537,14 @@ execute_in_shell(const char *cmd) shell, strerror(errno)); } - /* 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); + if (stdfd_devnull(1, 1, 0) == -1) + fatal_f("stdfd_devnull failed"); closefrom(STDERR_FILENO + 1); argv[0] = shell; @@ -523,19 +555,17 @@ execute_in_shell(const char *cmd) 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); + ssh_signal(SIGTERM, SIG_DFL); kill(getpid(), SIGTERM); _exit(1); } /* Parent. */ if (pid == -1) - fatal("%s: fork: %.100s", __func__, strerror(errno)); - - close(devnull); + fatal_f("fork: %.100s", strerror(errno)); while (waitpid(pid, &status, 0) == -1) { if (errno != EINTR && errno != EAGAIN) - fatal("%s: waitpid: %s", __func__, strerror(errno)); + fatal_f("waitpid: %s", strerror(errno)); } if (!WIFEXITED(status)) { error("command '%.100s' exited abnormally", cmd); @@ -642,6 +672,8 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw, if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "exec") == 0) { + char *conn_hash_hex, *keyalias; + if (gethostname(thishost, sizeof(thishost)) == -1) fatal("gethostname: %s", strerror(errno)); strlcpy(shorthost, thishost, sizeof(shorthost)); @@ -649,11 +681,17 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw, snprintf(portstr, sizeof(portstr), "%d", port); snprintf(uidstr, sizeof(uidstr), "%llu", (unsigned long long)pw->pw_uid); + conn_hash_hex = ssh_connection_hash(thishost, host, + portstr, ruser); + keyalias = options->host_key_alias ? + options->host_key_alias : host; cmd = percent_expand(arg, + "C", conn_hash_hex, "L", shorthost, "d", pw->pw_dir, "h", host, + "k", keyalias, "l", thishost, "n", original_host, "p", portstr, @@ -661,6 +699,7 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw, "u", pw->pw_name, "i", uidstr, (char *)NULL); + free(conn_hash_hex); if (result != 1) { /* skip execution if prior predicate failed */ debug3("%.200s line %d: skipped exec " @@ -707,7 +746,7 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw, static void rm_env(Options *options, const char *arg, const char *filename, int linenum) { - int i, j; + int i, j, onum_send_env = options->num_send_env; char *cp; /* Remove an environment variable */ @@ -730,6 +769,11 @@ rm_env(Options *options, const char *arg, const char *filename, int linenum) options->num_send_env--; /* NB. don't increment i */ } + if (onum_send_env != options->num_send_env) { + options->send_env = xrecallocarray(options->send_env, + onum_send_env, options->num_send_env, + sizeof(*options->send_env)); + } } /* @@ -833,6 +877,30 @@ static const struct multistate multistate_canonicalizehostname[] = { { "always", SSH_CANONICALISE_ALWAYS }, { NULL, -1 } }; +static const struct multistate multistate_compression[] = { +#ifdef WITH_ZLIB + { "yes", COMP_ZLIB }, +#endif + { "no", COMP_NONE }, + { NULL, -1 } +}; + +static int +parse_multistate_value(const char *arg, const char *filename, int linenum, + const struct multistate *multistate_ptr) +{ + int i; + + if (!arg || *arg == '\0') { + error("%s line %d: missing argument.", filename, linenum); + return -1; + } + for (i = 0; multistate_ptr[i].key != NULL; i++) { + if (strcasecmp(arg, multistate_ptr[i].key) == 0) + return multistate_ptr[i].value; + } + return -1; +} /* * Processes a single option line as used in the configuration files. This @@ -853,9 +921,9 @@ 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 *want_final_pass, int depth) { - char *s, **charptr, *endofnumber, *keyword, *arg, *arg2; - char **cpptr, fwdarg[256]; - u_int i, *uintptr, max_entries = 0; + char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, *p, ch; + char **cpptr, ***cppptr, fwdarg[256]; + u_int i, *uintptr, uvalue, max_entries = 0; int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0; int remotefwd, dynamicfwd; LogLevel *log_level_ptr; @@ -911,44 +979,67 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, intptr = &options->connection_timeout; parse_time: arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%s line %d: missing time value.", + if (!arg || *arg == '\0') { + error("%s line %d: missing time value.", filename, linenum); + return -1; + } if (strcmp(arg, "none") == 0) value = -1; - else if ((value = convtime(arg)) == -1) - fatal("%s line %d: invalid time value.", + else if ((value = convtime(arg)) == -1) { + error("%s line %d: invalid time value.", filename, linenum); + return -1; + } 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.", + if (!arg || *arg == '\0') { + error("%s line %d: missing argument.", filename, linenum); + return -1; + } + value = -1; + multistate_ptr = multistate_flag; 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 (value != -1) { + if (*activep && *intptr == -1) + *intptr = value; + break; + } + /* ForwardAgent wasn't 'yes' or 'no', assume a path */ if (*activep && *intptr == -1) - *intptr = value; - break; + *intptr = 1; + + charptr = &options->forward_agent_sock_path; + goto parse_agent_path; case oForwardX11: intptr = &options->forward_x11; - goto parse_flag; + parse_flag: + multistate_ptr = multistate_flag; + parse_multistate: + arg = strdelim(&s); + if ((value = parse_multistate_value(arg, filename, linenum, + multistate_ptr)) == -1) { + error("%s line %d: unsupported option \"%s\".", + filename, linenum, arg); + return -1; + } + if (*activep && *intptr == -1) + *intptr = value; + break; case oForwardX11Trusted: intptr = &options->forward_x11_trusted; @@ -1018,7 +1109,8 @@ parse_time: case oCompression: intptr = &options->compression; - goto parse_flag; + multistate_ptr = multistate_compression; + goto parse_multistate; case oTCPKeepAlive: intptr = &options->tcp_keep_alive; @@ -1034,18 +1126,24 @@ parse_time: case oRekeyLimit: arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, + if (!arg || *arg == '\0') { + error("%.200s line %d: Missing argument.", filename, linenum); + return -1; + } if (strcmp(arg, "default") == 0) { val64 = 0; } else { - if (scan_scaled(arg, &val64) == -1) - fatal("%.200s line %d: Bad number '%s': %s", + if (scan_scaled(arg, &val64) == -1) { + error("%.200s line %d: Bad number '%s': %s", filename, linenum, arg, strerror(errno)); - if (val64 != 0 && val64 < 16) - fatal("%.200s line %d: RekeyLimit too small", + return -1; + } + if (val64 != 0 && val64 < 16) { + error("%.200s line %d: RekeyLimit too small", filename, linenum); + return -1; + } } if (*activep && options->rekey_limit == -1) options->rekey_limit = val64; @@ -1061,13 +1159,19 @@ parse_time: case oIdentityFile: arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); + if (!arg || *arg == '\0') { + error("%.200s line %d: Missing argument.", + filename, linenum); + return -1; + } 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); + if (*intptr >= SSH_MAX_IDENTITY_FILES) { + error("%.200s line %d: Too many identity files " + "specified (max %d).", filename, linenum, + SSH_MAX_IDENTITY_FILES); + return -1; + } add_identity_file(options, NULL, arg, flags & SSHCONF_USERCONF); } @@ -1075,16 +1179,19 @@ parse_time: case oCertificateFile: arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", + if (!arg || *arg == '\0') { + error("%.200s line %d: Missing argument.", filename, linenum); + return -1; + } if (*activep) { intptr = &options->num_certificate_files; if (*intptr >= SSH_MAX_CERTIFICATE_FILES) { - fatal("%.200s line %d: Too many certificate " + error("%.200s line %d: Too many certificate " "files specified (max %d).", filename, linenum, SSH_MAX_CERTIFICATE_FILES); + return -1; } add_certificate_file(options, arg, flags & SSHCONF_USERCONF); @@ -1099,9 +1206,11 @@ parse_time: charptr = &options->user; parse_string: arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", + if (!arg || *arg == '\0') { + error("%.200s line %d: Missing argument.", filename, linenum); + return -1; + } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; @@ -1113,10 +1222,11 @@ parse_string: 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); + if ((*uintptr) >= max_entries) { + error("%s line %d: too many known " + "hosts files.", filename, linenum); + return -1; + } cpptr[(*uintptr)++] = xstrdup(arg); } } @@ -1152,14 +1262,25 @@ parse_char_array: charptr = &options->pkcs11_provider; goto parse_string; + case oSecurityKeyProvider: + charptr = &options->sk_provider; + goto parse_string; + + case oKnownHostsCommand: + charptr = &options->known_hosts_command; + goto parse_command; + 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); + if (s == NULL) { + error("%.200s line %d: Missing argument.", + filename, linenum); + return -1; + } len = strspn(s, WHITESPACE "="); if (*activep && *charptr == NULL) *charptr = xstrdup(s + len); @@ -1167,25 +1288,31 @@ parse_command: case oProxyJump: if (s == NULL) { - fatal("%.200s line %d: Missing argument.", + error("%.200s line %d: Missing argument.", filename, linenum); + return -1; } len = strspn(s, WHITESPACE "="); if (parse_jump(s + len, options, *activep) == -1) { - fatal("%.200s line %d: Invalid ProxyJump \"%s\"", + error("%.200s line %d: Invalid ProxyJump \"%s\"", filename, linenum, s + len); + return -1; } return 0; case oPort: arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", + if (!arg || *arg == '\0') { + error("%.200s line %d: Missing argument.", filename, linenum); + return -1; + } value = a2port(arg); - if (value <= 0) - fatal("%.200s line %d: Bad port '%s'.", + if (value <= 0) { + error("%.200s line %d: Bad port '%s'.", filename, linenum, arg); + return -1; + } if (*activep && options->port == -1) options->port = value; break; @@ -1194,78 +1321,100 @@ parse_command: intptr = &options->connection_attempts; parse_int: arg = strdelim(&s); - if ((errstr = atoi_err(arg, &value)) != NULL) - fatal("%s line %d: integer value %s.", + if ((errstr = atoi_err(arg, &value)) != NULL) { + error("%s line %d: integer value %s.", filename, linenum, errstr); + return -1; + } 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 || *arg == '\0') { + error("%.200s line %d: Missing argument.", + filename, linenum); + return -1; + } if (*arg != '-' && - !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) - fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.", + !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){ + error("%.200s line %d: Bad SSH2 cipher spec '%s'.", filename, linenum, arg ? arg : ""); + return -1; + } 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 || *arg == '\0') { + error("%.200s line %d: Missing argument.", + filename, linenum); + return -1; + } if (*arg != '-' && - !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) - fatal("%.200s line %d: Bad SSH2 MAC spec '%s'.", + !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) { + error("%.200s line %d: Bad SSH2 MAC spec '%s'.", filename, linenum, arg ? arg : ""); + return -1; + } 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.", + if (!arg || *arg == '\0') { + error("%.200s line %d: Missing argument.", filename, linenum); + return -1; + } if (*arg != '-' && !kex_names_valid(*arg == '+' || *arg == '^' ? - arg + 1 : arg)) - fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.", + arg + 1 : arg)) { + error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.", filename, linenum, arg ? arg : ""); + return -1; + } if (*activep && options->kex_algorithms == NULL) options->kex_algorithms = xstrdup(arg); break; case oHostKeyAlgorithms: charptr = &options->hostkeyalgorithms; -parse_keytypes: +parse_pubkey_algos: arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", + if (!arg || *arg == '\0') { + error("%.200s line %d: Missing argument.", filename, linenum); + return -1; + } if (*arg != '-' && !sshkey_names_valid2(*arg == '+' || *arg == '^' ? - arg + 1 : arg, 1)) - fatal("%s line %d: Bad key types '%s'.", - filename, linenum, arg ? arg : ""); + arg + 1 : arg, 1)) { + error("%s line %d: Bad key types '%s'.", + filename, linenum, arg ? arg : ""); + return -1; + } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case oCASignatureAlgorithms: charptr = &options->ca_sign_algorithms; - goto parse_keytypes; + goto parse_pubkey_algos; 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'", + if (value == SYSLOG_LEVEL_NOT_SET) { + error("%.200s line %d: unsupported log level '%s'", filename, linenum, arg ? arg : ""); + return -1; + } if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) *log_level_ptr = (LogLevel) value; break; @@ -1274,20 +1423,36 @@ parse_keytypes: 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'", + if (value == SYSLOG_FACILITY_NOT_SET) { + error("%.200s line %d: unsupported log facility '%s'", filename, linenum, arg ? arg : ""); + return -1; + } if (*log_facility_ptr == -1) *log_facility_ptr = (SyslogFacility) value; break; + case oLogVerbose: + cppptr = &options->log_verbose; + uintptr = &options->num_log_verbose; + if (*activep && *uintptr == 0) { + while ((arg = strdelim(&s)) != NULL && *arg != '\0') { + *cppptr = xrecallocarray(*cppptr, *uintptr, + *uintptr + 1, sizeof(**cppptr)); + (*cppptr)[(*uintptr)++] = xstrdup(arg); + } + } + return 0; + case oLocalForward: case oRemoteForward: case oDynamicForward: arg = strdelim(&s); - if (arg == NULL || *arg == '\0') - fatal("%.200s line %d: Missing port argument.", + if (!arg || *arg == '\0') { + error("%.200s line %d: Missing argument.", filename, linenum); + return -1; + } remotefwd = (opcode == oRemoteForward); dynamicfwd = (opcode == oDynamicForward); @@ -1297,9 +1462,11 @@ parse_keytypes: if (arg2 == NULL || *arg2 == '\0') { if (remotefwd) dynamicfwd = 1; - else - fatal("%.200s line %d: Missing target " + else { + error("%.200s line %d: Missing target " "argument.", filename, linenum); + return -1; + } } else { /* construct a string for parse_forward */ snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, @@ -1309,9 +1476,11 @@ parse_keytypes: if (dynamicfwd) strlcpy(fwdarg, arg, sizeof(fwdarg)); - if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) - fatal("%.200s line %d: Bad forwarding specification.", + if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) { + error("%.200s line %d: Bad forwarding specification.", filename, linenum); + return -1; + } if (*activep) { if (remotefwd) { @@ -1322,14 +1491,61 @@ parse_keytypes: } break; + case oPermitRemoteOpen: + uintptr = &options->num_permitted_remote_opens; + cppptr = &options->permitted_remote_opens; + arg = strdelim(&s); + 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; + *cppptr = xcalloc(1, sizeof(**cppptr)); + (*cppptr)[0] = xstrdup(arg); + } + break; + } + for (; arg != NULL && *arg != '\0'; arg = strdelim(&s)) { + arg2 = xstrdup(arg); + 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); + /* + * don't want to use permitopen_port to avoid + * dependency on channels.[ch] here. + */ + if (arg == NULL || + (strcmp(arg, "*") != 0 && a2port(arg) <= 0)) { + fatal("%s line %d: bad port number in %s", + filename, linenum, + lookup_opcode_name(opcode)); + } + if (*activep && uvalue == 0) { + opt_array_append(filename, linenum, + lookup_opcode_name(opcode), + cppptr, uintptr, arg2); + } + free(arg2); + } + break; + case oClearAllForwardings: intptr = &options->clear_forwardings; goto parse_flag; case oHost: - if (cmdline) - fatal("Host directive not supported as a command-line " + if (cmdline) { + error("Host directive not supported as a command-line " "option"); + return -1; + } *activep = 0; arg2 = NULL; while ((arg = strdelim(&s)) != NULL && *arg != '\0') { @@ -1359,23 +1575,30 @@ parse_keytypes: return 0; case oMatch: - if (cmdline) - fatal("Host directive not supported as a command-line " + if (cmdline) { + error("Host directive not supported as a command-line " "option"); + return -1; + } value = match_cfg_line(options, &s, pw, host, original_host, flags & SSHCONF_FINAL, want_final_pass, filename, linenum); - if (value < 0) - fatal("%.200s line %d: Bad Match condition", filename, + if (value < 0) { + error("%.200s line %d: Bad Match condition", filename, linenum); + return -1; + } *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 (!arg || *arg == '\0') { + error("%.200s line %d: Missing argument.", + filename, linenum); + return -1; + } if (strcmp(arg, "none") == 0) value = SSH_ESCAPECHAR_NONE; else if (arg[1] == '\0') @@ -1384,10 +1607,9 @@ parse_keytypes: (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) value = (u_char) arg[1] & 31; else { - fatal("%.200s line %d: Bad escape character.", + error("%.200s line %d: Bad escape character.", filename, linenum); - /* NOTREACHED */ - value = 0; /* Avoid compiler warning. */ + return -1; } if (*activep && *intptr == -1) *intptr = value; @@ -1416,9 +1638,11 @@ parse_keytypes: case oSendEnv: while ((arg = strdelim(&s)) != NULL && *arg != '\0') { - if (strchr(arg, '=') != NULL) - fatal("%s line %d: Invalid environment name.", + if (strchr(arg, '=') != NULL) { + error("%s line %d: Invalid environment name.", filename, linenum); + return -1; + } if (!*activep) continue; if (*arg == '-') { @@ -1427,9 +1651,11 @@ parse_keytypes: continue; } else { /* Adding an env var */ - if (options->num_send_env >= INT_MAX) - fatal("%s line %d: too many send env.", + if (options->num_send_env >= INT_MAX) { + error("%s line %d: too many send env.", filename, linenum); + return -1; + } options->send_env = xrecallocarray( options->send_env, options->num_send_env, options->num_send_env + 1, @@ -1443,15 +1669,19 @@ parse_keytypes: case oSetEnv: value = options->num_setenv; while ((arg = strdelimw(&s)) != NULL && *arg != '\0') { - if (strchr(arg, '=') == NULL) - fatal("%s line %d: Invalid SetEnv.", + if (strchr(arg, '=') == NULL) { + error("%s line %d: Invalid SetEnv.", filename, linenum); + return -1; + } if (!*activep || value != 0) continue; /* Adding a setenv var */ - if (options->num_setenv >= INT_MAX) - fatal("%s line %d: too many SetEnv.", + if (options->num_setenv >= INT_MAX) { + error("%s line %d: too many SetEnv.", filename, linenum); + return -1; + } options->setenv = xrecallocarray( options->setenv, options->num_setenv, options->num_setenv + 1, sizeof(*options->setenv)); @@ -1472,9 +1702,11 @@ parse_keytypes: /* 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" + if (!arg || *arg == '\0') { + error("%.200s line %d: Missing ControlPersist" " argument.", filename, linenum); + return -1; + } value = 0; value2 = 0; /* timeout */ if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) @@ -1483,9 +1715,11 @@ parse_keytypes: value = 1; else if ((value2 = convtime(arg)) >= 0) value = 1; - else - fatal("%.200s line %d: Bad ControlPersist argument.", + else { + error("%.200s line %d: Bad ControlPersist argument.", filename, linenum); + return -1; + } if (*activep && *intptr == -1) { *intptr = value; options->control_persist_timeout = value2; @@ -1503,11 +1737,17 @@ parse_keytypes: case oTunnelDevice: arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", filename, linenum); + if (!arg || *arg == '\0') { + error("%.200s line %d: Missing argument.", + filename, linenum); + return -1; + } value = a2tun(arg, &value2); - if (value == SSH_TUNID_ERR) - fatal("%.200s line %d: Bad tun device.", filename, linenum); + if (value == SSH_TUNID_ERR) { + error("%.200s line %d: Bad tun device.", + filename, linenum); + return -1; + } if (*activep) { options->tun_local = value; options->tun_remote = value2; @@ -1531,9 +1771,11 @@ parse_keytypes: goto parse_flag; case oInclude: - if (cmdline) - fatal("Include directive not supported as a " + if (cmdline) { + error("Include directive not supported as a " "command-line option"); + return -1; + } value = 0; while ((arg = strdelim(&s)) != NULL && *arg != '\0') { /* @@ -1543,9 +1785,11 @@ parse_keytypes: * 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.", + if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) { + error("%.200s line %d: bad include path %s.", filename, linenum, arg); + return -1; + } if (!path_absolute(arg) && *arg != '~') { xasprintf(&arg2, "%s/%s", (flags & SSHCONF_USERCONF) ? @@ -1563,12 +1807,14 @@ parse_keytypes: "files",filename, linenum, arg2); free(arg2); continue; - } else if (r != 0 || gl.gl_pathc < 0) - fatal("%.200s line %d: glob failed for %s.", + } else if (r != 0) { + error("%.200s line %d: glob failed for %s.", filename, linenum, arg2); + return -1; + } free(arg2); oactive = *activep; - for (i = 0; i < (u_int)gl.gl_pathc; i++) { + for (i = 0; i < gl.gl_pathc; i++) { debug3("%.200s line %d: Including file %s " "depth %d%s", filename, linenum, gl.gl_pathv[i], depth, @@ -1579,9 +1825,11 @@ parse_keytypes: (oactive ? 0 : SSHCONF_NEVERMATCH), activep, want_final_pass, depth + 1); if (r != 1 && errno != ENOENT) { - fatal("Can't open user config file " + error("Can't open user config file " "%.100s: %.100s", gl.gl_pathv[i], strerror(errno)); + globfree(&gl); + return -1; } /* * don't let Match in includes clobber the @@ -1599,15 +1847,19 @@ parse_keytypes: case oIPQoS: arg = strdelim(&s); - if ((value = parse_ipqos(arg)) == -1) - fatal("%s line %d: Bad IPQoS value: %s", + if ((value = parse_ipqos(arg)) == -1) { + error("%s line %d: Bad IPQoS value: %s", filename, linenum, arg); + return -1; + } arg = strdelim(&s); if (arg == NULL) value2 = value; - else if ((value2 = parse_ipqos(arg)) == -1) - fatal("%s line %d: Bad IPQoS value: %s", + else if ((value2 = parse_ipqos(arg)) == -1) { + error("%s line %d: Bad IPQoS value: %s", filename, linenum, arg); + return -1; + } if (*activep) { options->ip_qos_interactive = value; options->ip_qos_bulk = value2; @@ -1631,14 +1883,18 @@ parse_keytypes: 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, + error("%s line %d: %s", filename, linenum, errstr); + return -1; } if (!*activep || value) continue; - if (options->num_canonical_domains >= MAX_CANON_DOMAINS) - fatal("%s line %d: too many hostname suffixes.", + if (options->num_canonical_domains >= + MAX_CANON_DOMAINS) { + error("%s line %d: too many hostname suffixes.", filename, linenum); + return -1; + } options->canonical_domains[ options->num_canonical_domains++] = xstrdup(arg); } @@ -1654,18 +1910,22 @@ parse_keytypes: lowercase(arg); if ((arg2 = strchr(arg, ':')) == NULL || arg2[1] == '\0') { - fatal("%s line %d: " + error("%s line %d: " "Invalid permitted CNAME \"%s\"", filename, linenum, arg); + return -1; } *arg2 = '\0'; arg2++; } if (!*activep || value) continue; - if (options->num_permitted_cnames >= MAX_CANON_DOMAINS) - fatal("%s line %d: too many permitted CNAMEs.", + if (options->num_permitted_cnames >= + MAX_CANON_DOMAINS) { + error("%s line %d: too many permitted CNAMEs.", filename, linenum); + return -1; + } cname = options->permitted_cnames + options->num_permitted_cnames++; cname->source_list = xstrdup(arg); @@ -1688,12 +1948,17 @@ parse_keytypes: case oStreamLocalBindMask: arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum); + if (!arg || *arg == '\0') { + error("%.200s line %d: Missing StreamLocalBindMask " + "argument.", filename, linenum); + return -1; + } /* 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); + if (arg == endofnumber || value < 0 || value > 0777) { + error("%.200s line %d: Bad mask.", filename, linenum); + return -1; + } options->fwd_opts.streamlocal_bind_mask = (mode_t)value; break; @@ -1708,12 +1973,16 @@ parse_keytypes: case oFingerprintHash: intptr = &options->fingerprint_hash; arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", + if (!arg || *arg == '\0') { + error("%.200s line %d: Missing argument.", filename, linenum); - if ((value = ssh_digest_alg_by_name(arg)) == -1) - fatal("%.200s line %d: Invalid hash algorithm \"%s\".", + return -1; + } + if ((value = ssh_digest_alg_by_name(arg)) == -1) { + error("%.200s line %d: Invalid hash algorithm \"%s\".", filename, linenum, arg); + return -1; + } if (*activep && *intptr == -1) *intptr = value; break; @@ -1723,29 +1992,69 @@ parse_keytypes: multistate_ptr = multistate_yesnoask; goto parse_multistate; - case oHostbasedKeyTypes: - charptr = &options->hostbased_key_types; - goto parse_keytypes; + case oHostbasedAcceptedAlgorithms: + charptr = &options->hostbased_accepted_algos; + goto parse_pubkey_algos; - case oPubkeyAcceptedKeyTypes: - charptr = &options->pubkey_key_types; - goto parse_keytypes; + case oPubkeyAcceptedAlgorithms: + charptr = &options->pubkey_accepted_algos; + goto parse_pubkey_algos; case oAddKeysToAgent: - intptr = &options->add_keys_to_agent; - multistate_ptr = multistate_yesnoaskconfirm; - goto parse_multistate; + arg = strdelim(&s); + arg2 = strdelim(&s); + value = parse_multistate_value(arg, filename, linenum, + multistate_yesnoaskconfirm); + value2 = 0; /* unlimited lifespan by default */ + if (value == 3 && arg2 != NULL) { + /* allow "AddKeysToAgent confirm 5m" */ + if ((value2 = convtime(arg2)) == -1 || + value2 > INT_MAX) { + error("%s line %d: invalid time value.", + filename, linenum); + return -1; + } + } else if (value == -1 && arg2 == NULL) { + if ((value2 = convtime(arg)) == -1 || + value2 > INT_MAX) { + error("%s line %d: unsupported option", + filename, linenum); + return -1; + } + value = 1; /* yes */ + } else if (value == -1 || arg2 != NULL) { + error("%s line %d: unsupported option", + filename, linenum); + return -1; + } + if (*activep && options->add_keys_to_agent == -1) { + options->add_keys_to_agent = value; + options->add_keys_to_agent_lifespan = value2; + } + break; case oIdentityAgent: charptr = &options->identity_agent; arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing argument.", + if (!arg || *arg == '\0') { + error("%.200s line %d: Missing argument.", filename, linenum); + return -1; + } + parse_agent_path: /* 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.", + if ((arg2 = dollar_expand(&r, arg)) == NULL || r) { + error("%.200s line %d: Invalid environment expansion " + "%s.", filename, linenum, arg); + return -1; + } + free(arg2); + /* check for legacy environment format */ + if (arg[0] == '$' && arg[1] != '{' && + !valid_env_name(arg + 1)) { + error("%.200s line %d: Invalid environment name %s.", filename, linenum, arg); + return -1; } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); @@ -1762,13 +2071,15 @@ parse_keytypes: return 0; default: - fatal("%s: Unimplemented opcode %d", __func__, opcode); + error("%s line %d: Unimplemented opcode %d", + filename, linenum, 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\".", + error("%.200s line %d: garbage at end of line; \"%.200s\".", filename, linenum, arg); + return -1; } return 0; } @@ -1796,7 +2107,7 @@ read_config_file_depth(const char *filename, struct passwd *pw, int flags, int *activep, int *want_final_pass, int depth) { FILE *f; - char *line = NULL; + char *cp, *line = NULL; size_t linesize = 0; int linenum; int bad_options = 0; @@ -1838,6 +2149,13 @@ read_config_file_depth(const char *filename, struct passwd *pw, while (getline(&line, &linesize, f) != -1) { /* Update line number counter. */ linenum++; + /* + * 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) + *cp = '\0'; if (process_config_line_depth(options, pw, host, original_host, line, filename, linenum, activep, flags, want_final_pass, depth) != 0) @@ -1870,6 +2188,7 @@ initialize_options(Options * options) { memset(options, 'X', sizeof(*options)); options->forward_agent = -1; + options->forward_agent_sock_path = NULL; options->forward_x11 = -1; options->forward_x11_trusted = -1; options->forward_x11_timeout = -1; @@ -1905,7 +2224,9 @@ initialize_options(Options * options) options->hostkeyalgorithms = NULL; options->ca_sign_algorithms = NULL; options->num_identity_files = 0; + memset(options->identity_keys, 0, sizeof(options->identity_keys)); options->num_certificate_files = 0; + memset(options->certificates, 0, sizeof(options->certificates)); options->hostname = NULL; options->host_key_alias = NULL; options->proxy_command = NULL; @@ -1921,12 +2242,17 @@ initialize_options(Options * options) options->num_local_forwards = 0; options->remote_forwards = NULL; options->num_remote_forwards = 0; + options->permitted_remote_opens = NULL; + options->num_permitted_remote_opens = 0; options->log_facility = SYSLOG_FACILITY_NOT_SET; options->log_level = SYSLOG_LEVEL_NOT_SET; + options->num_log_verbose = 0; + options->log_verbose = NULL; options->preferred_authentications = NULL; options->bind_address = NULL; options->bind_interface = NULL; options->pkcs11_provider = NULL; + options->sk_provider = NULL; options->enable_ssh_keysign = - 1; options->no_host_authentication_for_localhost = - 1; options->identities_only = - 1; @@ -1951,6 +2277,7 @@ initialize_options(Options * options) options->permit_local_command = -1; options->remote_command = NULL; options->add_keys_to_agent = -1; + options->add_keys_to_agent_lifespan = -1; options->identity_agent = NULL; options->visual_host_key = -1; options->ip_qos_interactive = -1; @@ -1966,8 +2293,9 @@ initialize_options(Options * options) options->revoked_host_keys = NULL; options->fingerprint_hash = -1; options->update_hostkeys = -1; - options->hostbased_key_types = NULL; - options->pubkey_key_types = NULL; + options->hostbased_accepted_algos = NULL; + options->pubkey_accepted_algos = NULL; + options->known_hosts_command = NULL; } /* @@ -1989,11 +2317,12 @@ fill_default_options_for_canonicalization(Options *options) * Called after processing other sources of option data, this fills those * options for which no value has been specified with their default values. */ -void +int fill_default_options(Options * options) { char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; - int r; + char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; + int ret = 0, r; if (options->forward_agent == -1) options->forward_agent = 0; @@ -2017,7 +2346,7 @@ fill_default_options(Options * options) clear_forwardings(options); if (options->xauth_location == NULL) - options->xauth_location = _PATH_XAUTH; + options->xauth_location = xstrdup(_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) @@ -2041,7 +2370,7 @@ fill_default_options(Options * options) if (options->batch_mode == -1) options->batch_mode = 0; if (options->check_host_ip == -1) - options->check_host_ip = 1; + options->check_host_ip = 0; if (options->strict_host_key_checking == -1) options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK; if (options->compression == -1) @@ -2057,16 +2386,22 @@ fill_default_options(Options * options) 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) + if (options->add_keys_to_agent == -1) { options->add_keys_to_agent = 0; + options->add_keys_to_agent_lifespan = 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); + add_identity_file(options, "~/", + _PATH_SSH_CLIENT_ID_ECDSA_SK, 0); #endif add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ED25519, 0); + add_identity_file(options, "~/", + _PATH_SSH_CLIENT_ID_ED25519_SK, 0); add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0); } if (options->escape_char == -1) @@ -2077,6 +2412,15 @@ fill_default_options(Options * options) options->system_hostfiles[options->num_system_hostfiles++] = xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); } + if (options->update_hostkeys == -1) { + if (options->verify_host_key_dns <= 0 && + (options->num_user_hostfiles == 0 || + (options->num_user_hostfiles == 1 && strcmp(options-> + user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0))) + options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES; + else + options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO; + } if (options->num_user_hostfiles == 0) { options->user_hostfiles[options->num_user_hostfiles++] = xstrdup(_PATH_SSH_USER_HOSTFILE); @@ -2137,8 +2481,13 @@ fill_default_options(Options * options) 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; +#ifdef ENABLE_SK_INTERNAL + if (options->sk_provider == NULL) + options->sk_provider = xstrdup("internal"); +#else + if (options->sk_provider == NULL) + options->sk_provider = xstrdup("$SSH_SK_PROVIDER"); +#endif /* Expand KEX name lists */ all_cipher = cipher_alg_list(',', 0); @@ -2146,24 +2495,27 @@ fill_default_options(Options * options) all_kex = kex_alg_list(','); all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); + /* remove unsupported algos from default lists */ + def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher); + def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac); + def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex); + def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); + def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); #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)); \ + defaults, all)) != 0) { \ + error_fr(r, "%s", #what); \ + goto fail; \ + } \ } while (0) - 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); + ASSEMBLE(ciphers, def_cipher, all_cipher); + ASSEMBLE(macs, def_mac, all_mac); + ASSEMBLE(kex_algorithms, def_kex, all_kex); + ASSEMBLE(hostbased_accepted_algos, def_key, all_key); + ASSEMBLE(pubkey_accepted_algos, def_key, all_key); + ASSEMBLE(ca_sign_algorithms, def_sig, 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 { \ @@ -2178,6 +2530,8 @@ fill_default_options(Options * options) CLEAR_ON_NONE(options->control_path); CLEAR_ON_NONE(options->revoked_host_keys); CLEAR_ON_NONE(options->pkcs11_provider); + CLEAR_ON_NONE(options->sk_provider); + CLEAR_ON_NONE(options->known_hosts_command); if (options->jump_host != NULL && strcmp(options->jump_host, "none") == 0 && options->jump_port == 0 && options->jump_user == NULL) { @@ -2189,6 +2543,103 @@ fill_default_options(Options * options) /* 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 */ + + /* success */ + ret = 0; + fail: + free(all_cipher); + free(all_mac); + free(all_kex); + free(all_key); + free(all_sig); + free(def_cipher); + free(def_mac); + free(def_kex); + free(def_key); + free(def_sig); + return ret; +} + +void +free_options(Options *o) +{ + int i; + + if (o == NULL) + return; + +#define FREE_ARRAY(type, n, a) \ + do { \ + type _i; \ + for (_i = 0; _i < (n); _i++) \ + free((a)[_i]); \ + } while (0) + + free(o->forward_agent_sock_path); + free(o->xauth_location); + FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose); + free(o->log_verbose); + free(o->ciphers); + free(o->macs); + free(o->hostkeyalgorithms); + free(o->kex_algorithms); + free(o->ca_sign_algorithms); + free(o->hostname); + free(o->host_key_alias); + free(o->proxy_command); + free(o->user); + FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles); + FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles); + free(o->preferred_authentications); + free(o->bind_address); + free(o->bind_interface); + free(o->pkcs11_provider); + free(o->sk_provider); + for (i = 0; i < o->num_identity_files; i++) { + free(o->identity_files[i]); + sshkey_free(o->identity_keys[i]); + } + for (i = 0; i < o->num_certificate_files; i++) { + free(o->certificate_files[i]); + sshkey_free(o->certificates[i]); + } + free(o->identity_agent); + for (i = 0; i < o->num_local_forwards; i++) { + free(o->local_forwards[i].listen_host); + free(o->local_forwards[i].listen_path); + free(o->local_forwards[i].connect_host); + free(o->local_forwards[i].connect_path); + } + free(o->local_forwards); + for (i = 0; i < o->num_remote_forwards; i++) { + free(o->remote_forwards[i].listen_host); + free(o->remote_forwards[i].listen_path); + free(o->remote_forwards[i].connect_host); + free(o->remote_forwards[i].connect_path); + } + free(o->remote_forwards); + free(o->stdio_forward_host); + FREE_ARRAY(int, o->num_send_env, o->send_env); + free(o->send_env); + FREE_ARRAY(int, o->num_setenv, o->setenv); + free(o->setenv); + free(o->control_path); + free(o->local_command); + free(o->remote_command); + FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains); + for (i = 0; i < o->num_permitted_cnames; i++) { + free(o->permitted_cnames[i].source_list); + free(o->permitted_cnames[i].target_list); + } + free(o->revoked_host_keys); + free(o->hostbased_accepted_algos); + free(o->pubkey_accepted_algos); + free(o->jump_user); + free(o->jump_host); + free(o->jump_extra); + free(o->ignored_unknown); + explicit_bzero(o, sizeof(*o)); +#undef FREE_ARRAY } struct fwdarg { @@ -2274,12 +2725,19 @@ parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remo { struct fwdarg fwdargs[4]; char *p, *cp; - int i; + int i, err; memset(fwd, 0, sizeof(*fwd)); memset(fwdargs, 0, sizeof(fwdargs)); - cp = p = xstrdup(fwdspec); + /* + * We expand environment variables before checking if we think they're + * paths so that if ${VAR} expands to a fully qualified path it is + * treated as a path. + */ + cp = p = dollar_expand(&err, fwdspec); + if (p == NULL || err) + return 0; /* skip leading spaces */ while (isspace((u_char)*cp)) @@ -2405,7 +2863,7 @@ parse_jump(const char *s, Options *o, int active) { char *orig, *sdup, *cp; char *host = NULL, *user = NULL; - int ret = -1, port = -1, first; + int r, ret = -1, port = -1, first; active &= o->proxy_command == NULL && o->jump_host == NULL; @@ -2421,13 +2879,15 @@ parse_jump(const char *s, Options *o, int active) 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) + r = parse_ssh_uri(cp, &user, &host, &port); + if (r == -1 || (r == 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) + r = parse_ssh_uri(cp, NULL, NULL, NULL); + if (r == -1 || (r == 1 && + parse_user_host_port(cp, NULL, NULL, NULL) != 0)) goto out; } first = 0; /* only check syntax for subsequent hosts */ @@ -2460,12 +2920,27 @@ parse_jump(const char *s, Options *o, int active) int parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp) { - char *path; - int r; + char *user = NULL, *host = NULL, *path = NULL; + int r, port; - r = parse_uri("ssh", uri, userp, hostp, portp, &path); + r = parse_uri("ssh", uri, &user, &host, &port, &path); if (r == 0 && path != NULL) r = -1; /* path not allowed */ + if (r == 0) { + if (userp != NULL) { + *userp = user; + user = NULL; + } + if (hostp != NULL) { + *hostp = host; + host = NULL; + } + if (portp != NULL) + *portp = port; + } + free(user); + free(host); + free(path); return r; } @@ -2611,14 +3086,19 @@ dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) void dump_client_config(Options *o, const char *host) { - int i; + int i, r; char buf[8], *all_key; - /* This is normally prepared in ssh_kex2 */ + /* + * Expand HostKeyAlgorithms name lists. This isn't handled in + * fill_default_options() like the other algorithm lists because + * the host key algorithms are by default dynamically chosen based + * on the host's keys found in known_hosts. + */ 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__); + if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(), + all_key)) != 0) + fatal_fr(r, "expand HostKeyAlgorithms"); free(all_key); /* Most interesting options first: user, host, port */ @@ -2627,7 +3107,6 @@ dump_client_config(Options *o, const char *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); @@ -2640,7 +3119,6 @@ dump_client_config(Options *o, const char *host) 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); @@ -2677,27 +3155,29 @@ dump_client_config(Options *o, const char *host) /* 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(oCiphers, o->ciphers); 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(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos); 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(oKexAlgorithms, o->kex_algorithms); + dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms); 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); + dump_cfg_string(oMacs, o->macs); #ifdef ENABLE_PKCS11 dump_cfg_string(oPKCS11Provider, o->pkcs11_provider); #endif + dump_cfg_string(oSecurityKeyProvider, o->sk_provider); dump_cfg_string(oPreferredAuthentications, o->preferred_authentications); - dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types); + dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys); dump_cfg_string(oXAuthLocation, o->xauth_location); + dump_cfg_string(oKnownHostsCommand, o->known_hosts_command); /* Forwards */ dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); @@ -2712,9 +3192,33 @@ dump_client_config(Options *o, const char *host) 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); + dump_cfg_strarray_oneline(oLogVerbose, + o->num_log_verbose, o->log_verbose); /* Special cases */ + /* PermitRemoteOpen */ + if (o->num_permitted_remote_opens == 0) + printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen)); + else + dump_cfg_strarray_oneline(oPermitRemoteOpen, + o->num_permitted_remote_opens, o->permitted_remote_opens); + + /* AddKeysToAgent */ + if (o->add_keys_to_agent_lifespan <= 0) + dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent); + else { + printf("addkeystoagent%s %d\n", + o->add_keys_to_agent == 3 ? " confirm" : "", + o->add_keys_to_agent_lifespan); + } + + /* oForwardAgent */ + if (o->forward_agent_sock_path == NULL) + dump_cfg_fmtint(oForwardAgent, o->forward_agent); + else + dump_cfg_string(oForwardAgent, o->forward_agent_sock_path); + /* oConnectTimeout */ if (o->connection_timeout == -1) printf("connecttimeout none\n"); diff --git a/readconf.h b/readconf.h index 8e36bf32a..2fba866eb 100644 --- a/readconf.h +++ b/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.129 2018/11/23 05:08:07 djm Exp $ */ +/* $OpenBSD: readconf.h,v 1.140 2021/02/15 20:43:15 markus Exp $ */ /* * Author: Tatu Ylonen @@ -29,6 +29,7 @@ struct allowed_cname { typedef struct { int forward_agent; /* Forward authentication agent. */ + char *forward_agent_sock_path; /* Optional path of the agent. */ int forward_x11; /* Forward X11 display. */ int forward_x11_timeout; /* Expiration for Cookies */ int forward_x11_trusted; /* Trust Forward X11 display. */ @@ -54,7 +55,8 @@ typedef struct { int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */ SyslogFacility log_facility; /* Facility for system logging. */ LogLevel log_level; /* Level for logging. */ - + u_int num_log_verbose; /* Verbose log overrides */ + char **log_verbose; int port; /* Port to connect. */ int address_family; int connection_attempts; /* Max attempts (seconds) before @@ -82,6 +84,7 @@ typedef struct { char *bind_address; /* local socket address for connection to sshd */ char *bind_interface; /* local interface for bind address */ char *pkcs11_provider; /* PKCS#11 provider */ + char *sk_provider; /* Security key provider */ int verify_host_key_dns; /* Verify host key using DNS */ int num_identity_files; /* Number of files for RSA/DSA identities. */ @@ -95,6 +98,7 @@ typedef struct { struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; int add_keys_to_agent; + int add_keys_to_agent_lifespan; char *identity_agent; /* Optional path to ssh-agent socket */ /* Local TCP/IP forward requests. */ @@ -106,6 +110,10 @@ typedef struct { struct Forward *remote_forwards; int clear_forwardings; + /* Restrict remote dynamic forwarding */ + char **permitted_remote_opens; + u_int num_permitted_remote_opens; + /* stdio forwarding (-W) host and port */ char *stdio_forward_host; int stdio_forward_port; @@ -157,14 +165,16 @@ typedef struct { int update_hostkeys; /* one of SSH_UPDATE_HOSTKEYS_* */ - char *hostbased_key_types; - char *pubkey_key_types; + char *hostbased_accepted_algos; + char *pubkey_accepted_algos; char *jump_user; char *jump_host; int jump_port; char *jump_extra; + char *known_hosts_command; + char *ignored_unknown; /* Pattern list of unknown tokens to ignore */ } Options; @@ -197,9 +207,13 @@ typedef struct { #define SSH_STRICT_HOSTKEY_YES 2 #define SSH_STRICT_HOSTKEY_ASK 3 +const char *kex_default_pk_alg(void); +char *ssh_connection_hash(const char *thishost, const char *host, + const char *portstr, const char *user); void initialize_options(Options *); -void fill_default_options(Options *); +int fill_default_options(Options *); void fill_default_options_for_canonicalization(Options *); +void free_options(Options *o); 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 *, diff --git a/readpass.c b/readpass.c index 676bd7aa1..54541fd03 100644 --- a/readpass.c +++ b/readpass.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readpass.c,v 1.54 2019/06/28 13:35:04 deraadt Exp $ */ +/* $OpenBSD: readpass.c,v 1.68 2020/11/10 07:46:20 claudio Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -48,7 +48,7 @@ #include "uidswap.h" static char * -ssh_askpass(char *askpass, const char *msg) +ssh_askpass(char *askpass, const char *msg, const char *env_hint) { pid_t pid, ret; size_t len; @@ -58,14 +58,14 @@ ssh_askpass(char *askpass, const char *msg) void (*osigchld)(int); if (fflush(stdout) != 0) - error("ssh_askpass: fflush: %s", strerror(errno)); + error_f("fflush: %s", strerror(errno)); if (askpass == NULL) fatal("internal error: askpass undefined"); if (pipe(p) == -1) { - error("ssh_askpass: pipe: %s", strerror(errno)); + error_f("pipe: %s", strerror(errno)); return NULL; } - osigchld = signal(SIGCHLD, SIG_DFL); + osigchld = ssh_signal(SIGCHLD, SIG_DFL); #ifdef FORK_NOT_SUPPORTED fcntl(p[0], F_SETFD, FD_CLOEXEC); fcntl(p[1], F_SETFD, FD_CLOEXEC); @@ -94,16 +94,18 @@ ssh_askpass(char *askpass, const char *msg) } #else if ((pid = fork()) == -1) { - error("ssh_askpass: fork: %s", strerror(errno)); - signal(SIGCHLD, osigchld); + error_f("fork: %s", strerror(errno)); + ssh_signal(SIGCHLD, osigchld); return NULL; } if (pid == 0) { close(p[0]); if (dup2(p[1], STDOUT_FILENO) == -1) - fatal("ssh_askpass: dup2: %s", strerror(errno)); + fatal_f("dup2: %s", strerror(errno)); + if (env_hint != NULL) + setenv("SSH_ASKPASS_PROMPT", env_hint, 1); execlp(askpass, askpass, msg, (char *)NULL); - fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno)); + fatal_f("exec(%s): %s", askpass, strerror(errno)); } #endif close(p[1]); @@ -124,7 +126,7 @@ ssh_askpass(char *askpass, const char *msg) while ((ret = waitpid(pid, &status, 0)) == -1) if (errno != EINTR) break; - signal(SIGCHLD, osigchld); + ssh_signal(SIGCHLD, osigchld); if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { explicit_bzero(buf, sizeof(buf)); return NULL; @@ -136,6 +138,9 @@ ssh_askpass(char *askpass, const char *msg) return pass; } +/* private/internal read_passphrase flags */ +#define RP_ASK_PERMISSION 0x8000 /* pass hint to askpass for confirm UI */ + /* * Reads a passphrase from /dev/tty with echo turned off/on. Returns the * passphrase (allocated with xmalloc). Exits if EOF is encountered. If @@ -146,10 +151,26 @@ char * read_passphrase(const char *prompt, int flags) { char cr = '\r', *askpass = NULL, *ret, buf[1024]; - int rppflags, use_askpass = 0, ttyfd; + int rppflags, ttyfd, use_askpass = 0, allow_askpass = 0; + const char *askpass_hint = NULL; + const char *s; + + if ((s = getenv("DISPLAY")) != NULL) + allow_askpass = *s != '\0'; + if ((s = getenv(SSH_ASKPASS_REQUIRE_ENV)) != NULL) { + if (strcasecmp(s, "force") == 0) { + use_askpass = 1; + allow_askpass = 1; + } else if (strcasecmp(s, "prefer") == 0) + use_askpass = allow_askpass; + else if (strcasecmp(s, "never") == 0) + allow_askpass = 0; + } rppflags = (flags & RP_ECHO) ? RPP_ECHO_ON : RPP_ECHO_OFF; - if (flags & RP_USE_ASKPASS) + if (use_askpass) + debug_f("requested to askpass"); + else if (flags & RP_USE_ASKPASS) use_askpass = 1; else if (flags & RP_ALLOW_STDIN) { if (!isatty(STDIN_FILENO)) { @@ -175,10 +196,10 @@ read_passphrase(const char *prompt, int flags) } } - if ((flags & RP_USE_ASKPASS) && getenv("DISPLAY") == NULL) + if ((flags & RP_USE_ASKPASS) && !allow_askpass) return (flags & RP_ALLOW_EOF) ? NULL : xstrdup(""); - if (use_askpass && getenv("DISPLAY")) { + if (use_askpass && allow_askpass) { if (getenv(SSH_ASKPASS_ENV)) askpass = getenv(SSH_ASKPASS_ENV); else @@ -187,8 +208,9 @@ read_passphrase(const char *prompt, int flags) #ifdef WINDOWS if (getenv(SSH_ASKPASS_ENV)) { #endif - - if ((ret = ssh_askpass(askpass, prompt)) == NULL) + if ((flags & RP_ASK_PERMISSION) != 0) + askpass_hint = "confirm"; + if ((ret = ssh_askpass(askpass, prompt, askpass_hint)) == NULL) if (!(flags & RP_ALLOW_EOF)) return xstrdup(""); return ret; @@ -220,7 +242,8 @@ ask_permission(const char *fmt, ...) vsnprintf(prompt, sizeof(prompt), fmt, args); va_end(args); - p = read_passphrase(prompt, RP_USE_ASKPASS|RP_ALLOW_EOF); + p = read_passphrase(prompt, + RP_USE_ASKPASS|RP_ALLOW_EOF|RP_ASK_PERMISSION); if (p != NULL) { /* * Accept empty responses and responses consisting @@ -234,3 +257,111 @@ ask_permission(const char *fmt, ...) return (allowed); } + +static void +writemsg(const char *msg) +{ + (void)write(STDERR_FILENO, "\r", 1); + (void)write(STDERR_FILENO, msg, strlen(msg)); + (void)write(STDERR_FILENO, "\r\n", 2); +} + +struct notifier_ctx { + pid_t pid; + void (*osigchld)(int); +}; + +struct notifier_ctx * +notify_start(int force_askpass, const char *fmt, ...) +{ + va_list args; + char *prompt = NULL; + pid_t pid = -1; + void (*osigchld)(int) = NULL; + const char *askpass, *s; + struct notifier_ctx *ret = NULL; + + va_start(args, fmt); + xvasprintf(&prompt, fmt, args); + va_end(args); + + if (fflush(NULL) != 0) + error_f("fflush: %s", strerror(errno)); + if (!force_askpass && isatty(STDERR_FILENO)) { + writemsg(prompt); + goto out_ctx; + } + if ((askpass = getenv("SSH_ASKPASS")) == NULL) + askpass = _PATH_SSH_ASKPASS_DEFAULT; + if (*askpass == '\0') { + debug3_f("cannot notify: no askpass"); + goto out; + } + if (getenv("DISPLAY") == NULL && + ((s = getenv(SSH_ASKPASS_REQUIRE_ENV)) == NULL || + strcmp(s, "force") != 0)) { + debug3_f("cannot notify: no display"); + goto out; + } + osigchld = ssh_signal(SIGCHLD, SIG_DFL); + if ((pid = fork()) == -1) { + error_f("fork: %s", strerror(errno)); + ssh_signal(SIGCHLD, osigchld); + free(prompt); + return NULL; + } + if (pid == 0) { + if (stdfd_devnull(1, 1, 0) == -1) + fatal_f("stdfd_devnull failed"); + closefrom(STDERR_FILENO + 1); + setenv("SSH_ASKPASS_PROMPT", "none", 1); /* hint to UI */ + execlp(askpass, askpass, prompt, (char *)NULL); + error_f("exec(%s): %s", askpass, strerror(errno)); + _exit(1); + /* NOTREACHED */ + } + out_ctx: + if ((ret = calloc(1, sizeof(*ret))) == NULL) { + kill(pid, SIGTERM); + fatal_f("calloc failed"); + } + ret->pid = pid; + ret->osigchld = osigchld; + out: + free(prompt); + return ret; +} + +void +notify_complete(struct notifier_ctx *ctx, const char *fmt, ...) +{ + int ret; + char *msg = NULL; + va_list args; + + if (ctx != NULL && fmt != NULL && ctx->pid == -1) { + /* + * notify_start wrote to stderr, so send conclusion message + * there too + */ + va_start(args, fmt); + xvasprintf(&msg, fmt, args); + va_end(args); + writemsg(msg); + free(msg); + } + + if (ctx == NULL || ctx->pid <= 0) { + free(ctx); + return; + } + kill(ctx->pid, SIGTERM); + while ((ret = waitpid(ctx->pid, NULL, 0)) == -1) { + if (errno != EINTR) + break; + } + if (ret == -1) + fatal_f("waitpid: %s", strerror(errno)); + ssh_signal(SIGCHLD, ctx->osigchld); + free(ctx); +} diff --git a/regress/Makefile b/regress/Makefile index 34c47e8cb..43da7c7db 100644 --- a/regress/Makefile +++ b/regress/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.104 2019/09/03 08:37:45 djm Exp $ +# $OpenBSD: Makefile,v 1.110 2020/12/22 06:03:36 djm Exp $ tests: prep file-tests t-exec unit @@ -41,6 +41,7 @@ LTESTS= connect \ agent-getpeereid \ agent-timeout \ agent-ptrace \ + agent-subprocess \ keyscan \ keygen-change \ keygen-convert \ @@ -66,6 +67,7 @@ LTESTS= connect \ cfgparse \ cfgmatch \ cfgmatchlisten \ + percent \ addrmatch \ localcommand \ forcecommand \ @@ -87,10 +89,12 @@ LTESTS= connect \ principals-command \ cert-file \ cfginclude \ + servcfginclude \ allow-deny-users \ authinfo \ - sshsig - + sshsig \ + keygen-comment \ + knownhosts-command INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers @@ -119,10 +123,10 @@ CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \ 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-rsa_oldfmt \ + ssh-rsa_oldfmt knownhosts_command \ 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 \ + ssh_proxy_* sshd.log sshd_config sshd_config.* \ + sshd_config.* 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 \ @@ -248,6 +252,8 @@ unit: $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ -d ${.CURDIR}/unittests/sshkey/testdata ; \ + $$V ${.OBJDIR}/unittests/sshsig/test_sshsig \ + -d ${.CURDIR}/unittests/sshsig/testdata ; \ $$V ${.OBJDIR}/unittests/bitmap/test_bitmap ; \ $$V ${.OBJDIR}/unittests/conversion/test_conversion ; \ $$V ${.OBJDIR}/unittests/kex/test_kex ; \ diff --git a/regress/addrmatch.sh b/regress/addrmatch.sh index 2741389ee..8480b88c7 100644 --- a/regress/addrmatch.sh +++ b/regress/addrmatch.sh @@ -1,4 +1,4 @@ -# $OpenBSD: addrmatch.sh,v 1.4 2012/05/13 01:42:32 dtucker Exp $ +# $OpenBSD: addrmatch.sh,v 1.6 2020/08/28 03:17:13 dtucker Exp $ # Placed in the Public Domain. tid="address match" @@ -46,7 +46,7 @@ run_trial user 19.0.0.1 somehost 1.2.3.4 5678 match4 "localport" if test "$TEST_SSH_IPV6" != "no"; then run_trial user ::1 somehost.example.com ::2 1234 match2 "bare IP6 address" -run_trial user ::2 somehost.exaple.com ::2 1234 nomatch "deny IPv6" +run_trial user ::2 somehost.example.com ::2 1234 nomatch "deny IPv6" run_trial user ::3 somehost ::2 1234 nomatch "IP6 negated" run_trial user ::4 somehost ::2 1234 nomatch "IP6 no match" run_trial user 2000::1 somehost ::2 1234 match2 "IP6 network" @@ -55,5 +55,17 @@ run_trial user ::5 somehost ::1 1234 match3 "IP6 localaddress" run_trial user ::5 somehost ::2 5678 match4 "IP6 localport" fi +# +# Check that we catch invalid address/mask in Match Address/Localaddress +# +for i in 10.0.1.0/8 10.0.0.1/24 2000:aa:bb:01::/56; do + for a in address localaddress; do + verbose "test invalid Match $a $i" + echo "Match $a $i" > $OBJ/sshd_proxy + ${SUDO} ${SSHD} -f $OBJ/sshd_proxy -t >/dev/null 2>&1 && \ + fail "accepted invalid match $a $i" + done +done + cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy rm $OBJ/sshd_proxy_bak diff --git a/regress/agent-getpeereid.sh b/regress/agent-getpeereid.sh index 769c29e8d..524340816 100644 --- a/regress/agent-getpeereid.sh +++ b/regress/agent-getpeereid.sh @@ -1,4 +1,4 @@ -# $OpenBSD: agent-getpeereid.sh,v 1.10 2018/02/09 03:40:22 dtucker Exp $ +# $OpenBSD: agent-getpeereid.sh,v 1.11 2019/11/26 23:43:10 djm Exp $ # Placed in the Public Domain. tid="disallow agent attach from other uid" @@ -26,7 +26,7 @@ case "x$SUDO" in esac trace "start agent" -eval `${SSHAGENT} -s -a ${ASOCK}` > /dev/null +eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s -a ${ASOCK}` > /dev/null r=$? if [ $r -ne 0 ]; then fail "could not start ssh-agent: exit code $r" diff --git a/regress/agent-pkcs11.sh b/regress/agent-pkcs11.sh index 5205d9067..fbbaea518 100644 --- a/regress/agent-pkcs11.sh +++ b/regress/agent-pkcs11.sh @@ -1,4 +1,4 @@ -# $OpenBSD: agent-pkcs11.sh,v 1.6 2019/01/21 09:13:41 djm Exp $ +# $OpenBSD: agent-pkcs11.sh,v 1.7 2019/11/26 23:43:10 djm Exp $ # Placed in the Public Domain. tid="pkcs11 agent test" @@ -75,7 +75,7 @@ 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 +eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null r=$? if [ $r -ne 0 ]; then fail "could not start ssh-agent: exit code $r" diff --git a/regress/agent-ptrace.sh b/regress/agent-ptrace.sh index 2d795ee32..9cd68d7ec 100644 --- a/regress/agent-ptrace.sh +++ b/regress/agent-ptrace.sh @@ -41,7 +41,7 @@ else fi trace "start agent" -eval `${SSHAGENT} -s` > /dev/null +eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null r=$? if [ $r -ne 0 ]; then fail "could not start ssh-agent: exit code $r" diff --git a/regress/agent-subprocess.sh b/regress/agent-subprocess.sh new file mode 100644 index 000000000..2f36d70cc --- /dev/null +++ b/regress/agent-subprocess.sh @@ -0,0 +1,22 @@ +# $OpenBSD: agent-subprocess.sh,v 1.1 2020/06/19 05:07:09 dtucker Exp $ +# Placed in the Public Domain. + +tid="agent subprocess" + +trace "ensure agent exits when run as subprocess" +${SSHAGENT} sh -c "echo \$SSH_AGENT_PID >$OBJ/pidfile; sleep 1" + +pid=`cat $OBJ/pidfile` + +# Currently ssh-agent polls every 10s so we need to wait at least that long. +n=12 +while kill -0 $pid >/dev/null 2>&1 && test "$n" -gt "0"; do + n=$(($n - 1)) + sleep 1 +done + +if test "$n" -eq "0"; then + fail "agent still running" +fi + +rm -f $OBJ/pidfile diff --git a/regress/agent-timeout.sh b/regress/agent-timeout.sh index 048005ec8..9b2f168d1 100644 --- a/regress/agent-timeout.sh +++ b/regress/agent-timeout.sh @@ -1,4 +1,4 @@ -# $OpenBSD: agent-timeout.sh,v 1.5 2019/09/03 08:37:06 djm Exp $ +# $OpenBSD: agent-timeout.sh,v 1.6 2019/11/26 23:43:10 djm Exp $ # Placed in the Public Domain. tid="agent timeout test" @@ -9,7 +9,7 @@ fi SSHAGENT_TIMEOUT=10 trace "start agent" -eval `${SSHAGENT} -s` > /dev/null +eval `${SSHAGENT} -s ${EXTRA_AGENT_ARGS}` > /dev/null r=$? if [ $r -ne 0 ]; then fail "could not start ssh-agent: exit code $r" diff --git a/regress/agent.sh b/regress/agent.sh index c20058bb4..13f0239a7 100644 --- a/regress/agent.sh +++ b/regress/agent.sh @@ -1,4 +1,4 @@ -# $OpenBSD: agent.sh,v 1.15 2019/07/23 07:39:43 dtucker Exp $ +# $OpenBSD: agent.sh,v 1.20 2021/02/25 03:27:34 djm Exp $ # Placed in the Public Domain. tid="simple agent test" @@ -8,17 +8,25 @@ if [ $? -ne 2 ]; then fail "ssh-add -l did not fail with exit code 2" fi -trace "start agent" -eval `${SSHAGENT} -s` > /dev/null +trace "start agent, args ${EXTRA_AGENT_ARGS} -s" +eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null r=$? if [ $r -ne 0 ]; then fatal "could not start ssh-agent: exit code $r" fi + +eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s | sed 's/SSH_/FW_SSH_/g'` > /dev/null +r=$? +if [ $r -ne 0 ]; then + fatal "could not start second ssh-agent: exit code $r" +fi + if [ "$os" == "windows" ]; then #windows ssh-agent doesn't support "-s" option so we need to set SSH_AUTH_SOCK env here. SSH_AUTH_SOCK="\\\\.\\pipe\\openssh-ssh-agent" ${SSHADD} -D fi + ${SSHADD} -l > /dev/null 2>&1 if [ $? -ne 1 ]; then fail "ssh-add -l did not fail with exit code 1" @@ -42,13 +50,21 @@ for t in ${SSH_KEYTYPES}; do # add to authorized keys cat $OBJ/$t-agent.pub >> $OBJ/authorized_keys_$USER - # add privat key to agent + # add private key to agent ${SSHADD} $OBJ/$t-agent > /dev/null 2>&1 if [ $? -ne 0 ]; then - fail "ssh-add did succeed exit code 0" + fail "ssh-add failed exit code $?" fi - # Remove private key to ensure that we aren't accidentally using it. - rm -f $OBJ/$t-agent + # add private key to second agent + SSH_AUTH_SOCK=$FW_SSH_AUTH_SOCK ${SSHADD} $OBJ/$t-agent > /dev/null 2>&1 + if [ $? -ne 0 ]; then + fail "ssh-add failed exit code $?" + fi + # Move private key to ensure that we aren't accidentally using it. + # Keep the corresponding public keys/certs around for later use. + mv -f $OBJ/$t-agent $OBJ/$t-agent-private + cp -f $OBJ/$t-agent.pub $OBJ/$t-agent-private.pub + cp -f $OBJ/$t-agent-cert.pub $OBJ/$t-agent-private-cert.pub done # Remove explicit identity directives from ssh_proxy @@ -77,8 +93,8 @@ fi for t in ${SSH_KEYTYPES}; do trace "connect via agent using $t key" if [ "$t" = "ssh-dss" ]; then - echo "PubkeyAcceptedKeyTypes +ssh-dss" >> $OBJ/ssh_proxy - echo "PubkeyAcceptedKeyTypes +ssh-dss" >> $OBJ/sshd_proxy + echo "PubkeyAcceptedAlgorithms +ssh-dss" >> $OBJ/ssh_proxy + echo "PubkeyAcceptedAlgorithms +ssh-dss" >> $OBJ/sshd_proxy fi ${SSH} -F $OBJ/ssh_proxy -i $OBJ/$t-agent.pub -oIdentitiesOnly=yes \ somehost exit 52 @@ -94,6 +110,11 @@ r=$? if [ $r -ne 0 ]; then fail "ssh-add -l via agent fwd failed (exit code $r)" fi +${SSH} "-oForwardAgent=$SSH_AUTH_SOCK" -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1 +r=$? +if [ $r -ne 0 ]; then + fail "ssh-add -l via agent path fwd failed (exit code $r)" +fi ${SSH} -A -F $OBJ/ssh_proxy somehost \ "${SSH} -F $OBJ/ssh_proxy somehost exit 52" r=$? @@ -101,6 +122,30 @@ if [ $r -ne 52 ]; then fail "agent fwd failed (exit code $r)" fi +trace "agent forwarding different agent" +${SSH} "-oForwardAgent=$FW_SSH_AUTH_SOCK" -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1 +r=$? +if [ $r -ne 0 ]; then + fail "ssh-add -l via agent path fwd of different agent failed (exit code $r)" +fi +${SSH} '-oForwardAgent=$FW_SSH_AUTH_SOCK' -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1 +r=$? +if [ $r -ne 0 ]; then + fail "ssh-add -l via agent path env fwd of different agent failed (exit code $r)" +fi + +# Remove keys from forwarded agent, ssh-add on remote machine should now fail. +SSH_AUTH_SOCK=$FW_SSH_AUTH_SOCK ${SSHADD} -D > /dev/null 2>&1 +r=$? +if [ $r -ne 0 ]; then + fail "ssh-add -D failed: exit code $r" +fi +${SSH} '-oForwardAgent=$FW_SSH_AUTH_SOCK' -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1 +r=$? +if [ $r -ne 1 ]; then + fail "ssh-add -l with different agent did not fail with exit code 1 (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 @@ -116,12 +161,73 @@ for t in ${SSH_KEYTYPES}; do fi done +## Deletion tests. + 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 +# make sure they're gone +${SSHADD} -l > /dev/null 2>&1 +r=$? +if [ $r -ne 1 ]; then + fail "ssh-add -l returned unexpected exit code: $r" +fi +trace "readd keys" +# re-add keys/certs to agent +for t in ${SSH_KEYTYPES}; do + ${SSHADD} $OBJ/$t-agent-private >/dev/null 2>&1 || \ + fail "ssh-add failed exit code $?" +done +# make sure they are there +${SSHADD} -l > /dev/null 2>&1 +r=$? +if [ $r -ne 0 ]; then + fail "ssh-add -l failed: exit code $r" +fi + +check_key_absent() { + ${SSHADD} -L | grep "^$1 " >/dev/null + if [ $? -eq 0 ]; then + fail "$1 key unexpectedly present" + fi +} +check_key_present() { + ${SSHADD} -L | grep "^$1 " >/dev/null + if [ $? -ne 0 ]; then + fail "$1 key missing from agent" + fi +} + +# delete the ed25519 key +trace "delete single key by file" +${SSHADD} -qdk $OBJ/ssh-ed25519-agent || fail "ssh-add -d ed25519 failed" +check_key_absent ssh-ed25519 +check_key_present ssh-ed25519-cert-v01@openssh.com +# Put key/cert back. +${SSHADD} $OBJ/ssh-ed25519-agent-private >/dev/null 2>&1 || \ + fail "ssh-add failed exit code $?" +check_key_present ssh-ed25519 +# Delete both key and certificate. +trace "delete key/cert by file" +${SSHADD} -qd $OBJ/ssh-ed25519-agent || fail "ssh-add -d ed25519 failed" +check_key_absent ssh-ed25519 +check_key_absent ssh-ed25519-cert-v01@openssh.com +# Put key/cert back. +${SSHADD} $OBJ/ssh-ed25519-agent-private >/dev/null 2>&1 || \ + fail "ssh-add failed exit code $?" +check_key_present ssh-ed25519 +# Delete certificate via stdin +${SSHADD} -qd - < $OBJ/ssh-ed25519-agent-cert.pub || fail "ssh-add -d - failed" +check_key_present ssh-ed25519 +check_key_absent ssh-ed25519-cert-v01@openssh.com +# Delete key via stdin +${SSHADD} -qd - < $OBJ/ssh-ed25519-agent.pub || fail "ssh-add -d - failed" +check_key_absent ssh-ed25519 +check_key_absent ssh-ed25519-cert-v01@openssh.com trace "kill agent" ${SSHAGENT} -k > /dev/null +SSH_AGENT_PID=$FW_SSH_AGENT_PID ${SSHAGENT} -k > /dev/null diff --git a/regress/cert-file.sh b/regress/cert-file.sh index 1157a3582..94e672a99 100644 --- a/regress/cert-file.sh +++ b/regress/cert-file.sh @@ -1,4 +1,4 @@ -# $OpenBSD: cert-file.sh,v 1.7 2018/04/10 00:14:10 djm Exp $ +# $OpenBSD: cert-file.sh,v 1.8 2019/11/26 23:43:10 djm Exp $ # Placed in the Public Domain. tid="ssh with certificates" @@ -120,7 +120,7 @@ if [ $? -ne 2 ]; then fi trace "start agent" -eval `${SSHAGENT} -s` > /dev/null +eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null r=$? if [ $r -ne 0 ]; then fatal "could not start ssh-agent: exit code $r" diff --git a/regress/cert-hostkey.sh b/regress/cert-hostkey.sh index 12a0315e7..e4278e345 100644 --- a/regress/cert-hostkey.sh +++ b/regress/cert-hostkey.sh @@ -1,4 +1,4 @@ -# $OpenBSD: cert-hostkey.sh,v 1.18 2019/07/25 08:28:15 dtucker Exp $ +# $OpenBSD: cert-hostkey.sh,v 1.24 2021/02/25 03:27:34 djm Exp $ # Placed in the Public Domain. tid="certified host keys" @@ -9,7 +9,7 @@ rm -f $OBJ/cert_host_key* $OBJ/host_krl_* # Allow all hostkey/pubkey types, prefer certs for the client rsa=0 types="" -for i in `$SSH -Q key`; do +for i in `$SSH -Q key | maybe_filter_sk`; do if [ "$os" == "windows" ]; then i=${i/$'\r'/} # remove CR (carriage return) fi @@ -32,12 +32,12 @@ for i in `$SSH -Q key`; do done ( echo "HostKeyAlgorithms ${types}" - echo "PubkeyAcceptedKeyTypes *" + echo "PubkeyAcceptedAlgorithms *" ) >> $OBJ/ssh_proxy cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak ( echo "HostKeyAlgorithms *" - echo "PubkeyAcceptedKeyTypes *" + echo "PubkeyAcceptedAlgorithms *" ) >> $OBJ/sshd_proxy_bak HOSTS='localhost-with-alias,127.0.0.1,::1' @@ -73,12 +73,7 @@ touch $OBJ/host_revoked_plain touch $OBJ/host_revoked_cert cat $OBJ/host_ca_key.pub $OBJ/host_ca_key2.pub > $OBJ/host_revoked_ca -if [ "$os" == "windows" ]; then - # remove CR (carriage return) - PLAIN_TYPES=`$SSH -Q key-plain | sed 's/\r$//' | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'` -else - PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'` -fi +PLAIN_TYPES=`echo "$SSH_KEYTYPES" | 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" @@ -139,7 +134,7 @@ attempt_connect() { } # Basic connect and revocation tests. -for privsep in yes sandbox ; do +for privsep in yes ; do for ktype in $PLAIN_TYPES ; do verbose "$tid: host ${ktype} cert connect privsep $privsep" ( @@ -177,7 +172,7 @@ for ktype in $PLAIN_TYPES ; do 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 sandbox ; do +for privsep in yes ; do for ktype in $PLAIN_TYPES ; do verbose "$tid: host ${ktype} revoked cert privsep $privsep" ( @@ -260,7 +255,7 @@ test_one() { 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 not yet valid" failure "-h -V20300101:20320101" 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" diff --git a/regress/cert-userkey.sh b/regress/cert-userkey.sh index a70f58f42..eca85d205 100644 --- a/regress/cert-userkey.sh +++ b/regress/cert-userkey.sh @@ -1,4 +1,4 @@ -# $OpenBSD: cert-userkey.sh,v 1.21 2019/07/25 08:28:15 dtucker Exp $ +# $OpenBSD: cert-userkey.sh,v 1.26 2021/02/25 03:27:34 djm Exp $ # Placed in the Public Domain. tid="certified user keys" @@ -8,10 +8,11 @@ cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak if [ "$os" == "windows" ]; then # remove CR (carriage return) - PLAIN_TYPES=`$SSH -Q key-plain | sed 's/\r$//' | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` + PLAIN_TYPES=`$SSH -Q key-plain | sed 's/\r$//' | maybe_filter_sk | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` else - PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` + PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` fi + EXTRA_TYPES="" rsa="" @@ -21,8 +22,10 @@ if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then fi kname() { - case $ktype in - rsa-sha2-*) n="$ktype" ;; + case $1 in + rsa-sha2-*) n="$1" ;; + sk-ecdsa-*) n="sk-ecdsa" ;; + sk-ssh-ed25519*) n="sk-ssh-ed25519" ;; # 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 @@ -62,7 +65,7 @@ done # Test explicitly-specified principals for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do t=$(kname $ktype) - for privsep in yes sandbox ; do + for privsep in yes ; do _prefix="${ktype} privsep $privsep" # Setup for AuthorizedPrincipalsFile @@ -73,11 +76,11 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do echo "AuthorizedPrincipalsFile " \ "$OBJ/authorized_principals_%u" echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" - echo "PubkeyAcceptedKeyTypes ${t}" + echo "PubkeyAcceptedAlgorithms ${t}" ) > $OBJ/sshd_proxy ( cat $OBJ/ssh_proxy_bak - echo "PubkeyAcceptedKeyTypes ${t}" + echo "PubkeyAcceptedAlgorithms ${t}" ) > $OBJ/ssh_proxy # Missing authorized_principals @@ -151,11 +154,11 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do ( cat $OBJ/sshd_proxy_bak echo "UsePrivilegeSeparation $privsep" - echo "PubkeyAcceptedKeyTypes ${t}" + echo "PubkeyAcceptedAlgorithms ${t}" ) > $OBJ/sshd_proxy ( cat $OBJ/ssh_proxy_bak - echo "PubkeyAcceptedKeyTypes ${t}" + echo "PubkeyAcceptedAlgorithms ${t}" ) > $OBJ/ssh_proxy # Wrong principals list @@ -199,19 +202,19 @@ basic_tests() { for ktype in $PLAIN_TYPES ; do t=$(kname $ktype) - for privsep in yes no ; do + for privsep in yes ; do _prefix="${ktype} privsep $privsep $auth" # Simple connect verbose "$tid: ${_prefix} connect" ( cat $OBJ/sshd_proxy_bak echo "UsePrivilegeSeparation $privsep" - echo "PubkeyAcceptedKeyTypes ${t}" + echo "PubkeyAcceptedAlgorithms ${t}" echo "$extra_sshd" ) > $OBJ/sshd_proxy ( cat $OBJ/ssh_proxy_bak - echo "PubkeyAcceptedKeyTypes ${t}" + echo "PubkeyAcceptedAlgorithms ${t}" ) > $OBJ/ssh_proxy ${SSH} -i $OBJ/cert_user_key_${ktype} \ @@ -226,7 +229,7 @@ basic_tests() { cat $OBJ/sshd_proxy_bak echo "UsePrivilegeSeparation $privsep" echo "RevokedKeys $OBJ/cert_user_key_revoked" - echo "PubkeyAcceptedKeyTypes ${t}" + echo "PubkeyAcceptedAlgorithms ${t}" echo "$extra_sshd" ) > $OBJ/sshd_proxy cp $OBJ/cert_user_key_${ktype}.pub \ @@ -259,7 +262,7 @@ basic_tests() { ( cat $OBJ/sshd_proxy_bak echo "RevokedKeys $OBJ/user_ca_key.pub" - echo "PubkeyAcceptedKeyTypes ${t}" + echo "PubkeyAcceptedAlgorithms ${t}" echo "$extra_sshd" ) > $OBJ/sshd_proxy ${SSH} -i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \ @@ -272,7 +275,7 @@ basic_tests() { verbose "$tid: $auth CA does not authenticate" ( cat $OBJ/sshd_proxy_bak - echo "PubkeyAcceptedKeyTypes ${t}" + echo "PubkeyAcceptedAlgorithms ${t}" echo "$extra_sshd" ) > $OBJ/sshd_proxy verbose "$tid: ensure CA key does not authenticate user" @@ -310,7 +313,7 @@ test_one() { echo > $OBJ/authorized_keys_$USER echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" \ >> $OBJ/sshd_proxy - echo "PubkeyAcceptedKeyTypes ${t}*" \ + echo "PubkeyAcceptedAlgorithms ${t}*" \ >> $OBJ/sshd_proxy if test "x$auth_opt" != "x" ; then echo $auth_opt >> $OBJ/sshd_proxy @@ -342,7 +345,7 @@ test_one() { 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 not yet valid" failure "-n ${USER} -V20300101:20320101" 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" diff --git a/regress/connect-privsep.sh b/regress/connect-privsep.sh index b6abb65e3..76137b060 100644 --- a/regress/connect-privsep.sh +++ b/regress/connect-privsep.sh @@ -22,7 +22,7 @@ fi # Because sandbox is sensitive to changes in libc, especially malloc, retest # with every malloc.conf option (and none). -if [ -z "TEST_MALLOC_OPTIONS" ]; then +if [ -z "$TEST_MALLOC_OPTIONS" ]; then mopts="C F G J R S U X < >" else mopts=`echo $TEST_MALLOC_OPTIONS | sed 's/./& /g'` diff --git a/regress/connect.sh b/regress/connect.sh index 1b344b603..46f12b7b3 100644 --- a/regress/connect.sh +++ b/regress/connect.sh @@ -1,11 +1,18 @@ -# $OpenBSD: connect.sh,v 1.6 2017/04/30 23:34:55 djm Exp $ +# $OpenBSD: connect.sh,v 1.8 2020/01/25 02:57:53 dtucker Exp $ # Placed in the Public Domain. tid="simple connect" start_sshd +trace "direct connect" ${SSH} -F $OBJ/ssh_config somehost true if [ $? -ne 0 ]; then - fail "ssh connect with failed" + fail "ssh direct connect failed" +fi + +trace "proxy connect" +${SSH} -F $OBJ/ssh_config -o "proxycommand $NC %h %p" somehost true +if [ $? -ne 0 ]; then + fail "ssh proxycommand connect failed" fi diff --git a/regress/dhgex.sh b/regress/dhgex.sh index ae64a9fb6..6dd4cfe3f 100644 --- a/regress/dhgex.sh +++ b/regress/dhgex.sh @@ -1,4 +1,4 @@ -# $OpenBSD: dhgex.sh,v 1.6 2019/10/06 11:49:50 dtucker Exp $ +# $OpenBSD: dhgex.sh,v 1.7 2020/12/21 22:48:41 dtucker Exp $ # Placed in the Public Domain. tid="dhgex" @@ -58,4 +58,4 @@ check 3072 3des-cbc # 112 bits. check 3072 `${SSH} -Q cipher | grep 128` check 7680 `${SSH} -Q cipher | grep 192` check 8192 `${SSH} -Q cipher | grep 256` -check 8192 rijndael-cbc@lysator.liu.se chacha20-poly1305@openssh.com +check 8192 chacha20-poly1305@openssh.com diff --git a/regress/hostkey-agent.sh b/regress/hostkey-agent.sh index 32735f607..4145d7fd2 100644 --- a/regress/hostkey-agent.sh +++ b/regress/hostkey-agent.sh @@ -1,4 +1,4 @@ -# $OpenBSD: hostkey-agent.sh,v 1.7 2017/04/30 23:34:55 djm Exp $ +# $OpenBSD: hostkey-agent.sh,v 1.11 2019/12/16 02:39:05 djm Exp $ # Placed in the Public Domain. tid="hostkey agent" @@ -6,7 +6,7 @@ tid="hostkey agent" rm -f $OBJ/agent-key.* $OBJ/ssh_proxy.orig $OBJ/known_hosts.orig trace "start agent" -eval `${SSHAGENT} -s` > /dev/null +eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null r=$? [ $r -ne 0 ] && fatal "could not start ssh-agent: exit code $r" @@ -19,11 +19,7 @@ fi echo "HostKeyAgent $SSH_AUTH_SOCK" >> $OBJ/sshd_proxy.orig trace "load hostkeys" -for k in `${SSH} -Q key-plain` ; do - if [ "$os" == "windows" ]; then - k=${k/$'\r'/} # remove CR (carriage return) - fi - +for k in $SSH_KEYTYPES ; do ${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k" ( printf 'localhost-with-alias,127.0.0.1,::1 ' @@ -39,11 +35,8 @@ cp $OBJ/known_hosts.orig $OBJ/known_hosts unset SSH_AUTH_SOCK -for ps in no yes; do - for k in `${SSH} -Q key-plain` ; do - if [ "$os" == "windows" ]; then - k=${k/$'\r'/} # remove CR (carriage return) - fi +for ps in yes; do + for k in $SSH_KEYTYPES ; do verbose "key type $k privsep=$ps" cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy diff --git a/regress/hostkey-rotate.sh b/regress/hostkey-rotate.sh index 471d97a27..2852c457c 100644 --- a/regress/hostkey-rotate.sh +++ b/regress/hostkey-rotate.sh @@ -1,19 +1,15 @@ -# $OpenBSD: hostkey-rotate.sh,v 1.6 2019/08/30 05:08:28 dtucker Exp $ +# $OpenBSD: hostkey-rotate.sh,v 1.9 2020/10/07 06:38:16 djm Exp $ # Placed in the Public Domain. tid="hostkey rotate" -# Need full names here since they are used in HostKeyAlgorithms -if [ "$os" == "windows" ]; then - HOSTKEY_TYPES=`${SSH} -Q key-plain | sed 's/\r$//'` # remove CR (carriage return) -else - HOSTKEY_TYPES=`${SSH} -Q key-plain` -fi - -rm -f $OBJ/hkr.* $OBJ/ssh_proxy.orig +rm -f $OBJ/hkr.* $OBJ/ssh_proxy.orig $OBJ/ssh_proxy.orig grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig +mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig +grep -vi 'globalknownhostsfile' $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy echo "UpdateHostkeys=yes" >> $OBJ/ssh_proxy +echo "GlobalKnownHostsFile=none" >> $OBJ/ssh_proxy rm $OBJ/known_hosts # The "primary" key type is ed25519 since it's supported even when built @@ -24,7 +20,7 @@ secondary="$primary" trace "prepare hostkeys" nkeys=0 all_algs="" -for k in $HOSTKEY_TYPES; do +for k in $SSH_HOSTKEY_TYPES; do ${SSHKEYGEN} -qt $k -f $OBJ/hkr.$k -N '' || fatal "ssh-keygen $k" echo "Hostkey $OBJ/hkr.${k}" >> $OBJ/sshd_proxy.orig nkeys=`expr $nkeys + 1` @@ -71,15 +67,12 @@ verbose "learn additional hostkeys" dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$all_algs # Check that other keys learned expect_nkeys $nkeys "learn hostkeys" -for k in $HOSTKEY_TYPES; do +for k in $SSH_HOSTKEY_TYPES; do check_key_present $k || fail "didn't learn keytype $k" done # Check each key type -for k in $HOSTKEY_TYPES; do - if [ "$os" == "windows" ]; then - k=`echo $k | sed 's/\r$//'` # remove CR (carriage return) - fi +for k in $SSH_HOSTKEY_TYPES; do verbose "learn additional hostkeys, type=$k" dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$k,$all_algs expect_nkeys $nkeys "learn hostkeys $k" diff --git a/regress/integrity.sh b/regress/integrity.sh index ccbd3701c..0ad886c26 100644 --- a/regress/integrity.sh +++ b/regress/integrity.sh @@ -1,4 +1,4 @@ -# $OpenBSD: integrity.sh,v 1.23 2017/04/30 23:34:55 djm Exp $ +# $OpenBSD: integrity.sh,v 1.24 2020/01/21 08:06:27 djm Exp $ # Placed in the Public Domain. tid="integrity" @@ -25,7 +25,7 @@ fi # >> $OBJ/ssh_proxy # sshd-command for proxy (see test-exec.sh) -cmd="$SUDO sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy" +cmd="$SUDO env SSH_SK_HELPER="$SSH_SK_HELPER" sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy" for m in $macs; do trace "test $tid: mac $m" diff --git a/regress/key-options.sh b/regress/key-options.sh index 112c9bd8e..2f3d66e2e 100644 --- a/regress/key-options.sh +++ b/regress/key-options.sh @@ -7,6 +7,12 @@ origkeys="$OBJ/authkeys_orig" authkeys="$OBJ/authorized_keys_${USER}" cp $authkeys $origkeys +# Allocating ptys can require privileges on some platforms. +skip_pty="" +if ! config_defined HAVE_OPENPTY && [ "x$SUDO" = "x" ]; then + skip_pty="no openpty(3) and SUDO not set" +fi + # Test command= forced command for c in 'command="echo bar"' 'no-pty,command="echo bar"'; do sed "s/.*/$c &/" $origkeys >$authkeys @@ -27,7 +33,7 @@ expect_pty_succeed() { rm -f $OBJ/data sed "s/.*/$opts &/" $origkeys >$authkeys verbose "key option pty $which" - config_defined HAVE_OPENPTY || verbose "skipped for no openpty(3)" + [ "x$skip_pty" != "x" ] && verbose "skipped because $skip_pty" && return ${SSH} -ttq -F $OBJ/ssh_proxy somehost "tty > $OBJ/data; exit 0" if [ $? -ne 0 ] ; then fail "key option failed $which" @@ -45,7 +51,7 @@ expect_pty_fail() { rm -f $OBJ/data sed "s/.*/$opts &/" $origkeys >$authkeys verbose "key option pty $which" - config_defined HAVE_OPENPTY || verbose "skipped for no openpty(3)" + [ "x$skip_pty" != "x" ] && verbose "skipped because $skip_pty" && return ${SSH} -ttq -F $OBJ/ssh_proxy somehost "tty > $OBJ/data; exit 0" if [ $? -eq 0 ]; then r=`cat $OBJ/data` diff --git a/regress/keygen-change.sh b/regress/keygen-change.sh index 2204b8bb7..3863e33b5 100644 --- a/regress/keygen-change.sh +++ b/regress/keygen-change.sh @@ -1,4 +1,4 @@ -# $OpenBSD: keygen-change.sh,v 1.6 2017/04/30 23:34:55 djm Exp $ +# $OpenBSD: keygen-change.sh,v 1.9 2019/12/16 02:39:05 djm Exp $ # Placed in the Public Domain. tid="change passphrase for key" @@ -6,14 +6,7 @@ tid="change passphrase for key" S1="secret1" S2="2secret" -if [ "$os" == "windows" ]; then - KEYTYPES=`${SSH} -Q key-plain | sed 's/\r$//'` # remove CR (carriage return) -else - KEYTYPES=`${SSH} -Q key-plain` -fi - -for t in $KEYTYPES; do - # generate user key for agent +for t in $SSH_KEYTYPES; do trace "generating $t key" rm -f $OBJ/$t-key ${SSHKEYGEN} -q -N ${S1} -t $t -f $OBJ/$t-key diff --git a/regress/keygen-comment.sh b/regress/keygen-comment.sh new file mode 100644 index 000000000..af571d390 --- /dev/null +++ b/regress/keygen-comment.sh @@ -0,0 +1,52 @@ +#    Placed in the Public Domain. + +tid="Comment extraction from private key" + +S1="secret1" + +check_fingerprint () { + file="$1" + comment="$2" + trace "fingerprinting $file" + if ! ${SSHKEYGEN} -l -E sha256 -f $file > $OBJ/$t-fgp ; then + fail "ssh-keygen -l failed for $t-key" + fi + if ! egrep "^([0-9]+) SHA256:(.){43} ${comment} \(.*\)\$" \ + $OBJ/$t-fgp >/dev/null 2>&1 ; then + fail "comment is not correctly recovered for $t-key" + fi + rm -f $OBJ/$t-fgp +} + +for fmt in '' RFC4716 PKCS8 PEM; do + for t in $SSH_KEYTYPES; do + trace "generating $t key in '$fmt' format" + rm -f $OBJ/$t-key* + oldfmt="" + case "$fmt" in + PKCS8|PEM) oldfmt=1 ;; + esac + # Some key types like ssh-ed25519 and *@openssh.com are never + # stored in old formats. + case "$t" in + ssh-ed25519|*openssh.com) test -z "$oldfmt" || continue ;; + esac + comment="foo bar" + fmtarg="" + test -z "$fmt" || fmtarg="-m $fmt" + ${SSHKEYGEN} $fmtarg -N '' -C "${comment}" \ + -t $t -f $OBJ/$t-key >/dev/null 2>&1 || \ + fatal "keygen of $t in format $fmt failed" + check_fingerprint $OBJ/$t-key "${comment}" + check_fingerprint $OBJ/$t-key.pub "${comment}" + # Output fingerprint using only private file + trace "fingerprinting $t key using private key file" + rm -f $OBJ/$t-key.pub + if [ ! -z "$oldfmt" ] ; then + # Comment cannot be recovered from old format keys. + comment="no comment" + fi + check_fingerprint $OBJ/$t-key "${comment}" + rm -f $OBJ/$t-key* + done +done diff --git a/regress/keygen-moduli.sh b/regress/keygen-moduli.sh index a8eccfb69..8be53f92f 100644 --- a/regress/keygen-moduli.sh +++ b/regress/keygen-moduli.sh @@ -1,4 +1,4 @@ -# $OpenBSD: keygen-moduli.sh,v 1.3 2019/07/23 08:19:29 dtucker Exp $ +# $OpenBSD: keygen-moduli.sh,v 1.4 2020/01/02 13:25:38 dtucker Exp $ # Placed in the Public Domain. tid="keygen moduli" @@ -14,10 +14,10 @@ done # and "skip 2 and run to the end with checkpointing". Since our test data # file has 3 lines, these should always result in 1 line of output. if [ "x$dhgex" = "x1" ]; then - for i in "-J1" "-j1 -J1" "-j2 -K $OBJ/moduli.ckpt"; do + for i in "-O lines=1" "-O start-line=1 -O lines=1" "-O start-line=2 -O checkpoint=$OBJ/moduli.ckpt"; do trace "keygen $i" rm -f $OBJ/moduli.out $OBJ/moduli.ckpt - ${SSHKEYGEN} -T $OBJ/moduli.out -f ${SRC}/moduli.in $i 2>/dev/null || \ + ${SSHKEYGEN} -M screen -f ${SRC}/moduli.in $i $OBJ/moduli.out 2>/dev/null || \ fail "keygen screen failed $i" lines=`wc -l <$OBJ/moduli.out` test "$lines" -eq "1" || fail "expected 1 line, got $lines" diff --git a/regress/keyscan.sh b/regress/keyscan.sh index 764472b9d..75a14ee0e 100644 --- a/regress/keyscan.sh +++ b/regress/keyscan.sh @@ -1,15 +1,9 @@ -# $OpenBSD: keyscan.sh,v 1.9 2019/01/28 03:50:39 dtucker Exp $ +# $OpenBSD: keyscan.sh,v 1.13 2020/01/22 07:31:27 dtucker Exp $ # Placed in the Public Domain. tid="keyscan" -if [ "$os" == "windows" ]; then - # Remove CR (carriage return) - KEYTYPES=`${SSH} -Q key-plain | sed 's/\r$//'` -else - KEYTYPES=`${SSH} -Q key-plain` -fi -for i in $KEYTYPES; do +for i in $SSH_KEYTYPES; do if [ -z "$algs" ]; then algs="$i" else @@ -20,9 +14,9 @@ echo "HostKeyAlgorithms $algs" >> $OBJ/sshd_config start_sshd -for t in $KEYTYPES; do +for t in $SSH_KEYTYPES; do trace "keyscan type $t" - ${SSHKEYSCAN} -t $t -p $PORT 127.0.0.1 127.0.0.1 127.0.0.1 \ + ${SSHKEYSCAN} -t $t -T 15 -p $PORT 127.0.0.1 127.0.0.1 127.0.0.1 \ > /dev/null 2>&1 r=$? if [ $r -ne 0 ]; then diff --git a/regress/keytype.sh b/regress/keytype.sh index 13095088e..f1c045183 100644 --- a/regress/keytype.sh +++ b/regress/keytype.sh @@ -1,4 +1,4 @@ -# $OpenBSD: keytype.sh,v 1.8 2019/07/23 13:49:14 dtucker Exp $ +# $OpenBSD: keytype.sh,v 1.11 2021/02/25 03:27:34 djm Exp $ # Placed in the Public Domain. tid="login with different key types" @@ -16,43 +16,56 @@ for i in ${SSH_KEYTYPES}; do ecdsa-sha2-nistp256) ktypes="$ktypes ecdsa-256" ;; ecdsa-sha2-nistp384) ktypes="$ktypes ecdsa-384" ;; ecdsa-sha2-nistp521) ktypes="$ktypes ecdsa-521" ;; + sk-ssh-ed25519*) ktypes="$ktypes ed25519-sk" ;; + sk-ecdsa-sha2-nistp256*) ktypes="$ktypes ecdsa-sk" ;; esac done for kt in $ktypes; do rm -f $OBJ/key.$kt - bits=`echo ${kt} | awk -F- '{print $2}'` - type=`echo ${kt} | awk -F- '{print $1}'` + xbits=`echo ${kt} | awk -F- '{print $2}'` + xtype=`echo ${kt} | awk -F- '{print $1}'` + case "$kt" in + *sk) type="$kt"; bits="n/a"; bits_arg="";; + *) type=$xtype; bits=$xbits; bits_arg="-b $bits";; + esac verbose "keygen $type, $bits bits" - ${SSHKEYGEN} -b $bits -q -N '' -t $type -f $OBJ/key.$kt ||\ + ${SSHKEYGEN} $bits_arg -q -N '' -t $type -f $OBJ/key.$kt || \ fail "ssh-keygen for type $type, $bits bits failed" done +kname_to_ktype() { + case $1 in + dsa-1024) echo ssh-dss;; + ecdsa-256) echo ecdsa-sha2-nistp256;; + ecdsa-384) echo ecdsa-sha2-nistp384;; + ecdsa-521) echo ecdsa-sha2-nistp521;; + ed25519-512) echo ssh-ed25519;; + rsa-*) echo rsa-sha2-512,rsa-sha2-256,ssh-rsa;; + ed25519-sk) echo sk-ssh-ed25519@openssh.com;; + ecdsa-sk) echo sk-ecdsa-sha2-nistp256@openssh.com;; + esac +} + tries="1 2 3" for ut in $ktypes; do - htypes=$ut + user_type=`kname_to_ktype "$ut"` + htypes="$ut" #htypes=$ktypes for ht in $htypes; do - case $ht in - dsa-1024) t=ssh-dss;; - ecdsa-256) t=ecdsa-sha2-nistp256;; - ecdsa-384) t=ecdsa-sha2-nistp384;; - ecdsa-521) t=ecdsa-sha2-nistp521;; - ed25519-512) t=ssh-ed25519;; - rsa-*) t=rsa-sha2-512,rsa-sha2-256,ssh-rsa;; - esac + host_type=`kname_to_ktype "$ht"` trace "ssh connect, userkey $ut, hostkey $ht" ( grep -v HostKey $OBJ/sshd_proxy_bak echo HostKey $OBJ/key.$ht - echo PubkeyAcceptedKeyTypes $t - echo HostKeyAlgorithms $t + echo PubkeyAcceptedAlgorithms $user_type + echo HostKeyAlgorithms $host_type ) > $OBJ/sshd_proxy ( grep -v IdentityFile $OBJ/ssh_proxy_bak echo IdentityFile $OBJ/key.$ut - echo PubkeyAcceptedKeyTypes $t - echo HostKeyAlgorithms $t + echo PubkeyAcceptedAlgorithms $user_type + echo HostKeyAlgorithms $host_type ) > $OBJ/ssh_proxy ( printf 'localhost-with-alias,127.0.0.1,::1 ' diff --git a/regress/knownhosts-command.sh b/regress/knownhosts-command.sh new file mode 100644 index 000000000..f15df670b --- /dev/null +++ b/regress/knownhosts-command.sh @@ -0,0 +1,53 @@ +# $OpenBSD: knownhosts-command.sh,v 1.2 2020/12/22 06:47:24 djm Exp $ +# Placed in the Public Domain. + +tid="known hosts command " + +rm -f $OBJ/knownhosts_command $OBJ/ssh_proxy_khc +cp $OBJ/ssh_proxy $OBJ/ssh_proxy_orig + +( grep -vi GlobalKnownHostsFile $OBJ/ssh_proxy_orig | \ + grep -vi UserKnownHostsFile; + echo "GlobalKnownHostsFile none" ; + echo "UserKnownHostsFile none" ; + echo "KnownHostsCommand $OBJ/knownhosts_command '%t' '%K' '%u'" ; +) > $OBJ/ssh_proxy + +verbose "simple connection" +cat > $OBJ/knownhosts_command << _EOF +#!/bin/sh +cat $OBJ/known_hosts +_EOF +chmod a+x $OBJ/knownhosts_command +${SSH} -F $OBJ/ssh_proxy x true || fail "ssh connect failed" + +verbose "no keys" +cat > $OBJ/knownhosts_command << _EOF +#!/bin/sh +exit 0 +_EOF +chmod a+x $OBJ/knownhosts_command +${SSH} -F $OBJ/ssh_proxy x true && fail "ssh connect succeeded with no keys" + +verbose "bad exit status" +cat > $OBJ/knownhosts_command << _EOF +#!/bin/sh +cat $OBJ/known_hosts +exit 1 +_EOF +chmod a+x $OBJ/knownhosts_command +${SSH} -F $OBJ/ssh_proxy x true && fail "ssh connect succeeded with bad exit" + +for keytype in ${SSH_HOSTKEY_TYPES} ; do + test "x$keytype" = "xssh-dss" && continue + verbose "keytype $keytype" + cat > $OBJ/knownhosts_command << _EOF +#!/bin/sh +die() { echo "\$@" 1>&2 ; exit 1; } +test "x\$1" = "x$keytype" || die "wrong keytype \$1 (expected $keytype)" +test "x\$3" = "x$LOGNAME" || die "wrong username \$3 (expected $LOGNAME)" +grep -- "\$1.*\$2" $OBJ/known_hosts +_EOF + ${SSH} -F $OBJ/ssh_proxy -oHostKeyAlgorithms=$keytype x true || + fail "ssh connect failed for keytype $x" +done diff --git a/regress/krl.sh b/regress/krl.sh index fdd87686c..bf73c9e37 100644 --- a/regress/krl.sh +++ b/regress/krl.sh @@ -1,16 +1,19 @@ -# $OpenBSD: krl.sh,v 1.8 2019/07/25 09:17:35 dtucker Exp $ +# $OpenBSD: krl.sh,v 1.11 2019/12/16 02:39:05 djm Exp $ # Placed in the Public Domain. tid="key revocation lists" # Use ed25519 by default since it's fast and it's supported when building # w/out OpenSSL. Populate ktype[2-4] with the other types if supported. -ktype1=ed25519; ktype2=ed25519; ktype3=ed25519; ktype4=ed25519 -for t in `${SSH} -Q key-plain`; do +ktype1=ed25519; ktype2=ed25519; ktype3=ed25519; +ktype4=ed25519; ktype5=ed25519; ktype6=ed25519; +for t in $SSH_KEYTYPES; do case "$t" in ecdsa*) ktype2=ecdsa ;; ssh-rsa) ktype3=rsa ;; ssh-dss) ktype4=dsa ;; + sk-ssh-ed25519@openssh.com) ktype5=ed25519-sk ;; + sk-ecdsa-sha2-nistp256@openssh.com) ktype6=ecdsa-sk ;; esac done @@ -34,6 +37,7 @@ serial: 10 serial: 15 serial: 30 serial: 50 +serial: 90 serial: 999 # The following sum to 500-799 serial: 500 @@ -56,7 +60,7 @@ if [ "$os" == "windows" ]; then else revokedids=`jot 500 300` fi -for n in 1 2 3 4 10 15 30 50 $revokedids 999 1000 1001 1002; do +for n in 1 2 3 4 10 15 30 50 90 $revokedids 999 1000 1001 1002; do test "x$n" = "x499" && continue # Fill in by-ID revocation spec. echo "id: revoked $n" >> $OBJ/revoked-keyid @@ -69,9 +73,11 @@ keygen() { # supported. keytype=$ktype1 case $N in - 2 | 10 | 510 | 1001) keytype=$ktype2 ;; - 4 | 30 | 520 | 1002) keytype=$ktype3 ;; - 8 | 50 | 530 | 1003) keytype=$ktype4 ;; + 2 | 10 | 510 | 1001) keytype=$ktype2 ;; + 4 | 30 | 520 | 1002) keytype=$ktype3 ;; + 8 | 50 | 530 | 1003) keytype=$ktype4 ;; + 16 | 70 | 540 | 1004) keytype=$ktype5 ;; + 32 | 90 | 550 | 1005) keytype=$ktype6 ;; esac $SSHKEYGEN -t $keytype -f $f -C "" -N "" > /dev/null \ || fatal "$SSHKEYGEN failed" @@ -83,7 +89,7 @@ keygen() { # Generate some keys. verbose "$tid: generating test keys" -REVOKED_SERIALS="1 4 10 50 500 510 520 799 999" +REVOKED_SERIALS="1 4 10 50 90 500 510 520 550 799 999" for n in $REVOKED_SERIALS ; do f=`keygen $n` RKEYS="$RKEYS ${f}.pub" diff --git a/regress/limit-keytype.sh b/regress/limit-keytype.sh index 2eb51ab1b..e333de9a7 100644 --- a/regress/limit-keytype.sh +++ b/regress/limit-keytype.sh @@ -1,20 +1,25 @@ -# $OpenBSD: limit-keytype.sh,v 1.6 2019/07/26 04:22:21 dtucker Exp $ +# $OpenBSD: limit-keytype.sh,v 1.10 2021/02/25 03:27:34 djm Exp $ # Placed in the Public Domain. tid="restrict pubkey type" +# XXX sk-* keys aren't actually tested ATM. + 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 -ktype1=ed25519; ktype2=$ktype1; ktype3=$ktype1; ktype4=$ktype1 -for t in `${SSH} -Q key-plain`; do +ktype1=ed25519; ktype2=ed25519; ktype3=ed25519; +ktype4=ed25519; ktype5=ed25519; ktype6=ed25519; +for t in $SSH_KEYTYPES ; do case "$t" in ssh-rsa) ktype2=rsa ;; ecdsa*) ktype3=ecdsa ;; # unused ssh-dss) ktype4=dsa ;; + sk-ssh-ed25519@openssh.com) ktype5=ed25519-sk ;; + sk-ecdsa-sha2-nistp256@openssh.com) ktype6=ecdsa-sk ;; esac done @@ -31,6 +36,10 @@ ${SSHKEYGEN} -q -N '' -t $ktype2 -f $OBJ/user_key3 || \ fatal "ssh-keygen failed" ${SSHKEYGEN} -q -N '' -t $ktype4 -f $OBJ/user_key4 || \ fatal "ssh-keygen failed" +${SSHKEYGEN} -q -N '' -t $ktype5 -f $OBJ/user_key5 || \ + fatal "ssh-keygen failed" +${SSHKEYGEN} -q -N '' -t $ktype6 -f $OBJ/user_key6 || \ + fatal "ssh-keygen failed" ${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \ -z $$ -n ${USER},mekmitasdigoat $OBJ/user_key3 || fatal "couldn't sign user_key1" @@ -60,7 +69,7 @@ prepare_config() { ) > $OBJ/sshd_proxy } -# Return the required parameter for PubkeyAcceptedKeyTypes corresponding to +# Return the required parameter for PubkeyAcceptedAlgorithms corresponding to # the supplied key type. keytype() { case "$1" in @@ -68,6 +77,8 @@ keytype() { ed25519) printf "ssh-ed25519" ;; dsa) printf "ssh-dss" ;; rsa) printf "rsa-sha2-256,rsa-sha2-512,ssh-rsa" ;; + sk-ecdsa) printf "sk-ecdsa-*" ;; + sk-ssh-ed25519) printf "sk-ssh-ed25519-*" ;; esac } @@ -81,14 +92,14 @@ ${SSH} $opts -i $OBJ/user_key2 proxy true || fatal "key2 failed" # Allow plain Ed25519 and RSA. The certificate should fail. verbose "allow $ktype2,$ktype1" prepare_config \ - "PubkeyAcceptedKeyTypes `keytype $ktype2`,`keytype $ktype1`" + "PubkeyAcceptedAlgorithms `keytype $ktype2`,`keytype $ktype1`" ${SSH} $certopts proxy true && fatal "cert succeeded" ${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed" ${SSH} $opts -i $OBJ/user_key2 proxy true || fatal "key2 failed" # Allow Ed25519 only. verbose "allow $ktype1" -prepare_config "PubkeyAcceptedKeyTypes `keytype $ktype1`" +prepare_config "PubkeyAcceptedAlgorithms `keytype $ktype1`" ${SSH} $certopts proxy true && fatal "cert succeeded" ${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed" if [ "$ktype1" != "$ktype2" ]; then @@ -97,15 +108,15 @@ fi # Allow all certs. Plain keys should fail. verbose "allow cert only" -prepare_config "PubkeyAcceptedKeyTypes *-cert-v01@openssh.com" +prepare_config "PubkeyAcceptedAlgorithms *-cert-v01@openssh.com" ${SSH} $certopts proxy true || fatal "cert failed" ${SSH} $opts -i $OBJ/user_key1 proxy true && fatal "key1 succeeded" ${SSH} $opts -i $OBJ/user_key2 proxy true && fatal "key2 succeeded" # Allow RSA in main config, Ed25519 for non-existent user. verbose "match w/ no match" -prepare_config "PubkeyAcceptedKeyTypes `keytype $ktype2`" \ - "Match user x$USER" "PubkeyAcceptedKeyTypes +`keytype $ktype1`" +prepare_config "PubkeyAcceptedAlgorithms `keytype $ktype2`" \ + "Match user x$USER" "PubkeyAcceptedAlgorithms +`keytype $ktype1`" ${SSH} $certopts proxy true && fatal "cert succeeded" if [ "$ktype1" != "$ktype2" ]; then ${SSH} $opts -i $OBJ/user_key1 proxy true && fatal "key1 succeeded" @@ -116,11 +127,11 @@ ${SSH} $opts -i $OBJ/user_key2 proxy true || fatal "key2 failed" verbose "match w/ matching" if [ "$os" == "windows" ]; then # If User is domainuser then it will be in "domain/user" so convert it to "domain\user" - prepare_config "PubkeyAcceptedKeyTypes `keytype $ktype4`" \ - "Match user ${USER//\//\\}" "PubkeyAcceptedKeyTypes +`keytype $ktype1`" + prepare_config "PubkeyAcceptedAlgorithms `keytype $ktype4`" \ + "Match user ${USER//\//\\}" "PubkeyAcceptedAlgorithms +`keytype $ktype1`" else - prepare_config "PubkeyAcceptedKeyTypes `keytype $ktype4`" \ - "Match user $USER" "PubkeyAcceptedKeyTypes +`keytype $ktype1`" + prepare_config "PubkeyAcceptedAlgorithms `keytype $ktype4`" \ + "Match user $USER" "PubkeyAcceptedAlgorithms +`keytype $ktype1`" fi ${SSH} $certopts proxy true || fatal "cert failed" ${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed" diff --git a/regress/misc/Makefile b/regress/misc/Makefile index 14c0c279f..b9149f287 100644 --- a/regress/misc/Makefile +++ b/regress/misc/Makefile @@ -1,3 +1,3 @@ -SUBDIR= kexfuzz +SUBDIR= sk-dummy .include diff --git a/regress/misc/fuzz-harness/Makefile b/regress/misc/fuzz-harness/Makefile index 85179ac4e..e879fcdae 100644 --- a/regress/misc/fuzz-harness/Makefile +++ b/regress/misc/fuzz-harness/Makefile @@ -1,33 +1,52 @@ # NB. libssh and libopenbsd-compat should be built with the same sanitizer opts. -CXX=clang++-6.0 -FUZZ_FLAGS=-fsanitize=address,undefined -fsanitize-coverage=edge,trace-pc +CC=clang-11 +CXX=clang++-11 +FUZZ_FLAGS=-fsanitize=address,fuzzer -fno-omit-frame-pointer FUZZ_LIBS=-lFuzzer -CXXFLAGS=-O2 -g -Wall -Wextra -I ../../.. $(FUZZ_FLAGS) +CXXFLAGS=-O2 -g -Wall -Wextra -Wno-unused-parameter -I ../../.. $(FUZZ_FLAGS) +CFLAGS=$(CXXFLAGS) LDFLAGS=-L ../../.. -L ../../../openbsd-compat -g $(FUZZ_FLAGS) -LIBS=-lssh -lopenbsd-compat -lcrypto $(FUZZ_LIBS) +LIBS=-lssh -lopenbsd-compat -lcrypto -lfido2 -lcbor $(FUZZ_LIBS) +SK_NULL_OBJS=ssh-sk-null.o +COMMON_DEPS=../../../libssh.a -TARGETS=pubkey_fuzz sig_fuzz authopt_fuzz sshsig_fuzz sshsigopt_fuzz +TARGETS=pubkey_fuzz sig_fuzz authopt_fuzz sshsig_fuzz \ + sshsigopt_fuzz privkey_fuzz kex_fuzz agent_fuzz all: $(TARGETS) .cc.o: $(CXX) $(CXXFLAGS) -c $< -o $@ -pubkey_fuzz: pubkey_fuzz.o - $(CXX) -o $@ pubkey_fuzz.o $(LDFLAGS) $(LIBS) +pubkey_fuzz: pubkey_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) + $(CXX) -o $@ pubkey_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS) -sig_fuzz: sig_fuzz.o - $(CXX) -o $@ sig_fuzz.o $(LDFLAGS) $(LIBS) +sig_fuzz: sig_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) + $(CXX) -o $@ sig_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS) -authopt_fuzz: authopt_fuzz.o - $(CXX) -o $@ authopt_fuzz.o ../../../auth-options.o $(LDFLAGS) $(LIBS) +authopt_fuzz: authopt_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) + $(CXX) -o $@ authopt_fuzz.o $(SK_NULL_OBJS) ../../../auth-options.o $(LDFLAGS) $(LIBS) -sshsig_fuzz: sshsig_fuzz.o - $(CXX) -o $@ sshsig_fuzz.o ../../../sshsig.o $(LDFLAGS) $(LIBS) +sshsig_fuzz: sshsig_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) + $(CXX) -o $@ sshsig_fuzz.o $(SK_NULL_OBJS) ../../../sshsig.o $(LDFLAGS) $(LIBS) -sshsigopt_fuzz: sshsigopt_fuzz.o - $(CXX) -o $@ sshsigopt_fuzz.o ../../../sshsig.o $(LDFLAGS) $(LIBS) +sshsigopt_fuzz: sshsigopt_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) + $(CXX) -o $@ sshsigopt_fuzz.o $(SK_NULL_OBJS) ../../../sshsig.o $(LDFLAGS) $(LIBS) + +privkey_fuzz: privkey_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) + $(CXX) -o $@ privkey_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS) + +kex_fuzz: kex_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS) + $(CXX) -o $@ kex_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS) -lz + +agent_fuzz: agent_fuzz.o agent_fuzz_helper.o sk-dummy.o ../../../ssh-sk.o $(COMMON_DEPS) + $(CXX) -o $@ agent_fuzz.o agent_fuzz_helper.o sk-dummy.o ../../../ssh-sk.o $(LDFLAGS) $(LIBS) -lz + +agent_fuzz_helper.o: agent_fuzz_helper.c ../../../ssh-agent.c + +sk-dummy.o: ../sk-dummy/sk-dummy.c + $(CC) $(CFLAGS) -c -o $@ ../sk-dummy/sk-dummy.c -DSK_DUMMY_INTEGRATE=1 $(LDFLAGS) clean: -rm -f *.o $(TARGETS) diff --git a/regress/misc/fuzz-harness/agent_fuzz.cc b/regress/misc/fuzz-harness/agent_fuzz.cc new file mode 100644 index 000000000..ad85b2f9a --- /dev/null +++ b/regress/misc/fuzz-harness/agent_fuzz.cc @@ -0,0 +1,15 @@ +// cc_fuzz_target test for ssh-agent. +extern "C" { + +#include +#include + +extern void test_one(const uint8_t* s, size_t slen); + +int LLVMFuzzerTestOneInput(const uint8_t* s, size_t slen) +{ + test_one(s, slen); + return 0; +} + +} // extern diff --git a/regress/misc/fuzz-harness/agent_fuzz_helper.c b/regress/misc/fuzz-harness/agent_fuzz_helper.c new file mode 100644 index 000000000..1d419820c --- /dev/null +++ b/regress/misc/fuzz-harness/agent_fuzz_helper.c @@ -0,0 +1,177 @@ +#include "fixed-keys.h" +#include + +#define main(ac, av) xxxmain(ac, av) +#include "../../../ssh-agent.c" + +void test_one(const uint8_t* s, size_t slen); + +static int +devnull_or_die(void) +{ + int fd; + + if ((fd = open("/dev/null", O_RDWR)) == -1) { + error_f("open /dev/null: %s", strerror(errno)); + abort(); + } + return fd; +} + +static struct sshkey * +pubkey_or_die(const char *s) +{ + char *tmp, *cp; + struct sshkey *pubkey; + int r; + + tmp = cp = xstrdup(s); + if ((pubkey = sshkey_new(KEY_UNSPEC)) == NULL) + abort(); + if ((r = sshkey_read(pubkey, &cp)) != 0) { + error_fr(r, "parse"); + abort(); + } + free(tmp); + return pubkey; +} + +static struct sshkey * +privkey_or_die(const char *s) +{ + int r; + struct sshbuf *b; + struct sshkey *privkey; + + if ((b = sshbuf_from(s, strlen(s))) == NULL) { + error_f("sshbuf_from failed"); + abort(); + } + if ((r = sshkey_parse_private_fileblob(b, "", &privkey, NULL)) != 0) { + error_fr(r, "parse"); + abort(); + } + sshbuf_free(b); + return privkey; +} + +static void +add_key(const char *privkey, const char *certpath) +{ + Identity *id; + int r; + struct sshkey *cert; + + id = xcalloc(1, sizeof(Identity)); + TAILQ_INSERT_TAIL(&idtab->idlist, id, next); + idtab->nentries++; + id->key = privkey_or_die(privkey); + id->comment = xstrdup("rhododaktulos Eos"); + if (sshkey_is_sk(id->key)) + id->sk_provider = xstrdup("internal"); + + /* Now the cert too */ + id = xcalloc(1, sizeof(Identity)); + TAILQ_INSERT_TAIL(&idtab->idlist, id, next); + idtab->nentries++; + id->key = privkey_or_die(privkey); + cert = pubkey_or_die(certpath); + if ((r = sshkey_to_certified(id->key)) != 0) { + error_fr(r, "sshkey_to_certified"); + abort(); + } + if ((r = sshkey_cert_copy(cert, id->key)) != 0) { + error_fr(r, "sshkey_cert_copy"); + abort(); + } + sshkey_free(cert); + id->comment = xstrdup("outis"); + if (sshkey_is_sk(id->key)) + id->sk_provider = xstrdup("internal"); +} + +static void +cleanup_idtab(void) +{ + Identity *id; + + if (idtab == NULL) return; + for (id = TAILQ_FIRST(&idtab->idlist); id; + id = TAILQ_FIRST(&idtab->idlist)) { + TAILQ_REMOVE(&idtab->idlist, id, next); + free_identity(id); + } + free(idtab); + idtab = NULL; +} + +static void +reset_idtab(void) +{ + cleanup_idtab(); + idtab_init(); + // Load keys. + add_key(PRIV_RSA, CERT_RSA); + add_key(PRIV_DSA, CERT_DSA); + add_key(PRIV_ECDSA, CERT_ECDSA); + add_key(PRIV_ED25519, CERT_ED25519); + add_key(PRIV_ECDSA_SK, CERT_ECDSA_SK); + add_key(PRIV_ED25519_SK, CERT_ED25519_SK); +} + +static void +cleanup_sockettab(void) +{ + u_int i; + for (i = 0; i < sockets_alloc; i++) { + if (sockets[i].type != AUTH_UNUSED) + close_socket(sockets + i); + } + free(sockets); + sockets = NULL; + sockets_alloc = 0; +} + +static void +reset_sockettab(int devnull) +{ + int fd; + + cleanup_sockettab(); + if ((fd = dup(devnull)) == -1) { + error_f("dup: %s", strerror(errno)); + abort(); + } + new_socket(AUTH_CONNECTION, fd); + assert(sockets[0].type == AUTH_CONNECTION); + assert(sockets[0].fd == fd); +} + +#define MAX_MESSAGES 256 +void +test_one(const uint8_t* s, size_t slen) +{ + static int devnull = -1; + size_t i, olen, nlen; + + if (devnull == -1) { + log_init(__progname, SYSLOG_LEVEL_DEBUG3, + SYSLOG_FACILITY_AUTH, 1); + devnull = devnull_or_die(); + allowed_providers = xstrdup(""); + setenv("DISPLAY", "", 1); /* ban askpass */ + } + + reset_idtab(); + reset_sockettab(devnull); + (void)sshbuf_put(sockets[0].input, s, slen); + for (i = 0; i < MAX_MESSAGES; i++) { + olen = sshbuf_len(sockets[0].input); + process_message(0); + nlen = sshbuf_len(sockets[0].input); + if (nlen == 0 || nlen == olen) + break; + } + cleanup_idtab(); + cleanup_sockettab(); +} diff --git a/regress/misc/fuzz-harness/fixed-keys.h b/regress/misc/fuzz-harness/fixed-keys.h new file mode 100644 index 000000000..c6e7c6cc1 --- /dev/null +++ b/regress/misc/fuzz-harness/fixed-keys.h @@ -0,0 +1,119 @@ +/* + * Some keys used by fuzzers + */ + +#define PRIV_RSA \ +"-----BEGIN OPENSSH PRIVATE KEY-----\n"\ +"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n"\ +"NhAAAAAwEAAQAAAQEA3+epf+VGKoGPaAZXrf6S0cyumQnddkGBnVFX0A5eh37RtLug0qY5\n"\ +"thxsBUbGGVr9mTd2QXwLujBwYg5l1MP/Fmg+5312Zgx9pHmS+qKULbar0hlNgptNEb+aNU\n"\ +"d3o9qg3aXqXm7+ZnjAV05ef/mxNRN2ZvuEkw7cRppTJcbBI+vF3lXuCXnX2klDI95Gl2AW\n"\ +"3WHRtanqLHZXuBkjjRBDKc7MUq/GP1hmLiAd95dvU7fZjRlIEsP84zGEI1Fb0L/kmPHcOt\n"\ +"iVfHft8CtmC9v6+94JrOiPBBNScV+dyrgAGPsdKdr/1vIpQmCNiI8s3PCiD8J7ZiBaYm0I\n"\ +"8fq5G/qnUwAAA7ggw2dXIMNnVwAAAAdzc2gtcnNhAAABAQDf56l/5UYqgY9oBlet/pLRzK\n"\ +"6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZm\n"\ +"DH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGml\n"\ +"MlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29T\n"\ +"t9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v\n"\ +"/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAwEAAQAAAQEArWm5B4tFasppjUHM\n"\ +"SsAuajtCxtizI1Hc10EW59cZM4vvUzE2f6+qZvdgWj3UU/L7Et23w0QVuSCnCerox379ZB\n"\ +"ddEOFFAAiQjwBx65hbd4RRUymxtIQfjq18++LcMJW1nbVQ7c69ThQbtALIggmbS+ZE/8Gx\n"\ +"jkwmIrCH0Ww8TlpsPe+mNHuyNk7UEZoXLm22lNLqq5qkIL5JgT6M2iNJpMOJy9/CKi6kO4\n"\ +"JPuVwjdG4C5pBPaMN3KJ1IvAlSlLGNaXnfXcn85gWfsCjsZmH3liey2NJamqp/w83BrKUg\n"\ +"YZvMR2qeWZaKkFTahpzN5KRK1BFeB37O0P84Dzh1biDX8QAAAIEAiWXW8ePYFwLpa2mFIh\n"\ +"VvRTdcrN70rVK5eWVaL3pyS4vGA56Jixq86dHveOnbSY+iNb1jQidtXc8SWUt2wtHqZ32h\n"\ +"Lji9/hMSKqe9SEP3xvDRDmUJqsVw0ySyrFrzm4160QY6RKU3CIQCVFslMZ9fxmrfZ/hxoU\n"\ +"0X3FVsxmC4+kwAAACBAPOc1YERpV6PjANBrGR+1o1RCdACbm5myc42QzSNIaOZmgrYs+Gt\n"\ +"7+EcoqSdbJzHJNCNQfF+A+vjbIkFiuZqq/5wwr59qXx5OAlijLB/ywwKmTWq6lp//Zxny+\n"\ +"ka3sIGNO14eQvmxNDnlLL+RIZleCTEKBXSW6CZhr+uHMZFKKMtAAAAgQDrSkm+LbILB7H9\n"\ +"jxEBZLhv53aAn4u81kFKQOJ7PzzpBGSoD12i7oIJu5siSD5EKDNVEr+SvCf0ISU3BuMpzl\n"\ +"t3YrPrHRheOFhn5e3j0e//zB8rBC0DGB4CtTDdeh7rOXUL4K0pz+8wEpNkV62SWxhC6NRW\n"\ +"I79JhtGkh+GtcnkEfwAAAAAB\n"\ +"-----END OPENSSH PRIVATE KEY-----\n" +#define PUB_RSA \ +"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdT" +#define CERT_RSA \ +"ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg89JX6OBMYDSxER8fnU5y8xxeMCHR/hI0uVqdEhNyCpcAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAAAAA+0AAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQGCDA6PWw4x9bHQl0w7NqifHepumqD3dmyMx+hZGuPRon+TsyCjfytu7hWmV7l9XUF0fPQNFQ7FGat5e+7YUNgE= id_rsa.pub" +#define PRIV_DSA \ +"-----BEGIN OPENSSH PRIVATE KEY-----\n"\ +"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH\n"\ +"NzAAAAgQCsGTfjpQ465EOkfQXJM9BOvfRQE0fqlykAls+ncz+T7hrbeScRu8xpwzsznJNm\n"\ +"xlW8o6cUDiHmBJ5OHgamUC9N7YJeU/6fnOAZifgN8mqK6k8pKHuje8ANOiYgHLl0yiASQA\n"\ +"3//qMyzZ+W/hemoLSmLAbEqlfWVeyYx+wta1Vm+QAAABUAvWyehvUvdHvQxavYgS5p0t5Q\n"\ +"d7UAAACBAIRA9Yy+f4Kzqpv/qICPO3zk42UuP7WAhSW2nCbQdLlCiSTxcjKgcvXNRckwJP\n"\ +"44JjSHOtJy/AMtJrPIbLYG6KuWTdBlEHFiG6DafvLG+qPMSL2bPjXTOhuOMbCHIZ+5WBkW\n"\ +"THeG/Nv11iI01Of9V6tXkig23K370flkRkXFi9MdAAAAgCt6YUcQkNwG7B/e5M1FZsLP9O\n"\ +"kVB3BwLAOjmWdHpyhu3HpwSJa3XLEvhXN0i6IVI2KgPo/2GtYA6rHt14L+6u1pmhh8sAvQ\n"\ +"ksp3qZB+xh/NP+hBqf0sbHX0yYbzKOvI5SCc/kKK6yagcBZOsubM/KC8TxyVgmD5c6WzYs\n"\ +"h5TEpvAAAB2PHjRbbx40W2AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FAT\n"\ +"R+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4B\n"\ +"mJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1r\n"\ +"VWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS\n"\ +"4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIb\n"\ +"oNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRc\n"\ +"WL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SL\n"\ +"ohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJ\n"\ +"z+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAUUA+OGldMi76ClO/sstpdbBUE\n"\ +"lq8AAAAAAQI=\n"\ +"-----END OPENSSH PRIVATE KEY-----\n" +#define PUB_DSA \ +"ssh-dss AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8=" +#define CERT_DSA \ +"ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAguF716Yub+vVKNlONKLsfxGYWkRe/PyjfYdGRTsFaDvAAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAAAAAD6AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAjMQEZcbdUYJBjIC4GxByFDOb8tv71vDZdx7irHwaqIjx5rzpJUuOV1r8ZO4kY+Yaiun1yrWj2QYkfJrHBvD1DA== id_dsa.pub" +#define PRIV_ECDSA \ +"-----BEGIN OPENSSH PRIVATE KEY-----\n"\ +"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS\n"\ +"1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTDJ0VlMv+0rguNzaJ1DF2KueHaxRSQ\n"\ +"6LpIxGbulrg1a8RPbnMXwag5GcDiDllD2lDUJUuBEWyjXA0rZoZX35ELAAAAoE/Bbr5PwW\n"\ +"6+AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43N\n"\ +"onUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQ\n"\ +"sAAAAhAIhE6hCID5oOm1TDktc++KFKyScjLifcZ6Cgv5xSSyLOAAAAAAECAwQFBgc=\n"\ +"-----END OPENSSH PRIVATE KEY-----\n" +#define PUB_ECDSA \ +"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQs=" +#define CERT_ECDSA \ +"ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgVJZuM/1AOe6n++qRWMyUuAThYqLvvQxj5CGflLODp60AAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQsAAAAAAAAD6QAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAtdJpcF6ZmQL+ueices4QZeL7AK8Xuo08jyLgiolhjKy2jj4LSUki4aX/ZeZeJuby1ovGrfaeFAgx3itPLR7IAQ== id_ecdsa.pub" +#define PRIV_ED25519 \ +"-----BEGIN OPENSSH PRIVATE KEY-----\n"\ +"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW\n"\ +"QyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAIhWlP99VpT/\n"\ +"fQAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAw\n"\ +"AAAEDE1rlcMC0s0X3TKVZAOVavZOywwkXw8tO5dLObxaCMEDPQXmEVMVLmeFRyafKMVWgP\n"\ +"Dkv8/uRBTwmcEDatZzMDAAAAAAECAwQF\n"\ +"-----END OPENSSH PRIVATE KEY-----\n" +#define PUB_ED25519 \ +"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMD" +#define CERT_ED25519 \ +"ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIMDQjYH6XRzH3j3MW1DdjCoAfvrHfgjnVGF+sLK0pBfqAAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAAAAAA+sAAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQBj0og+s09/HpwdHZbzN0twooKPDWWrxGfnP1Joy6cDnY2BCSQ7zg9vbq11kLF8H/sKOTZWAQrUZ7LlChOu9Ogw= id_ed25519.pub" +#define PRIV_ECDSA_SK \ +"-----BEGIN OPENSSH PRIVATE KEY-----\n"\ +"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2\n"\ +"RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQTYyU76zop1\n"\ +"VOb4DfKWYnR5b0TOC3zw8DzObAfHWB5o6xls+tOYiEleXvIEi00Da2iCK47habZTOhLyeB\n"\ +"X2Avu5AAAABHNzaDoAAAGYqUAQSKlAEEgAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv\n"\ +"cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEE2MlO+s6KdVTm+A3ylmJ0eW9Ezgt88PA8zm\n"\ +"wHx1geaOsZbPrTmIhJXl7yBItNA2togiuO4Wm2UzoS8ngV9gL7uQAAAARzc2g6AQAAAOMt\n"\ +"LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJSHFsZjNsWTkxZFhwUn\n"\ +"dYZDBrS0lYWmNpeDRRcDBNSU15Ny9JMUxXSTFuWG9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn\n"\ +"QUUyTWxPK3M2S2RWVG0rQTN5bG1KMGVXOUV6Z3Q4OFBBOHptd0h4MWdlYU9zWmJQclRtSW\n"\ +"hKClhsN3lCSXROQTJ0b2dpdU80V20yVXpvUzhuZ1Y5Z0w3dVE9PQotLS0tLUVORCBFQyBQ\n"\ +"UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAbZGptQGRqbS5zeWQuY29ycC5nb29nbGUuY29tAQ\n"\ +"IDBAUG\n"\ +"-----END OPENSSH PRIVATE KEY-----\n" +#define PUB_ECDSA_SK \ +"sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOg==" +#define CERT_ECDSA_SK \ +"sk-ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAK3NrLWVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgKLHtIca++5VoDrUAXU/KqGJZ7jZEnuJSTvt7VrYY9foAAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOgAAAAAAAAPqAAAAAQAAAAd1bHlzc2VzAAAAFwAAAAd1bHlzc2VzAAAACG9keXNzZXVzAAAAAAAAAAD//////////wAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEB1naZOQDLaDr+fwn6E9x8/8HeiaUubDzPexfNQMz+m/7RD0gd5uJhHYUfDb5+/sIx1I7bUEeRIDkBbmZ2foo0E" +#define PRIV_ED25519_SK \ +"-----BEGIN OPENSSH PRIVATE KEY-----\n"\ +"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2\n"\ +"gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACCTJtH10vWhIDxd62edvMLg9u2cwYKyqa7332je\n"\ +"RArHjAAAAARzc2g6AAAAwN7vvE3e77xNAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2\n"\ +"9tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoBAAAAQEsS\n"\ +"xLFiVzfpH2mt9xh8i/zmHV646Hud4QruNBAGNl8gkybR9dL1oSA8XetnnbzC4PbtnMGCsq\n"\ +"mu999o3kQKx4wAAAAAAAAAG2RqbUBkam0uc3lkLmNvcnAuZ29vZ2xlLmNvbQECAwQFBg==\n"\ +"-----END OPENSSH PRIVATE KEY-----\n" +#define PUB_ED25519_SK \ +"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDo=" +#define CERT_ED25519_SK \ +"sk-ssh-ed25519-cert-v01@openssh.com AAAAI3NrLXNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJiT+C/VLMWholFZ4xhOyJr0nSLZSFRIM3I07wUNTRPaAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoAAAAAAAAD7AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAX0Pu13B94pVR3qq8MJQGkOS1Cd7AAM1k6O2VSwyDPM/LfsWIQ4ywgxDmk3hjXWOY7BqljuMxo5VO4JymEIhQBA==" diff --git a/regress/misc/fuzz-harness/kex_fuzz.cc b/regress/misc/fuzz-harness/kex_fuzz.cc new file mode 100644 index 000000000..4740a7cb0 --- /dev/null +++ b/regress/misc/fuzz-harness/kex_fuzz.cc @@ -0,0 +1,461 @@ +// libfuzzer driver for key exchange fuzzing. + + +#include +#include +#include +#include +#include +#include + +extern "C" { + +#include "includes.h" +#include "ssherr.h" +#include "ssh_api.h" +#include "sshbuf.h" +#include "packet.h" +#include "myproposal.h" +#include "xmalloc.h" +#include "authfile.h" +#include "log.h" + +#include "fixed-keys.h" + +// Define if you want to generate traces. +/* #define STANDALONE 1 */ + +static int prepare_key(struct shared_state *st, int keytype, int bits); + +struct shared_state { + size_t nkeys; + struct sshkey **privkeys, **pubkeys; +}; + +struct test_state { + struct sshbuf *smsgs, *cmsgs; /* output, for standalone mode */ + struct sshbuf *sin, *cin; /* input; setup per-test in do_kex_with_key */ + struct sshbuf *s_template, *c_template; /* main copy of input */ +}; + +static int +do_send_and_receive(struct ssh *from, struct ssh *to, + struct sshbuf *store, int clobber, size_t *n) +{ + u_char type; + size_t len; + const u_char *buf; + int r; + + for (*n = 0;; (*n)++) { + if ((r = ssh_packet_next(from, &type)) != 0) { + debug_fr(r, "ssh_packet_next"); + return r; + } + if (type != 0) + return 0; + buf = ssh_output_ptr(from, &len); + debug_f("%zu%s", len, clobber ? " ignore" : ""); + if (len == 0) + return 0; + if ((r = ssh_output_consume(from, len)) != 0) { + debug_fr(r, "ssh_output_consume"); + return r; + } + if (store != NULL && (r = sshbuf_put(store, buf, len)) != 0) { + debug_fr(r, "sshbuf_put"); + return r; + } + if (!clobber && (r = ssh_input_append(to, buf, len)) != 0) { + debug_fr(r, "ssh_input_append"); + return r; + } + } +} + +static int +run_kex(struct test_state *ts, struct ssh *client, struct ssh *server) +{ + int r = 0; + size_t cn, sn; + + /* If fuzzing, replace server/client input */ + if (ts->sin != NULL) { + if ((r = ssh_input_append(server, sshbuf_ptr(ts->sin), + sshbuf_len(ts->sin))) != 0) { + error_fr(r, "ssh_input_append"); + return r; + } + sshbuf_reset(ts->sin); + } + if (ts->cin != NULL) { + if ((r = ssh_input_append(client, sshbuf_ptr(ts->cin), + sshbuf_len(ts->cin))) != 0) { + error_fr(r, "ssh_input_append"); + return r; + } + sshbuf_reset(ts->cin); + } + while (!server->kex->done || !client->kex->done) { + cn = sn = 0; + debug_f("S:"); + if ((r = do_send_and_receive(server, client, + ts->smsgs, ts->cin != NULL, &sn)) != 0) { + debug_fr(r, "S->C"); + break; + } + debug_f("C:"); + if ((r = do_send_and_receive(client, server, + ts->cmsgs, ts->sin != NULL, &cn)) != 0) { + debug_fr(r, "C->S"); + break; + } + if (cn == 0 && sn == 0) { + debug_f("kex stalled"); + r = SSH_ERR_PROTOCOL_ERROR; + break; + } + } + debug_fr(r, "done"); + return r; +} + +static void +store_key(struct shared_state *st, struct sshkey *pubkey, + struct sshkey *privkey) +{ + if (st == NULL || pubkey->type < 0 || pubkey->type > INT_MAX || + privkey->type != pubkey->type || + ((size_t)pubkey->type < st->nkeys && + st->pubkeys[pubkey->type] != NULL)) + abort(); + if ((size_t)pubkey->type >= st->nkeys) { + st->pubkeys = (struct sshkey **)xrecallocarray(st->pubkeys, + st->nkeys, pubkey->type + 1, sizeof(*st->pubkeys)); + st->privkeys = (struct sshkey **)xrecallocarray(st->privkeys, + st->nkeys, privkey->type + 1, sizeof(*st->privkeys)); + st->nkeys = privkey->type + 1; + } + debug_f("store %s at %d", sshkey_ssh_name(pubkey), pubkey->type); + st->pubkeys[pubkey->type] = pubkey; + st->privkeys[privkey->type] = privkey; +} + +static int +prepare_keys(struct shared_state *st) +{ + if (prepare_key(st, KEY_RSA, 2048) != 0 || + prepare_key(st, KEY_DSA, 1024) != 0 || + prepare_key(st, KEY_ECDSA, 256) != 0 || + prepare_key(st, KEY_ED25519, 256) != 0) { + error_f("key prepare failed"); + return -1; + } + return 0; +} + +static struct sshkey * +get_pubkey(struct shared_state *st, int keytype) +{ + if (st == NULL || keytype < 0 || (size_t)keytype >= st->nkeys || + st->pubkeys == NULL || st->pubkeys[keytype] == NULL) + abort(); + return st->pubkeys[keytype]; +} + +static struct sshkey * +get_privkey(struct shared_state *st, int keytype) +{ + if (st == NULL || keytype < 0 || (size_t)keytype >= st->nkeys || + st->privkeys == NULL || st->privkeys[keytype] == NULL) + abort(); + return st->privkeys[keytype]; +} + +static int +do_kex_with_key(struct shared_state *st, struct test_state *ts, + const char *kex, int keytype) +{ + struct ssh *client = NULL, *server = NULL; + struct sshkey *privkey = NULL, *pubkey = NULL; + struct sshbuf *state = NULL; + struct kex_params kex_params; + const char *ccp, *proposal[PROPOSAL_MAX] = { KEX_CLIENT }; + char *myproposal[PROPOSAL_MAX] = {0}, *keyname = NULL; + int i, r; + + ts->cin = ts->sin = NULL; + if (ts->c_template != NULL && + (ts->cin = sshbuf_fromb(ts->c_template)) == NULL) + abort(); + if (ts->s_template != NULL && + (ts->sin = sshbuf_fromb(ts->s_template)) == NULL) + abort(); + + pubkey = get_pubkey(st, keytype); + privkey = get_privkey(st, keytype); + keyname = xstrdup(sshkey_ssh_name(privkey)); + if (ts->cin != NULL) { + debug_f("%s %s clobber client %zu", kex, keyname, + sshbuf_len(ts->cin)); + } else if (ts->sin != NULL) { + debug_f("%s %s clobber server %zu", kex, keyname, + sshbuf_len(ts->sin)); + } else + debug_f("%s %s noclobber", kex, keyname); + + for (i = 0; i < PROPOSAL_MAX; i++) { + ccp = proposal[i]; +#ifdef CIPHER_NONE_AVAIL + if (i == PROPOSAL_ENC_ALGS_CTOS || i == PROPOSAL_ENC_ALGS_STOC) + ccp = "none"; +#endif + if (i == PROPOSAL_SERVER_HOST_KEY_ALGS) + ccp = keyname; + else if (i == PROPOSAL_KEX_ALGS && kex != NULL) + ccp = kex; + if ((myproposal[i] = strdup(ccp)) == NULL) { + error_f("strdup prop %d", i); + goto fail; + } + } + memcpy(kex_params.proposal, myproposal, sizeof(myproposal)); + if ((r = ssh_init(&client, 0, &kex_params)) != 0) { + error_fr(r, "init client"); + goto fail; + } + if ((r = ssh_init(&server, 1, &kex_params)) != 0) { + error_fr(r, "init server"); + goto fail; + } + if ((r = ssh_add_hostkey(server, privkey)) != 0 || + (r = ssh_add_hostkey(client, pubkey)) != 0) { + error_fr(r, "add hostkeys"); + goto fail; + } + if ((r = run_kex(ts, client, server)) != 0) { + error_fr(r, "kex"); + goto fail; + } + /* XXX rekex, set_state, etc */ + fail: + for (i = 0; i < PROPOSAL_MAX; i++) + free(myproposal[i]); + sshbuf_free(ts->sin); + sshbuf_free(ts->cin); + sshbuf_free(state); + ssh_free(client); + ssh_free(server); + free(keyname); + return r; +} + +static int +prepare_key(struct shared_state *st, int kt, int bits) +{ + const char *pubstr = NULL; + const char *privstr = NULL; + char *tmp, *cp; + struct sshkey *privkey = NULL, *pubkey = NULL; + struct sshbuf *b = NULL; + int r; + + switch (kt) { + case KEY_RSA: + pubstr = PUB_RSA; + privstr = PRIV_RSA; + break; + case KEY_DSA: + pubstr = PUB_DSA; + privstr = PRIV_DSA; + break; + case KEY_ECDSA: + pubstr = PUB_ECDSA; + privstr = PRIV_ECDSA; + break; + case KEY_ED25519: + pubstr = PUB_ED25519; + privstr = PRIV_ED25519; + break; + default: + abort(); + } + if ((b = sshbuf_from(privstr, strlen(privstr))) == NULL) + abort(); + if ((r = sshkey_parse_private_fileblob(b, "", &privkey, NULL)) != 0) { + error_fr(r, "priv %d", kt); + abort(); + } + sshbuf_free(b); + tmp = cp = xstrdup(pubstr); + if ((pubkey = sshkey_new(KEY_UNSPEC)) == NULL) + abort(); + if ((r = sshkey_read(pubkey, &cp)) != 0) { + error_fr(r, "pub %d", kt); + abort(); + } + free(tmp); + + store_key(st, pubkey, privkey); + return 0; +} + +#if defined(STANDALONE) + +#if 0 /* use this if generating new keys to embed above */ +static int +prepare_key(struct shared_state *st, int keytype, int bits) +{ + struct sshkey *privkey = NULL, *pubkey = NULL; + int r; + + if ((r = sshkey_generate(keytype, bits, &privkey)) != 0) { + error_fr(r, "generate"); + abort(); + } + if ((r = sshkey_from_private(privkey, &pubkey)) != 0) { + error_fr(r, "make pubkey"); + abort(); + } + store_key(st, pubkey, privkey); + return 0; +} +#endif + +int main(void) +{ + static struct shared_state *st; + struct test_state *ts; + const int keytypes[] = { KEY_RSA, KEY_DSA, KEY_ECDSA, KEY_ED25519, -1 }; + const char *kextypes[] = { + "sntrup761x25519-sha512@openssh.com", + "curve25519-sha256@libssh.org", + "ecdh-sha2-nistp256", + "diffie-hellman-group1-sha1", + "diffie-hellman-group-exchange-sha1", + NULL, + }; + int i, j; + char *path; + FILE *f; + + log_init("kex_fuzz", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 1); + + if (st == NULL) { + st = (struct shared_state *)xcalloc(1, sizeof(*st)); + prepare_keys(st); + } + /* Run each kex method for each key and save client/server packets */ + for (i = 0; keytypes[i] != -1; i++) { + for (j = 0; kextypes[j] != NULL; j++) { + ts = (struct test_state *)xcalloc(1, sizeof(*ts)); + ts->smsgs = sshbuf_new(); + ts->cmsgs = sshbuf_new(); + do_kex_with_key(st, ts, kextypes[j], keytypes[i]); + xasprintf(&path, "S2C-%s-%s", + kextypes[j], sshkey_type(st->pubkeys[keytypes[i]])); + debug_f("%s", path); + if ((f = fopen(path, "wb+")) == NULL) + abort(); + if (fwrite(sshbuf_ptr(ts->smsgs), 1, + sshbuf_len(ts->smsgs), f) != sshbuf_len(ts->smsgs)) + abort(); + fclose(f); + free(path); + //sshbuf_dump(ts->smsgs, stderr); + xasprintf(&path, "C2S-%s-%s", + kextypes[j], sshkey_type(st->pubkeys[keytypes[i]])); + debug_f("%s", path); + if ((f = fopen(path, "wb+")) == NULL) + abort(); + if (fwrite(sshbuf_ptr(ts->cmsgs), 1, + sshbuf_len(ts->cmsgs), f) != sshbuf_len(ts->cmsgs)) + abort(); + fclose(f); + free(path); + //sshbuf_dump(ts->cmsgs, stderr); + sshbuf_free(ts->smsgs); + sshbuf_free(ts->cmsgs); + free(ts); + } + } + for (i = 0; keytypes[i] != -1; i++) { + xasprintf(&path, "%s.priv", + sshkey_type(st->privkeys[keytypes[i]])); + debug_f("%s", path); + if (sshkey_save_private(st->privkeys[keytypes[i]], path, + "", "", SSHKEY_PRIVATE_OPENSSH, NULL, 0) != 0) + abort(); + free(path); + xasprintf(&path, "%s.pub", + sshkey_type(st->pubkeys[keytypes[i]])); + debug_f("%s", path); + if (sshkey_save_public(st->pubkeys[keytypes[i]], path, "") != 0) + abort(); + free(path); + } +} +#else /* !STANDALONE */ +static void +do_kex(struct shared_state *st, struct test_state *ts, const char *kex) +{ + do_kex_with_key(st, ts, kex, KEY_RSA); + do_kex_with_key(st, ts, kex, KEY_DSA); + do_kex_with_key(st, ts, kex, KEY_ECDSA); + do_kex_with_key(st, ts, kex, KEY_ED25519); +} + +static void +kex_tests(struct shared_state *st, struct test_state *ts) +{ + do_kex(st, ts, "sntrup761x25519-sha512@openssh.com"); + do_kex(st, ts, "curve25519-sha256@libssh.org"); + do_kex(st, ts, "ecdh-sha2-nistp256"); + do_kex(st, ts, "diffie-hellman-group1-sha1"); + do_kex(st, ts, "diffie-hellman-group-exchange-sha1"); +} + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + static struct shared_state *st; + struct test_state *ts; + u_char crbuf[SSH_MAX_PRE_BANNER_LINES * 4]; + u_char zbuf[4096] = {0}; + static LogLevel loglevel = SYSLOG_LEVEL_INFO; + + if (st == NULL) { + if (getenv("DEBUG") != NULL || getenv("KEX_FUZZ_DEBUG") != NULL) + loglevel = SYSLOG_LEVEL_DEBUG3; + log_init("kex_fuzz", + loglevel, SYSLOG_FACILITY_AUTH, 1); + st = (struct shared_state *)xcalloc(1, sizeof(*st)); + prepare_keys(st); + } + + /* Ensure that we can complete (fail) banner exchange at least */ + memset(crbuf, '\n', sizeof(crbuf)); + + ts = (struct test_state *)xcalloc(1, sizeof(*ts)); + if ((ts->s_template = sshbuf_new()) == NULL || + sshbuf_put(ts->s_template, data, size) != 0 || + sshbuf_put(ts->s_template, crbuf, sizeof(crbuf)) != 0 || + sshbuf_put(ts->s_template, zbuf, sizeof(zbuf)) != 0) + abort(); + kex_tests(st, ts); + sshbuf_free(ts->s_template); + free(ts); + + ts = (struct test_state *)xcalloc(1, sizeof(*ts)); + if ((ts->c_template = sshbuf_new()) == NULL || + sshbuf_put(ts->c_template, data, size) != 0 || + sshbuf_put(ts->c_template, crbuf, sizeof(crbuf)) != 0 || + sshbuf_put(ts->c_template, zbuf, sizeof(zbuf)) != 0) + abort(); + kex_tests(st, ts); + sshbuf_free(ts->c_template); + free(ts); + + return 0; +} +#endif /* STANDALONE */ +} /* extern "C" */ diff --git a/regress/misc/fuzz-harness/privkey_fuzz.cc b/regress/misc/fuzz-harness/privkey_fuzz.cc new file mode 100644 index 000000000..ff0b0f776 --- /dev/null +++ b/regress/misc/fuzz-harness/privkey_fuzz.cc @@ -0,0 +1,21 @@ +#include +#include +#include + +extern "C" { + +#include "sshkey.h" +#include "sshbuf.h" + +int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + struct sshkey *k = NULL; + struct sshbuf *b = sshbuf_from(data, size); + int r = sshkey_private_deserialize(b, &k); + if (r == 0) sshkey_free(k); + sshbuf_free(b); + return 0; +} + +} // extern + diff --git a/regress/misc/fuzz-harness/sig_fuzz.cc b/regress/misc/fuzz-harness/sig_fuzz.cc index dd1fda091..b32502ba0 100644 --- a/regress/misc/fuzz-harness/sig_fuzz.cc +++ b/regress/misc/fuzz-harness/sig_fuzz.cc @@ -31,19 +31,31 @@ int LLVMFuzzerTestOneInput(const uint8_t* sig, size_t slen) static struct sshkey *ecdsa384 = generate_or_die(KEY_ECDSA, 384); static struct sshkey *ecdsa521 = generate_or_die(KEY_ECDSA, 521); #endif + struct sshkey_sig_details *details = NULL; static struct sshkey *ed25519 = generate_or_die(KEY_ED25519, 0); static const char *data = "If everyone started announcing his nose had " "run away, I don’t know how it would all end"; static const size_t dlen = strlen(data); #ifdef WITH_OPENSSL - sshkey_verify(rsa, sig, slen, (const u_char *)data, dlen, NULL, 0); - sshkey_verify(dsa, sig, slen, (const u_char *)data, dlen, NULL, 0); - sshkey_verify(ecdsa256, sig, slen, (const u_char *)data, dlen, NULL, 0); - sshkey_verify(ecdsa384, sig, slen, (const u_char *)data, dlen, NULL, 0); - sshkey_verify(ecdsa521, sig, slen, (const u_char *)data, dlen, NULL, 0); + sshkey_verify(rsa, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); + sshkey_sig_details_free(details); + details = NULL; + sshkey_verify(dsa, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); + sshkey_sig_details_free(details); + details = NULL; + sshkey_verify(ecdsa256, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); + sshkey_sig_details_free(details); + details = NULL; + sshkey_verify(ecdsa384, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); + sshkey_sig_details_free(details); + details = NULL; + sshkey_verify(ecdsa521, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); + sshkey_sig_details_free(details); + details = NULL; #endif - sshkey_verify(ed25519, sig, slen, (const u_char *)data, dlen, NULL, 0); + sshkey_verify(ed25519, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); + sshkey_sig_details_free(details); return 0; } diff --git a/regress/misc/fuzz-harness/ssh-sk-null.cc b/regress/misc/fuzz-harness/ssh-sk-null.cc new file mode 100644 index 000000000..199af1121 --- /dev/null +++ b/regress/misc/fuzz-harness/ssh-sk-null.cc @@ -0,0 +1,51 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2019 Google LLC + * + * 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. + */ + +extern "C" { + +#include "includes.h" + +#include + +#include "ssherr.h" +#include "ssh-sk.h" + +int +sshsk_enroll(int type, const char *provider_path, const char *device, + const char *application, const char *userid, uint8_t flags, + const char *pin, struct sshbuf *challenge_buf, + struct sshkey **keyp, struct sshbuf *attest) +{ + return SSH_ERR_FEATURE_UNSUPPORTED; +} + +int +sshsk_sign(const char *provider_path, struct sshkey *key, + u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, + u_int compat, const char *pin) +{ + return SSH_ERR_FEATURE_UNSUPPORTED; +} + +int +sshsk_load_resident(const char *provider_path, const char *device, + const char *pin, struct sshkey ***keysp, size_t *nkeysp) +{ + return SSH_ERR_FEATURE_UNSUPPORTED; +} + +}; diff --git a/regress/misc/fuzz-harness/sshsig_fuzz.cc b/regress/misc/fuzz-harness/sshsig_fuzz.cc index fe09ccb87..02211a096 100644 --- a/regress/misc/fuzz-harness/sshsig_fuzz.cc +++ b/regress/misc/fuzz-harness/sshsig_fuzz.cc @@ -22,10 +22,12 @@ int LLVMFuzzerTestOneInput(const uint8_t* sig, size_t slen) struct sshbuf *signature = sshbuf_from(sig, slen); struct sshbuf *message = sshbuf_from(data, strlen(data)); struct sshkey *k = NULL; + struct sshkey_sig_details *details = NULL; extern char *__progname; log_init(__progname, SYSLOG_LEVEL_QUIET, SYSLOG_FACILITY_USER, 1); - sshsig_verifyb(signature, message, "castle", &k); + sshsig_verifyb(signature, message, "castle", &k, &details); + sshkey_sig_details_free(details); sshkey_free(k); sshbuf_free(signature); sshbuf_free(message); diff --git a/regress/misc/fuzz-harness/testdata/README b/regress/misc/fuzz-harness/testdata/README new file mode 100644 index 000000000..752053001 --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/README @@ -0,0 +1,4 @@ +This is preparatory data for fuzzing testing including scripts and test keys, +corresponding to ../fixed-keys that are used in the fuzz tests and consequent +fuzzing seed corpora. They should not be changed unless the affected seed +corpora are also regenerated. diff --git a/regress/misc/fuzz-harness/testdata/create-agent-corpus.sh b/regress/misc/fuzz-harness/testdata/create-agent-corpus.sh new file mode 100755 index 000000000..1043b9ff4 --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/create-agent-corpus.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +# Exercise ssh-agent to generate fuzzing corpus + +# XXX assumes agent hacked up with sk-dummy.o and ssh-sk.o linked directly +# and dumping of e->request for each message. + +set -xe +SSH_AUTH_SOCK=$PWD/sock +rm -f agent-[0-9]* $SSH_AUTH_SOCK +export SSH_AUTH_SOCK +../../../../ssh-agent -D -a $SSH_AUTH_SOCK & +sleep 1 +AGENT_PID=$! +trap "kill $AGENT_PID" EXIT + +PRIV="id_dsa id_ecdsa id_ecdsa_sk id_ed25519 id_ed25519_sk id_rsa" + +# add keys +ssh-add $PRIV + +# sign +ssh-add -T *.pub + +# list +ssh-add -l + +# remove individually +ssh-add -d $PRIV + +# re-add with constraints +ssh-add -c -t 3h $PRIV + +# delete all +ssh-add -D + +# attempt to add a PKCS#11 token +ssh-add -s /fake || : + +# attempt to delete PKCS#11 +ssh-add -e /fake || : + +ssh-add -L + diff --git a/regress/misc/fuzz-harness/testdata/id_dsa b/regress/misc/fuzz-harness/testdata/id_dsa new file mode 100644 index 000000000..88bf5566c --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_dsa @@ -0,0 +1,21 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH +NzAAAAgQCsGTfjpQ465EOkfQXJM9BOvfRQE0fqlykAls+ncz+T7hrbeScRu8xpwzsznJNm +xlW8o6cUDiHmBJ5OHgamUC9N7YJeU/6fnOAZifgN8mqK6k8pKHuje8ANOiYgHLl0yiASQA +3//qMyzZ+W/hemoLSmLAbEqlfWVeyYx+wta1Vm+QAAABUAvWyehvUvdHvQxavYgS5p0t5Q +d7UAAACBAIRA9Yy+f4Kzqpv/qICPO3zk42UuP7WAhSW2nCbQdLlCiSTxcjKgcvXNRckwJP +44JjSHOtJy/AMtJrPIbLYG6KuWTdBlEHFiG6DafvLG+qPMSL2bPjXTOhuOMbCHIZ+5WBkW +THeG/Nv11iI01Of9V6tXkig23K370flkRkXFi9MdAAAAgCt6YUcQkNwG7B/e5M1FZsLP9O +kVB3BwLAOjmWdHpyhu3HpwSJa3XLEvhXN0i6IVI2KgPo/2GtYA6rHt14L+6u1pmhh8sAvQ +ksp3qZB+xh/NP+hBqf0sbHX0yYbzKOvI5SCc/kKK6yagcBZOsubM/KC8TxyVgmD5c6WzYs +h5TEpvAAAB2PHjRbbx40W2AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FAT +R+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4B +mJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1r +VWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS +4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIb +oNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRc +WL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SL +ohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJ +z+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAUUA+OGldMi76ClO/sstpdbBUE +lq8AAAAAAQI= +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/misc/fuzz-harness/testdata/id_dsa-cert.pub b/regress/misc/fuzz-harness/testdata/id_dsa-cert.pub new file mode 100644 index 000000000..3afb87fe6 --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_dsa-cert.pub @@ -0,0 +1 @@ +ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAguF716Yub+vVKNlONKLsfxGYWkRe/PyjfYdGRTsFaDvAAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAAAAAD6AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAjMQEZcbdUYJBjIC4GxByFDOb8tv71vDZdx7irHwaqIjx5rzpJUuOV1r8ZO4kY+Yaiun1yrWj2QYkfJrHBvD1DA== id_dsa.pub diff --git a/regress/misc/fuzz-harness/testdata/id_dsa.pub b/regress/misc/fuzz-harness/testdata/id_dsa.pub new file mode 100644 index 000000000..6f91c4e07 --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_dsa.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8= diff --git a/regress/misc/fuzz-harness/testdata/id_ecdsa b/regress/misc/fuzz-harness/testdata/id_ecdsa new file mode 100644 index 000000000..c1a96c6f9 --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_ecdsa @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS +1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTDJ0VlMv+0rguNzaJ1DF2KueHaxRSQ +6LpIxGbulrg1a8RPbnMXwag5GcDiDllD2lDUJUuBEWyjXA0rZoZX35ELAAAAoE/Bbr5PwW +6+AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43N +onUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQ +sAAAAhAIhE6hCID5oOm1TDktc++KFKyScjLifcZ6Cgv5xSSyLOAAAAAAECAwQFBgc= +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/misc/fuzz-harness/testdata/id_ecdsa-cert.pub b/regress/misc/fuzz-harness/testdata/id_ecdsa-cert.pub new file mode 100644 index 000000000..9de599917 --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_ecdsa-cert.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgVJZuM/1AOe6n++qRWMyUuAThYqLvvQxj5CGflLODp60AAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQsAAAAAAAAD6QAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAtdJpcF6ZmQL+ueices4QZeL7AK8Xuo08jyLgiolhjKy2jj4LSUki4aX/ZeZeJuby1ovGrfaeFAgx3itPLR7IAQ== id_ecdsa.pub diff --git a/regress/misc/fuzz-harness/testdata/id_ecdsa.pub b/regress/misc/fuzz-harness/testdata/id_ecdsa.pub new file mode 100644 index 000000000..30a7cc23b --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_ecdsa.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQs= diff --git a/regress/misc/fuzz-harness/testdata/id_ecdsa_sk b/regress/misc/fuzz-harness/testdata/id_ecdsa_sk new file mode 100644 index 000000000..5a364ed39 --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_ecdsa_sk @@ -0,0 +1,14 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 +RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQTYyU76zop1 +VOb4DfKWYnR5b0TOC3zw8DzObAfHWB5o6xls+tOYiEleXvIEi00Da2iCK47habZTOhLyeB +X2Avu5AAAABHNzaDoAAAGYqUAQSKlAEEgAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv +cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEE2MlO+s6KdVTm+A3ylmJ0eW9Ezgt88PA8zm +wHx1geaOsZbPrTmIhJXl7yBItNA2togiuO4Wm2UzoS8ngV9gL7uQAAAARzc2g6AQAAAOMt +LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJSHFsZjNsWTkxZFhwUn +dYZDBrS0lYWmNpeDRRcDBNSU15Ny9JMUxXSTFuWG9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn +QUUyTWxPK3M2S2RWVG0rQTN5bG1KMGVXOUV6Z3Q4OFBBOHptd0h4MWdlYU9zWmJQclRtSW +hKClhsN3lCSXROQTJ0b2dpdU80V20yVXpvUzhuZ1Y5Z0w3dVE9PQotLS0tLUVORCBFQyBQ +UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAbZGptQGRqbS5zeWQuY29ycC5nb29nbGUuY29tAQ +IDBAUG +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/misc/fuzz-harness/testdata/id_ecdsa_sk-cert.pub b/regress/misc/fuzz-harness/testdata/id_ecdsa_sk-cert.pub new file mode 100644 index 000000000..14040fad7 --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_ecdsa_sk-cert.pub @@ -0,0 +1 @@ +sk-ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAK3NrLWVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgKLHtIca++5VoDrUAXU/KqGJZ7jZEnuJSTvt7VrYY9foAAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOgAAAAAAAAPqAAAAAQAAAAd1bHlzc2VzAAAAFwAAAAd1bHlzc2VzAAAACG9keXNzZXVzAAAAAAAAAAD//////////wAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEB1naZOQDLaDr+fwn6E9x8/8HeiaUubDzPexfNQMz+m/7RD0gd5uJhHYUfDb5+/sIx1I7bUEeRIDkBbmZ2foo0E djm@djm.syd.corp.google.com diff --git a/regress/misc/fuzz-harness/testdata/id_ecdsa_sk.pub b/regress/misc/fuzz-harness/testdata/id_ecdsa_sk.pub new file mode 100644 index 000000000..1b5e829b7 --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_ecdsa_sk.pub @@ -0,0 +1 @@ +sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOg== djm@djm.syd.corp.google.com diff --git a/regress/misc/fuzz-harness/testdata/id_ed25519 b/regress/misc/fuzz-harness/testdata/id_ed25519 new file mode 100644 index 000000000..6a7fbac92 --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_ed25519 @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAIhWlP99VpT/ +fQAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAw +AAAEDE1rlcMC0s0X3TKVZAOVavZOywwkXw8tO5dLObxaCMEDPQXmEVMVLmeFRyafKMVWgP +Dkv8/uRBTwmcEDatZzMDAAAAAAECAwQF +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/misc/fuzz-harness/testdata/id_ed25519-cert.pub b/regress/misc/fuzz-harness/testdata/id_ed25519-cert.pub new file mode 100644 index 000000000..6a95fed2a --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_ed25519-cert.pub @@ -0,0 +1 @@ +ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIMDQjYH6XRzH3j3MW1DdjCoAfvrHfgjnVGF+sLK0pBfqAAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAAAAAA+sAAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQBj0og+s09/HpwdHZbzN0twooKPDWWrxGfnP1Joy6cDnY2BCSQ7zg9vbq11kLF8H/sKOTZWAQrUZ7LlChOu9Ogw= id_ed25519.pub diff --git a/regress/misc/fuzz-harness/testdata/id_ed25519.pub b/regress/misc/fuzz-harness/testdata/id_ed25519.pub new file mode 100644 index 000000000..87b617447 --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_ed25519.pub @@ -0,0 +1,2 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMD + diff --git a/regress/misc/fuzz-harness/testdata/id_ed25519_sk b/regress/misc/fuzz-harness/testdata/id_ed25519_sk new file mode 100644 index 000000000..9dcda6c46 --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_ed25519_sk @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 +gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACCTJtH10vWhIDxd62edvMLg9u2cwYKyqa7332je +RArHjAAAAARzc2g6AAAAwN7vvE3e77xNAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 +9tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoBAAAAQEsS +xLFiVzfpH2mt9xh8i/zmHV646Hud4QruNBAGNl8gkybR9dL1oSA8XetnnbzC4PbtnMGCsq +mu999o3kQKx4wAAAAAAAAAG2RqbUBkam0uc3lkLmNvcnAuZ29vZ2xlLmNvbQECAwQFBg== +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/misc/fuzz-harness/testdata/id_ed25519_sk-cert.pub b/regress/misc/fuzz-harness/testdata/id_ed25519_sk-cert.pub new file mode 100644 index 000000000..9e41eec00 --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_ed25519_sk-cert.pub @@ -0,0 +1 @@ +sk-ssh-ed25519-cert-v01@openssh.com AAAAI3NrLXNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJiT+C/VLMWholFZ4xhOyJr0nSLZSFRIM3I07wUNTRPaAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoAAAAAAAAD7AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAX0Pu13B94pVR3qq8MJQGkOS1Cd7AAM1k6O2VSwyDPM/LfsWIQ4ywgxDmk3hjXWOY7BqljuMxo5VO4JymEIhQBA== djm@djm.syd.corp.google.com diff --git a/regress/misc/fuzz-harness/testdata/id_ed25519_sk.pub b/regress/misc/fuzz-harness/testdata/id_ed25519_sk.pub new file mode 100644 index 000000000..38d198444 --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_ed25519_sk.pub @@ -0,0 +1 @@ +sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDo= djm@djm.syd.corp.google.com diff --git a/regress/misc/fuzz-harness/testdata/id_rsa b/regress/misc/fuzz-harness/testdata/id_rsa new file mode 100644 index 000000000..574fecf47 --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_rsa @@ -0,0 +1,27 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn +NhAAAAAwEAAQAAAQEA3+epf+VGKoGPaAZXrf6S0cyumQnddkGBnVFX0A5eh37RtLug0qY5 +thxsBUbGGVr9mTd2QXwLujBwYg5l1MP/Fmg+5312Zgx9pHmS+qKULbar0hlNgptNEb+aNU +d3o9qg3aXqXm7+ZnjAV05ef/mxNRN2ZvuEkw7cRppTJcbBI+vF3lXuCXnX2klDI95Gl2AW +3WHRtanqLHZXuBkjjRBDKc7MUq/GP1hmLiAd95dvU7fZjRlIEsP84zGEI1Fb0L/kmPHcOt +iVfHft8CtmC9v6+94JrOiPBBNScV+dyrgAGPsdKdr/1vIpQmCNiI8s3PCiD8J7ZiBaYm0I +8fq5G/qnUwAAA7ggw2dXIMNnVwAAAAdzc2gtcnNhAAABAQDf56l/5UYqgY9oBlet/pLRzK +6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZm +DH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGml +MlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29T +t9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v +/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAwEAAQAAAQEArWm5B4tFasppjUHM +SsAuajtCxtizI1Hc10EW59cZM4vvUzE2f6+qZvdgWj3UU/L7Et23w0QVuSCnCerox379ZB +ddEOFFAAiQjwBx65hbd4RRUymxtIQfjq18++LcMJW1nbVQ7c69ThQbtALIggmbS+ZE/8Gx +jkwmIrCH0Ww8TlpsPe+mNHuyNk7UEZoXLm22lNLqq5qkIL5JgT6M2iNJpMOJy9/CKi6kO4 +JPuVwjdG4C5pBPaMN3KJ1IvAlSlLGNaXnfXcn85gWfsCjsZmH3liey2NJamqp/w83BrKUg +YZvMR2qeWZaKkFTahpzN5KRK1BFeB37O0P84Dzh1biDX8QAAAIEAiWXW8ePYFwLpa2mFIh +VvRTdcrN70rVK5eWVaL3pyS4vGA56Jixq86dHveOnbSY+iNb1jQidtXc8SWUt2wtHqZ32h +Lji9/hMSKqe9SEP3xvDRDmUJqsVw0ySyrFrzm4160QY6RKU3CIQCVFslMZ9fxmrfZ/hxoU +0X3FVsxmC4+kwAAACBAPOc1YERpV6PjANBrGR+1o1RCdACbm5myc42QzSNIaOZmgrYs+Gt +7+EcoqSdbJzHJNCNQfF+A+vjbIkFiuZqq/5wwr59qXx5OAlijLB/ywwKmTWq6lp//Zxny+ +ka3sIGNO14eQvmxNDnlLL+RIZleCTEKBXSW6CZhr+uHMZFKKMtAAAAgQDrSkm+LbILB7H9 +jxEBZLhv53aAn4u81kFKQOJ7PzzpBGSoD12i7oIJu5siSD5EKDNVEr+SvCf0ISU3BuMpzl +t3YrPrHRheOFhn5e3j0e//zB8rBC0DGB4CtTDdeh7rOXUL4K0pz+8wEpNkV62SWxhC6NRW +I79JhtGkh+GtcnkEfwAAAAAB +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/misc/fuzz-harness/testdata/id_rsa-cert.pub b/regress/misc/fuzz-harness/testdata/id_rsa-cert.pub new file mode 100644 index 000000000..01761a38f --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_rsa-cert.pub @@ -0,0 +1 @@ +ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg89JX6OBMYDSxER8fnU5y8xxeMCHR/hI0uVqdEhNyCpcAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAAAAA+0AAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQGCDA6PWw4x9bHQl0w7NqifHepumqD3dmyMx+hZGuPRon+TsyCjfytu7hWmV7l9XUF0fPQNFQ7FGat5e+7YUNgE= id_rsa.pub diff --git a/regress/misc/fuzz-harness/testdata/id_rsa.pub b/regress/misc/fuzz-harness/testdata/id_rsa.pub new file mode 100644 index 000000000..05015e12b --- /dev/null +++ b/regress/misc/fuzz-harness/testdata/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdT diff --git a/regress/misc/kexfuzz/README b/regress/misc/kexfuzz/README deleted file mode 100644 index 504c26f3b..000000000 --- a/regress/misc/kexfuzz/README +++ /dev/null @@ -1,34 +0,0 @@ -This is a harness to help with fuzzing KEX. - -To use it, you first set it to count packets in each direction: - -./kexfuzz -K diffie-hellman-group1-sha1 -k host_ed25519_key -c -S2C: 29 -C2S: 31 - -Then get it to record a particular packet (in this case the 4th -packet from client->server): - -./kexfuzz -K diffie-hellman-group1-sha1 -k host_ed25519_key \ - -d -D C2S -i 3 -f packet_3 - -Fuzz the packet somehow: - -dd if=/dev/urandom of=packet_3 bs=32 count=1 # Just for example - -Then re-run the key exchange substituting the modified packet in -its original sequence: - -./kexfuzz -K diffie-hellman-group1-sha1 -k host_ed25519_key \ - -r -D C2S -i 3 -f packet_3 - -A comprehensive KEX fuzz run would fuzz every packet in both -directions for each key exchange type and every hostkey type. -This will take some time. - -Limitations: kexfuzz can't change the ordering of packets at -present. It is limited to replacing individual packets with -fuzzed variants with the same type. It really should allow -insertion, deletion on replacement of packets too. - -$OpenBSD: README,v 1.3 2017/10/20 02:13:41 djm Exp $ diff --git a/regress/misc/kexfuzz/kexfuzz.c b/regress/misc/kexfuzz/kexfuzz.c deleted file mode 100644 index 7051e87b1..000000000 --- a/regress/misc/kexfuzz/kexfuzz.c +++ /dev/null @@ -1,457 +0,0 @@ -/* $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 -#include -#include -#ifdef HAVE_STDINT_H -# include -#endif -#include -#include -#include -#include -#ifdef HAVE_ERR_H -# include -#endif - -#include "ssherr.h" -#include "ssh_api.h" -#include "sshbuf.h" -#include "packet.h" -#include "myproposal.h" -#include "authfile.h" -#include "log.h" - -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] = 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] = kex_gen_server; -# endif -#endif - 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/misc/kexfuzz/Makefile b/regress/misc/sk-dummy/Makefile similarity index 51% rename from regress/misc/kexfuzz/Makefile rename to regress/misc/sk-dummy/Makefile index 20802cb87..29e313c82 100644 --- a/regress/misc/kexfuzz/Makefile +++ b/regress/misc/sk-dummy/Makefile @@ -1,53 +1,23 @@ -# $OpenBSD: Makefile,v 1.4 2019/01/21 12:50:12 djm Exp $ +# $OpenBSD: Makefile,v 1.2 2019/11/29 00:13:29 djm Exp $ .include .include -# XXX detect from ssh binary? -SSH1?= no -OPENSSL?= yes - -PROG= kexfuzz -SRCS= kexfuzz.c +PROG= sk-dummy.so +NOMAN= SSHREL=../../../../../usr.bin/ssh .PATH: ${.CURDIR}/${SSHREL} + +SRCS=sk-dummy.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+=compat.c ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c -SRCS+=cipher-chachapoly.c chacha.c poly1305.c +SRCS+=ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c +OPENSSL?= yes -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 +CFLAGS+= -fPIC .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 @@ -82,16 +52,15 @@ CDIAGFLAGS+= -Wno-unused-parameter CDIAGFLAGS+= -Wold-style-definition .endif - CFLAGS+=-I${.CURDIR}/${SSHREL} -LDADD+= -lutil -lz -DPADD+= ${LIBUTIL} ${LIBZ} - .if (${OPENSSL:L} == "yes") LDADD+= -lcrypto DPADD+= ${LIBCRYPTO} .endif +$(PROG): $(OBJS) + $(CC) $(LDFLAGS) -shared -o $@ $(OBJS) $(LDADD) + .include diff --git a/regress/misc/sk-dummy/fatal.c b/regress/misc/sk-dummy/fatal.c new file mode 100644 index 000000000..c6e4b5d6f --- /dev/null +++ b/regress/misc/sk-dummy/fatal.c @@ -0,0 +1,27 @@ +/* public domain */ + +#include "includes.h" + +#include +#include +#include +#include + +#include "log.h" + +void +sshfatal(const char *file, const char *func, int line, int showfunc, + LogLevel level, const char *suffix, const char *fmt, ...) +{ + va_list ap; + + if (showfunc) + fprintf(stderr, "%s: ", func); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + if (suffix != NULL) + fprintf(stderr, ": %s", suffix); + fputc('\n', stderr); + _exit(1); +} diff --git a/regress/misc/sk-dummy/sk-dummy.c b/regress/misc/sk-dummy/sk-dummy.c new file mode 100644 index 000000000..4003362d7 --- /dev/null +++ b/regress/misc/sk-dummy/sk-dummy.c @@ -0,0 +1,539 @@ +/* + * Copyright (c) 2019 Markus Friedl + * + * 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 HAVE_STDINT_H +#include +#endif +#include +#include +#include +#include +#include + +#include "crypto_api.h" +#include "sk-api.h" + +#include +#include +#include +#include +#include +#include +#include + +/* #define SK_DEBUG 1 */ + +/* Compatibility with OpenSSH 1.0.x */ +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) +#define ECDSA_SIG_get0(sig, pr, ps) \ + do { \ + (*pr) = sig->r; \ + (*ps) = sig->s; \ + } while (0) +#endif + +#if SSH_SK_VERSION_MAJOR != 0x00070000 +# error SK API has changed, sk-dummy.c needs an update +#endif + +#ifdef SK_DUMMY_INTEGRATE +# define sk_api_version ssh_sk_api_version +# define sk_enroll ssh_sk_enroll +# define sk_sign ssh_sk_sign +# define sk_load_resident_keys ssh_sk_load_resident_keys +#endif /* !SK_STANDALONE */ + +static void skdebug(const char *func, const char *fmt, ...) + __attribute__((__format__ (printf, 2, 3))); + +static void +skdebug(const char *func, const char *fmt, ...) +{ +#if defined(SK_DEBUG) + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "sk-dummy %s: ", func); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); + va_end(ap); +#else + (void)func; /* XXX */ + (void)fmt; /* XXX */ +#endif +} + +uint32_t +sk_api_version(void) +{ + return SSH_SK_VERSION_MAJOR; +} + +static int +pack_key_ecdsa(struct sk_enroll_response *response) +{ +#ifdef OPENSSL_HAS_ECC + EC_KEY *key = NULL; + const EC_GROUP *g; + const EC_POINT *q; + int ret = -1; + long privlen; + BIO *bio = NULL; + char *privptr; + + response->public_key = NULL; + response->public_key_len = 0; + response->key_handle = NULL; + response->key_handle_len = 0; + + if ((key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)) == NULL) { + skdebug(__func__, "EC_KEY_new_by_curve_name"); + goto out; + } + if (EC_KEY_generate_key(key) != 1) { + skdebug(__func__, "EC_KEY_generate_key"); + goto out; + } + EC_KEY_set_asn1_flag(key, OPENSSL_EC_NAMED_CURVE); + if ((bio = BIO_new(BIO_s_mem())) == NULL || + (g = EC_KEY_get0_group(key)) == NULL || + (q = EC_KEY_get0_public_key(key)) == NULL) { + skdebug(__func__, "couldn't get key parameters"); + goto out; + } + response->public_key_len = EC_POINT_point2oct(g, q, + POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); + if (response->public_key_len == 0 || response->public_key_len > 2048) { + skdebug(__func__, "bad pubkey length %zu", + response->public_key_len); + goto out; + } + if ((response->public_key = malloc(response->public_key_len)) == NULL) { + skdebug(__func__, "malloc pubkey failed"); + goto out; + } + if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED, + response->public_key, response->public_key_len, NULL) == 0) { + skdebug(__func__, "EC_POINT_point2oct failed"); + goto out; + } + /* Key handle contains PEM encoded private key */ + if (!PEM_write_bio_ECPrivateKey(bio, key, NULL, NULL, 0, NULL, NULL)) { + skdebug(__func__, "PEM_write_bio_ECPrivateKey failed"); + goto out; + } + if ((privlen = BIO_get_mem_data(bio, &privptr)) <= 0) { + skdebug(__func__, "BIO_get_mem_data failed"); + goto out; + } + if ((response->key_handle = malloc(privlen)) == NULL) { + skdebug(__func__, "malloc key_handle failed"); + goto out; + } + response->key_handle_len = (size_t)privlen; + memcpy(response->key_handle, privptr, response->key_handle_len); + /* success */ + ret = 0; + out: + if (ret != 0) { + if (response->public_key != NULL) { + memset(response->public_key, 0, + response->public_key_len); + free(response->public_key); + response->public_key = NULL; + } + if (response->key_handle != NULL) { + memset(response->key_handle, 0, + response->key_handle_len); + free(response->key_handle); + response->key_handle = NULL; + } + } + BIO_free(bio); + EC_KEY_free(key); + return ret; +#else + return -1; +#endif +} + +static int +pack_key_ed25519(struct sk_enroll_response *response) +{ + int ret = -1; + u_char pk[crypto_sign_ed25519_PUBLICKEYBYTES]; + u_char sk[crypto_sign_ed25519_SECRETKEYBYTES]; + + response->public_key = NULL; + response->public_key_len = 0; + response->key_handle = NULL; + response->key_handle_len = 0; + + memset(pk, 0, sizeof(pk)); + memset(sk, 0, sizeof(sk)); + crypto_sign_ed25519_keypair(pk, sk); + + response->public_key_len = sizeof(pk); + if ((response->public_key = malloc(response->public_key_len)) == NULL) { + skdebug(__func__, "malloc pubkey failed"); + goto out; + } + memcpy(response->public_key, pk, sizeof(pk)); + /* Key handle contains sk */ + response->key_handle_len = sizeof(sk); + if ((response->key_handle = malloc(response->key_handle_len)) == NULL) { + skdebug(__func__, "malloc key_handle failed"); + goto out; + } + memcpy(response->key_handle, sk, sizeof(sk)); + /* success */ + ret = 0; + out: + if (ret != 0) + free(response->public_key); + return ret; +} + +static int +check_options(struct sk_option **options) +{ + size_t i; + + if (options == NULL) + return 0; + for (i = 0; options[i] != NULL; i++) { + skdebug(__func__, "requested unsupported option %s", + options[i]->name); + if (options[i]->required) { + skdebug(__func__, "unknown required option"); + return -1; + } + } + return 0; +} + +int +sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, + const char *application, uint8_t flags, const char *pin, + struct sk_option **options, struct sk_enroll_response **enroll_response) +{ + struct sk_enroll_response *response = NULL; + int ret = SSH_SK_ERR_GENERAL; + + (void)flags; /* XXX; unused */ + + if (enroll_response == NULL) { + skdebug(__func__, "enroll_response == NULL"); + goto out; + } + *enroll_response = NULL; + if (check_options(options) != 0) + goto out; /* error already logged */ + if ((response = calloc(1, sizeof(*response))) == NULL) { + skdebug(__func__, "calloc response failed"); + goto out; + } + switch(alg) { + case SSH_SK_ECDSA: + if (pack_key_ecdsa(response) != 0) + goto out; + break; + case SSH_SK_ED25519: + if (pack_key_ed25519(response) != 0) + goto out; + break; + default: + skdebug(__func__, "unsupported key type %d", alg); + return -1; + } + /* Have to return something here */ + if ((response->signature = calloc(1, 1)) == NULL) { + skdebug(__func__, "calloc signature failed"); + goto out; + } + response->signature_len = 0; + + *enroll_response = response; + response = NULL; + ret = 0; + out: + if (response != NULL) { + free(response->public_key); + free(response->key_handle); + free(response->signature); + free(response->attestation_cert); + free(response); + } + return ret; +} + +static void +dump(const char *preamble, const void *sv, size_t l) +{ +#ifdef SK_DEBUG + const u_char *s = (const u_char *)sv; + size_t i; + + fprintf(stderr, "%s (len %zu):\n", preamble, l); + for (i = 0; i < l; i++) { + if (i % 16 == 0) + fprintf(stderr, "%04zu: ", i); + fprintf(stderr, "%02x", s[i]); + if (i % 16 == 15 || i == l - 1) + fprintf(stderr, "\n"); + } +#endif +} + +static int +sig_ecdsa(const uint8_t *message, size_t message_len, + const char *application, uint32_t counter, uint8_t flags, + const uint8_t *key_handle, size_t key_handle_len, + struct sk_sign_response *response) +{ +#ifdef OPENSSL_HAS_ECC + ECDSA_SIG *sig = NULL; + const BIGNUM *sig_r, *sig_s; + int ret = -1; + BIO *bio = NULL; + EVP_PKEY *pk = NULL; + EC_KEY *ec = NULL; + SHA256_CTX ctx; + uint8_t apphash[SHA256_DIGEST_LENGTH]; + uint8_t sighash[SHA256_DIGEST_LENGTH]; + uint8_t countbuf[4]; + + /* Decode EC_KEY from key handle */ + if ((bio = BIO_new(BIO_s_mem())) == NULL || + BIO_write(bio, key_handle, key_handle_len) != (int)key_handle_len) { + skdebug(__func__, "BIO setup failed"); + goto out; + } + if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, "")) == NULL) { + skdebug(__func__, "PEM_read_bio_PrivateKey failed"); + goto out; + } + if (EVP_PKEY_base_id(pk) != EVP_PKEY_EC) { + skdebug(__func__, "Not an EC key: %d", EVP_PKEY_base_id(pk)); + goto out; + } + if ((ec = EVP_PKEY_get1_EC_KEY(pk)) == NULL) { + skdebug(__func__, "EVP_PKEY_get1_EC_KEY failed"); + goto out; + } + /* Expect message to be pre-hashed */ + if (message_len != SHA256_DIGEST_LENGTH) { + skdebug(__func__, "bad message len %zu", message_len); + goto out; + } + /* Prepare data to be signed */ + dump("message", message, message_len); + SHA256_Init(&ctx); + SHA256_Update(&ctx, application, strlen(application)); + SHA256_Final(apphash, &ctx); + dump("apphash", apphash, sizeof(apphash)); + countbuf[0] = (counter >> 24) & 0xff; + countbuf[1] = (counter >> 16) & 0xff; + countbuf[2] = (counter >> 8) & 0xff; + countbuf[3] = counter & 0xff; + dump("countbuf", countbuf, sizeof(countbuf)); + dump("flags", &flags, sizeof(flags)); + SHA256_Init(&ctx); + SHA256_Update(&ctx, apphash, sizeof(apphash)); + SHA256_Update(&ctx, &flags, sizeof(flags)); + SHA256_Update(&ctx, countbuf, sizeof(countbuf)); + SHA256_Update(&ctx, message, message_len); + SHA256_Final(sighash, &ctx); + dump("sighash", sighash, sizeof(sighash)); + /* create and encode signature */ + if ((sig = ECDSA_do_sign(sighash, sizeof(sighash), ec)) == NULL) { + skdebug(__func__, "ECDSA_do_sign failed"); + goto out; + } + ECDSA_SIG_get0(sig, &sig_r, &sig_s); + response->sig_r_len = BN_num_bytes(sig_r); + response->sig_s_len = BN_num_bytes(sig_s); + if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL || + (response->sig_s = calloc(1, response->sig_s_len)) == NULL) { + skdebug(__func__, "calloc signature failed"); + goto out; + } + BN_bn2bin(sig_r, response->sig_r); + BN_bn2bin(sig_s, response->sig_s); + ret = 0; + out: + explicit_bzero(&ctx, sizeof(ctx)); + explicit_bzero(&apphash, sizeof(apphash)); + explicit_bzero(&sighash, sizeof(sighash)); + ECDSA_SIG_free(sig); + if (ret != 0) { + free(response->sig_r); + free(response->sig_s); + response->sig_r = NULL; + response->sig_s = NULL; + } + BIO_free(bio); + EC_KEY_free(ec); + EVP_PKEY_free(pk); + return ret; +#else + return -1; +#endif +} + +static int +sig_ed25519(const uint8_t *message, size_t message_len, + const char *application, uint32_t counter, uint8_t flags, + const uint8_t *key_handle, size_t key_handle_len, + struct sk_sign_response *response) +{ + size_t o; + int ret = -1; + SHA256_CTX ctx; + uint8_t apphash[SHA256_DIGEST_LENGTH]; + uint8_t signbuf[sizeof(apphash) + sizeof(flags) + + sizeof(counter) + SHA256_DIGEST_LENGTH]; + uint8_t sig[crypto_sign_ed25519_BYTES + sizeof(signbuf)]; + unsigned long long smlen; + + if (key_handle_len != crypto_sign_ed25519_SECRETKEYBYTES) { + skdebug(__func__, "bad key handle length %zu", key_handle_len); + goto out; + } + /* Expect message to be pre-hashed */ + if (message_len != SHA256_DIGEST_LENGTH) { + skdebug(__func__, "bad message len %zu", message_len); + goto out; + } + /* Prepare data to be signed */ + dump("message", message, message_len); + SHA256_Init(&ctx); + SHA256_Update(&ctx, application, strlen(application)); + SHA256_Final(apphash, &ctx); + dump("apphash", apphash, sizeof(apphash)); + + memcpy(signbuf, apphash, sizeof(apphash)); + o = sizeof(apphash); + signbuf[o++] = flags; + signbuf[o++] = (counter >> 24) & 0xff; + signbuf[o++] = (counter >> 16) & 0xff; + signbuf[o++] = (counter >> 8) & 0xff; + signbuf[o++] = counter & 0xff; + memcpy(signbuf + o, message, message_len); + o += message_len; + if (o != sizeof(signbuf)) { + skdebug(__func__, "bad sign buf len %zu, expected %zu", + o, sizeof(signbuf)); + goto out; + } + dump("signbuf", signbuf, sizeof(signbuf)); + /* create and encode signature */ + smlen = sizeof(signbuf); + if (crypto_sign_ed25519(sig, &smlen, signbuf, sizeof(signbuf), + key_handle) != 0) { + skdebug(__func__, "crypto_sign_ed25519 failed"); + goto out; + } + if (smlen <= sizeof(signbuf)) { + skdebug(__func__, "bad sign smlen %llu, expected min %zu", + smlen, sizeof(signbuf) + 1); + goto out; + } + response->sig_r_len = (size_t)(smlen - sizeof(signbuf)); + if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) { + skdebug(__func__, "calloc signature failed"); + goto out; + } + memcpy(response->sig_r, sig, response->sig_r_len); + dump("sig_r", response->sig_r, response->sig_r_len); + ret = 0; + out: + explicit_bzero(&ctx, sizeof(ctx)); + explicit_bzero(&apphash, sizeof(apphash)); + explicit_bzero(&signbuf, sizeof(signbuf)); + explicit_bzero(&sig, sizeof(sig)); + if (ret != 0) { + free(response->sig_r); + response->sig_r = NULL; + } + return ret; +} + +int +sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, + const char *application, const uint8_t *key_handle, size_t key_handle_len, + uint8_t flags, const char *pin, struct sk_option **options, + struct sk_sign_response **sign_response) +{ + struct sk_sign_response *response = NULL; + int ret = SSH_SK_ERR_GENERAL; + SHA256_CTX ctx; + uint8_t message[32]; + + if (sign_response == NULL) { + skdebug(__func__, "sign_response == NULL"); + goto out; + } + *sign_response = NULL; + if (check_options(options) != 0) + goto out; /* error already logged */ + if ((response = calloc(1, sizeof(*response))) == NULL) { + skdebug(__func__, "calloc response failed"); + goto out; + } + SHA256_Init(&ctx); + SHA256_Update(&ctx, data, datalen); + SHA256_Final(message, &ctx); + response->flags = flags; + response->counter = 0x12345678; + switch(alg) { + case SSH_SK_ECDSA: + if (sig_ecdsa(message, sizeof(message), application, + response->counter, flags, key_handle, key_handle_len, + response) != 0) + goto out; + break; + case SSH_SK_ED25519: + if (sig_ed25519(message, sizeof(message), application, + response->counter, flags, key_handle, key_handle_len, + response) != 0) + goto out; + break; + default: + skdebug(__func__, "unsupported key type %d", alg); + return -1; + } + *sign_response = response; + response = NULL; + ret = 0; + out: + explicit_bzero(message, sizeof(message)); + if (response != NULL) { + free(response->sig_r); + free(response->sig_s); + free(response); + } + return ret; +} + +int +sk_load_resident_keys(const char *pin, struct sk_option **options, + struct sk_resident_key ***rks, size_t *nrks) +{ + return SSH_SK_ERR_UNSUPPORTED; +} diff --git a/regress/multiplex.sh b/regress/multiplex.sh index 382158886..7a3478e23 100644 --- a/regress/multiplex.sh +++ b/regress/multiplex.sh @@ -1,4 +1,4 @@ -# $OpenBSD: multiplex.sh,v 1.30 2019/07/05 04:03:13 dtucker Exp $ +# $OpenBSD: multiplex.sh,v 1.33 2020/06/24 15:16:23 markus Exp $ # Placed in the Public Domain. make_tmpdir @@ -12,9 +12,6 @@ if [ "$os" == "windows" ]; then exit 0 fi - -NC=$OBJ/netcat - trace "will use ProxyCommand $proxycmd" if config_defined DISABLE_FD_PASSING ; then echo "skipped (not supported on this platform)" @@ -25,7 +22,7 @@ P=3301 # test port wait_for_mux_master_ready() { - for i in 1 2 3 4 5; do + for i in 1 2 3 4 5 6 7 8 9; do ${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost \ >/dev/null 2>&1 && return 0 sleep $i @@ -106,22 +103,24 @@ 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 + for mode in "" "-Oproxy"; do + trace "exit status $s over multiplexed connection ($mode)" + verbose "test $tid: status $s ($mode)" + ${SSH} -F $OBJ/ssh_config -S $CTL $mode 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 \ + trace "exit status $s with early close over multiplexed connection ($mode)" + ${SSH} -F $OBJ/ssh_config -S $CTL -n $mode 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 done verbose "test $tid: cmd check" diff --git a/regress/multipubkey.sh b/regress/multipubkey.sh index 4d443ec45..9b2273353 100644 --- a/regress/multipubkey.sh +++ b/regress/multipubkey.sh @@ -1,4 +1,4 @@ -# $OpenBSD: multipubkey.sh,v 1.2 2018/10/31 11:09:27 dtucker Exp $ +# $OpenBSD: multipubkey.sh,v 1.3 2019/12/11 18:47:14 djm Exp $ # Placed in the Public Domain. tid="multiple pubkey" @@ -31,7 +31,7 @@ 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 yes sandbox ; do +for privsep in yes ; do ( grep -v "Protocol" $OBJ/sshd_proxy.orig echo "Protocol 2" diff --git a/regress/netcat.c b/regress/netcat.c index 56bd09de5..20ec3f595 100644 --- a/regress/netcat.c +++ b/regress/netcat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: netcat.c,v 1.126 2014/10/30 16:08:31 tedu Exp $ */ +/* $OpenBSD: netcat.c,v 1.131 2015/09/03 23:06:28 sobrado Exp $ */ /* * Copyright (c) 2001 Eric Jackson * @@ -44,14 +44,15 @@ #include #include +#include +#include #include +#include #include #include #include #include #include -#include -#include #include "atomicio.h" #ifdef HAVE_POLL_H @@ -64,6 +65,12 @@ #ifdef HAVE_ERR_H # include #endif +#ifdef HAVE_SYS_BYTEORDER_H +# include +#endif + +/* rename to avoid collision in libssh */ +#define timeout_connect netcat_timeout_connect /* Telnet options from arpa/telnet.h */ #define IAC 255 @@ -130,7 +137,7 @@ int udptest(int); int unix_bind(char *); int unix_connect(char *); int unix_listen(char *); -void set_common_sockopts(int); +void set_common_sockopts(int, int); int map_tos(char *, int *); void report_connect(const struct sockaddr *, socklen_t); void usage(int); @@ -159,6 +166,8 @@ main(int argc, char *argv[]) uport = NULL; sv = NULL; + signal(SIGPIPE, SIG_IGN); + while ((ch = getopt(argc, argv, "46DdFhI:i:klNnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) { switch (ch) { @@ -645,7 +654,7 @@ remote_connect(const char *host, const char *port, struct addrinfo hints) freeaddrinfo(ares); } - set_common_sockopts(s); + set_common_sockopts(s, res0->ai_family); if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0) break; @@ -745,7 +754,7 @@ local_listen(char *host, char *port, struct addrinfo hints) if (ret == -1) err(1, "setsockopt SO_REUSEADDR"); #endif - set_common_sockopts(s); + set_common_sockopts(s, res0->ai_family); if (bind(s, (struct sockaddr *)res0->ai_addr, res0->ai_addrlen) == 0) @@ -1031,17 +1040,17 @@ fdpass(int nfd) bzero(&pfd, sizeof(pfd)); pfd.fd = STDOUT_FILENO; + pfd.events = POLLOUT; for (;;) { r = sendmsg(STDOUT_FILENO, &msg, 0); if (r == -1) { if (errno == EAGAIN || errno == EINTR) { - pfd.events = POLLOUT; if (poll(&pfd, 1, -1) == -1) err(1, "poll"); continue; } err(1, "sendmsg"); - } else if (r == -1) + } else if (r != 1) errx(1, "sendmsg: unexpected return value %zd", r); else break; @@ -1165,7 +1174,7 @@ udptest(int s) } void -set_common_sockopts(int s) +set_common_sockopts(int s, int af) { int x = 1; @@ -1181,11 +1190,22 @@ set_common_sockopts(int s) &x, sizeof(x)) == -1) err(1, "setsockopt"); } +#if defined(IP_TOS) && defined(IPV6_TCLASS) if (Tflag != -1) { - if (setsockopt(s, IPPROTO_IP, IP_TOS, - &Tflag, sizeof(Tflag)) == -1) + int proto, option; + + if (af == AF_INET6) { + proto = IPPROTO_IPV6; + option = IPV6_TCLASS; + } else { + proto = IPPROTO_IP; + option = IP_TOS; + } + + if (setsockopt(s, proto, option, &Tflag, sizeof(Tflag)) == -1) err(1, "set IP ToS"); } +#endif if (Iflag) { if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &Iflag, sizeof(Iflag)) == -1) @@ -1201,6 +1221,7 @@ set_common_sockopts(int s) int map_tos(char *s, int *val) { +#ifdef IP_TOS /* DiffServ Codepoints and other TOS mappings */ const struct toskeywords { const char *keyword; @@ -1242,6 +1263,7 @@ map_tos(char *s, int *val) return (1); } } +#endif return (0); } @@ -1314,7 +1336,7 @@ usage(int ret) { fprintf(stderr, "usage: nc [-46DdFhklNnrStUuvz] [-I length] [-i interval] [-O length]\n" - "\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n" + "\t [-P proxy_username] [-p source_port] [-s source] [-T toskeyword]\n" "\t [-V rtable] [-w timeout] [-X proxy_protocol]\n" "\t [-x proxy_address[:port]] [destination] [port]\n"); if (ret) diff --git a/regress/percent.sh b/regress/percent.sh new file mode 100644 index 000000000..72f07f4b8 --- /dev/null +++ b/regress/percent.sh @@ -0,0 +1,119 @@ +# $OpenBSD: percent.sh,v 1.11 2021/02/05 22:03:40 dtucker Exp $ +# Placed in the Public Domain. + +tid="percent expansions" + +if [ -x "/usr/xpg4/bin/id" ]; then + PATH=/usr/xpg4/bin:$PATH + export PATH +fi + +USER=`id -u -n` +USERID=`id -u` +HOST=`hostname | cut -f1 -d.` +HOSTNAME=`hostname` + +# Localcommand is evaluated after connection because %T is not available +# until then. Because of this we use a different method of exercising it, +# and we can't override the remote user otherwise authentication will fail. +# We also have to explicitly enable it. +echo "permitlocalcommand yes" >> $OBJ/ssh_proxy + +trial() +{ + opt="$1"; arg="$2"; expect="$3" + + trace "test $opt=$arg $expect" + rm -f $OBJ/actual + got="" + case "$opt" in + localcommand) + ${SSH} -F $OBJ/ssh_proxy -o $opt="echo '$arg' >$OBJ/actual" \ + somehost true + got=`cat $OBJ/actual` + ;; + userknownhostsfile) + # Move the userknownhosts file to what the expansion says, + # make sure ssh works then put it back. + mv "$OBJ/known_hosts" "$OBJ/$expect" + ${SSH} -F $OBJ/ssh_proxy -o $opt="$OBJ/$arg" somehost true && \ + got="$expect" + mv "$OBJ/$expect" "$OBJ/known_hosts" + ;; + matchexec) + (cat $OBJ/ssh_proxy && \ + echo "Match Exec \"echo '$arg' >$OBJ/actual\"") \ + >$OBJ/ssh_proxy_match + ${SSH} -F $OBJ/ssh_proxy_match remuser@somehost true || true + got=`cat $OBJ/actual` + ;; + *forward) + # LocalForward and RemoteForward take two args and only + # operate on Unix domain socket paths + got=`${SSH} -F $OBJ/ssh_proxy -o $opt="/$arg /$arg" -G \ + remuser@somehost | awk '$1=="'$opt'"{print $2" "$3}'` + expect="/$expect /$expect" + ;; + *) + got=`${SSH} -F $OBJ/ssh_proxy -o $opt="$arg" -G \ + remuser@somehost | awk '$1=="'$opt'"{print $2}'` + esac + if [ "$got" != "$expect" ]; then + fail "$opt=$arg expect $expect got $got" + fi +} + +for i in matchexec localcommand remotecommand controlpath identityagent \ + forwardagent localforward remoteforward userknownhostsfile; do + verbose $tid $i percent + case "$i" in + localcommand|userknownhostsfile) + # Any test that's going to actually make a connection needs + # to use the real username. + REMUSER=$USER ;; + *) + REMUSER=remuser ;; + esac + if [ "$i" = "$localcommand" ]; then + trial $i '%T' NONE + fi + # Matches implementation in readconf.c:ssh_connection_hash() + HASH=`printf "${HOSTNAME}127.0.0.1${PORT}$REMUSER" | + openssl sha1 | cut -f2 -d' '` + trial $i '%%' '%' + trial $i '%C' $HASH + trial $i '%i' $USERID + trial $i '%h' 127.0.0.1 + trial $i '%L' $HOST + trial $i '%l' $HOSTNAME + trial $i '%n' somehost + trial $i '%k' localhost-with-alias + trial $i '%p' $PORT + trial $i '%r' $REMUSER + trial $i '%u' $USER + # We can't specify a full path outside the regress dir, so skip tests + # containing %d for UserKnownHostsFile + if [ "$i" != "userknownhostsfile" ]; then + trial $i '%d' $HOME + trial $i '%%/%C/%i/%h/%d/%L/%l/%n/%p/%r/%u' \ + "%/$HASH/$USERID/127.0.0.1/$HOME/$HOST/$HOSTNAME/somehost/$PORT/$REMUSER/$USER" + fi +done + +# Subset of above since we don't expand shell-style variables on anything that +# runs a command because the shell will expand those. +for i in controlpath identityagent forwardagent localforward remoteforward \ + userknownhostsfile; do + verbose $tid $i dollar + FOO=bar + export FOO + trial $i '${FOO}' $FOO +done + + +# A subset of options support tilde expansion +for i in controlpath identityagent forwardagent; do + verbose $tid $i tilde + trial $i '~' $HOME/ + trial $i '~/.ssh' $HOME/.ssh +done diff --git a/regress/principals-command.sh b/regress/principals-command.sh index 7d380325b..5e535c133 100644 --- a/regress/principals-command.sh +++ b/regress/principals-command.sh @@ -1,4 +1,4 @@ -# $OpenBSD: principals-command.sh,v 1.7 2019/09/06 04:24:06 dtucker Exp $ +# $OpenBSD: principals-command.sh,v 1.11 2019/12/16 02:39:05 djm Exp $ # Placed in the Public Domain. tid="authorized principals command" @@ -12,7 +12,7 @@ if [ -z "$SUDO" -a ! -w /var/run ]; then exit 0 fi -case "`${SSH} -Q key-plain`" in +case "$SSH_KEYTYPES" in *ssh-rsa*) userkeytype=rsa ;; *) userkeytype=ed25519 ;; esac @@ -63,7 +63,7 @@ fi if [ -x $PRINCIPALS_COMMAND ]; then # Test explicitly-specified principals - for privsep in yes sandbox ; do + for privsep in yes ; do _prefix="privsep $privsep" # Setup for AuthorizedPrincipalsCommand diff --git a/regress/proxy-connect.sh b/regress/proxy-connect.sh index 39bbd3c96..8847fe0c6 100644 --- a/regress/proxy-connect.sh +++ b/regress/proxy-connect.sh @@ -1,9 +1,15 @@ -# $OpenBSD: proxy-connect.sh,v 1.11 2017/09/26 22:39:25 dtucker Exp $ +# $OpenBSD: proxy-connect.sh,v 1.12 2020/01/23 11:19:12 dtucker Exp $ # Placed in the Public Domain. tid="proxy connect" -for c in no yes; do +if [ "`${SSH} -Q compression`" = "none" ]; then + comp="no" +else + comp="no yes" +fi + +for c in $comp; do verbose "plain username comp=$c" opts="-oCompression=$c -F $OBJ/ssh_proxy" SSH_CONNECTION=`${SSH} $opts 999.999.999.999 'echo $SSH_CONNECTION'` diff --git a/regress/putty-ciphers.sh b/regress/putty-ciphers.sh index 191a2bda8..708c288d7 100644 --- a/regress/putty-ciphers.sh +++ b/regress/putty-ciphers.sh @@ -1,4 +1,4 @@ -# $OpenBSD: putty-ciphers.sh,v 1.6 2017/05/08 01:52:49 djm Exp $ +# $OpenBSD: putty-ciphers.sh,v 1.7 2020/01/23 03:35:07 dtucker Exp $ # Placed in the Public Domain. tid="putty ciphers" @@ -8,7 +8,7 @@ if test "x$REGRESS_INTEROP_PUTTY" != "xyes" ; then exit 0 fi -for c in aes 3des aes128-ctr aes192-ctr aes256-ctr ; do +for c in aes 3des aes128-ctr aes192-ctr aes256-ctr chacha20 ; do verbose "$tid: cipher $c" cp ${OBJ}/.putty/sessions/localhost_proxy \ ${OBJ}/.putty/sessions/cipher_$c diff --git a/regress/putty-kex.sh b/regress/putty-kex.sh index 71c09701b..686d0e1af 100644 --- a/regress/putty-kex.sh +++ b/regress/putty-kex.sh @@ -1,4 +1,4 @@ -# $OpenBSD: putty-kex.sh,v 1.4 2016/11/25 03:02:01 dtucker Exp $ +# $OpenBSD: putty-kex.sh,v 1.5 2020/01/23 03:24:38 dtucker Exp $ # Placed in the Public Domain. tid="putty KEX" @@ -8,7 +8,7 @@ if test "x$REGRESS_INTEROP_PUTTY" != "xyes" ; then exit 0 fi -for k in dh-gex-sha1 dh-group1-sha1 dh-group14-sha1 ; do +for k in dh-gex-sha1 dh-group1-sha1 dh-group14-sha1 ecdh ; do verbose "$tid: kex $k" cp ${OBJ}/.putty/sessions/localhost_proxy \ ${OBJ}/.putty/sessions/kex_$k diff --git a/regress/putty-transfer.sh b/regress/putty-transfer.sh index 4928d4533..14b41022f 100644 --- a/regress/putty-transfer.sh +++ b/regress/putty-transfer.sh @@ -1,4 +1,4 @@ -# $OpenBSD: putty-transfer.sh,v 1.6 2018/02/23 03:03:00 djm Exp $ +# $OpenBSD: putty-transfer.sh,v 1.7 2020/01/23 11:19:12 dtucker Exp $ # Placed in the Public Domain. tid="putty transfer data" @@ -8,7 +8,13 @@ if test "x$REGRESS_INTEROP_PUTTY" != "xyes" ; then exit 0 fi -for c in 0 1 ; do +if [ "`${SSH} -Q compression`" = "none" ]; then + comp="0" +else + comp="0 1" +fi + +for c in $comp; do verbose "$tid: compression $c" rm -f ${COPY} cp ${OBJ}/.putty/sessions/localhost_proxy \ diff --git a/regress/reexec.sh b/regress/reexec.sh index 83fcda220..50ca7e206 100644 --- a/regress/reexec.sh +++ b/regress/reexec.sh @@ -9,7 +9,10 @@ SSHD_COPY=$OBJ/sshd # Start a sshd and then delete it start_sshd_copy () { - cp $SSHD_ORIG $SSHD_COPY + # NB. prefer ln to cp here. On some OSX 19.4 configurations, + # djm has seen failure after fork() when the executable image + # has been removed from the filesystem. + ln $SSHD_ORIG $SSHD_COPY || cp $SSHD_ORIG $SSHD_COPY SSHD=$SSHD_COPY start_sshd SSHD=$SSHD_ORIG diff --git a/regress/servcfginclude.sh b/regress/servcfginclude.sh new file mode 100644 index 000000000..b6a9a248f --- /dev/null +++ b/regress/servcfginclude.sh @@ -0,0 +1,188 @@ +# Placed in the Public Domain. + +tid="server config include" + +cat > $OBJ/sshd_config.i << _EOF +HostKey $OBJ/host.ssh-ed25519 +Match host a + Banner /aa + +Match host b + Banner /bb + Include $OBJ/sshd_config.i.* + +Match host c + Include $OBJ/sshd_config.i.* + Banner /cc + +Match host m + Include $OBJ/sshd_config.i.* + +Match Host d + Banner /dd + +Match Host e + Banner /ee + Include $OBJ/sshd_config.i.* + +Match Host f + Include $OBJ/sshd_config.i.* + Banner /ff + +Match Host n + Include $OBJ/sshd_config.i.* +_EOF + +cat > $OBJ/sshd_config.i.0 << _EOF +Match host xxxxxx +_EOF + +cat > $OBJ/sshd_config.i.1 << _EOF +Match host a + Banner /aaa + +Match host b + Banner /bbb + +Match host c + Banner /ccc + +Match Host d + Banner /ddd + +Match Host e + Banner /eee + +Match Host f + Banner /fff +_EOF + +cat > $OBJ/sshd_config.i.2 << _EOF +Match host a + Banner /aaaa + +Match host b + Banner /bbbb + +Match host c + Banner /cccc + +Match Host d + Banner /dddd + +Match Host e + Banner /eeee + +Match Host f + Banner /ffff + +Match all + Banner /xxxx +_EOF + +trial() { + _host="$1" + _exp="$2" + _desc="$3" + test -z "$_desc" && _desc="test match" + trace "$_desc host=$_host expect=$_exp" + ${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i -T \ + -C "host=$_host,user=test,addr=127.0.0.1" > $OBJ/sshd_config.out || + fatal "ssh config parse failed: $_desc host=$_host expect=$_exp" + _got=`grep -i '^banner ' $OBJ/sshd_config.out | awk '{print $2}'` + if test "x$_exp" != "x$_got" ; then + fail "$desc_ host $_host include fail: expected $_exp got $_got" + fi +} + +trial a /aa +trial b /bb +trial c /ccc +trial d /dd +trial e /ee +trial f /fff +trial m /xxxx +trial n /xxxx +trial x none + +# Prepare an included config with an error. + +cat > $OBJ/sshd_config.i.3 << _EOF +Banner xxxx + Junk +_EOF + +trace "disallow invalid config host=a" +${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i \ + -C "host=a,user=test,addr=127.0.0.1" 2>/dev/null && \ + fail "sshd include allowed invalid config" + +trace "disallow invalid config host=x" +${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i \ + -C "host=x,user=test,addr=127.0.0.1" 2>/dev/null && \ + fail "sshd include allowed invalid config" + +rm -f $OBJ/sshd_config.i.* + +# Ensure that a missing include is not fatal. +cat > $OBJ/sshd_config.i << _EOF +HostKey $OBJ/host.ssh-ed25519 +Include $OBJ/sshd_config.i.* +Banner /aa +_EOF + +trial a /aa "missing include non-fatal" + +# Ensure that Match/Host in an included config does not affect parent. +cat > $OBJ/sshd_config.i.x << _EOF +Match host x +_EOF + +trial a /aa "included file does not affect match state" + +# Ensure the empty include directive is not accepted +cat > $OBJ/sshd_config.i.x << _EOF +Include +_EOF + +trace "disallow invalid with no argument" +${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i.x -T \ + -C "host=x,user=test,addr=127.0.0.1" 2>/dev/null && \ + fail "sshd allowed Include with no argument" + +# Ensure the Include before any Match block works as expected (bug #3122) +cat > $OBJ/sshd_config.i << _EOF +Banner /xx +HostKey $OBJ/host.ssh-ed25519 +Include $OBJ/sshd_config.i.2 +Match host a + Banner /aaaa +_EOF +cat > $OBJ/sshd_config.i.2 << _EOF +Match host a + Banner /aa +_EOF + +trace "Include before match blocks" +trial a /aa "included file before match blocks is properly evaluated" + +# Port in included file is correctly interpretted (bug #3169) +cat > $OBJ/sshd_config.i << _EOF +Include $OBJ/sshd_config.i.2 +Port 7722 +_EOF +cat > $OBJ/sshd_config.i.2 << _EOF +HostKey $OBJ/host.ssh-ed25519 +_EOF + +trace "Port after included files" +${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i -T \ + -C "host=x,user=test,addr=127.0.0.1" > $OBJ/sshd_config.out || \ + fail "failed to parse Port after included files" +_port=`grep -i '^port ' $OBJ/sshd_config.out | awk '{print $2}'` +if test "x7722" != "x$_port" ; then + fail "The Port in included file was intertepretted wrongly. Expected 7722, got $_port" +fi + +# cleanup +rm -f $OBJ/sshd_config.i $OBJ/sshd_config.i.* $OBJ/sshd_config.out diff --git a/regress/sftp-badcmds.sh b/regress/sftp-badcmds.sh index 7f85c4f22..5b016d558 100644 --- a/regress/sftp-badcmds.sh +++ b/regress/sftp-badcmds.sh @@ -1,4 +1,4 @@ -# $OpenBSD: sftp-badcmds.sh,v 1.6 2013/05/17 10:26:26 dtucker Exp $ +# $OpenBSD: sftp-badcmds.sh,v 1.7 2020/03/13 03:18:45 djm Exp $ # Placed in the Public Domain. tid="sftp invalid commands" @@ -58,7 +58,7 @@ rm -rf ${COPY} cp ${DATA2} ${COPY} verbose "$tid: glob put files to local file" echo "put /bin/l* $COPY" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 -cmp ${DATA2} ${COPY} || fail "put successed when it should have failed" +cmp ${DATA2} ${COPY} || fail "put succeeded when it should have failed" rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd diff --git a/regress/ssh2putty.sh b/regress/ssh2putty.sh index bcf83afe9..dcb975d95 100755 --- a/regress/ssh2putty.sh +++ b/regress/ssh2putty.sh @@ -1,5 +1,5 @@ #!/bin/sh -# $OpenBSD: ssh2putty.sh,v 1.3 2015/05/08 07:26:13 djm Exp $ +# $OpenBSD: ssh2putty.sh,v 1.5 2019/11/21 05:18:47 tb Exp $ if test "x$1" = "x" -o "x$2" = "x" -o "x$3" = "x" ; then echo "Usage: ssh2putty hostname port ssh-private-key" diff --git a/regress/sshcfgparse.sh b/regress/sshcfgparse.sh index 566d5b701..bc1eb8cb2 100644 --- a/regress/sshcfgparse.sh +++ b/regress/sshcfgparse.sh @@ -1,4 +1,4 @@ -# $OpenBSD: sshcfgparse.sh,v 1.5 2019/07/23 13:32:48 dtucker Exp $ +# $OpenBSD: sshcfgparse.sh,v 1.7 2021/02/24 23:12:35 dtucker Exp $ # Placed in the Public Domain. tid="ssh config parse" @@ -92,32 +92,32 @@ if [ "$os" == "windows" ]; then fi test "$f" = "baz" || fail "user first match user@host, expected 'baz' got '$f'" -verbose "pubkeyacceptedkeytypes" +verbose "pubkeyacceptedalgorithms" # Default set -f=`${SSH} -GF none host | awk '/^pubkeyacceptedkeytypes /{print $2}'` +f=`${SSH} -GF none host | awk '/^pubkeyacceptedalgorithms /{print $2}'` if [ "$os" == "windows" ]; then f=${f/$'\r'/} # remove CR (carriage return) fi expect_result_present "$f" "ssh-ed25519" "ssh-ed25519-cert-v01.*" expect_result_absent "$f" "ssh-dss" # Explicit override -f=`${SSH} -GF none -opubkeyacceptedkeytypes=ssh-ed25519 host | \ - awk '/^pubkeyacceptedkeytypes /{print $2}'` +f=`${SSH} -GF none -opubkeyacceptedalgorithms=ssh-ed25519 host | \ + awk '/^pubkeyacceptedalgorithms /{print $2}'` if [ "$os" == "windows" ]; then f=${f/$'\r'/} # remove CR (carriage return) fi expect_result_present "$f" "ssh-ed25519" expect_result_absent "$f" "ssh-ed25519-cert-v01.*" "ssh-dss" # Removal from default set -f=`${SSH} -GF none -opubkeyacceptedkeytypes=-ssh-ed25519-cert* host | \ - awk '/^pubkeyacceptedkeytypes /{print $2}'` +f=`${SSH} -GF none -opubkeyacceptedalgorithms=-ssh-ed25519-cert* host | \ + awk '/^pubkeyacceptedalgorithms /{print $2}'` if [ "$os" == "windows" ]; then f=${f/$'\r'/} # remove CR (carriage return) fi expect_result_present "$f" "ssh-ed25519" expect_result_absent "$f" "ssh-ed25519-cert-v01.*" "ssh-dss" -f=`${SSH} -GF none -opubkeyacceptedkeytypes=-ssh-ed25519 host | \ - awk '/^pubkeyacceptedkeytypes /{print $2}'` +f=`${SSH} -GF none -opubkeyacceptedalgorithms=-ssh-ed25519 host | \ + awk '/^pubkeyacceptedalgorithms /{print $2}'` if [ "$os" == "windows" ]; then f=${f/$'\r'/} # remove CR (carriage return) fi @@ -126,15 +126,15 @@ expect_result_absent "$f" "ssh-ed25519" "ssh-dss" # Append to default set. # This is not tested when built !WITH_OPENSSL if [ "$dsa" = "1" ]; then - f=`${SSH} -GF none -opubkeyacceptedkeytypes=+ssh-dss-cert* host | \ - awk '/^pubkeyacceptedkeytypes /{print $2}'` + f=`${SSH} -GF none -opubkeyacceptedalgorithms=+ssh-dss-cert* host | \ + awk '/^pubkeyacceptedalgorithms /{print $2}'` if [ "$os" == "windows" ]; then f=${f/$'\r'/} # remove CR (carriage return) fi expect_result_present "$f" "ssh-ed25519" "ssh-dss-cert-v01.*" expect_result_absent "$f" "ssh-dss" - f=`${SSH} -GF none -opubkeyacceptedkeytypes=+ssh-dss host | \ - awk '/^pubkeyacceptedkeytypes /{print $2}'` + f=`${SSH} -GF none -opubkeyacceptedalgorithms=+ssh-dss host | \ + awk '/^pubkeyacceptedalgorithms /{print $2}'` if [ "$os" == "windows" ]; then f=${f/$'\r'/} # remove CR (carriage return) fi @@ -142,5 +142,15 @@ if [ "$dsa" = "1" ]; then expect_result_absent "$f" "ssh-dss-cert-v01.*" fi +verbose "agentforwarding" +f=`${SSH} -GF none host | awk '/^forwardagent /{print$2}'` +expect_result_present "$f" "no" +f=`${SSH} -GF none -oforwardagent=no host | awk '/^forwardagent /{print$2}'` +expect_result_present "$f" "no" +f=`${SSH} -GF none -oforwardagent=yes host | awk '/^forwardagent /{print$2}'` +expect_result_present "$f" "yes" +f=`${SSH} -GF none '-oforwardagent=SSH_AUTH_SOCK.forward' host | awk '/^forwardagent /{print$2}'` +expect_result_present "$f" "SSH_AUTH_SOCK.forward" + # cleanup rm -f $OBJ/ssh_config.[012] diff --git a/regress/sshsig.sh b/regress/sshsig.sh index eb99486ae..1e2f9dda4 100644 --- a/regress/sshsig.sh +++ b/regress/sshsig.sh @@ -1,4 +1,4 @@ -# $OpenBSD: sshsig.sh,v 1.2 2019/10/04 03:39:19 djm Exp $ +# $OpenBSD: sshsig.sh,v 1.4 2020/03/13 03:18:45 djm Exp $ # Placed in the Public Domain. tid="sshsig" @@ -23,7 +23,7 @@ CA_PRIV=$OBJ/sigca-key CA_PUB=$OBJ/sigca-key.pub trace "start agent" -eval `${SSHAGENT} -s` > /dev/null +eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null r=$? if [ $r -ne 0 ]; then fatal "could not start ssh-agent: exit code $r" @@ -133,7 +133,7 @@ for t in $SIGNKEYS; do # check-novalidate with invalid data ${SSHKEYGEN} -vvv -Y check-novalidate -s $sigfile -n $sig_namespace \ < $DATA2 >/dev/null 2>&1 && \ - fail "sucessfully checked signature for $t key with invalid data" + fail "succeeded checking signature for $t key with invalid data" # Check signing keys using ssh-agent. ${SSHADD} -D >/dev/null 2>&1 # Remove all previously-loaded keys. diff --git a/regress/test-exec.sh b/regress/test-exec.sh index 322f89a72..209eb2e6f 100644 --- a/regress/test-exec.sh +++ b/regress/test-exec.sh @@ -1,4 +1,4 @@ -# $OpenBSD: test-exec.sh,v 1.66 2019/07/05 04:12:46 dtucker Exp $ +# $OpenBSD: test-exec.sh,v 1.77 2021/02/17 03:59:00 dtucker Exp $ # Placed in the Public Domain. #SUDO=sudo @@ -29,6 +29,16 @@ else PORT=4242 fi +# If configure tells us to use a different egrep, create a wrapper function +# to call it. This means we don't need to change all the tests that depend +# on a good implementation. +if test "x${EGREP}" != "x"; then + egrep () +{ + ${EGREP} "$@" +} +fi + if [ "$os" == "windows" ]; then USER=$TEST_SSH_USER USER_DOMAIN=$TEST_SSH_USER_DOMAIN @@ -41,10 +51,23 @@ else elif logname >/dev/null 2>&1; then USER=`logname` else - USER=`id -un` + 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 fi fi +if test -z "$LOGNAME"; then + LOGNAME="${USER}" + export LOGNAME +fi + OBJ=$1 if [ "x$OBJ" = "x" ]; then echo '$OBJ not defined' @@ -92,6 +115,9 @@ PLINK=plink PUTTYGEN=puttygen CONCH=conch +# Tools used by multiple tests +NC=$OBJ/netcat + if [ "x$TEST_SSH_SSH" != "x" ]; then SSH="${TEST_SSH_SSH}" fi @@ -140,6 +166,12 @@ if [ "x$TEST_SSH_CONCH" != "x" ]; then *) CONCH=`which ${TEST_SSH_CONCH} 2>/dev/null` ;; esac fi +if [ "x$TEST_SSH_PKCS11_HELPER" != "x" ]; then + SSH_PKCS11_HELPER="${TEST_SSH_PKCS11_HELPER}" +fi +if [ "x$TEST_SSH_SK_HELPER" != "x" ]; then + SSH_SK_HELPER="${TEST_SSH_SK_HELPER}" +fi # Path to sshd must be absolute for rexec case "$SSHD" in @@ -246,6 +278,7 @@ fi chmod a+rx $OBJ/ssh-log-wrapper.sh REAL_SSH="$SSH" +REAL_SSHD="$SSHD" SSH="$SSHLOGWRAP" # Some test data. We make a copy because some tests will overwrite it. @@ -271,6 +304,7 @@ increase_datafile_size() # these should be used in tests export SSH SSHD SSHAGENT SSHADD SSHKEYGEN SSHKEYSCAN SFTP SFTPSERVER SCP +export SSH_PKCS11_HELPER SSH_SK_HELPER #echo $SSH $SSHD $SSHAGENT $SSHADD $SSHKEYGEN $SSHKEYSCAN $SFTP $SFTPSERVER $SCP # Portable specific functions @@ -322,6 +356,15 @@ md5 () { wc -c fi } + +# Some platforms don't have hostname at all, but on others uname -n doesn't +# provide the fully qualified name we need, so in the former case we create +# our own hostname function. +if ! have_prog hostname; then + hostname() { + uname -n + } +fi # End of portable specific functions stop_sshd () @@ -481,6 +524,31 @@ EOF # be abused to locally escalate privileges. if [ ! -z "$TEST_SSH_UNSAFE_PERMISSIONS" ]; then echo "StrictModes no" >> $OBJ/sshd_config +else + # check and warn if excessive permissions are likely to cause failures. + unsafe="" + dir="${OBJ}" + while test ${dir} != "/"; do + if test -d "${dir}" && ! test -h "${dir}"; then + perms=`ls -ld ${dir}` + case "${perms}" in + ?????w????*|????????w?*) unsafe="${unsafe} ${dir}" ;; + esac + fi + dir=`dirname ${dir}` + done + if ! test -z "${unsafe}"; then + cat <> $OBJ/ssh_config + echo "SecurityKeyProvider $SSH_SK_PROVIDER" >> $OBJ/sshd_config + echo "SecurityKeyProvider $SSH_SK_PROVIDER" >> $OBJ/sshd_proxy +fi +export EXTRA_AGENT_ARGS + +maybe_filter_sk() { + if test -z "$SSH_SK_PROVIDER" ; then + grep -v ^sk + else + cat + fi +} + +SSH_KEYTYPES=`$SSH -Q key-plain | maybe_filter_sk` +SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | maybe_filter_sk` + if [ "$os" == "windows" ]; then SSH_KEYTYPES=`echo $SSH_KEYTYPES | tr -d '\r','\n'` # remove \r\n + SSH_HOSTKEY_TYPES=`echo $SSH_HOSTKEY_TYPES | tr -d '\r','\n'` # remove \r\n + OBJ_WIN_FORMAT=`windows_path $OBJ` first_key_type=${SSH_KEYTYPES%% *} if [ "x$USER_DOMAIN" != "x" ]; then # For domain user, create folders @@ -537,30 +635,29 @@ if [ "$os" == "windows" ]; then fi fi -if [ "$os" == "windows" ]; then - OBJ_WIN_FORMAT=`windows_path $OBJ` -fi - for t in ${SSH_KEYTYPES}; do # generate user key - trace "generating key type $t" - if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN_BIN} -nt $OBJ/$t ]; then + trace "generating key type $t" rm -f $OBJ/$t ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\ fail "ssh-keygen for $t failed" + else + trace "using cached key type $t" fi + # setup authorized keys + cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER + echo IdentityFile $OBJ/$t >> $OBJ/ssh_config +done + +for t in ${SSH_HOSTKEY_TYPES}; do # 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 if [ "$os" == "windows" ]; then @@ -585,10 +682,11 @@ 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 +# If PuTTY is present, new enough and we are running a PuTTY test, prepare +# keys and configuration. REGRESS_INTEROP_PUTTY=no -if test -x "$PUTTYGEN" -a -x "$PLINK" ; then +if test -x "$PUTTYGEN" -a -x "$PLINK" && + "$PUTTYGEN" --help 2>&1 | grep -- --new-passphrase >/dev/null; then REGRESS_INTEROP_PUTTY=yes fi case "$SCRIPT" in @@ -601,13 +699,13 @@ if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then # Add a PuTTY key to authorized_keys rm -f ${OBJ}/putty.rsa2 - if ! puttygen -t rsa -o ${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 + echo "Your installed version of PuTTY is too old to support --new-passphrase, skipping test" >&2 + exit 1 fi - puttygen -O public-openssh ${OBJ}/putty.rsa2 \ + "$PUTTYGEN" -O public-openssh ${OBJ}/putty.rsa2 \ >> $OBJ/authorized_keys_$USER # Convert rsa2 host key to PuTTY format @@ -631,8 +729,6 @@ if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then PUTTYDIR=${OBJ}/.putty export PUTTYDIR - - REGRESS_INTEROP_PUTTY=yes fi # create a proxy version of the client config @@ -641,7 +737,7 @@ fi if [ "$os" == "windows" ]; then echo proxycommand `windows_path ${SSHD}` -i -f $OBJ_WIN_FORMAT/sshd_proxy else - echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy + echo proxycommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy fi ) > $OBJ/ssh_proxy @@ -658,7 +754,8 @@ start_sshd () #TODO (Code BUG) : -E is writing the data the cygwin terminal. ${SSHD} -f $OBJ/sshd_config "$@" & else - $SUDO ${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE + $SUDO env SSH_SK_HELPER="$SSH_SK_HELPER" \ + ${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE fi trace "wait for sshd" diff --git a/regress/unittests/Makefile b/regress/unittests/Makefile index 4e56e1104..4d26b7477 100644 --- a/regress/unittests/Makefile +++ b/regress/unittests/Makefile @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile,v 1.11 2019/04/28 22:53:26 dtucker Exp $ +# $OpenBSD: Makefile,v 1.12 2020/06/19 04:34:21 djm Exp $ REGRESS_FAIL_EARLY?= yes SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys utf8 match conversion -SUBDIR+=authopt misc +SUBDIR+=authopt misc sshsig .include diff --git a/regress/unittests/Makefile.inc b/regress/unittests/Makefile.inc index 428ef6836..370224aa5 100644 --- a/regress/unittests/Makefile.inc +++ b/regress/unittests/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.13 2018/10/17 23:28:05 djm Exp $ +# $OpenBSD: Makefile.inc,v 1.14 2019/11/25 10:32:35 djm Exp $ REGRESS_FAIL_EARLY?= yes @@ -74,6 +74,9 @@ LDADD+= -lcrypto DPADD+= ${LIBCRYPTO} .endif +LDADD+= -lfido2 -lcbor -lusbhid +DPADD+= ${LIBFIDO2} ${LIBCBOR} ${LIBUSBHID} + UNITTEST_ARGS?= .if (${UNITTEST_VERBOSE:L} != "no") diff --git a/regress/unittests/authopt/Makefile b/regress/unittests/authopt/Makefile new file mode 100644 index 000000000..71a7be5bd --- /dev/null +++ b/regress/unittests/authopt/Makefile @@ -0,0 +1,27 @@ +# $OpenBSD: Makefile,v 1.6 2021/01/09 12:24:30 dtucker Exp $ + +PROG=test_authopt +SRCS=tests.c + +SRCS+=auth-options.c + +# From usr.bin/ssh +SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c +SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c +SRCS+=ssh-dss.c 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+=addr.c 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 ssh-ecdsa-sk.c ssh-sk.c +SRCS+=ssh-ed25519-sk.c sk-usbhid.c + +SRCS+=digest-openssl.c +#SRCS+=digest-libc.c +SRCS+=utf8.c + +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} -d ${.CURDIR}/testdata + +.include diff --git a/regress/unittests/conversion/Makefile b/regress/unittests/conversion/Makefile index 8b2a09cc3..5793c4934 100644 --- a/regress/unittests/conversion/Makefile +++ b/regress/unittests/conversion/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.2 2017/12/21 00:41:22 djm Exp $ +# $OpenBSD: Makefile,v 1.4 2021/01/09 12:24:30 dtucker Exp $ PROG=test_conversion SRCS=tests.c @@ -6,6 +6,7 @@ SRCS=tests.c # From usr.bin/ssh SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c SRCS+=atomicio.c misc.c xmalloc.c log.c uidswap.c cleanup.c fatal.c ssherr.c +SRCS+=match.c addr.c addrmatch.c REGRESS_TARGETS=run-regress-${PROG} diff --git a/regress/unittests/conversion/tests.c b/regress/unittests/conversion/tests.c index ae1154d42..bbdc5f5a7 100644 --- a/regress/unittests/conversion/tests.c +++ b/regress/unittests/conversion/tests.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tests.c,v 1.2 2019/06/14 04:03:48 djm Exp $ */ +/* $OpenBSD: tests.c,v 1.3 2021/01/18 11:43:34 dtucker Exp $ */ /* * Regress test for conversions * @@ -26,28 +26,28 @@ tests(void) char buf[1024]; TEST_START("conversion_convtime"); - ASSERT_LONG_EQ(convtime("0"), 0); - ASSERT_LONG_EQ(convtime("1"), 1); - ASSERT_LONG_EQ(convtime("1S"), 1); + ASSERT_INT_EQ(convtime("0"), 0); + ASSERT_INT_EQ(convtime("1"), 1); + ASSERT_INT_EQ(convtime("1S"), 1); /* from the examples in the comment above the function */ - ASSERT_LONG_EQ(convtime("90m"), 5400); - ASSERT_LONG_EQ(convtime("1h30m"), 5400); - ASSERT_LONG_EQ(convtime("2d"), 172800); - ASSERT_LONG_EQ(convtime("1w"), 604800); + ASSERT_INT_EQ(convtime("90m"), 5400); + ASSERT_INT_EQ(convtime("1h30m"), 5400); + ASSERT_INT_EQ(convtime("2d"), 172800); + ASSERT_INT_EQ(convtime("1w"), 604800); /* negative time is not allowed */ - ASSERT_LONG_EQ(convtime("-7"), -1); - ASSERT_LONG_EQ(convtime("-9d"), -1); + ASSERT_INT_EQ(convtime("-7"), -1); + ASSERT_INT_EQ(convtime("-9d"), -1); /* overflow */ - snprintf(buf, sizeof buf, "%llu", (unsigned long long)LONG_MAX); - ASSERT_LONG_EQ(convtime(buf), -1); - snprintf(buf, sizeof buf, "%llu", (unsigned long long)LONG_MAX + 1); - ASSERT_LONG_EQ(convtime(buf), -1); + snprintf(buf, sizeof buf, "%llu", (unsigned long long)INT_MAX); + ASSERT_INT_EQ(convtime(buf), INT_MAX); + snprintf(buf, sizeof buf, "%llu", (unsigned long long)INT_MAX + 1); + ASSERT_INT_EQ(convtime(buf), -1); /* overflow with multiplier */ - snprintf(buf, sizeof buf, "%lluM", (unsigned long long)LONG_MAX/60 + 1); - ASSERT_LONG_EQ(convtime(buf), -1); - ASSERT_LONG_EQ(convtime("1000000000000000000000w"), -1); + snprintf(buf, sizeof buf, "%lluM", (unsigned long long)INT_MAX/60 + 1); + ASSERT_INT_EQ(convtime(buf), -1); + ASSERT_INT_EQ(convtime("1000000000000000000000w"), -1); TEST_DONE(); } diff --git a/regress/unittests/hostkeys/Makefile b/regress/unittests/hostkeys/Makefile index 336885122..9a53423ee 100644 --- a/regress/unittests/hostkeys/Makefile +++ b/regress/unittests/hostkeys/Makefile @@ -1,19 +1,21 @@ -# $OpenBSD: Makefile,v 1.4 2017/12/21 00:41:22 djm Exp $ +# $OpenBSD: Makefile,v 1.9 2021/01/09 12:24:30 dtucker Exp $ PROG=test_hostkeys SRCS=tests.c test_iterate.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+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c +SRCS+=ssh-dss.c 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 hostfile.c +SRCS+=addr.c addrmatch.c bitmap.c hostfile.c SRCS+=ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c -SRCS+=cipher-chachapoly.c chacha.c poly1305.c +SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c +SRCS+=ssh-ed25519-sk.c sk-usbhid.c SRCS+=digest-openssl.c #SRCS+=digest-libc.c +SRCS+=utf8.c REGRESS_TARGETS=run-regress-${PROG} diff --git a/regress/unittests/hostkeys/test_iterate.c b/regress/unittests/hostkeys/test_iterate.c index 5904121ef..a5b17d7e4 100644 --- a/regress/unittests/hostkeys/test_iterate.c +++ b/regress/unittests/hostkeys/test_iterate.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_iterate.c,v 1.6 2018/07/16 03:09:59 djm Exp $ */ +/* $OpenBSD: test_iterate.c,v 1.7 2020/12/21 01:31:06 djm Exp $ */ /* * Regress test for hostfile.h hostkeys_foreach() * @@ -194,6 +194,7 @@ struct expected expected_full[] = { KEY_UNSPEC, /* key type */ NULL, /* deserialised key */ NULL, /* comment */ + 0, /* note */ } }, { "dsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, @@ -207,6 +208,7 @@ struct expected expected_full[] = { KEY_DSA, NULL, /* filled at runtime */ "DSA #1", + 0, } }, { "ecdsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, @@ -220,6 +222,7 @@ struct expected expected_full[] = { KEY_ECDSA, NULL, /* filled at runtime */ "ECDSA #1", + 0, } }, { "ed25519_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, @@ -233,6 +236,7 @@ struct expected expected_full[] = { KEY_ED25519, NULL, /* filled at runtime */ "ED25519 #1", + 0, } }, { "rsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, @@ -246,6 +250,7 @@ struct expected expected_full[] = { KEY_RSA, NULL, /* filled at runtime */ "RSA #1", + 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, @@ -259,6 +264,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, @@ -272,6 +278,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, { "dsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, @@ -285,6 +292,7 @@ struct expected expected_full[] = { KEY_DSA, NULL, /* filled at runtime */ "DSA #2", + 0, } }, { "ecdsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, @@ -298,6 +306,7 @@ struct expected expected_full[] = { KEY_ECDSA, NULL, /* filled at runtime */ "ECDSA #2", + 0, } }, { "ed25519_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, @@ -311,6 +320,7 @@ struct expected expected_full[] = { KEY_ED25519, NULL, /* filled at runtime */ "ED25519 #2", + 0, } }, { "rsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, @@ -324,6 +334,7 @@ struct expected expected_full[] = { KEY_RSA, NULL, /* filled at runtime */ "RSA #2", + 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, @@ -337,6 +348,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, @@ -350,6 +362,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, { "dsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, @@ -363,6 +376,7 @@ struct expected expected_full[] = { KEY_DSA, NULL, /* filled at runtime */ "DSA #3", + 0, } }, { "ecdsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, @@ -376,6 +390,7 @@ struct expected expected_full[] = { KEY_ECDSA, NULL, /* filled at runtime */ "ECDSA #3", + 0, } }, { "ed25519_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, @@ -389,6 +404,7 @@ struct expected expected_full[] = { KEY_ED25519, NULL, /* filled at runtime */ "ED25519 #3", + 0, } }, { "rsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, @@ -402,6 +418,7 @@ struct expected expected_full[] = { KEY_RSA, NULL, /* filled at runtime */ "RSA #3", + 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, @@ -415,6 +432,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, @@ -428,6 +446,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, { "dsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { NULL, @@ -441,6 +460,7 @@ struct expected expected_full[] = { KEY_DSA, NULL, /* filled at runtime */ "DSA #5", + 0, } }, { "ecdsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { NULL, @@ -454,6 +474,7 @@ struct expected expected_full[] = { KEY_ECDSA, NULL, /* filled at runtime */ "ECDSA #5", + 0, } }, { "ed25519_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { NULL, @@ -467,6 +488,7 @@ struct expected expected_full[] = { KEY_ED25519, NULL, /* filled at runtime */ "ED25519 #5", + 0, } }, { "rsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { NULL, @@ -480,6 +502,7 @@ struct expected expected_full[] = { KEY_RSA, NULL, /* filled at runtime */ "RSA #5", + 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, @@ -493,6 +516,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, /* * The next series have each key listed multiple times, as the @@ -511,6 +535,7 @@ struct expected expected_full[] = { KEY_DSA, NULL, /* filled at runtime */ "DSA #6", + 0, } }, { "dsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { NULL, @@ -524,6 +549,7 @@ struct expected expected_full[] = { KEY_DSA, NULL, /* filled at runtime */ "DSA #6", + 0, } }, { "dsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { NULL, @@ -537,6 +563,7 @@ struct expected expected_full[] = { KEY_DSA, NULL, /* filled at runtime */ "DSA #6", + 0, } }, { "ecdsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { NULL, @@ -550,6 +577,7 @@ struct expected expected_full[] = { KEY_ECDSA, NULL, /* filled at runtime */ "ECDSA #6", + 0, } }, { "ecdsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { NULL, @@ -563,6 +591,7 @@ struct expected expected_full[] = { KEY_ECDSA, NULL, /* filled at runtime */ "ECDSA #6", + 0, } }, { "ecdsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { NULL, @@ -576,6 +605,7 @@ struct expected expected_full[] = { KEY_ECDSA, NULL, /* filled at runtime */ "ECDSA #6", + 0, } }, { "ed25519_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { NULL, @@ -589,6 +619,7 @@ struct expected expected_full[] = { KEY_ED25519, NULL, /* filled at runtime */ "ED25519 #6", + 0, } }, { "ed25519_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { NULL, @@ -602,6 +633,7 @@ struct expected expected_full[] = { KEY_ED25519, NULL, /* filled at runtime */ "ED25519 #6", + 0, } }, { "ed25519_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { NULL, @@ -615,6 +647,7 @@ struct expected expected_full[] = { KEY_ED25519, NULL, /* filled at runtime */ "ED25519 #6", + 0, } }, { "rsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { NULL, @@ -628,6 +661,7 @@ struct expected expected_full[] = { KEY_RSA, NULL, /* filled at runtime */ "RSA #6", + 0, } }, { "rsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { NULL, @@ -641,6 +675,7 @@ struct expected expected_full[] = { KEY_RSA, NULL, /* filled at runtime */ "RSA #6", + 0, } }, { "rsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { NULL, @@ -654,6 +689,7 @@ struct expected expected_full[] = { KEY_RSA, NULL, /* filled at runtime */ "RSA #6", + 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, @@ -667,6 +703,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, @@ -680,6 +717,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, @@ -693,6 +731,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, { "ed25519_4.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, @@ -706,6 +745,7 @@ struct expected expected_full[] = { KEY_ED25519, NULL, /* filled at runtime */ "ED25519 #4", + 0, } }, { "ecdsa_4.pub" , -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, { NULL, @@ -719,6 +759,7 @@ struct expected expected_full[] = { KEY_ECDSA, NULL, /* filled at runtime */ "ECDSA #4", + 0, } }, { "dsa_4.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, 0, 0, -1, { NULL, @@ -732,6 +773,7 @@ struct expected expected_full[] = { KEY_DSA, NULL, /* filled at runtime */ "DSA #4", + 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, @@ -745,6 +787,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, @@ -758,6 +801,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, @@ -771,6 +815,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, @@ -784,6 +829,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, { NULL, -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, { NULL, @@ -797,6 +843,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, @@ -810,6 +857,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, NULL, + 0, } }, { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, @@ -823,6 +871,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, /* filled at runtime */ NULL, + 0, } }, { NULL, HKF_STATUS_OK, KEY_RSA, HKF_MATCH_HOST, 0, 0, 0, -1, { NULL, @@ -836,6 +885,7 @@ struct expected expected_full[] = { KEY_UNSPEC, NULL, /* filled at runtime */ NULL, + 0, } }, }; @@ -853,7 +903,7 @@ test_iterate(void) ctx.flags = HKF_WANT_PARSE_KEY; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, NULL, NULL, ctx.flags), 0); + check, &ctx, NULL, NULL, ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -864,7 +914,7 @@ test_iterate(void) ctx.flags = 0; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, NULL, NULL, ctx.flags), 0); + check, &ctx, NULL, NULL, ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -876,7 +926,7 @@ test_iterate(void) ctx.match_host_p = 1; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, "prometheus.example.com", NULL, ctx.flags), 0); + check, &ctx, "prometheus.example.com", NULL, ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -888,7 +938,7 @@ test_iterate(void) ctx.match_host_s = 1; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, "sisyphus.example.com", NULL, ctx.flags), 0); + check, &ctx, "sisyphus.example.com", NULL, ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -900,7 +950,7 @@ test_iterate(void) ctx.match_host_p = 1; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, "prometheus.example.com", NULL, ctx.flags), 0); + check, &ctx, "prometheus.example.com", NULL, ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -912,7 +962,7 @@ test_iterate(void) ctx.match_host_s = 1; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, "sisyphus.example.com", NULL, ctx.flags), 0); + check, &ctx, "sisyphus.example.com", NULL, ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -923,7 +973,7 @@ test_iterate(void) ctx.flags = 0; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, "actaeon.example.org", NULL, ctx.flags), 0); + check, &ctx, "actaeon.example.org", NULL, ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -934,7 +984,7 @@ test_iterate(void) ctx.flags = HKF_WANT_MATCH; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, "actaeon.example.org", NULL, ctx.flags), 0); + check, &ctx, "actaeon.example.org", NULL, ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -946,7 +996,7 @@ test_iterate(void) ctx.match_ipv4 = 1; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags), 0); + check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -958,7 +1008,8 @@ test_iterate(void) ctx.match_ipv6 = 1; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, "tiresias.example.org", "2001:db8::1", ctx.flags), 0); + check, &ctx, "tiresias.example.org", "2001:db8::1", + ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -970,7 +1021,7 @@ test_iterate(void) ctx.match_ipv4 = 1; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags), 0); + check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -982,7 +1033,8 @@ test_iterate(void) ctx.match_ipv6 = 1; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, "tiresias.example.org", "2001:db8::1", ctx.flags), 0); + check, &ctx, "tiresias.example.org", "2001:db8::1", + ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -993,7 +1045,8 @@ test_iterate(void) ctx.flags = 0; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, "tiresias.example.org", "192.168.0.1", ctx.flags), 0); + check, &ctx, "tiresias.example.org", "192.168.0.1", + ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -1004,7 +1057,7 @@ test_iterate(void) ctx.flags = HKF_WANT_MATCH; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, "tiresias.example.org", "::1", ctx.flags), 0); + check, &ctx, "tiresias.example.org", "::1", ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -1017,7 +1070,7 @@ test_iterate(void) ctx.match_ipv4 = 1; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags), 0); + check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -1031,7 +1084,7 @@ test_iterate(void) prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), check, &ctx, "prometheus.example.com", - "2001:db8::1", ctx.flags), 0); + "2001:db8::1", ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -1044,7 +1097,7 @@ test_iterate(void) ctx.match_ipv4 = 1; prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), - check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags), 0); + check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); @@ -1058,7 +1111,7 @@ test_iterate(void) prepare_expected(expected_full, ctx.nexpected); ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"), check, &ctx, "prometheus.example.com", - "2001:db8::1", ctx.flags), 0); + "2001:db8::1", ctx.flags, 0), 0); cleanup_expected(expected_full, ctx.nexpected); TEST_DONE(); } diff --git a/regress/unittests/kex/Makefile b/regress/unittests/kex/Makefile index 7b4c644e5..50b117c07 100644 --- a/regress/unittests/kex/Makefile +++ b/regress/unittests/kex/Makefile @@ -1,16 +1,17 @@ -# $OpenBSD: Makefile,v 1.6 2019/01/21 12:35:20 djm Exp $ +# $OpenBSD: Makefile,v 1.12 2021/01/09 12:24:30 dtucker 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+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c +SRCS+=ssh-dss.c 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+=addr.c addrmatch.c bitmap.c packet.c dispatch.c canohost.c ssh_api.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+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c +SRCS+=ssh-ed25519-sk.c sk-usbhid.c SRCS+= kex.c SRCS+= dh.c @@ -22,8 +23,9 @@ SRCS+= kexgexs.c SRCS+= kexc25519.c SRCS+= smult_curve25519_ref.c SRCS+= kexgen.c -SRCS+= kexsntrup4591761x25519.c -SRCS+= sntrup4591761.c +SRCS+= kexsntrup761x25519.c +SRCS+= sntrup761.c +SRCS+= utf8.c SRCS+=digest-openssl.c #SRCS+=digest-libc.c diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c index 0e7cd9e07..06bd001ae 100644 --- a/regress/unittests/kex/test_kex.c +++ b/regress/unittests/kex/test_kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_kex.c,v 1.4 2019/01/21 12:35:20 djm Exp $ */ +/* $OpenBSD: test_kex.c,v 1.5 2020/12/29 01:02:15 djm Exp $ */ /* * Regress test KEX * @@ -152,6 +152,7 @@ do_kex_with_key(char *kex, int keytype, int bits) #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ server2->kex->kex[KEX_C25519_SHA256] = kex_gen_server; + server2->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = 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; @@ -201,5 +202,6 @@ kex_tests(void) do_kex("diffie-hellman-group-exchange-sha1"); do_kex("diffie-hellman-group14-sha1"); do_kex("diffie-hellman-group1-sha1"); + do_kex("sntrup761x25519-sha512@openssh.com"); #endif /* WITH_OPENSSL */ } diff --git a/regress/unittests/match/Makefile b/regress/unittests/match/Makefile index 87e75826a..939163d30 100644 --- a/regress/unittests/match/Makefile +++ b/regress/unittests/match/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.4 2017/12/21 03:01:49 djm Exp $ +# $OpenBSD: Makefile,v 1.5 2021/01/09 12:24:31 dtucker Exp $ PROG=test_match SRCS=tests.c @@ -6,7 +6,7 @@ SRCS=tests.c # From usr.bin/ssh SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c SRCS+=match.c misc.c log.c uidswap.c fatal.c ssherr.c addrmatch.c xmalloc.c -SRCS+=cleanup.c atomicio.c +SRCS+=cleanup.c atomicio.c addr.c REGRESS_TARGETS=run-regress-${PROG} diff --git a/regress/unittests/match/tests.c b/regress/unittests/match/tests.c index 3d9af55f2..4fefaf4f3 100644 --- a/regress/unittests/match/tests.c +++ b/regress/unittests/match/tests.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tests.c,v 1.5 2018/07/04 13:51:45 djm Exp $ */ +/* $OpenBSD: tests.c,v 1.7 2020/07/15 06:43:16 dtucker Exp $ */ /* * Regress test for matching functions * @@ -105,7 +105,7 @@ tests(void) #define CHECK_FILTER(string,filter,expected) \ do { \ - char *result = match_filter_blacklist((string), (filter)); \ + char *result = match_filter_denylist((string), (filter)); \ ASSERT_STRING_EQ(result, expected); \ free(result); \ } while (0) diff --git a/regress/unittests/misc/Makefile b/regress/unittests/misc/Makefile new file mode 100644 index 000000000..04eddcd78 --- /dev/null +++ b/regress/unittests/misc/Makefile @@ -0,0 +1,26 @@ +# $OpenBSD: Makefile,v 1.4 2021/01/09 12:24:31 dtucker Exp $ + +PROG=test_misc +SRCS=tests.c + +# From usr.bin/ssh/Makefile.inc +SRCS+= sshbuf.c +SRCS+= sshbuf-getput-basic.c +SRCS+= sshbuf-misc.c +SRCS+= ssherr.c +SRCS+= log.c +SRCS+= xmalloc.c +SRCS+= misc.c +SRCS+= match.c +SRCS+= addr.c +SRCS+= addrmatch.c + +# From usr.bin/ssh/sshd/Makefile +SRCS+= atomicio.c cleanup.c fatal.c + +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} + +.include diff --git a/regress/unittests/misc/tests.c b/regress/unittests/misc/tests.c new file mode 100644 index 000000000..d873dc241 --- /dev/null +++ b/regress/unittests/misc/tests.c @@ -0,0 +1,172 @@ +/* $OpenBSD: tests.c,v 1.4 2021/01/15 02:58:11 dtucker Exp $ */ +/* + * Regress test for misc helper functions. + * + * Placed in the public domain. + */ + +#include +#include +#include +#include +#include +#include + +#include "test_helper.h" + +#include "log.h" +#include "misc.h" + +void +tests(void) +{ + int port, parseerr; + char *user, *host, *path, *ret; + char buf[1024]; + + TEST_START("misc_parse_user_host_path"); + ASSERT_INT_EQ(parse_user_host_path("someuser@some.host:some/path", + &user, &host, &path), 0); + ASSERT_STRING_EQ(user, "someuser"); + ASSERT_STRING_EQ(host, "some.host"); + ASSERT_STRING_EQ(path, "some/path"); + free(user); free(host); free(path); + TEST_DONE(); + + TEST_START("misc_parse_user_ipv4_path"); + ASSERT_INT_EQ(parse_user_host_path("someuser@1.22.33.144:some/path", + &user, &host, &path), 0); + ASSERT_STRING_EQ(user, "someuser"); + ASSERT_STRING_EQ(host, "1.22.33.144"); + ASSERT_STRING_EQ(path, "some/path"); + free(user); free(host); free(path); + TEST_DONE(); + + TEST_START("misc_parse_user_[ipv4]_path"); + ASSERT_INT_EQ(parse_user_host_path("someuser@[1.22.33.144]:some/path", + &user, &host, &path), 0); + ASSERT_STRING_EQ(user, "someuser"); + ASSERT_STRING_EQ(host, "1.22.33.144"); + ASSERT_STRING_EQ(path, "some/path"); + free(user); free(host); free(path); + TEST_DONE(); + + TEST_START("misc_parse_user_[ipv4]_nopath"); + ASSERT_INT_EQ(parse_user_host_path("someuser@[1.22.33.144]:", + &user, &host, &path), 0); + ASSERT_STRING_EQ(user, "someuser"); + ASSERT_STRING_EQ(host, "1.22.33.144"); + ASSERT_STRING_EQ(path, "."); + free(user); free(host); free(path); + TEST_DONE(); + + TEST_START("misc_parse_user_ipv6_path"); + ASSERT_INT_EQ(parse_user_host_path("someuser@[::1]:some/path", + &user, &host, &path), 0); + ASSERT_STRING_EQ(user, "someuser"); + ASSERT_STRING_EQ(host, "::1"); + ASSERT_STRING_EQ(path, "some/path"); + free(user); free(host); free(path); + TEST_DONE(); + + TEST_START("misc_parse_uri"); + ASSERT_INT_EQ(parse_uri("ssh", "ssh://someuser@some.host:22/some/path", + &user, &host, &port, &path), 0); + ASSERT_STRING_EQ(user, "someuser"); + ASSERT_STRING_EQ(host, "some.host"); + ASSERT_INT_EQ(port, 22); + ASSERT_STRING_EQ(path, "some/path"); + free(user); free(host); free(path); + TEST_DONE(); + + TEST_START("misc_convtime"); + ASSERT_INT_EQ(convtime("0"), 0); + ASSERT_INT_EQ(convtime("1"), 1); + ASSERT_INT_EQ(convtime("2s"), 2); + ASSERT_INT_EQ(convtime("3m"), 180); + ASSERT_INT_EQ(convtime("1m30"), 90); + ASSERT_INT_EQ(convtime("1m30s"), 90); + ASSERT_INT_EQ(convtime("1h1s"), 3601); + ASSERT_INT_EQ(convtime("1h30m"), 90 * 60); + ASSERT_INT_EQ(convtime("1d"), 24 * 60 * 60); + ASSERT_INT_EQ(convtime("1w"), 7 * 24 * 60 * 60); + ASSERT_INT_EQ(convtime("1w2d3h4m5"), 788645); + ASSERT_INT_EQ(convtime("1w2d3h4m5s"), 788645); + /* any negative number or error returns -1 */ + ASSERT_INT_EQ(convtime("-1"), -1); + ASSERT_INT_EQ(convtime(""), -1); + ASSERT_INT_EQ(convtime("trout"), -1); + ASSERT_INT_EQ(convtime("-77"), -1); + /* boundary conditions */ + snprintf(buf, sizeof buf, "%llu", (long long unsigned)INT_MAX); + ASSERT_INT_EQ(convtime(buf), INT_MAX); + snprintf(buf, sizeof buf, "%llu", (long long unsigned)INT_MAX + 1); + ASSERT_INT_EQ(convtime(buf), -1); + ASSERT_INT_EQ(convtime("3550w5d3h14m7s"), 2147483647); +#if INT_MAX == 2147483647 + ASSERT_INT_EQ(convtime("3550w5d3h14m8s"), -1); +#endif + TEST_DONE(); + + TEST_START("dollar_expand"); + if (setenv("FOO", "bar", 1) != 0) + abort(); + if (setenv("BAR", "baz", 1) != 0) + abort(); + if (unsetenv("BAZ") != 0) + abort(); +#define ASSERT_DOLLAR_EQ(x, y) do { \ + char *str = dollar_expand(NULL, (x)); \ + ASSERT_STRING_EQ(str, (y)); \ + free(str); \ +} while(0) + ASSERT_DOLLAR_EQ("${FOO}", "bar"); + ASSERT_DOLLAR_EQ(" ${FOO}", " bar"); + ASSERT_DOLLAR_EQ("${FOO} ", "bar "); + ASSERT_DOLLAR_EQ(" ${FOO} ", " bar "); + ASSERT_DOLLAR_EQ("${FOO}${BAR}", "barbaz"); + ASSERT_DOLLAR_EQ(" ${FOO} ${BAR}", " bar baz"); + ASSERT_DOLLAR_EQ("${FOO}${BAR} ", "barbaz "); + ASSERT_DOLLAR_EQ(" ${FOO} ${BAR} ", " bar baz "); + ASSERT_DOLLAR_EQ("$", "$"); + ASSERT_DOLLAR_EQ(" $", " $"); + ASSERT_DOLLAR_EQ("$ ", "$ "); + + /* suppress error messages for error handing tests */ + log_init("test_misc", SYSLOG_LEVEL_QUIET, SYSLOG_FACILITY_AUTH, 1); + /* error checking, non existent variable */ + ret = dollar_expand(&parseerr, "a${BAZ}"); + ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 0); + ret = dollar_expand(&parseerr, "${BAZ}b"); + ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 0); + ret = dollar_expand(&parseerr, "a${BAZ}b"); + ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 0); + /* invalid format */ + ret = dollar_expand(&parseerr, "${"); + ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1); + ret = dollar_expand(&parseerr, "${F"); + ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1); + ret = dollar_expand(&parseerr, "${FO"); + ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1); + /* empty variable name */ + ret = dollar_expand(&parseerr, "${}"); + ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1); + /* restore loglevel to default */ + log_init("test_misc", SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 1); + TEST_DONE(); + + TEST_START("percent_expand"); + ASSERT_STRING_EQ(percent_expand("%%", "%h", "foo", NULL), "%"); + ASSERT_STRING_EQ(percent_expand("%h", "h", "foo", NULL), "foo"); + ASSERT_STRING_EQ(percent_expand("%h ", "h", "foo", NULL), "foo "); + ASSERT_STRING_EQ(percent_expand(" %h", "h", "foo", NULL), " foo"); + ASSERT_STRING_EQ(percent_expand(" %h ", "h", "foo", NULL), " foo "); + ASSERT_STRING_EQ(percent_expand(" %a%b ", "a", "foo", "b", "bar", NULL), + " foobar "); + TEST_DONE(); + + TEST_START("percent_dollar_expand"); + ASSERT_STRING_EQ(percent_dollar_expand("%h${FOO}", "h", "foo", NULL), + "foobar"); + TEST_DONE(); +} diff --git a/regress/unittests/sshbuf/Makefile b/regress/unittests/sshbuf/Makefile index 0e8e9fd10..a8ddfaf7e 100644 --- a/regress/unittests/sshbuf/Makefile +++ b/regress/unittests/sshbuf/Makefile @@ -1,6 +1,6 @@ -# $OpenBSD: Makefile,v 1.7 2018/10/17 23:28:05 djm Exp $ +# $OpenBSD: Makefile,v 1.10 2021/01/09 12:24:31 dtucker Exp $ -.include +# $OpenBSD: Makefile,v 1.8 2020/01/26 00:09:50 djm Exp $ PROG=test_sshbuf SRCS=tests.c @@ -14,7 +14,8 @@ 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 +SRCS+=sshbuf-io.c atomicio.c misc.c xmalloc.c log.c fatal.c ssherr.c cleanup.c +SRCS+=match.c addr.c addrmatch.c run-regress-${PROG}: ${PROG} env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} diff --git a/regress/unittests/sshkey/Makefile b/regress/unittests/sshkey/Makefile index aa731df1c..d4a892375 100644 --- a/regress/unittests/sshkey/Makefile +++ b/regress/unittests/sshkey/Makefile @@ -1,19 +1,21 @@ -# $OpenBSD: Makefile,v 1.6 2018/10/17 23:28:05 djm Exp $ +# $OpenBSD: Makefile,v 1.11 2021/01/09 12:24:31 dtucker 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+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c +SRCS+=ssh-dss.c 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+=addr.c 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+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c +SRCS+=ssh-ed25519-sk.c sk-usbhid.c SRCS+=digest-openssl.c #SRCS+=digest-libc.c +SRCS+=utf8.c REGRESS_TARGETS=run-regress-${PROG} diff --git a/regress/unittests/sshkey/common.c b/regress/unittests/sshkey/common.c index e21638093..effea578c 100644 --- a/regress/unittests/sshkey/common.c +++ b/regress/unittests/sshkey/common.c @@ -1,4 +1,4 @@ -/* $OpenBSD: common.c,v 1.3 2018/09/13 09:03:20 djm Exp $ */ +/* $OpenBSD: common.c,v 1.4 2020/01/26 00:09:50 djm Exp $ */ /* * Helpers for key API tests * @@ -43,13 +43,10 @@ struct sshbuf * load_file(const char *name) { - int fd; - struct sshbuf *ret; + struct sshbuf *ret = NULL; - ASSERT_PTR_NE(ret = sshbuf_new(), NULL); - ASSERT_INT_NE(fd = open(test_data_file(name), O_RDONLY), -1); - ASSERT_INT_EQ(sshkey_load_file(fd, ret), 0); - close(fd); + ASSERT_INT_EQ(sshbuf_load_file(test_data_file(name), &ret), 0); + ASSERT_PTR_NE(ret, NULL); return ret; } diff --git a/regress/unittests/sshkey/mktestdata.sh b/regress/unittests/sshkey/mktestdata.sh index 93da34c64..fcd78e990 100755 --- a/regress/unittests/sshkey/mktestdata.sh +++ b/regress/unittests/sshkey/mktestdata.sh @@ -1,5 +1,5 @@ #!/bin/sh -# $OpenBSD: mktestdata.sh,v 1.7 2018/09/12 01:36:45 djm Exp $ +# $OpenBSD: mktestdata.sh,v 1.11 2020/06/19 03:48:49 djm Exp $ PW=mekmitasdigoat @@ -56,8 +56,8 @@ ecdsa_params() { awk '/^pub:/,/^ASN1 OID:/' | #\ grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.pub openssl ec -noout -text -in $_in | \ - grep "ASN1 OID:" | tr -d '\n' | \ - sed 's/.*: //;s/ *$//' > ${_outbase}.curve + grep "ASN1 OID:" | \ + sed 's/.*: //;s/ *$//' | tr -d '\n' > ${_outbase}.curve for x in priv pub curve ; do echo "" >> ${_outbase}.$x echo ============ ${_outbase}.$x @@ -70,6 +70,15 @@ set -ex cd testdata +if [ -f ../../../misc/sk-dummy/sk-dummy.so ] ; then + SK_DUMMY=../../../misc/sk-dummy/sk-dummy.so +elif [ -f ../../../misc/sk-dummy/obj/sk-dummy.so ] ; then + SK_DUMMY=../../../misc/sk-dummy/obj/sk-dummy.so +else + echo "Can't find sk-dummy.so" 1>&2 + exit 1 +fi + rm -f rsa_1 dsa_1 ecdsa_1 ed25519_1 rm -f rsa_2 dsa_2 ecdsa_2 ed25519_2 rm -f rsa_n dsa_n ecdsa_n # new-format keys @@ -77,35 +86,52 @@ rm -f rsa_1_pw dsa_1_pw ecdsa_1_pw ed25519_1_pw rm -f rsa_n_pw dsa_n_pw ecdsa_n_pw rm -f pw *.pub *.bn.* *.param.* *.fp *.fp.bb -ssh-keygen -t rsa -b 1024 -C "RSA test key #1" -N "" -f rsa_1 -ssh-keygen -t dsa -b 1024 -C "DSA test key #1" -N "" -f dsa_1 -ssh-keygen -t ecdsa -b 256 -C "ECDSA test key #1" -N "" -f ecdsa_1 +ssh-keygen -t rsa -b 1024 -C "RSA test key #1" -N "" -f rsa_1 -m PEM +ssh-keygen -t dsa -b 1024 -C "DSA test key #1" -N "" -f dsa_1 -m PEM +ssh-keygen -t ecdsa -b 256 -C "ECDSA test key #1" -N "" -f ecdsa_1 -m PEM ssh-keygen -t ed25519 -C "ED25519 test key #1" -N "" -f ed25519_1 +ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key #1" \ + -N "" -f ecdsa_sk1 +ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key #1" \ + -N "" -f ed25519_sk1 -ssh-keygen -t rsa -b 2048 -C "RSA test key #2" -N "" -f rsa_2 -ssh-keygen -t dsa -b 1024 -C "DSA test key #2" -N "" -f dsa_2 -ssh-keygen -t ecdsa -b 521 -C "ECDSA test key #2" -N "" -f ecdsa_2 -ssh-keygen -t ed25519 -C "ED25519 test key #1" -N "" -f ed25519_2 + +ssh-keygen -t rsa -b 2048 -C "RSA test key #2" -N "" -f rsa_2 -m PEM +ssh-keygen -t dsa -b 1024 -C "DSA test key #2" -N "" -f dsa_2 -m PEM +ssh-keygen -t ecdsa -b 521 -C "ECDSA test key #2" -N "" -f ecdsa_2 -m PEM +ssh-keygen -t ed25519 -C "ED25519 test key #2" -N "" -f ed25519_2 +ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key #2" \ + -N "" -f ecdsa_sk2 +ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key #2" \ + -N "" -f ed25519_sk2 cp rsa_1 rsa_n cp dsa_1 dsa_n cp ecdsa_1 ecdsa_n +ssh-keygen -pf rsa_n -N "" +ssh-keygen -pf dsa_n -N "" +ssh-keygen -pf ecdsa_n -N "" + cp rsa_1 rsa_1_pw cp dsa_1 dsa_1_pw cp ecdsa_1 ecdsa_1_pw cp ed25519_1 ed25519_1_pw +cp ecdsa_sk1 ecdsa_sk1_pw +cp ed25519_sk1 ed25519_sk1_pw cp rsa_1 rsa_n_pw cp dsa_1 dsa_n_pw cp ecdsa_1 ecdsa_n_pw -ssh-keygen -pf rsa_1_pw -N "$PW" -ssh-keygen -pf dsa_1_pw -N "$PW" -ssh-keygen -pf ecdsa_1_pw -N "$PW" +ssh-keygen -pf rsa_1_pw -m PEM -N "$PW" +ssh-keygen -pf dsa_1_pw -m PEM -N "$PW" +ssh-keygen -pf ecdsa_1_pw -m PEM -N "$PW" ssh-keygen -pf ed25519_1_pw -N "$PW" -ssh-keygen -opf rsa_n_pw -N "$PW" -ssh-keygen -opf dsa_n_pw -N "$PW" -ssh-keygen -opf ecdsa_n_pw -N "$PW" +ssh-keygen -pf ecdsa_sk1_pw -m PEM -N "$PW" +ssh-keygen -pf ed25519_sk1_pw -N "$PW" +ssh-keygen -pf rsa_n_pw -N "$PW" +ssh-keygen -pf dsa_n_pw -N "$PW" +ssh-keygen -pf ecdsa_n_pw -N "$PW" rsa_params rsa_1 rsa_1.param rsa_params rsa_2 rsa_2.param @@ -113,7 +139,7 @@ dsa_params dsa_1 dsa_1.param dsa_params dsa_1 dsa_1.param ecdsa_params ecdsa_1 ecdsa_1.param ecdsa_params ecdsa_2 ecdsa_2.param -# XXX ed25519 params +# XXX ed25519, *sk params ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ @@ -127,6 +153,13 @@ ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ -V 19990101:20110101 -z 4 ed25519_1.pub +ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ + -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ + -V 19990101:20110101 -z 4 ecdsa_sk1.pub +ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ + -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ + -V 19990101:20110101 -z 4 ed25519_sk1.pub + # Make a few RSA variant signature too. cp rsa_1 rsa_1_sha1 @@ -148,30 +181,42 @@ ssh-keygen -s ecdsa_1 -I julius -n host1,host2 -h \ -V 19990101:20110101 -z 7 ecdsa_1.pub ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ -V 19990101:20110101 -z 8 ed25519_1.pub +ssh-keygen -s ecdsa_1 -I julius -n host1,host2 -h \ + -V 19990101:20110101 -z 7 ecdsa_sk1.pub +ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ + -V 19990101:20110101 -z 8 ed25519_sk1.pub ssh-keygen -lf rsa_1 | awk '{print $2}' > rsa_1.fp ssh-keygen -lf dsa_1 | awk '{print $2}' > dsa_1.fp ssh-keygen -lf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp ssh-keygen -lf ed25519_1 | awk '{print $2}' > ed25519_1.fp +ssh-keygen -lf ecdsa_sk1 | awk '{print $2}' > ecdsa_sk1.fp +ssh-keygen -lf ed25519_sk1 | awk '{print $2}' > ed25519_sk1.fp ssh-keygen -lf rsa_2 | awk '{print $2}' > rsa_2.fp ssh-keygen -lf dsa_2 | awk '{print $2}' > dsa_2.fp ssh-keygen -lf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp ssh-keygen -lf ed25519_2 | awk '{print $2}' > ed25519_2.fp +ssh-keygen -lf ecdsa_sk2 | awk '{print $2}' > ecdsa_sk2.fp +ssh-keygen -lf ed25519_sk2 | awk '{print $2}' > ed25519_sk2.fp +ssh-keygen -lf rsa_1-cert.pub | awk '{print $2}' > rsa_1-cert.fp ssh-keygen -lf dsa_1-cert.pub | awk '{print $2}' > dsa_1-cert.fp ssh-keygen -lf ecdsa_1-cert.pub | awk '{print $2}' > ecdsa_1-cert.fp ssh-keygen -lf ed25519_1-cert.pub | awk '{print $2}' > ed25519_1-cert.fp -ssh-keygen -lf rsa_1-cert.pub | awk '{print $2}' > rsa_1-cert.fp +ssh-keygen -lf ecdsa_sk1-cert.pub | awk '{print $2}' > ecdsa_sk1-cert.fp +ssh-keygen -lf ed25519_sk1-cert.pub | awk '{print $2}' > ed25519_sk1-cert.fp ssh-keygen -Bf rsa_1 | awk '{print $2}' > rsa_1.fp.bb ssh-keygen -Bf dsa_1 | awk '{print $2}' > dsa_1.fp.bb ssh-keygen -Bf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp.bb ssh-keygen -Bf ed25519_1 | awk '{print $2}' > ed25519_1.fp.bb +ssh-keygen -Bf ecdsa_sk1 | awk '{print $2}' > ecdsa_sk1.fp.bb +ssh-keygen -Bf ed25519_sk1 | awk '{print $2}' > ed25519_sk1.fp.bb ssh-keygen -Bf rsa_2 | awk '{print $2}' > rsa_2.fp.bb ssh-keygen -Bf dsa_2 | awk '{print $2}' > dsa_2.fp.bb ssh-keygen -Bf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp.bb ssh-keygen -Bf ed25519_2 | awk '{print $2}' > ed25519_2.fp.bb - -# XXX Extend ssh-keygen to do detached signatures (better to test/fuzz against) +ssh-keygen -Bf ecdsa_sk2 | awk '{print $2}' > ecdsa_sk2.fp.bb +ssh-keygen -Bf ed25519_sk2 | awk '{print $2}' > ed25519_sk2.fp.bb echo "$PW" > pw diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c index d46057a2a..8f34d85fd 100644 --- a/regress/unittests/sshkey/test_file.c +++ b/regress/unittests/sshkey/test_file.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_file.c,v 1.8 2018/09/13 09:03:20 djm Exp $ */ +/* $OpenBSD: test_file.c,v 1.9 2020/06/19 03:48:49 djm Exp $ */ /* * Regress test for sshkey.h key management API * @@ -430,6 +430,137 @@ sshkey_file_tests(void) sshkey_free(k1); +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) + TEST_START("parse ECDSA-SK from private"); + buf = load_file("ecdsa_sk1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k1, NULL); + ASSERT_INT_EQ(k1->type, KEY_ECDSA_SK); + TEST_DONE(); + + TEST_START("parse ECDSA-SK from private w/ passphrase"); + buf = load_file("ecdsa_sk1_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load ECDSA-SK from public"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_sk1.pub"), &k2, + NULL), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load ECDSA-SK cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_sk1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(k2->type, KEY_ECDSA_SK_CERT); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + TEST_DONE(); + + TEST_START("ECDSA-SK key hex fingerprint"); + buf = load_text_file("ecdsa_sk1.fp"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + TEST_START("ECDSA-SK cert hex fingerprint"); + buf = load_text_file("ecdsa_sk1-cert.fp"); + cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("ECDSA-SK key bubblebabble fingerprint"); + buf = load_text_file("ecdsa_sk1.fp.bb"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + sshkey_free(k1); +#endif + + TEST_START("parse Ed25519-SK from private"); + buf = load_file("ed25519_sk1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k1, NULL); + ASSERT_INT_EQ(k1->type, KEY_ED25519_SK); + /* XXX check key contents */ + TEST_DONE(); + + TEST_START("parse Ed25519-SK from private w/ passphrase"); + buf = load_file("ed25519_sk1_pw"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, + (const char *)sshbuf_ptr(pw), &k2, NULL), 0); + sshbuf_free(buf); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load Ed25519-SK from public"); + ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_sk1.pub"), + &k2, NULL), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("load Ed25519-SK cert"); + ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_sk1"), &k2), 0); + ASSERT_PTR_NE(k2, NULL); + ASSERT_INT_EQ(k2->type, KEY_ED25519_SK_CERT); + ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + TEST_DONE(); + + TEST_START("Ed25519-SK key hex fingerprint"); + buf = load_text_file("ed25519_sk1.fp"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + TEST_START("Ed25519-SK cert hex fingerprint"); + buf = load_text_file("ed25519_sk1-cert.fp"); + cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + sshkey_free(k2); + TEST_DONE(); + + TEST_START("Ed25519-SK key bubblebabble fingerprint"); + buf = load_text_file("ed25519_sk1.fp.bb"); + cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); + ASSERT_PTR_NE(cp, NULL); + ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); + sshbuf_free(buf); + free(cp); + TEST_DONE(); + + sshkey_free(k1); + sshbuf_free(pw); } diff --git a/regress/unittests/sshkey/test_fuzz.c b/regress/unittests/sshkey/test_fuzz.c index 1323f8997..f111446a9 100644 --- a/regress/unittests/sshkey/test_fuzz.c +++ b/regress/unittests/sshkey/test_fuzz.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_fuzz.c,v 1.9 2018/10/17 23:28:05 djm Exp $ */ +/* $OpenBSD: test_fuzz.c,v 1.12 2020/08/27 03:55:22 djm Exp $ */ /* * Fuzz tests for key parsing * @@ -87,10 +87,11 @@ sig_fuzz(struct sshkey *k, const char *sig_alg) 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_INT_EQ(sshkey_sign(k, &sig, &l, c, sizeof(c), + sig_alg, NULL, NULL, 0), 0); ASSERT_SIZE_T_GT(l, 0); fuzz = fuzz_begin(fuzzers, sig, l); - ASSERT_INT_EQ(sshkey_verify(k, sig, l, c, sizeof(c), NULL, 0), 0); + ASSERT_INT_EQ(sshkey_verify(k, sig, l, c, sizeof(c), NULL, 0, NULL), 0); free(sig); TEST_ONERROR(onerror, fuzz); for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { @@ -98,7 +99,7 @@ sig_fuzz(struct sshkey *k, const char *sig_alg) if (fuzz_matches_original(fuzz)) continue; ASSERT_INT_NE(sshkey_verify(k, fuzz_ptr(fuzz), fuzz_len(fuzz), - c, sizeof(c), NULL, 0), 0); + c, sizeof(c), NULL, 0, NULL), 0); } fuzz_cleanup(fuzz); } diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c index 42395b8db..7dc20cc85 100644 --- a/regress/unittests/sshkey/test_sshkey.c +++ b/regress/unittests/sshkey/test_sshkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_sshkey.c,v 1.18 2019/06/21 04:21:45 djm Exp $ */ +/* $OpenBSD: test_sshkey.c,v 1.21 2020/08/27 03:55:22 djm Exp $ */ /* * Regress test for sshkey.h key management API * @@ -101,7 +101,7 @@ build_cert(struct sshbuf *b, struct sshkey *k, const char *type, ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */ ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */ ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen, - sshbuf_ptr(b), sshbuf_len(b), sig_alg, 0), 0); + sshbuf_ptr(b), sshbuf_len(b), sig_alg, NULL, NULL, 0), 0); ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */ free(sigblob); @@ -120,14 +120,15 @@ signature_test(struct sshkey *k, struct sshkey *bad, const char *sig_alg, size_t len; u_char *sig; - ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg, 0), 0); + ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg, + NULL, NULL, 0), 0); ASSERT_SIZE_T_GT(len, 8); ASSERT_PTR_NE(sig, NULL); - ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0), 0); - ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, NULL, 0), 0); + ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); + ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, NULL, 0, NULL), 0); /* Fuzz test is more comprehensive, this is just a smoke test */ sig[len - 5] ^= 0x10; - ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, NULL, 0), 0); + ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); free(sig); } @@ -437,7 +438,7 @@ sshkey_tests(void) put_opt(k1->cert->extensions, "permit-X11-forwarding", NULL); put_opt(k1->cert->extensions, "permit-agent-forwarding", NULL); ASSERT_INT_EQ(sshkey_from_private(k2, &k1->cert->signature_key), 0); - ASSERT_INT_EQ(sshkey_certify(k1, k2, NULL), 0); + ASSERT_INT_EQ(sshkey_certify(k1, k2, NULL, NULL, NULL), 0); b = sshbuf_new(); ASSERT_PTR_NE(b, NULL); ASSERT_INT_EQ(sshkey_putb(k1, b), 0); diff --git a/regress/unittests/sshkey/testdata/dsa_n b/regress/unittests/sshkey/testdata/dsa_n index d3f24824f..657624e0e 100644 --- a/regress/unittests/sshkey/testdata/dsa_n +++ b/regress/unittests/sshkey/testdata/dsa_n @@ -1,12 +1,21 @@ ------BEGIN DSA PRIVATE KEY----- -MIIBvAIBAAKBgQD6kutNFRsHTwEAv6d39Lhsqy1apdHBZ9c2HfyRr7WmypyGIy2m -Ka43vzXI8CNwmRSYs+A6d0vJC7Pl+f9QzJ/04NWOA+MiwfurwrR3CRe61QRYb8Py -mcHOxueHs95IcjrbIPNn86cjnPP5qvv/guUzCjuww4zBdJOXpligrGt2XwIVAKMD -/50qQy7j8JaMk+1+Xtg1pK01AoGBAO7l9QVVbSSoy5lq6cOtvpf8UlwOa6+zBwbl -o4gmFd1RwX1yWkA8kQ7RrhCSg8Hc6mIGnKRgKRli/3LgbSfZ0obFJehkRtEWtN4P -h8fVUeS74iQbIwFQeKlYHIlNTRoGtAbdi3nHdV+BBkEQc1V3rjqYqhjOoz/yNsgz -LND26HrdAoGBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxb -OXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joo -t+LK84ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQtAhRYIbQ5 -KfXsZuBPuWe5FJz3ldaEgw== ------END DSA PRIVATE KEY----- +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABswAAAAdzc2gtZH +NzAAAAgQD6kutNFRsHTwEAv6d39Lhsqy1apdHBZ9c2HfyRr7WmypyGIy2mKa43vzXI8CNw +mRSYs+A6d0vJC7Pl+f9QzJ/04NWOA+MiwfurwrR3CRe61QRYb8PymcHOxueHs95IcjrbIP +Nn86cjnPP5qvv/guUzCjuww4zBdJOXpligrGt2XwAAABUAowP/nSpDLuPwloyT7X5e2DWk +rTUAAACBAO7l9QVVbSSoy5lq6cOtvpf8UlwOa6+zBwblo4gmFd1RwX1yWkA8kQ7RrhCSg8 +Hc6mIGnKRgKRli/3LgbSfZ0obFJehkRtEWtN4Ph8fVUeS74iQbIwFQeKlYHIlNTRoGtAbd +i3nHdV+BBkEQc1V3rjqYqhjOoz/yNsgzLND26HrdAAAAgQDnV6cn5qGxAWjqmQLr4I9T9L +oYxtj99VH7q79thVjwVNwPaq5MWzl8BNC8L4wr67EFf5a2ISc/7YsrONFXmobpVmROUgBz +FxiH/eS4i0oGlzI5KO46KLfiyvOJbS8psGeEDJ2I52UknJX9VLskDHFLW9+PiNLvWHJ8oa +dpkhbELQAAAdhWTOFbVkzhWwAAAAdzc2gtZHNzAAAAgQD6kutNFRsHTwEAv6d39Lhsqy1a +pdHBZ9c2HfyRr7WmypyGIy2mKa43vzXI8CNwmRSYs+A6d0vJC7Pl+f9QzJ/04NWOA+Miwf +urwrR3CRe61QRYb8PymcHOxueHs95IcjrbIPNn86cjnPP5qvv/guUzCjuww4zBdJOXplig +rGt2XwAAABUAowP/nSpDLuPwloyT7X5e2DWkrTUAAACBAO7l9QVVbSSoy5lq6cOtvpf8Ul +wOa6+zBwblo4gmFd1RwX1yWkA8kQ7RrhCSg8Hc6mIGnKRgKRli/3LgbSfZ0obFJehkRtEW +tN4Ph8fVUeS74iQbIwFQeKlYHIlNTRoGtAbdi3nHdV+BBkEQc1V3rjqYqhjOoz/yNsgzLN +D26HrdAAAAgQDnV6cn5qGxAWjqmQLr4I9T9LoYxtj99VH7q79thVjwVNwPaq5MWzl8BNC8 +L4wr67EFf5a2ISc/7YsrONFXmobpVmROUgBzFxiH/eS4i0oGlzI5KO46KLfiyvOJbS8psG +eEDJ2I52UknJX9VLskDHFLW9+PiNLvWHJ8oadpkhbELQAAABRYIbQ5KfXsZuBPuWe5FJz3 +ldaEgwAAAAAB +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ecdsa_n b/regress/unittests/sshkey/testdata/ecdsa_n index 80382b62d..9694f32e4 100644 --- a/regress/unittests/sshkey/testdata/ecdsa_n +++ b/regress/unittests/sshkey/testdata/ecdsa_n @@ -1,5 +1,8 @@ ------BEGIN EC PRIVATE KEY----- -MHcCAQEEIPPNyUAnjvFr+eT/7t/IyjuQQd/aLFiTY92LB9gIjyrMoAoGCCqGSM49 -AwEHoUQDQgAEDFlblkOrW9ydKVhtM+9AY3c9saBE7SG3lFx38nBavkADDaI9jh3/ -kvG/Jt9vpm22qwoklTCGDfzCkXkIKaWlBw== ------END EC PRIVATE KEY----- +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS +1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQQMWVuWQ6tb3J0pWG0z70Bjdz2xoETt +IbeUXHfycFq+QAMNoj2OHf+S8b8m32+mbbarCiSVMIYN/MKReQgppaUHAAAAoFrmmZBa5p +mQAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAxZW5ZDq1vcnSlY +bTPvQGN3PbGgRO0ht5Rcd/JwWr5AAw2iPY4d/5Lxvybfb6ZttqsKJJUwhg38wpF5CCmlpQ +cAAAAhAPPNyUAnjvFr+eT/7t/IyjuQQd/aLFiTY92LB9gIjyrMAAAAAAECAwQFBgc= +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1 b/regress/unittests/sshkey/testdata/ecdsa_sk1 new file mode 100644 index 000000000..b51fb73d6 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk1 @@ -0,0 +1,13 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 +RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQRnVT5Cji1D +Ge2+q2X0vATh6LYnODV+DJrshJorr5GnipW29RfuaDXs0WB6XBej9dOLazVRDjQrtV19Qg +O6cfkFAAAABHNzaDoAAAGQuPdnP7j3Zz8AAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv +cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEZ1U+Qo4tQxntvqtl9LwE4ei2Jzg1fgya7I +SaK6+Rp4qVtvUX7mg17NFgelwXo/XTi2s1UQ40K7VdfUIDunH5BQAAAARzc2g6AQAAAOMt +LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJRURmVFB4YzA0alN5Zk +Z5NlhoV1pTVlpzcnU5ZFlaSVpTOWhjeVFhcDlVT29Bb0dDQ3FHU000OQpBd0VIb1VRRFFn +QUVaMVUrUW80dFF4bnR2cXRsOUx3RTRlaTJKemcxZmd5YTdJU2FLNitScDRxVnR2VVg3bW +cxCjdORmdlbHdYby9YVGkyczFVUTQwSzdWZGZVSUR1bkg1QlE9PQotLS0tLUVORCBFQyBQ +UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAURUNEU0EtU0sgdGVzdCBrZXkgIzEBAgMEBQ== +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.fp b/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.fp new file mode 100644 index 000000000..d1921451d --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.fp @@ -0,0 +1 @@ +SHA256:Go7HO0CVPYG+BSDSk9ZUJBKGSrtBExp6obTa9iqzIUo diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.pub b/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.pub new file mode 100644 index 000000000..9586c61a7 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.pub @@ -0,0 +1 @@ +sk-ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAK3NrLWVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgE012YoSBE9hEC2FRzblcSx784JNo2A4g611A7I75YMMAAAAIbmlzdHAyNTYAAABBBGdVPkKOLUMZ7b6rZfS8BOHotic4NX4MmuyEmiuvkaeKlbb1F+5oNezRYHpcF6P104trNVEONCu1XX1CA7px+QUAAAAEc3NoOgAAAAAAAAAHAAAAAgAAAAZqdWxpdXMAAAASAAAABWhvc3QxAAAABWhvc3QyAAAAADaLg2AAAAAATR3h4AAAAAAAAAAAAAAAAAAAAGgAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAAhuaXN0cDI1NgAAAEEEAlTtPiWUHubBeCys4Xp0QF91dYARpkyqtCnzg10HRS+ZDgkMrSUvPPG+Ge8iqtnB951MBxDq9FqDFIkhQBYXDAAAAGQAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAEkAAAAhALY+eXRJjVGnMk38Sm5S+H5CloNq757ypsoxt+WYoadtAAAAIA42/mAhUfLij1GY7wl+OFrI+icB/t4tGiEUZmhx6Foo ECDSA-SK test key #1 diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1.fp b/regress/unittests/sshkey/testdata/ecdsa_sk1.fp new file mode 100644 index 000000000..d1921451d --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk1.fp @@ -0,0 +1 @@ +SHA256:Go7HO0CVPYG+BSDSk9ZUJBKGSrtBExp6obTa9iqzIUo diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1.fp.bb b/regress/unittests/sshkey/testdata/ecdsa_sk1.fp.bb new file mode 100644 index 000000000..cb9f4dd0d --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk1.fp.bb @@ -0,0 +1 @@ +xovem-sacac-dageg-vovoc-symyz-bozal-cibiv-cyvat-vylyn-romib-hoxax diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1.pub b/regress/unittests/sshkey/testdata/ecdsa_sk1.pub new file mode 100644 index 000000000..c3b21e02b --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk1.pub @@ -0,0 +1 @@ +sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGdVPkKOLUMZ7b6rZfS8BOHotic4NX4MmuyEmiuvkaeKlbb1F+5oNezRYHpcF6P104trNVEONCu1XX1CA7px+QUAAAAEc3NoOg== ECDSA-SK test key #1 diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1_pw b/regress/unittests/sshkey/testdata/ecdsa_sk1_pw new file mode 100644 index 000000000..4fa23a738 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk1_pw @@ -0,0 +1,14 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABB6vcJVx2 +cPc7yYRROup8VnAAAAEAAAAAEAAAB/AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3Bl +bnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGdVPkKOLUMZ7b6rZfS8BOHotic4NX4MmuyEmi +uvkaeKlbb1F+5oNezRYHpcF6P104trNVEONCu1XX1CA7px+QUAAAAEc3NoOgAAAZBrvCxe +xFz0bvzXwaPhrUHBeNCoZy/wNKDx0kxlxUPuA+lgOvy5l3lT3yxxd0qj5PQB+NTcuz8AAE +1f7aSWQNZSifox3COsBGoHV9C8i+glcxiBKheAZD+EBnRGjG8kbcaLhuYDW/I39qNe8lHW +YSDjmvsT55Hy0IAtVRAXizDoXKNdFPTZisC67WyOSJ3ED7Fy4bfT4ApbvhoFTwjikZBEhy +LOad1sbJa4eT19TsskYfQdnJf8sjAmCMOZY4ZV0FiNW5XZOp8nIal1oyULPfzTAm6oaeFN +0ImCSU3U8h4wUQ8q/3XvBWtTKycZaoou0AwPoP0QN95Ywte7FHezNPb/n8KD7k0S6h9XAX +UcBeCe5NHyov/0ZzA2p737hzm3w+MXGOboTQMu8WFXeGh4m7QH2o8ZJdgBhM5JF17uii+Q +ppGoPWHf33MXwB3wxWmKZ0ua0f9AVLkQ2DfFszUoBJE/kcHRd4kj4Q4FWXeMBN0GoH8gdE +gRWIlxn2/FAOce/BFPzzdP87H0jwz7SdcuVO1L +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk2 b/regress/unittests/sshkey/testdata/ecdsa_sk2 new file mode 100644 index 000000000..19db5a3f5 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk2 @@ -0,0 +1,13 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 +RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQSTl+SR6rTg +lOZmcQkCtJ3Pd+lWinezo/gHk4oZdZcTQsmEYs766BlWGuB2Bz3qQRLa6cXsP+4K9kAjAJ +7zdoFUAAAABHNzaDoAAAGQ1qllJtapZSYAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv +cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEk5fkkeq04JTmZnEJArSdz3fpVop3s6P4B5 +OKGXWXE0LJhGLO+ugZVhrgdgc96kES2unF7D/uCvZAIwCe83aBVAAAAARzc2g6AQAAAOMt +LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJSkxwVkxnSTVvdkRlOW +VMWmZodCs5WWlMaitnam0rTXhHTXg5NndiRWw0Wm9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn +QUVrNWZra2VxMDRKVG1abkVKQXJTZHozZnBWb3AzczZQNEI1T0tHWFdYRTBMSmhHTE8rdW +daClZocmdkZ2M5NmtFUzJ1bkY3RC91Q3ZaQUl3Q2U4M2FCVkE9PQotLS0tLUVORCBFQyBQ +UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAURUNEU0EtU0sgdGVzdCBrZXkgIzIBAgMEBQ== +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk2.fp b/regress/unittests/sshkey/testdata/ecdsa_sk2.fp new file mode 100644 index 000000000..1bc99ea0d --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk2.fp @@ -0,0 +1 @@ +SHA256:pz8VkgtRY3r50F4zSuzRlmq9c6vPTpJXLKKOgkyUcKE diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk2.fp.bb b/regress/unittests/sshkey/testdata/ecdsa_sk2.fp.bb new file mode 100644 index 000000000..bfee7658a --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk2.fp.bb @@ -0,0 +1 @@ +xobel-gavur-gorym-pedop-rarob-bunek-gucer-lofeg-syhaf-fylur-zoxix diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk2.pub b/regress/unittests/sshkey/testdata/ecdsa_sk2.pub new file mode 100644 index 000000000..2629d9509 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ecdsa_sk2.pub @@ -0,0 +1 @@ +sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBJOX5JHqtOCU5mZxCQK0nc936VaKd7Oj+AeTihl1lxNCyYRizvroGVYa4HYHPepBEtrpxew/7gr2QCMAnvN2gVQAAAAEc3NoOg== ECDSA-SK test key #2 diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1 b/regress/unittests/sshkey/testdata/ed25519_sk1 new file mode 100644 index 000000000..4196d9c6a --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk1 @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 +gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACAhaP5OS1PPOt7uumAvXlDtte9EHbqIT1EZEJ2y +2v3XMwAAAARzc2g6AAAAuBocY6UaHGOlAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 +9tAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoBAAAAQJYq +lGHhFoA25/q8X/rdTqDAb7dhqs4ehhd/w8x99CwiIWj+TktTzzre7rpgL15Q7bXvRB26iE +9RGRCdstr91zMAAAAAAAAAFkVEMjU1MTktU0sgdGVzdCBrZXkgIzEBAgM= +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1-cert.fp b/regress/unittests/sshkey/testdata/ed25519_sk1-cert.fp new file mode 100644 index 000000000..a6bb1a99c --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk1-cert.fp @@ -0,0 +1 @@ +SHA256:6WZVJ44bqhAWLVP4Ns0TDkoSQSsZo/h2K+mEvOaNFbw diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1-cert.pub b/regress/unittests/sshkey/testdata/ed25519_sk1-cert.pub new file mode 100644 index 000000000..3c72c268d --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk1-cert.pub @@ -0,0 +1 @@ +sk-ssh-ed25519-cert-v01@openssh.com AAAAI3NrLXNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJr7CuMntQKvHoUshx374fJLFEkyxKsEOBA1H6hk5scoAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoAAAAAAAAACAAAAAIAAAAGanVsaXVzAAAAEgAAAAVob3N0MQAAAAVob3N0MgAAAAA2i4NgAAAAAE0d4eAAAAAAAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIOo/0xneV3iM2qWEo5RUwvUYa2bjff292T5vvuXRomGQAAAAUwAAAAtzc2gtZWQyNTUxOQAAAECgsRGLDh1SI3m66MRp9D2iLP4wabQ0OrDgGidk7LsVn2XZHV5jBZN1RtNfe6PBMeVzfRtGUzOg18sO7H7uU+EC ED25519-SK test key #1 diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1.fp b/regress/unittests/sshkey/testdata/ed25519_sk1.fp new file mode 100644 index 000000000..a6bb1a99c --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk1.fp @@ -0,0 +1 @@ +SHA256:6WZVJ44bqhAWLVP4Ns0TDkoSQSsZo/h2K+mEvOaNFbw diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1.fp.bb b/regress/unittests/sshkey/testdata/ed25519_sk1.fp.bb new file mode 100644 index 000000000..1bfe20a48 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk1.fp.bb @@ -0,0 +1 @@ +xucac-vusip-tydoz-dudad-nerif-raran-tezun-cogyd-pamoh-bahef-ruxix diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1.pub b/regress/unittests/sshkey/testdata/ed25519_sk1.pub new file mode 100644 index 000000000..60fe00c39 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk1.pub @@ -0,0 +1 @@ +sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDo= ED25519-SK test key #1 diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1_pw b/regress/unittests/sshkey/testdata/ed25519_sk1_pw new file mode 100644 index 000000000..1c29ff07f --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk1_pw @@ -0,0 +1,9 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDr5R9Yf/ +ucEh0Ns6c34tcIAAAAEAAAAAEAAABKAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t +AAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoAAADA2T6owx +OSgKz4DvLnS3UJ/renbuew5mbkIWB1/y8xd3y5Usm08iUCAlKxep9dVRQvmyoTrc/7rHOM +DkokNw+WgKambnlYT/9QfqViZ9iCBtbdmhLM6ksUCgQefvquRyXoJxlWstjXUll6Ru+ZbT +H//Ss8C1bYtAiXR68OQ+rhDrvQxA9P8J1sGIlkuV3h8YXddSpyBW2Sn0LTHHBXYZo86cXZ +G4Lnc8aGYm65eqdHgkfRmht3eS8DTdzEBfBNH5Ml +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ed25519_sk2 b/regress/unittests/sshkey/testdata/ed25519_sk2 new file mode 100644 index 000000000..b9b748966 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk2 @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 +gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACAV8fu1Sc31QLK2R/zGPdN3ve5xuFvDc7mEAWxb +aI+YcwAAAARzc2g6AAAAuJCMX5uQjF+bAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 +9tAAAAIBXx+7VJzfVAsrZH/MY903e97nG4W8NzuYQBbFtoj5hzAAAABHNzaDoBAAAAQObE +PajcKI1W30EKOhBb6u+Fgx464kf7EjnqDSg4l7gAFfH7tUnN9UCytkf8xj3Td73ucbhbw3 +O5hAFsW2iPmHMAAAAAAAAAFkVEMjU1MTktU0sgdGVzdCBrZXkgIzIBAgM= +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/ed25519_sk2.fp b/regress/unittests/sshkey/testdata/ed25519_sk2.fp new file mode 100644 index 000000000..1c4369a00 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk2.fp @@ -0,0 +1 @@ +SHA256:b9BVPS5vuU4yu/FgweojLLg6zbfmBBoWLUgibdxxsoo diff --git a/regress/unittests/sshkey/testdata/ed25519_sk2.fp.bb b/regress/unittests/sshkey/testdata/ed25519_sk2.fp.bb new file mode 100644 index 000000000..f5fd9efd8 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk2.fp.bb @@ -0,0 +1 @@ +xemac-tizim-dihep-supar-zupib-cukak-pasis-febeg-dyguv-hutec-dyxox diff --git a/regress/unittests/sshkey/testdata/ed25519_sk2.pub b/regress/unittests/sshkey/testdata/ed25519_sk2.pub new file mode 100644 index 000000000..c7ed9f524 --- /dev/null +++ b/regress/unittests/sshkey/testdata/ed25519_sk2.pub @@ -0,0 +1 @@ +sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIBXx+7VJzfVAsrZH/MY903e97nG4W8NzuYQBbFtoj5hzAAAABHNzaDo= ED25519-SK test key #2 diff --git a/regress/unittests/sshkey/testdata/rsa1_1 b/regress/unittests/sshkey/testdata/rsa1_1 deleted file mode 100644 index 161cc04dc..000000000 Binary files a/regress/unittests/sshkey/testdata/rsa1_1 and /dev/null differ diff --git a/regress/unittests/sshkey/testdata/rsa1_1.fp b/regress/unittests/sshkey/testdata/rsa1_1.fp deleted file mode 100644 index 21b3d1a9a..000000000 --- a/regress/unittests/sshkey/testdata/rsa1_1.fp +++ /dev/null @@ -1 +0,0 @@ -SHA256:/kk7K9S9kwYFiFilnZYFwCsQJweI/SGQVR2nIa8VBhE diff --git a/regress/unittests/sshkey/testdata/rsa1_1.fp.bb b/regress/unittests/sshkey/testdata/rsa1_1.fp.bb deleted file mode 100644 index 62991b3e0..000000000 --- a/regress/unittests/sshkey/testdata/rsa1_1.fp.bb +++ /dev/null @@ -1 +0,0 @@ -xilil-nabyf-gynih-duheb-gokyp-bofet-nekac-bosod-lozin-kuvyh-poxix diff --git a/regress/unittests/sshkey/testdata/rsa1_1.param.n b/regress/unittests/sshkey/testdata/rsa1_1.param.n deleted file mode 100644 index 9a2549bbb..000000000 --- a/regress/unittests/sshkey/testdata/rsa1_1.param.n +++ /dev/null @@ -1 +0,0 @@ -00ce8ca77a556eba887f9a866c084a6402785354a81c10854d343181fa09351223a65f99915f8433d11a9c41677d307c03c3a39865b83e7172d2c1d878333c980438d6e4462106a0065cd75cfea7ca7f21538bf2f43f2af49cacee51b22e3bdcc5e87b59cc691f7c6942a77ef13bfdfb24300777b727348d0ba7900ba06b886729 diff --git a/regress/unittests/sshkey/testdata/rsa1_1.pub b/regress/unittests/sshkey/testdata/rsa1_1.pub deleted file mode 100644 index f665b0d64..000000000 --- a/regress/unittests/sshkey/testdata/rsa1_1.pub +++ /dev/null @@ -1 +0,0 @@ -1024 65537 145043942670517902781741650890610683756045780348507433188994725700923246927874581962206512480287863636935077725837494808988986557337885675565086448774391442851909709751605441036910145362277967349042489937363543710406342212883803780768870873303921572812138116796733586484633244057911618360651775855949808953129 RSA1 test key #1 diff --git a/regress/unittests/sshkey/testdata/rsa1_1_pw b/regress/unittests/sshkey/testdata/rsa1_1_pw deleted file mode 100644 index e73c6794a..000000000 Binary files a/regress/unittests/sshkey/testdata/rsa1_1_pw and /dev/null differ diff --git a/regress/unittests/sshkey/testdata/rsa1_2 b/regress/unittests/sshkey/testdata/rsa1_2 deleted file mode 100644 index 1d672ddea..000000000 Binary files a/regress/unittests/sshkey/testdata/rsa1_2 and /dev/null differ diff --git a/regress/unittests/sshkey/testdata/rsa1_2.fp b/regress/unittests/sshkey/testdata/rsa1_2.fp deleted file mode 100644 index 00516d521..000000000 --- a/regress/unittests/sshkey/testdata/rsa1_2.fp +++ /dev/null @@ -1 +0,0 @@ -SHA256:JaOeRCnLl/TLe7vn1+aQ4ONyKZCUhK5x3k4VHilmbpE diff --git a/regress/unittests/sshkey/testdata/rsa1_2.fp.bb b/regress/unittests/sshkey/testdata/rsa1_2.fp.bb deleted file mode 100644 index b4989a588..000000000 --- a/regress/unittests/sshkey/testdata/rsa1_2.fp.bb +++ /dev/null @@ -1 +0,0 @@ -xipag-zohut-zepuk-pisyv-kamog-pupus-netud-tudis-melup-cynov-gaxox diff --git a/regress/unittests/sshkey/testdata/rsa1_2.param.n b/regress/unittests/sshkey/testdata/rsa1_2.param.n deleted file mode 100644 index 25d438d06..000000000 --- a/regress/unittests/sshkey/testdata/rsa1_2.param.n +++ /dev/null @@ -1 +0,0 @@ -00cab091b57a154740c1bb7020f46a21a19dc40f647db2aab1babd30cabe241f0437391e68376ba35e48c624b8eaf6b59424d4c1a848c9fd1ef5cdc7c1b7f5e5df23b7ad513b79021286d38c52fdfae35656659e8649b2bf8bedf7c99664e45534007bd1c5dc3de1dafdf2d34ad087155951aa0f3d500b36d0d804bbccdef15ab31ca3dd40bdf5196065a97f397ef576caffb606be8232f6e0614aea0e979b9584296673fabb1dbd9f3212495c428842a2ab1f1768dd424fb6fdceeeab9126cacdfc834f0a0d09ba73ad8360d183ba85bb1565555cc6a536eb8d06df1a1e841107c021ae28a2d8b3465f9d8b58ef4045aea1c4ad7f8bf639574d6b142af67b4eb3 diff --git a/regress/unittests/sshkey/testdata/rsa1_2.pub b/regress/unittests/sshkey/testdata/rsa1_2.pub deleted file mode 100644 index acab6dda6..000000000 --- a/regress/unittests/sshkey/testdata/rsa1_2.pub +++ /dev/null @@ -1 +0,0 @@ -2048 65537 25587207108642486834576012232250034427766229965612147538722032399009467293691448851087324679403117563681753304072089087252850866332601294130674473984011813227791089686736237645788471744456489819306046398653719249100878753563464696688916667605969658659855996383142110932332560049231682024775766802333675397528993897914717996946881193454997890776063024953924432026083898531677702536941151535135950834711001926404724453460085864892836473957600610133803037286539329764689125111700732309717375455919436557475211197800228646235077584780367991159670572954337165006813357814232200750568307753718414790655085790471723847208627 RSA1 test key #2 diff --git a/regress/unittests/sshkey/testdata/rsa_n b/regress/unittests/sshkey/testdata/rsa_n index 5de3f8422..b8e585e51 100644 --- a/regress/unittests/sshkey/testdata/rsa_n +++ b/regress/unittests/sshkey/testdata/rsa_n @@ -1,15 +1,16 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQDLV5lUTt7FrADseB/CGhEZzpoojjEW5y8+ePvLppmK3MmMI18u -d6vxzpK3bwZLYkVSyfJYI0HmIuGhdu7yMrW6wb84gbq8C31Xoe9EORcIUuGSvDKd -NSM1SjlhDquRblDFB8kToqXyx1lqrXecXylxIUOL0jE+u0rU1967pDJx+wIDAQAB -AoGAXyj5mpjmbD+YlxGIWz/zrM4hGsWgd4VteKEJxT6MMI4uzCRpkMd0ck8oHiwZ -GAI/SwUzIsgtONQuH3AXVsUgghW4Ynn+8ksEv0IZ918WDMDwqvqkyrVzsOsZzqYj -Pf8DUDKCpwFjnlknJ04yvWBZvVhWtY4OiZ8GV0Ttsu3k+GECQQD1YHfvBb5FdJBv -Uhde2Il+jaFia8mwVVNNaiD2ECxXx6CzGz54ZLEB9NPVfDUZK8lJ4UJDqelWNh3i -PF3RefWDAkEA1CVBzAFL4mNwpleVPzrfy69xP3gWOa26MxM/GE6zx9jC7HgQ3KPa -WKdG/FuHs085aTRDaDLmGcZ8IvMuu7NgKQJAcIOKmxR0Gd8IN7NZugjqixggb0Pj -mLKXXwESGiJyYtHL0zTj4Uqyi6Ya2GJ66o7UXscmnmYz828fJtTtZBdbRwJBALfi -C2QvA32Zv/0PEXibKXy996WSC4G3ShwXZKtHHKHvCxY5BDSbehk59VesZrVPyG2e -NYdOBxD0cIlCzJE56/ECQAndVkxvO8hwyEFGGwF3faHIAe/OxVb+MjaU25//Pe1/ -h/e6tlCk4w9CODpyV685gV394eYwMcGDcIkipTNUDZs= ------END RSA PRIVATE KEY----- +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAlwAAAAdzc2gtcn +NhAAAAAwEAAQAAAIEAy1eZVE7exawA7HgfwhoRGc6aKI4xFucvPnj7y6aZitzJjCNfLner +8c6St28GS2JFUsnyWCNB5iLhoXbu8jK1usG/OIG6vAt9V6HvRDkXCFLhkrwynTUjNUo5YQ +6rkW5QxQfJE6Kl8sdZaq13nF8pcSFDi9IxPrtK1Nfeu6QycfsAAAH4to4I7raOCO4AAAAH +c3NoLXJzYQAAAIEAy1eZVE7exawA7HgfwhoRGc6aKI4xFucvPnj7y6aZitzJjCNfLner8c +6St28GS2JFUsnyWCNB5iLhoXbu8jK1usG/OIG6vAt9V6HvRDkXCFLhkrwynTUjNUo5YQ6r +kW5QxQfJE6Kl8sdZaq13nF8pcSFDi9IxPrtK1Nfeu6QycfsAAAADAQABAAAAgF8o+ZqY5m +w/mJcRiFs/86zOIRrFoHeFbXihCcU+jDCOLswkaZDHdHJPKB4sGRgCP0sFMyLILTjULh9w +F1bFIIIVuGJ5/vJLBL9CGfdfFgzA8Kr6pMq1c7DrGc6mIz3/A1AygqcBY55ZJydOMr1gWb +1YVrWODomfBldE7bLt5PhhAAAAQAndVkxvO8hwyEFGGwF3faHIAe/OxVb+MjaU25//Pe1/ +h/e6tlCk4w9CODpyV685gV394eYwMcGDcIkipTNUDZsAAABBAPVgd+8FvkV0kG9SF17YiX +6NoWJrybBVU01qIPYQLFfHoLMbPnhksQH009V8NRkryUnhQkOp6VY2HeI8XdF59YMAAABB +ANQlQcwBS+JjcKZXlT8638uvcT94FjmtujMTPxhOs8fYwux4ENyj2linRvxbh7NPOWk0Q2 +gy5hnGfCLzLruzYCkAAAAAAQID +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshsig/Makefile b/regress/unittests/sshsig/Makefile new file mode 100644 index 000000000..65564d1b2 --- /dev/null +++ b/regress/unittests/sshsig/Makefile @@ -0,0 +1,25 @@ +# $OpenBSD: Makefile,v 1.2 2021/01/09 12:24:31 dtucker Exp $ + +PROG=test_sshsig +SRCS=tests.c + +# From usr.bin/ssh +SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c +SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c +SRCS+=ssh-dss.c 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+=addr.c addrmatch.c bitmap.c sshsig.c +SRCS+=ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c +SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c +SRCS+=ssh-ed25519-sk.c sk-usbhid.c + +SRCS+=digest-openssl.c +#SRCS+=digest-libc.c +SRCS+=utf8.c + +REGRESS_TARGETS=run-regress-${PROG} + +run-regress-${PROG}: ${PROG} + env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} -d ${.CURDIR}/testdata + +.include diff --git a/regress/unittests/sshsig/mktestdata.sh b/regress/unittests/sshsig/mktestdata.sh new file mode 100755 index 000000000..d2300f9c6 --- /dev/null +++ b/regress/unittests/sshsig/mktestdata.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# $OpenBSD: mktestdata.sh,v 1.1 2020/06/19 04:32:09 djm Exp $ + +NAMESPACE=unittest + +set -ex + +cd testdata + +if [ -f ../../../misc/sk-dummy/sk-dummy.so ] ; then + SK_DUMMY=../../../misc/sk-dummy/sk-dummy.so +elif [ -f ../../../misc/sk-dummy/obj/sk-dummy.so ] ; then + SK_DUMMY=../../../misc/sk-dummy/obj/sk-dummy.so +else + echo "Can't find sk-dummy.so" 1>&2 + exit 1 +fi + +rm -f signed-data namespace +rm -f rsa dsa ecdsa ed25519 ecdsa_sk ed25519_sk +rm -f rsa.sig dsa.sig ecdsa.sig ed25519.sig ecdsa_sk.sig ed25519_sk.sig + +printf "This is a test, this is only a test" > signed-data +printf "$NAMESPACE" > namespace + +ssh-keygen -t rsa -C "RSA test" -N "" -f rsa -m PEM +ssh-keygen -t dsa -C "DSA test" -N "" -f dsa -m PEM +ssh-keygen -t ecdsa -C "ECDSA test" -N "" -f ecdsa -m PEM +ssh-keygen -t ed25519 -C "ED25519 test key" -N "" -f ed25519 +ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key" \ + -N "" -f ecdsa_sk +ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key" \ + -N "" -f ed25519_sk + +ssh-keygen -Y sign -f rsa -n $NAMESPACE - < signed-data > rsa.sig +ssh-keygen -Y sign -f dsa -n $NAMESPACE - < signed-data > dsa.sig +ssh-keygen -Y sign -f ecdsa -n $NAMESPACE - < signed-data > ecdsa.sig +ssh-keygen -Y sign -f ed25519 -n $NAMESPACE - < signed-data > ed25519.sig +ssh-keygen -w "$SK_DUMMY" \ + -Y sign -f ecdsa_sk -n $NAMESPACE - < signed-data > ecdsa_sk.sig +ssh-keygen -w "$SK_DUMMY" \ + -Y sign -f ed25519_sk -n $NAMESPACE - < signed-data > ed25519_sk.sig diff --git a/regress/unittests/sshsig/testdata/dsa b/regress/unittests/sshsig/testdata/dsa new file mode 100644 index 000000000..7c0063efc --- /dev/null +++ b/regress/unittests/sshsig/testdata/dsa @@ -0,0 +1,12 @@ +-----BEGIN DSA PRIVATE KEY----- +MIIBuwIBAAKBgQCXpndQdz2mQVnk+lYOF3nxDT+h6SiJmUvBFhnFWBv8tG4pTOkb +EwGufLEzGpzjTj+3bjVau7LFt37AFrqs4Num272BWNsYNIjOlGPgq7Xjv32FN00x +JYh1DoRs1cGGnvohlsWEamGGhTHD1a9ipctPEBV+NrxtZMrl+pO/ZZg8vQIVAKJB +P3iNYSpSuW74+q4WxLCuK8O3AoGAQldE+BIuxlvoG1IFiWesx0CU+H2KO0SEZc9A +SX/qjOabh0Fb78ofTlEf9gWHFfat8SvSJQIOPMVlb76Lio8AAMT8Eaa/qQKKYmQL +dNq4MLhhjxx5KLGt6J2JyFPExCv+qnHYHD59ngtLwKyqGjpSC8LPLktdXn8W/Aad +Ly1K7+MCgYBsMHBczhSeUh8w7i20CVg4OlNTmfJRVU2tO6OpMxZ/quitRm3hLKSN +u4xRkvHJwi4LhQtv1SXvLI5gs5P3gCG8tsIAiyCqLinHha63iBdJpqhnV/x/j7dB +yJr3xJbnmLdWLkkCtNk1Ir1/CuEz+ufAyLGdKWksEAu1UUlb501BkwIVAILIa3Rg +0h7J9lQpHJphvF3K0M1T +-----END DSA PRIVATE KEY----- diff --git a/regress/unittests/sshsig/testdata/dsa.pub b/regress/unittests/sshsig/testdata/dsa.pub new file mode 100644 index 000000000..e77aa7ef4 --- /dev/null +++ b/regress/unittests/sshsig/testdata/dsa.pub @@ -0,0 +1 @@ +ssh-dss AAAAB3NzaC1kc3MAAACBAJemd1B3PaZBWeT6Vg4XefENP6HpKImZS8EWGcVYG/y0bilM6RsTAa58sTManONOP7duNVq7ssW3fsAWuqzg26bbvYFY2xg0iM6UY+CrteO/fYU3TTEliHUOhGzVwYae+iGWxYRqYYaFMcPVr2Kly08QFX42vG1kyuX6k79lmDy9AAAAFQCiQT94jWEqUrlu+PquFsSwrivDtwAAAIBCV0T4Ei7GW+gbUgWJZ6zHQJT4fYo7RIRlz0BJf+qM5puHQVvvyh9OUR/2BYcV9q3xK9IlAg48xWVvvouKjwAAxPwRpr+pAopiZAt02rgwuGGPHHkosa3onYnIU8TEK/6qcdgcPn2eC0vArKoaOlILws8uS11efxb8Bp0vLUrv4wAAAIBsMHBczhSeUh8w7i20CVg4OlNTmfJRVU2tO6OpMxZ/quitRm3hLKSNu4xRkvHJwi4LhQtv1SXvLI5gs5P3gCG8tsIAiyCqLinHha63iBdJpqhnV/x/j7dByJr3xJbnmLdWLkkCtNk1Ir1/CuEz+ufAyLGdKWksEAu1UUlb501Bkw== DSA test diff --git a/regress/unittests/sshsig/testdata/dsa.sig b/regress/unittests/sshsig/testdata/dsa.sig new file mode 100644 index 000000000..0b14ad6b8 --- /dev/null +++ b/regress/unittests/sshsig/testdata/dsa.sig @@ -0,0 +1,13 @@ +-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAAbEAAAAHc3NoLWRzcwAAAIEAl6Z3UHc9pkFZ5PpWDhd58Q0/oekoiZ +lLwRYZxVgb/LRuKUzpGxMBrnyxMxqc404/t241Wruyxbd+wBa6rODbptu9gVjbGDSIzpRj +4Ku14799hTdNMSWIdQ6EbNXBhp76IZbFhGphhoUxw9WvYqXLTxAVfja8bWTK5fqTv2WYPL +0AAAAVAKJBP3iNYSpSuW74+q4WxLCuK8O3AAAAgEJXRPgSLsZb6BtSBYlnrMdAlPh9ijtE +hGXPQEl/6ozmm4dBW+/KH05RH/YFhxX2rfEr0iUCDjzFZW++i4qPAADE/BGmv6kCimJkC3 +TauDC4YY8ceSixreidichTxMQr/qpx2Bw+fZ4LS8Csqho6UgvCzy5LXV5/FvwGnS8tSu/j +AAAAgGwwcFzOFJ5SHzDuLbQJWDg6U1OZ8lFVTa07o6kzFn+q6K1GbeEspI27jFGS8cnCLg +uFC2/VJe8sjmCzk/eAIby2wgCLIKouKceFrreIF0mmqGdX/H+Pt0HImvfElueYt1YuSQK0 +2TUivX8K4TP658DIsZ0paSwQC7VRSVvnTUGTAAAACHVuaXR0ZXN0AAAAAAAAAAZzaGE1MT +IAAAA3AAAAB3NzaC1kc3MAAAAodi5lr0pqBpO76OY4N1CtfR85BCgZ95qfVjP/e9lToj0q +lwjSJJXUjw== +-----END SSH SIGNATURE----- diff --git a/regress/unittests/sshsig/testdata/ecdsa b/regress/unittests/sshsig/testdata/ecdsa new file mode 100644 index 000000000..55fb440e0 --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIFg0ZCSEB5LNeLsXYL25g3kqEWsqh52DR+yNOjyQJqyZoAoGCCqGSM49 +AwEHoUQDQgAE3sud88FV0N8FPspZSV7LWqj6uPPLRZiSsenNuEYAteWPyDgrZsWb +LzXBuUJucepaCNuW/QWgHBRbrjWj3ERm3A== +-----END EC PRIVATE KEY----- diff --git a/regress/unittests/sshsig/testdata/ecdsa.pub b/regress/unittests/sshsig/testdata/ecdsa.pub new file mode 100644 index 000000000..14ec6cf12 --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa.pub @@ -0,0 +1 @@ +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBN7LnfPBVdDfBT7KWUley1qo+rjzy0WYkrHpzbhGALXlj8g4K2bFmy81wblCbnHqWgjblv0FoBwUW641o9xEZtw= ECDSA test diff --git a/regress/unittests/sshsig/testdata/ecdsa.sig b/regress/unittests/sshsig/testdata/ecdsa.sig new file mode 100644 index 000000000..79781570c --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa.sig @@ -0,0 +1,7 @@ +-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAAGgAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAAhuaXN0cDI1NgAAAE +EE3sud88FV0N8FPspZSV7LWqj6uPPLRZiSsenNuEYAteWPyDgrZsWbLzXBuUJucepaCNuW +/QWgHBRbrjWj3ERm3AAAAAh1bml0dGVzdAAAAAAAAAAGc2hhNTEyAAAAZQAAABNlY2RzYS +1zaGEyLW5pc3RwMjU2AAAASgAAACEAycVNsTlE+XEZYyYiDxWZlliruf/pPMhEEMR/XLdQ +a4MAAAAhALQt+5gES7L3uKGptHB6UZQMuZ2WyI0C6FJs4v6AtMIU +-----END SSH SIGNATURE----- diff --git a/regress/unittests/sshsig/testdata/ecdsa_sk b/regress/unittests/sshsig/testdata/ecdsa_sk new file mode 100644 index 000000000..62ae44cb0 --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa_sk @@ -0,0 +1,13 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2 +RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQSg1WuY0XE+ +VexOsrJsFYuxyVoe6eQ/oXmyz2pEHKZw9moyWehv+Fs7oZWFp3JVmOtybKQ6dvfUZYauQE +/Ov4PAAAAABHNzaDoAAAGI6iV41+oleNcAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv +cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEoNVrmNFxPlXsTrKybBWLsclaHunkP6F5ss +9qRBymcPZqMlnob/hbO6GVhadyVZjrcmykOnb31GWGrkBPzr+DwAAAAARzc2g6AQAAAOMt +LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJQm9oeW54M2tpTFVEeS +t5UjU3WXBXSU5KektnU1p6WnV2VTljYXFla3JGcW9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn +QUVvTlZybU5GeFBsWHNUckt5YkJXTHNjbGFIdW5rUDZGNXNzOXFSQnltY1BacU1sbm9iL2 +hiCk82R1ZoYWR5VlpqcmNteWtPbmIzMUdXR3JrQlB6citEd0E9PQotLS0tLUVORCBFQyBQ +UklWQVRFIEtFWS0tLS0tCgAAAAAAAAARRUNEU0EtU0sgdGVzdCBrZXk= +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshsig/testdata/ecdsa_sk.pub b/regress/unittests/sshsig/testdata/ecdsa_sk.pub new file mode 100644 index 000000000..385ebf15b --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa_sk.pub @@ -0,0 +1 @@ +sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBKDVa5jRcT5V7E6ysmwVi7HJWh7p5D+hebLPakQcpnD2ajJZ6G/4WzuhlYWnclWY63JspDp299Rlhq5AT86/g8AAAAAEc3NoOg== ECDSA-SK test key diff --git a/regress/unittests/sshsig/testdata/ecdsa_sk.sig b/regress/unittests/sshsig/testdata/ecdsa_sk.sig new file mode 100644 index 000000000..86de36063 --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa_sk.sig @@ -0,0 +1,8 @@ +-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAAH8AAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBvcGVuc3NoLmNvbQ +AAAAhuaXN0cDI1NgAAAEEEoNVrmNFxPlXsTrKybBWLsclaHunkP6F5ss9qRBymcPZqMlno +b/hbO6GVhadyVZjrcmykOnb31GWGrkBPzr+DwAAAAARzc2g6AAAACHVuaXR0ZXN0AAAAAA +AAAAZzaGE1MTIAAAB3AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20A +AABIAAAAIHohGwyy8iKT3zwd1TYA9V/Ioo7h/3zCJUtyq/Qigt/HAAAAIGzidTwq7D/kFa +7Xjcp/KkdbIs4MfQpfAW/0OciajlpzARI0Vng= +-----END SSH SIGNATURE----- diff --git a/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.pub b/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.pub new file mode 100644 index 000000000..1597302ce --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.pub @@ -0,0 +1 @@ +sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBBRGwDjs4HhJFcn4tJ5Gr72KcmRmCS1OirETxaXvnsNApgoOLF1a/7rxldfSMHm73eT1nhHe97W8qicPPEAKDJQAAAALbWluZHJvdC5vcmc= diff --git a/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.sig b/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.sig new file mode 100644 index 000000000..4bdd8edc6 --- /dev/null +++ b/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.sig @@ -0,0 +1,13 @@ +-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAAIYAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBvcGVuc3NoLmNvbQ +AAAAhuaXN0cDI1NgAAAEEEFEbAOOzgeEkVyfi0nkavvYpyZGYJLU6KsRPFpe+ew0CmCg4s +XVr/uvGV19Iwebvd5PWeEd73tbyqJw88QAoMlAAAAAttaW5kcm90Lm9yZwAAAAh1bml0dG +VzdAAAAAAAAAAGc2hhNTEyAAABhwAAACt3ZWJhdXRobi1zay1lY2RzYS1zaGEyLW5pc3Rw +MjU2QG9wZW5zc2guY29tAAAASQAAACBj2oMT9tb5wRXe6mdmf4/lgAO8wrgr95ouozwNg4 +itnQAAACEAtU9g5wz3HchUiLfLD6plr9T4TiJ32lVCrATSjpiy0SMBAAADHwAAABdodHRw +czovL3d3dy5taW5kcm90Lm9yZwAAAON7InR5cGUiOiJ3ZWJhdXRobi5nZXQiLCJjaGFsbG +VuZ2UiOiJVMU5JVTBsSEFBQUFDSFZ1YVhSMFpYTjBBQUFBQUFBQUFBWnphR0UxTVRJQUFB +QkFMTHU4WmdjU3h0Nk1zRlV6dWlaZ0c2R3dNZEo5ZDd4ZUU3WW9SSXcwZzlpSEpfd3NGRD +cxbzRXbHllenZGV0VqYnFRMHFDN0Z3R3Bqa2pVUVAtTmQ2dyIsIm9yaWdpbiI6Imh0dHBz +Oi8vd3d3Lm1pbmRyb3Qub3JnIiwiY3Jvc3NPcmlnaW4iOmZhbHNlfQAAAAA= +-----END SSH SIGNATURE----- diff --git a/regress/unittests/sshsig/testdata/ed25519 b/regress/unittests/sshsig/testdata/ed25519 new file mode 100644 index 000000000..b44a63d3e --- /dev/null +++ b/regress/unittests/sshsig/testdata/ed25519 @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACCJYs0iDdw0Fe/FTzY1b78I4H/j+R6mz2AmLtwTjHYwBAAAAJjpGas/6Rmr +PwAAAAtzc2gtZWQyNTUxOQAAACCJYs0iDdw0Fe/FTzY1b78I4H/j+R6mz2AmLtwTjHYwBA +AAAEDpSKRA1QKW6kYiQftGRWh+H0fNekzYLG6c3bzseoCpEolizSIN3DQV78VPNjVvvwjg +f+P5HqbPYCYu3BOMdjAEAAAAEEVEMjU1MTkgdGVzdCBrZXkBAgMEBQ== +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshsig/testdata/ed25519.pub b/regress/unittests/sshsig/testdata/ed25519.pub new file mode 100644 index 000000000..b078e4516 --- /dev/null +++ b/regress/unittests/sshsig/testdata/ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIlizSIN3DQV78VPNjVvvwjgf+P5HqbPYCYu3BOMdjAE ED25519 test key diff --git a/regress/unittests/sshsig/testdata/ed25519.sig b/regress/unittests/sshsig/testdata/ed25519.sig new file mode 100644 index 000000000..8e8ff2a8a --- /dev/null +++ b/regress/unittests/sshsig/testdata/ed25519.sig @@ -0,0 +1,6 @@ +-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgiWLNIg3cNBXvxU82NW+/COB/4/ +keps9gJi7cE4x2MAQAAAAIdW5pdHRlc3QAAAAAAAAABnNoYTUxMgAAAFMAAAALc3NoLWVk +MjU1MTkAAABAihQsbUzuNEFflk5Tw1+H9aLS7tZQk0RG8KW1DtOmDYYnWe3D3UKiG3fcJa +DNg4vBWp1j1gLRiBMOF+gwYNegDg== +-----END SSH SIGNATURE----- diff --git a/regress/unittests/sshsig/testdata/ed25519_sk b/regress/unittests/sshsig/testdata/ed25519_sk new file mode 100644 index 000000000..3a434ecb9 --- /dev/null +++ b/regress/unittests/sshsig/testdata/ed25519_sk @@ -0,0 +1,8 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2 +gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACCbGg2F0GK7nOm4pQmAyCuGEjnhvs5q0TtjPbdN +//+yxwAAAARzc2g6AAAAuBw56jAcOeowAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2 +9tAAAAIJsaDYXQYruc6bilCYDIK4YSOeG+zmrRO2M9t03//7LHAAAABHNzaDoBAAAAQFXc +6dCwWewIk1EBofAouGZApW8+s0XekXenxtb78+x0mxoNhdBiu5zpuKUJgMgrhhI54b7Oat +E7Yz23Tf//sscAAAAAAAAAE0VEMjU1MTktU0sgdGVzdCBrZXkBAgMEBQY= +-----END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshsig/testdata/ed25519_sk.pub b/regress/unittests/sshsig/testdata/ed25519_sk.pub new file mode 100644 index 000000000..71051ec3b --- /dev/null +++ b/regress/unittests/sshsig/testdata/ed25519_sk.pub @@ -0,0 +1 @@ +sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJsaDYXQYruc6bilCYDIK4YSOeG+zmrRO2M9t03//7LHAAAABHNzaDo= ED25519-SK test key diff --git a/regress/unittests/sshsig/testdata/ed25519_sk.sig b/regress/unittests/sshsig/testdata/ed25519_sk.sig new file mode 100644 index 000000000..49b6818da --- /dev/null +++ b/regress/unittests/sshsig/testdata/ed25519_sk.sig @@ -0,0 +1,7 @@ +-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAAEoAAAAac2stc3NoLWVkMjU1MTlAb3BlbnNzaC5jb20AAAAgmxoNhd +Biu5zpuKUJgMgrhhI54b7OatE7Yz23Tf//sscAAAAEc3NoOgAAAAh1bml0dGVzdAAAAAAA +AAAGc2hhNTEyAAAAZwAAABpzay1zc2gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAAEAi+7eTjW +/+LQ2M+sCD+KFtH1n7VFFJon/SZFsxODyV8cWTlFKj617Ys1Ur5TV6uaEXQhck8rBA2oQI +HTPANLIPARI0Vng= +-----END SSH SIGNATURE----- diff --git a/regress/unittests/sshsig/testdata/namespace b/regress/unittests/sshsig/testdata/namespace new file mode 100644 index 000000000..1570cd548 --- /dev/null +++ b/regress/unittests/sshsig/testdata/namespace @@ -0,0 +1 @@ +unittest \ No newline at end of file diff --git a/regress/unittests/sshsig/testdata/rsa b/regress/unittests/sshsig/testdata/rsa new file mode 100644 index 000000000..228fad797 --- /dev/null +++ b/regress/unittests/sshsig/testdata/rsa @@ -0,0 +1,39 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIG4wIBAAKCAYEA386lmjRHtJpyj87BrS+ssMmtvc/1SPN0gXTPs9jZ1hYAq98P +ca3/RYVM4HaSu6COztQJ2ZnZD3Te/XeBnIU2mfuvQEl+DiwisGeNglVyRCi7787f +PFFfcxzZfDa7EB2qY8S3oaSGZK8QqzuGwmGAImjlQXz6J+HCd/eD/58GoCSSirIE +CFWCAt+uNrOC/EmgAzsbfcfaIbbVzA40tlgU3hO2J42kddz8CisDTtDKQABFcOaQ +ZycSfn7HDP+WgXLXXBUI9wVM1Tif1f+9MX08xIsvCvGzo7yLgbbTFLSGr5SkA+tO +rYuoA7V8fge0id/3pnVtG1Ui3I7vejeAwf0HZqtFeBEnOwkIJFmZeMtFeOVf+4ki +4h1rDqAvSscNvMtLp6OXpbAATATAuEWEkIQBl1rngnEe0iC9iU9itKMW6qJ4FtIb +4ACH1EoU1x8vqrFecg2hvqfk5CZBJIbV28JFuGjac3OxBZ17Fqb8ljomUir1GrET +2z66NMgb5TjDD7BVAgMBAAECggGACfjDGCPMLhfTkuS7bGP7ZcUWoKZrX1y5jCsQ +NgsraYaBcSb3ITGHdimCS139G68DreN0rOVV7oJejRyOAdNNo367SDn+C9ObmBCF +FZGJDdBiz0SAXceiYRaf+hDWNNmdheR16hXShxnlvDtivbZqZx4VWN2gp7Y/W+kD +UJhdSzVV8igMVfK5YDdnI7jL1UHSh1JS3z/QUEA9NmJLpvQ1uc9XBlwhP78g27Me +6pwS5tccQPOE65OqF0i+xa19nzbmnC940Y34yZeI/UE+PYaO2+asapvOfu/sboBH +Yb5BuWXVEkSeRWI23SpuZbmfNTtVgiRoRqOvqM4G88LkhYjZ6xpDggxQwJiShiiD +oWCucs0v3pX8H8/LbGs8l50SGI5nzUqAdZ7/QQucU/GuDiQtampntkLEDgf9KIw/ +SDrtCw1E9fnCWj4Z71IYfepY9bVY6QUEcfTdnDcYSY1Z5tVpzeMHVLeo0lbNVZv9 +2qmPnjjP/IvWbjjwu/PHpUWkUs0BAoHBAPx4YwPXWYgWnesMKXkjAHyO5KA4EyBr ++rcEmOZkZDibC8PKYzIK2ztptuthahVovW20R/QJhJkO5teGZMeGPFq+floCeC5P +la9CEYGYcTrzgSe1QM9IGMr1vGI1KIWck7VkJ0bkKoY40uIJSVZxnyG9pEpcwYSp +tnOqA/f5YZUFctWvXUz46OfiLKstXLrcrGIU7YRmLv2rW9twnpJYTzE98g3KpVJ2 +TI1pyvrDTdGeAQUTGCAjpviY6XR5d020vQKBwQDi76wsGLQ3XLI+OAE95Ljo0Mcl ++KdJPVVQPq/VcjKgZQndFloflMRrmgNHme9gmsHOrf8DLZvEDbtT+gbmWslMFZQ9 +om1kR404gfuGmfIYdBdOwWjuBLsZs3pfqDB4Xa3NkxljwOMYTp035n0r2UMFaSy3 +gvpW7fsdPOGAJsqNhSw/JNHcokHeBm7VbV0aD7tSyIghmARb5c98fmrSPbiEo8mP +ITIZlgbfZCq2KuXY4q16R3QvlpuSwitVobLR/3kCgcEAueH5JM7dQHFGe9RMhL/c +j9i1Q7GFg4183lsoKBkqIPMmylSsjB+qIihHYS4r6O9g6PCfOXH4iqiKFY0BjlWr +AjTW2naO/aniz1KZiQ0v8PNv2Eh/Gx4+AtDCjpwM5bLOnfLLaEp9dK1JttqXgGnP +fAwgdg+s+3votWgr29tkmU+VqPagfxeUg4Xm1XFkoL/wu5Yk+iIx3trXms1kMuOK +CvtMyBK3fetTmZqWs+Iv3XGz1oSkcqVNPiN3XyY/TJsRAoG/Q17jvjOXTNg4EkCO +HdHJE1Tnyl4HS7bpnOj/Sl6cqQFV7Ey2dKm1pjwSvS714bgP0UvWaRshIxLwif2w +DrLlD7FYUPPnhd24Dw6HnW4WcSwFv1uryv2cjgS6T6ueuB0Xe/AvmW2p/Y1ZHz9N +6baWLwUKQXCg4S3FXui0CVd6yoi+mgBUTSveYguG29WbziDde7YMs+xtXtravhrJ +m6C3Jql5LQSt2uqvH6KdC3ewxLKGzcZot7f+d5MtSj6216ECgcEA9PGmWeUkhVuW +Xz2c9iBeHwCtmDso7gVwxNnHqdqirB4f1nDCGbrJS7hz5Ss7/wfzekP2W5if2P6U +JPUdfykAQgALNn1twAtj1a+UAp31ZWu8JK/Qzt4hLJPBxzMo7MenJq189JmYmDnm +6D5d9vDLCW15gCZua89GZa8K8V50lYyeHBOHAyzNTfNlnMBkHyP645+nqpuEWzIT +3mCe2OAbl60o8VvvVUlAQyQ/ObLq37HHEoDu0U/YAnP157cxpa84 +-----END RSA PRIVATE KEY----- diff --git a/regress/unittests/sshsig/testdata/rsa.pub b/regress/unittests/sshsig/testdata/rsa.pub new file mode 100644 index 000000000..30142ac0a --- /dev/null +++ b/regress/unittests/sshsig/testdata/rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDfzqWaNEe0mnKPzsGtL6ywya29z/VI83SBdM+z2NnWFgCr3w9xrf9FhUzgdpK7oI7O1AnZmdkPdN79d4GchTaZ+69ASX4OLCKwZ42CVXJEKLvvzt88UV9zHNl8NrsQHapjxLehpIZkrxCrO4bCYYAiaOVBfPon4cJ394P/nwagJJKKsgQIVYIC3642s4L8SaADOxt9x9ohttXMDjS2WBTeE7YnjaR13PwKKwNO0MpAAEVw5pBnJxJ+fscM/5aBctdcFQj3BUzVOJ/V/70xfTzEiy8K8bOjvIuBttMUtIavlKQD606ti6gDtXx+B7SJ3/emdW0bVSLcju96N4DB/Qdmq0V4ESc7CQgkWZl4y0V45V/7iSLiHWsOoC9Kxw28y0uno5elsABMBMC4RYSQhAGXWueCcR7SIL2JT2K0oxbqongW0hvgAIfUShTXHy+qsV5yDaG+p+TkJkEkhtXbwkW4aNpzc7EFnXsWpvyWOiZSKvUasRPbPro0yBvlOMMPsFU= RSA test diff --git a/regress/unittests/sshsig/testdata/rsa.sig b/regress/unittests/sshsig/testdata/rsa.sig new file mode 100644 index 000000000..15a032e01 --- /dev/null +++ b/regress/unittests/sshsig/testdata/rsa.sig @@ -0,0 +1,19 @@ +-----BEGIN SSH SIGNATURE----- +U1NIU0lHAAAAAQAAAZcAAAAHc3NoLXJzYQAAAAMBAAEAAAGBAN/OpZo0R7Saco/Owa0vrL +DJrb3P9UjzdIF0z7PY2dYWAKvfD3Gt/0WFTOB2krugjs7UCdmZ2Q903v13gZyFNpn7r0BJ +fg4sIrBnjYJVckQou+/O3zxRX3Mc2Xw2uxAdqmPEt6GkhmSvEKs7hsJhgCJo5UF8+ifhwn +f3g/+fBqAkkoqyBAhVggLfrjazgvxJoAM7G33H2iG21cwONLZYFN4TtieNpHXc/AorA07Q +ykAARXDmkGcnEn5+xwz/loFy11wVCPcFTNU4n9X/vTF9PMSLLwrxs6O8i4G20xS0hq+UpA +PrTq2LqAO1fH4HtInf96Z1bRtVItyO73o3gMH9B2arRXgRJzsJCCRZmXjLRXjlX/uJIuId +aw6gL0rHDbzLS6ejl6WwAEwEwLhFhJCEAZda54JxHtIgvYlPYrSjFuqieBbSG+AAh9RKFN +cfL6qxXnINob6n5OQmQSSG1dvCRbho2nNzsQWdexam/JY6JlIq9RqxE9s+ujTIG+U4ww+w +VQAAAAh1bml0dGVzdAAAAAAAAAAGc2hhNTEyAAABlAAAAAxyc2Etc2hhMi01MTIAAAGACi +nEpBrQxZi0yOrrT6h98JFfZh0XXioih4fzmvtoV0yOReWClS+otGgXoJyZHcbaKNOjDwSM +rIkUoX6OUJmtHYP0HRELnKw35m33LdBPXpFGS4tRS7NeSpvc04KtjT6jYXY9FjWy5hcn17 +Sxc/3DnJqLgJBur8acY7FeIzpWmKixPd/dGkEjdWoD9gO6szLczGuQgrOdYmSRL4yKadTJ +lVjz5OSeKSYYGQy33US2XQassRRNYf4e9byTA3DKvHa/OcTt7lFerea0kZdDpAboqffz7T +Yaw/hFskAYLIEdTW3aoXBGHSOvu8AkDOtb7qwuxGSQ27pjkDLDNsp1ceCFaCaQ6X83RZuK +ACv9JUBI5KaSf81e0bs0KezJKkhB9czeZ6dk96qISbgayEBnvhYgXvUDKtHn7HzNlCJKfK +5ABhNxfGG2CD+NKqcrndwFgS1sQO3hbA84zPQb26ShBovT8ytHBmW1F8ZK4O9Bz61Q6EZK +vs/u6xP6LUean/so5daa +-----END SSH SIGNATURE----- diff --git a/regress/unittests/sshsig/testdata/signed-data b/regress/unittests/sshsig/testdata/signed-data new file mode 100644 index 000000000..7df4bedd1 --- /dev/null +++ b/regress/unittests/sshsig/testdata/signed-data @@ -0,0 +1 @@ +This is a test, this is only a test \ No newline at end of file diff --git a/regress/unittests/sshsig/tests.c b/regress/unittests/sshsig/tests.c new file mode 100644 index 000000000..bf59d58d1 --- /dev/null +++ b/regress/unittests/sshsig/tests.c @@ -0,0 +1,139 @@ +/* $OpenBSD: tests.c,v 1.2 2020/06/22 06:00:06 djm Exp $ */ +/* + * Regress test for sshbuf.h buffer API + * + * Placed in the public domain + */ + +#include "includes.h" + +#include +#include +#include +#include +#include +#ifdef HAVE_STDINT_H +#include +#endif +#include +#include +#include + +#include +#include + +#include "ssherr.h" +#include "authfile.h" +#include "sshkey.h" +#include "sshbuf.h" +#include "sshsig.h" +#include "log.h" + +#include "../test_helper/test_helper.h" + +static struct sshbuf * +load_file(const char *name) +{ + struct sshbuf *ret = NULL; + + ASSERT_INT_EQ(sshbuf_load_file(test_data_file(name), &ret), 0); + ASSERT_PTR_NE(ret, NULL); + return ret; +} + +static struct sshkey * +load_key(const char *name) +{ + struct sshkey *ret = NULL; + ASSERT_INT_EQ(sshkey_load_public(test_data_file(name), &ret, NULL), 0); + ASSERT_PTR_NE(ret, NULL); + return ret; +} + +static void +check_sig(const char *keyname, const char *signame, const struct sshbuf *msg, + const char *namespace) +{ + struct sshkey *k, *sign_key; + struct sshbuf *sig, *rawsig; + struct sshkey_sig_details *sig_details; + + k = load_key(keyname); + sig = load_file(signame); + sign_key = NULL; + sig_details = NULL; + rawsig = NULL; + ASSERT_INT_EQ(sshsig_dearmor(sig, &rawsig), 0); + ASSERT_INT_EQ(sshsig_verifyb(rawsig, msg, namespace, + &sign_key, &sig_details), 0); + ASSERT_INT_EQ(sshkey_equal(k, sign_key), 1); + sshkey_free(k); + sshkey_free(sign_key); + sshkey_sig_details_free(sig_details); + sshbuf_free(sig); + sshbuf_free(rawsig); +} + +void +tests(void) +{ + struct sshbuf *msg; + char *namespace; + +#if 0 + log_init("test_sshsig", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 1); +#endif + +#ifdef WITH_OPENSSL + OpenSSL_add_all_algorithms(); + ERR_load_CRYPTO_strings(); +#endif + + TEST_START("load data"); + msg = load_file("namespace"); + namespace = sshbuf_dup_string(msg); + ASSERT_PTR_NE(namespace, NULL); + sshbuf_free(msg); + msg = load_file("signed-data"); + TEST_DONE(); + +#ifdef WITH_OPENSSL + TEST_START("check RSA signature"); + check_sig("rsa.pub", "rsa.sig", msg, namespace); + TEST_DONE(); + + TEST_START("check DSA signature"); + check_sig("dsa.pub", "dsa.sig", msg, namespace); + TEST_DONE(); + +#ifdef OPENSSL_HAS_ECC + TEST_START("check ECDSA signature"); + check_sig("ecdsa.pub", "ecdsa.sig", msg, namespace); + TEST_DONE(); +#endif +#endif + + TEST_START("check ED25519 signature"); + check_sig("ed25519.pub", "ed25519.sig", msg, namespace); + TEST_DONE(); + +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) + TEST_START("check ECDSA-SK signature"); + check_sig("ecdsa_sk.pub", "ecdsa_sk.sig", msg, namespace); + TEST_DONE(); +#endif + + TEST_START("check ED25519-SK signature"); + check_sig("ed25519_sk.pub", "ed25519_sk.sig", msg, namespace); + TEST_DONE(); + +#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) + TEST_START("check ECDSA-SK webauthn signature"); + check_sig("ecdsa_sk_webauthn.pub", "ecdsa_sk_webauthn.sig", + msg, namespace); + TEST_DONE(); +#endif + + sshbuf_free(msg); + free(namespace); +} diff --git a/regress/unittests/sshsig/webauthn.html b/regress/unittests/sshsig/webauthn.html new file mode 100644 index 000000000..953041e61 --- /dev/null +++ b/regress/unittests/sshsig/webauthn.html @@ -0,0 +1,692 @@ + + + +webauthn test + + +

webauthn test

+

+This is a demo/test page for generating FIDO keys and signatures in SSH +formats. The page initially displays a form to generate a FIDO key and +convert it to a SSH public key. +

+

+Once a key has been generated, an additional form will be displayed to +allow signing of data using the just-generated key. The data may be signed +as either a raw SSH signature or wrapped in a sshsig message (the latter is +easier to test using command-line tools. +

+

+Lots of debugging is printed along the way. +

+

Enroll

+ +
+ + + + + + +
Username:
+
+ + + + + + + diff --git a/sandbox-darwin.c b/sandbox-darwin.c index a61de7495..59b4d286e 100644 --- a/sandbox-darwin.c +++ b/sandbox-darwin.c @@ -30,7 +30,7 @@ #include #include "log.h" -#include "sandbox.h" +#include "ssh-sandbox.h" #include "monitor.h" #include "xmalloc.h" diff --git a/sandbox-pledge.c b/sandbox-pledge.c index d28fc2727..302f1cfed 100644 --- a/sandbox-pledge.c +++ b/sandbox-pledge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sandbox-pledge.c,v 1.1 2015/10/09 01:37:08 deraadt Exp $ */ +/* $OpenBSD: sandbox-pledge.c,v 1.2 2020/10/18 11:32:01 djm Exp $ */ /* * Copyright (c) 2015 Theo de Raadt * @@ -46,7 +46,7 @@ ssh_sandbox_init(struct monitor *m) { struct ssh_sandbox *box; - debug3("%s: preparing pledge sandbox", __func__); + debug3_f("preparing pledge sandbox"); box = xcalloc(1, sizeof(*box)); box->child_pid = 0; @@ -57,14 +57,14 @@ void ssh_sandbox_child(struct ssh_sandbox *box) { if (pledge("stdio", NULL) == -1) - fatal("%s: pledge()", __func__); + fatal_f("pledge()"); } void ssh_sandbox_parent_finish(struct ssh_sandbox *box) { free(box); - debug3("%s: finished", __func__); + debug3_f("finished"); } void diff --git a/sandbox-rlimit.c b/sandbox-rlimit.c index 0bff3dfba..26c61d264 100644 --- a/sandbox-rlimit.c +++ b/sandbox-rlimit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sandbox-rlimit.c,v 1.4 2016/09/12 01:22:38 deraadt Exp $ */ +/* $OpenBSD: sandbox-rlimit.c,v 1.5 2020/10/18 11:32:01 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -49,7 +49,7 @@ ssh_sandbox_init(struct monitor *monitor) * Strictly, we don't need to maintain any state here but we need * to return non-NULL to satisfy the API. */ - debug3("%s: preparing rlimit sandbox", __func__); + debug3_f("preparing rlimit sandbox"); box = xcalloc(1, sizeof(*box)); box->child_pid = 0; @@ -65,18 +65,18 @@ ssh_sandbox_child(struct ssh_sandbox *box) #ifndef SANDBOX_SKIP_RLIMIT_FSIZE if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1) - fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", - __func__, strerror(errno)); + fatal_f("setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", + strerror(errno)); #endif #ifndef SANDBOX_SKIP_RLIMIT_NOFILE if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1) - fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s", - __func__, strerror(errno)); + fatal_f("setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s", + strerror(errno)); #endif #ifdef HAVE_RLIMIT_NPROC if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1) - fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", - __func__, strerror(errno)); + fatal_f("setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", + strerror(errno)); #endif } @@ -84,7 +84,7 @@ void ssh_sandbox_parent_finish(struct ssh_sandbox *box) { free(box); - debug3("%s: finished", __func__); + debug3_f("finished"); } void diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c index b5cda70bb..d8dc7120b 100644 --- a/sandbox-seccomp-filter.c +++ b/sandbox-seccomp-filter.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -177,6 +178,12 @@ static const struct sock_filter preauth_insns[] = { #ifdef __NR_shmdt SC_DENY(__NR_shmdt, EACCES), #endif +#ifdef __NR_ipc + SC_DENY(__NR_ipc, EACCES), +#endif +#ifdef __NR_statx + SC_DENY(__NR_statx, EACCES), +#endif /* Syscalls to permit */ #ifdef __NR_brk @@ -185,6 +192,9 @@ static const struct sock_filter preauth_insns[] = { #ifdef __NR_clock_gettime SC_ALLOW(__NR_clock_gettime), #endif +#ifdef __NR_clock_gettime64 + SC_ALLOW(__NR_clock_gettime64), +#endif #ifdef __NR_close SC_ALLOW(__NR_close), #endif @@ -197,6 +207,9 @@ static const struct sock_filter preauth_insns[] = { #ifdef __NR_futex SC_ALLOW(__NR_futex), #endif +#ifdef __NR_futex_time64 + SC_ALLOW(__NR_futex_time64), +#endif #ifdef __NR_geteuid SC_ALLOW(__NR_geteuid), #endif @@ -242,6 +255,15 @@ static const struct sock_filter preauth_insns[] = { #ifdef __NR_nanosleep SC_ALLOW(__NR_nanosleep), #endif +#ifdef __NR_clock_nanosleep + SC_ALLOW(__NR_clock_nanosleep), +#endif +#ifdef __NR_clock_nanosleep_time64 + SC_ALLOW(__NR_clock_nanosleep_time64), +#endif +#ifdef __NR_clock_gettime64 + SC_ALLOW(__NR_clock_gettime64), +#endif #ifdef __NR__newselect SC_ALLOW(__NR__newselect), #endif @@ -251,6 +273,9 @@ static const struct sock_filter preauth_insns[] = { #ifdef __NR_pselect6 SC_ALLOW(__NR_pselect6), #endif +#ifdef __NR_pselect6_time64 + SC_ALLOW(__NR_pselect6_time64), +#endif #ifdef __NR_read SC_ALLOW(__NR_read), #endif diff --git a/sandbox-systrace.c b/sandbox-systrace.c index 93e63b8e0..e61d581ae 100644 --- a/sandbox-systrace.c +++ b/sandbox-systrace.c @@ -105,7 +105,7 @@ ssh_sandbox_init(struct monitor *monitor) box = xcalloc(1, sizeof(*box)); box->systrace_fd = -1; box->child_pid = 0; - box->osigchld = signal(SIGCHLD, SIG_IGN); + box->osigchld = ssh_signal(SIGCHLD, SIG_IGN); return box; } @@ -114,7 +114,7 @@ void ssh_sandbox_child(struct ssh_sandbox *box) { debug3("%s: ready", __func__); - signal(SIGCHLD, box->osigchld); + ssh_signal(SIGCHLD, box->osigchld); if (kill(getpid(), SIGSTOP) != 0) fatal("%s: kill(%d, SIGSTOP)", __func__, getpid()); debug3("%s: started", __func__); @@ -133,7 +133,7 @@ ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid, do { pid = waitpid(child_pid, &status, WUNTRACED); } while (pid == -1 && errno == EINTR); - signal(SIGCHLD, box->osigchld); + ssh_signal(SIGCHLD, box->osigchld); if (!WIFSTOPPED(status)) { if (WIFSIGNALED(status)) fatal("%s: child terminated with signal %d", diff --git a/scp.1 b/scp.1 index dee7fcead..5471ea31b 100644 --- a/scp.1 +++ b/scp.1 @@ -8,17 +8,17 @@ .\" .\" Created: Sun May 7 00:14:37 1995 ylo .\" -.\" $OpenBSD: scp.1,v 1.86 2019/06/12 11:31:50 jmc Exp $ +.\" $OpenBSD: scp.1,v 1.95 2021/01/26 15:40:17 naddy Exp $ .\" -.Dd $Mdocdate: June 12 2019 $ +.Dd $Mdocdate: January 26 2021 $ .Dt SCP 1 .Os .Sh NAME .Nm scp -.Nd secure copy (remote file copy program) +.Nd OpenSSH secure file copy .Sh SYNOPSIS .Nm scp -.Op Fl 346BCpqrTv +.Op Fl 346ABCpqrTv .Op Fl c Ar cipher .Op Fl F Ar ssh_config .Op Fl i Ar identity_file @@ -31,11 +31,15 @@ .Sh DESCRIPTION .Nm copies files between hosts on a network. +.Pp It uses .Xr ssh 1 for data transfer, and uses the same authentication and provides the -same security as -.Xr ssh 1 . +same security as a login session. +The scp protocol requires execution of the remote user's shell to perform +.Xr glob 3 +pattern matching. +.Pp .Nm will ask for passwords or passphrases if they are needed for authentication. @@ -74,7 +78,10 @@ The options are as follows: 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. +Note that this option disables the progress meter and selects batch mode +for the second host, since +.Nm +cannot ask for passwords or passphrases for both hosts. .It Fl 4 Forces .Nm @@ -83,6 +90,11 @@ to use IPv4 addresses only. Forces .Nm to use IPv6 addresses only. +.It Fl A +Allows forwarding of +.Xr ssh-agent 1 +to the remote system. +The default is not to forward an authentication agent. .It Fl B Selects batch mode (prevents asking for passwords or passphrases). .It Fl C @@ -160,8 +172,8 @@ For full details of the options listed below, and their possible values, see .It GSSAPIDelegateCredentials .It HashKnownHosts .It Host +.It HostbasedAcceptedAlgorithms .It HostbasedAuthentication -.It HostbasedKeyTypes .It HostKeyAlgorithms .It HostKeyAlias .It Hostname @@ -172,6 +184,7 @@ For full details of the options listed below, and their possible values, see .It KbdInteractiveAuthentication .It KbdInteractiveDevices .It KexAlgorithms +.It KnownHostsCommand .It LogLevel .It MACs .It NoHostAuthenticationForLocalhost @@ -182,7 +195,7 @@ For full details of the options listed below, and their possible values, see .It PreferredAuthentications .It ProxyCommand .It ProxyJump -.It PubkeyAcceptedKeyTypes +.It PubkeyAcceptedAlgorithms .It PubkeyAuthentication .It RekeyLimit .It SendEnv diff --git a/scp.c b/scp.c index a812f29a5..a18f6aa0a 100644 --- a/scp.c +++ b/scp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scp.c,v 1.206 2019/09/09 02:31:19 dtucker Exp $ */ +/* $OpenBSD: scp.c,v 1.213 2020/10/18 11:32:01 djm Exp $ */ /* * scp - secure remote copy. This is basically patched BSD rcp which * uses ssh to do the data transfer (instead of using rcmd). @@ -94,7 +94,9 @@ #include #include #include +#ifdef HAVE_FNMATCH_H #include +#endif #include #include #include @@ -256,9 +258,9 @@ do_local_cmd(arglist *a) } do_cmd_pid = pid; - signal(SIGTERM, killchild); - signal(SIGINT, killchild); - signal(SIGHUP, killchild); + ssh_signal(SIGTERM, killchild); + ssh_signal(SIGINT, killchild); + ssh_signal(SIGHUP, killchild); while (waitpid(pid, &status, 0) == -1) if (errno != EINTR) @@ -314,9 +316,9 @@ do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout) close(reserved[0]); close(reserved[1]); - signal(SIGTSTP, suspchild); - signal(SIGTTIN, suspchild); - signal(SIGTTOU, suspchild); + ssh_signal(SIGTSTP, suspchild); + ssh_signal(SIGTTIN, suspchild); + ssh_signal(SIGTTOU, suspchild); /* Fork a child to execute the command on the remote host using ssh. */ #ifdef FORK_NOT_SUPPORTED @@ -383,9 +385,9 @@ do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout) *fdout = pin[1]; close(pout[1]); *fdin = pout[0]; - signal(SIGTERM, killchild); - signal(SIGINT, killchild); - signal(SIGHUP, killchild); + ssh_signal(SIGTERM, killchild); + ssh_signal(SIGINT, killchild); + ssh_signal(SIGHUP, killchild); return 0; } @@ -453,6 +455,7 @@ do_cmd2(char *host, char *remuser, int port, char *cmd, int fdin, int fdout) addargs(&args, "-l"); addargs(&args, "%s", remuser); } + addargs(&args, "-oBatchMode=yes"); addargs(&args, "--"); addargs(&args, "%s", host); addargs(&args, "%s", cmd); @@ -478,7 +481,11 @@ typedef struct { BUF *allocbuf(BUF *, int, int); void lostconn(int); int okname(char *); -void run_err(const char *,...); +void run_err(const char *,...) + __attribute__((__format__ (printf, 1, 2))) + __attribute__((__nonnull__ (1))); +int note_err(const char *,...) + __attribute__((__format__ (printf, 1, 2))); void verifydir(char *); struct passwd *pwd; @@ -561,7 +568,6 @@ main(int argc, char **argv) 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"); @@ -569,7 +575,7 @@ main(int argc, char **argv) fflag = Tflag = tflag = 0; while ((ch = getopt(argc, argv, - "dfl:prtTvBCc:i:P:q12346S:o:F:J:")) != -1) { + "12346ABCTdfpqrtvF:J:P:S:c:i:l:o:")) != -1) { switch (ch) { /* User-visible flags. */ case '1': @@ -578,6 +584,7 @@ main(int argc, char **argv) case '2': /* Ignored */ break; + case 'A': case '4': case '6': case 'C': @@ -659,6 +666,9 @@ main(int argc, char **argv) argc -= optind; argv += optind; + /* Do this last because we want the user to be able to override it */ + addargs(&args, "-oForwardAgent=no"); + if ((pwd = getpwuid(userid = getuid())) == NULL) fatal("unknown user %u", (u_int) userid); @@ -702,7 +712,7 @@ main(int argc, char **argv) iamrecursive ? " -r" : "", pflag ? " -p" : "", targetshouldbedirectory ? " -d" : ""); - (void) signal(SIGPIPE, lostconn); + (void) ssh_signal(SIGPIPE, lostconn); if (colon(argv[argc - 1])) /* Dest is remote host. */ toremote(argc, argv); @@ -981,7 +991,7 @@ brace_expand(const char *pattern, char ***patternsp, size_t *npatternsp) goto fail; } if (invalid) - fatal("%s: invalid brace pattern \"%s\"", __func__, cp); + fatal_f("invalid brace pattern \"%s\"", cp); if (expanded) { /* * Current entry expanded to new entries on the @@ -1414,9 +1424,6 @@ 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; @@ -1424,7 +1431,7 @@ sink(int argc, char **argv, const char *src) mode_t mode, omode, mask; off_t size, statbytes; unsigned long long ull; - int setimes, targisdir, wrerrno = 0; + int setimes, targisdir, wrerr; char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048]; char **patterns = NULL; size_t n, npatterns = 0; @@ -1458,7 +1465,7 @@ sink(int argc, char **argv, const char *src) * the requested destination file glob. */ if (brace_expand(src, &patterns, &npatterns) != 0) - fatal("%s: could not expand pattern", __func__); + fatal_f("could not expand pattern"); } for (first = 1;; first = 0) { cp = buf; @@ -1612,9 +1619,7 @@ sink(int argc, char **argv, const char *src) sink(1, vect, src); if (setimes) { setimes = 0; - if (utimes(vect[0], tv) == -1) - run_err("%s: set times: %s", - vect[0], strerror(errno)); + (void) utimes(vect[0], tv); } if (mod_flag) (void) chmod(vect[0], mode); @@ -1638,8 +1643,13 @@ bad: run_err("%s: %s", np, strerror(errno)); continue; } cp = bp->buf; - wrerr = NO; + wrerr = 0; + /* + * NB. do not use run_err() unless immediately followed by + * exit() below as it may send a spurious reply that might + * desyncronise us from the peer. Use note_err() instead. + */ statbytes = 0; if (showprogress) start_progress_meter(curfile, size, &statbytes); @@ -1664,11 +1674,12 @@ bad: run_err("%s: %s", np, strerror(errno)); if (count == bp->cnt) { /* Keep reading so we stay sync'd up. */ - if (wrerr == NO) { + if (!wrerr) { if (atomicio(vwrite, ofd, bp->buf, count) != count) { - wrerr = YES; - wrerrno = errno; + note_err("%s: %s", np, + strerror(errno)); + wrerr = 1; } } count = 0; @@ -1676,16 +1687,14 @@ bad: run_err("%s: %s", np, strerror(errno)); } } unset_nonblock(remin); - if (count != 0 && wrerr == NO && + if (count != 0 && !wrerr && 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; + note_err("%s: %s", np, strerror(errno)); + wrerr = 1; } + if (!wrerr && (!exists || S_ISREG(stb.st_mode)) && + ftruncate(ofd, size) != 0) + note_err("%s: truncate: %s", np, strerror(errno)); if (pflag) { if (exists || omode != mode) #ifdef HAVE_FCHMOD @@ -1693,9 +1702,8 @@ bad: run_err("%s: %s", np, strerror(errno)); #else /* HAVE_FCHMOD */ if (chmod(np, omode)) { #endif /* HAVE_FCHMOD */ - run_err("%s: set mode: %s", + note_err("%s: set mode: %s", np, strerror(errno)); - wrerr = DISPLAYED; } } else { if (!exists && omode != mode) @@ -1704,36 +1712,25 @@ bad: run_err("%s: %s", np, strerror(errno)); #else /* HAVE_FCHMOD */ if (chmod(np, omode & ~mask)) { #endif /* HAVE_FCHMOD */ - run_err("%s: set mode: %s", + note_err("%s: set mode: %s", np, strerror(errno)); - wrerr = DISPLAYED; } } - if (close(ofd) == -1) { - wrerr = YES; - wrerrno = errno; - } + if (close(ofd) == -1) + note_err("%s: close: %s", np, strerror(errno)); (void) response(); if (showprogress) stop_progress_meter(); - if (setimes && wrerr == NO) { + if (setimes && !wrerr) { setimes = 0; if (utimes(np, tv) == -1) { - run_err("%s: set times: %s", + note_err("%s: set times: %s", np, strerror(errno)); - wrerr = DISPLAYED; } } - switch (wrerr) { - case YES: - run_err("%s: %s", np, strerror(wrerrno)); - break; - case NO: + /* If no error was noted then signal success for this file */ + if (note_err(NULL) == 0) (void) atomicio(vwrite, remout, "", 1); - break; - case DISPLAYED: - break; - } } done: for (n = 0; n < npatterns; n++) @@ -1790,7 +1787,7 @@ void usage(void) { (void) fprintf(stderr, - "usage: scp [-346BCpqrTv] [-c cipher] [-F ssh_config] [-i identity_file]\n" + "usage: scp [-346ABCpqrTv] [-c cipher] [-F ssh_config] [-i identity_file]\n" " [-J destination] [-l limit] [-o ssh_option] [-P port]\n" " [-S program] source ... target\n"); exit(1); @@ -1821,6 +1818,38 @@ run_err(const char *fmt,...) } } +/* + * Notes a sink error for sending at the end of a file transfer. Returns 0 if + * no error has been noted or -1 otherwise. Use note_err(NULL) to flush + * any active error at the end of the transfer. + */ +int +note_err(const char *fmt, ...) +{ + static char *emsg; + va_list ap; + + /* Replay any previously-noted error */ + if (fmt == NULL) { + if (emsg == NULL) + return 0; + run_err("%s", emsg); + free(emsg); + emsg = NULL; + return -1; + } + + errs++; + /* Prefer first-noted error */ + if (emsg != NULL) + return -1; + + va_start(ap, fmt); + vasnmprintf(&emsg, INT_MAX, NULL, fmt, ap); + va_end(ap); + return -1; +} + void verifydir(char *cp) { diff --git a/servconf.c b/servconf.c index 8f281337b..6f64046c8 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.352 2019/09/06 14:45:34 naddy Exp $ */ +/* $OpenBSD: servconf.c,v 1.377 2021/02/24 01:18:08 dtucker Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -15,7 +15,8 @@ #include #include -#ifdef HAVE_SYS_SYSCTL_H +#include +#ifdef __OpenBSD__ #include #endif @@ -40,6 +41,11 @@ #ifdef HAVE_UTIL_H #include #endif +#ifdef USE_SYSTEM_GLOB +# include +#else +# include "openbsd-compat/glob.h" +#endif #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" @@ -69,6 +75,9 @@ static void add_listen_addr(ServerOptions *, const char *, const char *, int); static void add_one_listen_addr(ServerOptions *, const char *, const char *, int); +static void parse_server_config_depth(ServerOptions *options, + const char *filename, struct sshbuf *conf, struct include_list *includes, + struct connection_info *connectinfo, int flags, int *activep, int depth); /* Use of privilege separation or not */ extern int use_privsep; @@ -113,12 +122,15 @@ initialize_server_options(ServerOptions *options) options->tcp_keep_alive = -1; options->log_facility = SYSLOG_FACILITY_NOT_SET; options->log_level = SYSLOG_LEVEL_NOT_SET; + options->num_log_verbose = 0; + options->log_verbose = NULL; options->hostbased_authentication = -1; options->hostbased_uses_name_from_packet_only = -1; - options->hostbased_key_types = NULL; + options->hostbased_accepted_algos = NULL; options->hostkeyalgorithms = NULL; options->pubkey_authentication = -1; - options->pubkey_key_types = NULL; + options->pubkey_auth_options = -1; + options->pubkey_accepted_algos = NULL; options->kerberos_authentication = -1; options->kerberos_or_local_passwd = -1; options->kerberos_ticket_cleanup = -1; @@ -131,7 +143,7 @@ initialize_server_options(ServerOptions *options) options->challenge_response_authentication = -1; options->permit_empty_passwd = -1; options->permit_user_env = -1; - options->permit_user_env_whitelist = NULL; + options->permit_user_env_allowlist = NULL; options->compression = -1; options->rekey_limit = -1; options->rekey_interval = -1; @@ -153,6 +165,9 @@ initialize_server_options(ServerOptions *options) options->max_startups_begin = -1; options->max_startups_rate = -1; options->max_startups = -1; + options->per_source_max_startups = -1; + options->per_source_masklen_ipv4 = -1; + options->per_source_masklen_ipv6 = -1; options->max_authtries = -1; options->max_sessions = -1; options->banner = NULL; @@ -170,6 +185,7 @@ initialize_server_options(ServerOptions *options) options->authorized_keys_command = NULL; options->authorized_keys_command_user = NULL; options->revoked_keys_file = NULL; + options->sk_provider = NULL; options->trusted_user_ca_keys = NULL; options->authorized_principals_file = NULL; options->authorized_principals_command = NULL; @@ -193,6 +209,7 @@ static void assemble_algorithms(ServerOptions *o) { char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; + char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; int r; all_cipher = cipher_alg_list(',', 0); @@ -200,50 +217,35 @@ assemble_algorithms(ServerOptions *o) all_kex = kex_alg_list(','); all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); + /* remove unsupported algos from default lists */ + def_cipher = match_filter_allowlist(KEX_SERVER_ENCRYPT, all_cipher); + def_mac = match_filter_allowlist(KEX_SERVER_MAC, all_mac); + def_kex = match_filter_allowlist(KEX_SERVER_KEX, all_kex); + def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key); + def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig); #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)); \ + fatal_fr(r, "%s", #what); \ } 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); + ASSEMBLE(ciphers, def_cipher, all_cipher); + ASSEMBLE(macs, def_mac, all_mac); + ASSEMBLE(kex_algorithms, def_kex, all_kex); + ASSEMBLE(hostkeyalgorithms, def_key, all_key); + ASSEMBLE(hostbased_accepted_algos, def_key, all_key); + ASSEMBLE(pubkey_accepted_algos, def_key, all_key); + ASSEMBLE(ca_sign_algorithms, def_sig, all_sig); #undef ASSEMBLE free(all_cipher); free(all_mac); free(all_kex); free(all_key); free(all_sig); -} - -static void -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); + free(def_cipher); + free(def_mac); + free(def_kex); + free(def_key); + free(def_sig); } void @@ -252,7 +254,7 @@ servconf_add_hostkey(const char *file, const int line, { char *apath = derelativise_path(path); - array_append2(file, line, "HostKey", + opt_array_append2(file, line, "HostKey", &options->host_key_files, &options->host_key_file_userprovided, &options->num_host_key_files, apath, userprovided); free(apath); @@ -264,7 +266,7 @@ servconf_add_hostcert(const char *file, const int line, { char *apath = derelativise_path(path); - array_append(file, line, "HostCertificate", + opt_array_append(file, line, "HostCertificate", &options->host_cert_files, &options->num_host_cert_files, apath); free(apath); } @@ -341,6 +343,8 @@ fill_default_server_options(ServerOptions *options) options->hostbased_uses_name_from_packet_only = 0; if (options->pubkey_authentication == -1) options->pubkey_authentication = 1; + if (options->pubkey_auth_options == -1) + options->pubkey_auth_options = 0; if (options->kerberos_authentication == -1) options->kerberos_authentication = 0; if (options->kerberos_or_local_passwd == -1) @@ -365,10 +369,15 @@ fill_default_server_options(ServerOptions *options) options->permit_empty_passwd = 0; if (options->permit_user_env == -1) { options->permit_user_env = 0; - options->permit_user_env_whitelist = NULL; + options->permit_user_env_allowlist = NULL; } if (options->compression == -1) +#ifdef WITH_ZLIB options->compression = COMP_DELAYED; +#else + options->compression = COMP_NONE; +#endif + if (options->rekey_limit == -1) options->rekey_limit = 0; if (options->rekey_interval == -1) @@ -387,6 +396,12 @@ fill_default_server_options(ServerOptions *options) options->max_startups_rate = 30; /* 30% */ if (options->max_startups_begin == -1) options->max_startups_begin = 10; + if (options->per_source_max_startups == -1) + options->per_source_max_startups = INT_MAX; + if (options->per_source_masklen_ipv4 == -1) + options->per_source_masklen_ipv4 = 32; + if (options->per_source_masklen_ipv6 == -1) + options->per_source_masklen_ipv6 = 128; if (options->max_authtries == -1) options->max_authtries = DEFAULT_AUTH_FAIL_MAX; if (options->max_sessions == -1) @@ -398,11 +413,11 @@ fill_default_server_options(ServerOptions *options) if (options->client_alive_count_max == -1) options->client_alive_count_max = 3; if (options->num_authkeys_files == 0) { - array_append("[default]", 0, "AuthorizedKeysFiles", + opt_array_append("[default]", 0, "AuthorizedKeysFiles", &options->authorized_keys_files, &options->num_authkeys_files, _PATH_SSH_USER_PERMITTED_KEYS); - array_append("[default]", 0, "AuthorizedKeysFiles", + opt_array_append("[default]", 0, "AuthorizedKeysFiles", &options->authorized_keys_files, &options->num_authkeys_files, _PATH_SSH_USER_PERMITTED_KEYS2); @@ -425,6 +440,8 @@ fill_default_server_options(ServerOptions *options) options->disable_forwarding = 0; if (options->expose_userauth_info == -1) options->expose_userauth_info = 0; + if (options->sk_provider == NULL) + options->sk_provider = xstrdup("internal"); assemble_algorithms(options); @@ -444,10 +461,12 @@ fill_default_server_options(ServerOptions *options) CLEAR_ON_NONE(options->banner); CLEAR_ON_NONE(options->trusted_user_ca_keys); CLEAR_ON_NONE(options->revoked_keys_file); + CLEAR_ON_NONE(options->sk_provider); 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); + CLEAR_ON_NONE(options->host_key_agent); 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++) @@ -461,15 +480,6 @@ fill_default_server_options(ServerOptions *options) 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. */ @@ -479,7 +489,7 @@ typedef enum { sUsePAM, /* Standard Options */ sPort, sHostKeyFile, sLoginGraceTime, - sPermitRootLogin, sLogFacility, sLogLevel, + sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, sRhostsRSAAuthentication, sRSAAuthentication, sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, sKerberosGetAFSToken, sChallengeResponseAuthentication, @@ -491,17 +501,17 @@ typedef enum { sPermitUserEnvironment, sAllowTcpForwarding, sCompression, sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile, - sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes, + sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedAlgorithms, sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions, sBanner, sUseDNS, sHostbasedAuthentication, - sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes, - sHostKeyAlgorithms, + sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedAlgorithms, + sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, - sHostCertificate, + sHostCertificate, sInclude, sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser, sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum, @@ -509,13 +519,15 @@ typedef enum { sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, sStreamLocalBindMask, sStreamLocalBindUnlink, sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, - sExposeAuthInfo, sRDomain, + sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, 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) +#define SSHCFG_GLOBAL 0x01 /* allowed in main section of config */ +#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ +#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) +#define SSHCFG_NEVERMATCH 0x04 /* Match never matches; internal only */ +#define SSHCFG_MATCH_ONLY 0x08 /* Match only in conditional blocks; internal only */ /* Textual representation of the tokens. */ static struct { @@ -542,15 +554,19 @@ static struct { { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL }, { "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, { "loglevel", sLogLevel, SSHCFG_ALL }, + { "logverbose", sLogVerbose, SSHCFG_ALL }, { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL }, { "rhostsrsaauthentication", sDeprecated, SSHCFG_ALL }, { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL }, { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL }, - { "hostbasedacceptedkeytypes", sHostbasedAcceptedKeyTypes, SSHCFG_ALL }, + { "hostbasedacceptedalgorithms", sHostbasedAcceptedAlgorithms, SSHCFG_ALL }, + { "hostbasedacceptedkeytypes", sHostbasedAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */ { "hostkeyalgorithms", sHostKeyAlgorithms, SSHCFG_GLOBAL }, { "rsaauthentication", sDeprecated, SSHCFG_ALL }, { "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL }, - { "pubkeyacceptedkeytypes", sPubkeyAcceptedKeyTypes, SSHCFG_ALL }, + { "pubkeyacceptedalgorithms", sPubkeyAcceptedAlgorithms, SSHCFG_ALL }, + { "pubkeyacceptedkeytypes", sPubkeyAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */ + { "pubkeyauthoptions", sPubkeyAuthOptions, SSHCFG_ALL }, { "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */ #ifdef KRB5 { "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL }, @@ -591,7 +607,7 @@ static struct { #else { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL }, #endif - { "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL }, + { "ignorerhosts", sIgnoreRhosts, SSHCFG_ALL }, { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, @@ -617,6 +633,8 @@ static struct { { "gatewayports", sGatewayPorts, SSHCFG_ALL }, { "subsystem", sSubsystem, SSHCFG_GLOBAL }, { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, + { "persourcemaxstartups", sPerSourceMaxStartups, SSHCFG_GLOBAL }, + { "persourcenetblocksize", sPerSourceNetBlockSize, SSHCFG_GLOBAL }, { "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, { "maxsessions", sMaxSessions, SSHCFG_ALL }, { "banner", sBanner, SSHCFG_ALL }, @@ -643,6 +661,7 @@ static struct { { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, + { "include", sInclude, SSHCFG_ALL }, { "ipqos", sIPQoS, SSHCFG_ALL }, { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, @@ -658,6 +677,7 @@ static struct { { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL }, { "rdomain", sRDomain, SSHCFG_ALL }, { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, + { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, { NULL, sBadOption, 0 } }; @@ -719,7 +739,7 @@ derelativise_path(const char *path) if (path_absolute(expanded)) return expanded; if (getcwd(cwd, sizeof(cwd)) == NULL) - fatal("%s: getcwd: %s", __func__, strerror(errno)); + fatal_f("getcwd: %s", strerror(errno)); xasprintf(&ret, "%s/%s", cwd, expanded); free(expanded); return ret; @@ -762,7 +782,7 @@ add_one_listen_addr(ServerOptions *options, const char *addr, if (i >= options->num_listen_addrs) { /* No entry for this rdomain; allocate one */ if (i >= INT_MAX) - fatal("%s: too many listen addresses", __func__); + fatal_f("too many listen addresses"); options->listen_addrs = xrecallocarray(options->listen_addrs, options->num_listen_addrs, options->num_listen_addrs + 1, sizeof(*options->listen_addrs)); @@ -899,10 +919,10 @@ process_permitopen_list(struct ssh *ssh, ServerOpCodes opcode, ch = '\0'; host = hpdelim2(&arg, &ch); if (host == NULL || ch == '/') - fatal("%s: missing host in %s", __func__, what); + fatal_f("missing host in %s", what); host = cleanhostname(host); if (arg == NULL || ((port = permitopen_port(arg)) < 0)) - fatal("%s: bad port number in %s", __func__, what); + fatal_f("bad port number in %s", what); /* Send it to channels layer */ channel_add_permission(ssh, FORWARD_ADM, where, host, port); @@ -1082,6 +1102,9 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) "%.100s' at line %d", ci->host, arg, line); } else if (strcasecmp(attrib, "address") == 0) { if (ci == NULL || (ci->test && ci->address == NULL)) { + if (addr_match_list(NULL, arg) != 0) + fatal("Invalid Match address argument " + "'%s' at line %d", arg, line); result = 0; continue; } @@ -1101,6 +1124,10 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) } } else if (strcasecmp(attrib, "localaddress") == 0){ if (ci == NULL || (ci->test && ci->laddress == NULL)) { + if (addr_match_list(NULL, arg) != 0) + fatal("Invalid Match localaddress " + "argument '%s' at line %d", arg, + line); result = 0; continue; } @@ -1178,6 +1205,12 @@ static const struct multistate multistate_flag[] = { { "no", 0 }, { NULL, -1 } }; +static const struct multistate multistate_ignore_rhosts[] = { + { "yes", IGNORE_RHOSTS_YES }, + { "no", IGNORE_RHOSTS_NO }, + { "shosts-only", IGNORE_RHOSTS_SHOSTS }, + { NULL, -1 } +}; static const struct multistate multistate_addressfamily[] = { { "inet", AF_INET }, { "inet6", AF_INET6 }, @@ -1193,8 +1226,10 @@ static const struct multistate multistate_permitrootlogin[] = { { NULL, -1 } }; static const struct multistate multistate_compression[] = { +#ifdef WITH_ZLIB { "yes", COMP_DELAYED }, { "delayed", COMP_DELAYED }, +#endif { "no", COMP_NONE }, { NULL, -1 } }; @@ -1213,13 +1248,14 @@ static const struct multistate multistate_tcpfwd[] = { { NULL, -1 } }; -int -process_server_config_line(ServerOptions *options, char *line, +static int +process_server_config_line_depth(ServerOptions *options, char *line, const char *filename, int linenum, int *activep, - struct connection_info *connectinfo) + struct connection_info *connectinfo, int *inc_flags, int depth, + struct include_list *includes) { char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p; - int cmdline = 0, *intptr, value, value2, n, port; + int cmdline = 0, *intptr, value, value2, n, port, oactive, r, found; SyslogFacility *log_facility_ptr; LogLevel *log_level_ptr; ServerOpCodes opcode; @@ -1228,6 +1264,8 @@ process_server_config_line(ServerOptions *options, char *line, long long val64; const struct multistate *multistate_ptr; const char *errstr; + struct include_item *item; + glob_t gbuf; /* Strip trailing whitespace. Allow \f (form feed) at EOL only */ if ((len = strlen(line)) == 0) @@ -1254,7 +1292,7 @@ process_server_config_line(ServerOptions *options, char *line, cmdline = 1; activep = &cmdline; } - if (*activep && opcode != sMatch) + if (*activep && opcode != sMatch && opcode != sInclude) debug3("%s:%d setting %s %s", filename, linenum, arg, cp); if (*activep == 0 && !(flags & SSHCFG_MATCH)) { if (connectinfo == NULL) { @@ -1422,13 +1460,14 @@ process_server_config_line(ServerOptions *options, char *line, case sIgnoreRhosts: intptr = &options->ignore_rhosts; - parse_flag: - multistate_ptr = multistate_flag; + multistate_ptr = multistate_ignore_rhosts; goto parse_multistate; case sIgnoreUserKnownHosts: intptr = &options->ignore_user_known_hosts; - goto parse_flag; + parse_flag: + multistate_ptr = multistate_flag; + goto parse_multistate; case sHostbasedAuthentication: intptr = &options->hostbased_authentication; @@ -1438,9 +1477,9 @@ process_server_config_line(ServerOptions *options, char *line, intptr = &options->hostbased_uses_name_from_packet_only; goto parse_flag; - case sHostbasedAcceptedKeyTypes: - charptr = &options->hostbased_key_types; - parse_keytypes: + case sHostbasedAcceptedAlgorithms: + charptr = &options->hostbased_accepted_algos; + parse_pubkey_algos: arg = strdelim(&cp); if (!arg || *arg == '\0') fatal("%s line %d: Missing argument.", @@ -1456,19 +1495,39 @@ process_server_config_line(ServerOptions *options, char *line, case sHostKeyAlgorithms: charptr = &options->hostkeyalgorithms; - goto parse_keytypes; + goto parse_pubkey_algos; case sCASignatureAlgorithms: charptr = &options->ca_sign_algorithms; - goto parse_keytypes; + goto parse_pubkey_algos; case sPubkeyAuthentication: intptr = &options->pubkey_authentication; goto parse_flag; - case sPubkeyAcceptedKeyTypes: - charptr = &options->pubkey_key_types; - goto parse_keytypes; + case sPubkeyAcceptedAlgorithms: + charptr = &options->pubkey_accepted_algos; + goto parse_pubkey_algos; + + case sPubkeyAuthOptions: + intptr = &options->pubkey_auth_options; + value = 0; + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (strcasecmp(arg, "none") == 0) + continue; + if (strcasecmp(arg, "touch-required") == 0) + value |= PUBKEYAUTH_TOUCH_REQUIRED; + else if (strcasecmp(arg, "verify-required") == 0) + value |= PUBKEYAUTH_VERIFY_REQUIRED; + else { + fatal("%s line %d: unsupported " + "PubkeyAuthOptions option %s", + filename, linenum, arg); + } + } + if (*activep && *intptr == -1) + *intptr = value; + break; case sKerberosAuthentication: intptr = &options->kerberos_authentication; @@ -1563,7 +1622,7 @@ process_server_config_line(ServerOptions *options, char *line, case sPermitUserEnvironment: intptr = &options->permit_user_env; - charptr = &options->permit_user_env_whitelist; + charptr = &options->permit_user_env_allowlist; arg = strdelim(&cp); if (!arg || *arg == '\0') fatal("%s line %d: missing argument.", @@ -1650,6 +1709,16 @@ process_server_config_line(ServerOptions *options, char *line, *log_level_ptr = (LogLevel) value; break; + case sLogVerbose: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (!*activep) + continue; + opt_array_append(filename, linenum, "oLogVerbose", + &options->log_verbose, &options->num_log_verbose, + arg); + } + break; + case sAllowTcpForwarding: intptr = &options->allow_tcp_forwarding; multistate_ptr = multistate_tcpfwd; @@ -1675,7 +1744,7 @@ process_server_config_line(ServerOptions *options, char *line, "\"%.100s\"", filename, linenum, arg); if (!*activep) continue; - array_append(filename, linenum, "AllowUsers", + opt_array_append(filename, linenum, "AllowUsers", &options->allow_users, &options->num_allow_users, arg); } @@ -1688,7 +1757,7 @@ process_server_config_line(ServerOptions *options, char *line, "\"%.100s\"", filename, linenum, arg); if (!*activep) continue; - array_append(filename, linenum, "DenyUsers", + opt_array_append(filename, linenum, "DenyUsers", &options->deny_users, &options->num_deny_users, arg); } @@ -1698,7 +1767,7 @@ process_server_config_line(ServerOptions *options, char *line, while ((arg = strdelim(&cp)) && *arg != '\0') { if (!*activep) continue; - array_append(filename, linenum, "AllowGroups", + opt_array_append(filename, linenum, "AllowGroups", &options->allow_groups, &options->num_allow_groups, arg); } @@ -1708,7 +1777,7 @@ process_server_config_line(ServerOptions *options, char *line, while ((arg = strdelim(&cp)) && *arg != '\0') { if (!*activep) continue; - array_append(filename, linenum, "DenyGroups", + opt_array_append(filename, linenum, "DenyGroups", &options->deny_groups, &options->num_deny_groups, arg); } @@ -1811,6 +1880,45 @@ process_server_config_line(ServerOptions *options, char *line, options->max_startups = options->max_startups_begin; break; + case sPerSourceNetBlockSize: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing PerSourceNetBlockSize spec.", + filename, linenum); + switch (n = sscanf(arg, "%d:%d", &value, &value2)) { + case 2: + if (value2 < 0 || value2 > 128) + n = -1; + /* FALLTHROUGH */ + case 1: + if (value < 0 || value > 32) + n = -1; + } + if (n != 1 && n != 2) + fatal("%s line %d: Invalid PerSourceNetBlockSize" + " spec.", filename, linenum); + if (*activep) { + options->per_source_masklen_ipv4 = value; + options->per_source_masklen_ipv6 = value2; + } + break; + + case sPerSourceMaxStartups: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing PerSourceMaxStartups spec.", + filename, linenum); + if (strcmp(arg, "none") == 0) { /* no limit */ + value = INT_MAX; + } else { + if ((errstr = atoi_err(arg, &value)) != NULL) + fatal("%s line %d: integer value %s.", + filename, linenum, errstr); + } + if (*activep) + options->per_source_max_startups = value; + break; + case sMaxAuthTries: intptr = &options->max_authtries; goto parse_int; @@ -1833,7 +1941,7 @@ process_server_config_line(ServerOptions *options, char *line, if (*activep && options->num_authkeys_files == 0) { while ((arg = strdelim(&cp)) && *arg != '\0') { arg = tilde_expand_filename(arg, getuid()); - array_append(filename, linenum, + opt_array_append(filename, linenum, "AuthorizedKeysFile", &options->authorized_keys_files, &options->num_authkeys_files, arg); @@ -1871,7 +1979,7 @@ process_server_config_line(ServerOptions *options, char *line, filename, linenum); if (!*activep) continue; - array_append(filename, linenum, "AcceptEnv", + opt_array_append(filename, linenum, "AcceptEnv", &options->accept_env, &options->num_accept_env, arg); } @@ -1885,7 +1993,7 @@ process_server_config_line(ServerOptions *options, char *line, filename, linenum); if (!*activep || uvalue != 0) continue; - array_append(filename, linenum, "SetEnv", + opt_array_append(filename, linenum, "SetEnv", &options->setenv, &options->num_setenv, arg); } break; @@ -1909,15 +2017,110 @@ process_server_config_line(ServerOptions *options, char *line, *intptr = value; break; + case sInclude: + if (cmdline) { + fatal("Include directive not supported as a " + "command-line option"); + } + value = 0; + while ((arg2 = strdelim(&cp)) != NULL && *arg2 != '\0') { + value++; + found = 0; + if (*arg2 != '/' && *arg2 != '~') { + xasprintf(&arg, "%s/%s", SSHDIR, arg2); + } else + arg = xstrdup(arg2); + + /* + * Don't let included files clobber the containing + * file's Match state. + */ + oactive = *activep; + + /* consult cache of include files */ + TAILQ_FOREACH(item, includes, entry) { + if (strcmp(item->selector, arg) != 0) + continue; + if (item->filename != NULL) { + parse_server_config_depth(options, + item->filename, item->contents, + includes, connectinfo, + (*inc_flags & SSHCFG_MATCH_ONLY + ? SSHCFG_MATCH_ONLY : (oactive + ? 0 : SSHCFG_NEVERMATCH)), + activep, depth + 1); + } + found = 1; + *activep = oactive; + } + if (found != 0) { + free(arg); + continue; + } + + /* requested glob was not in cache */ + debug2("%s line %d: new include %s", + filename, linenum, arg); + if ((r = glob(arg, 0, NULL, &gbuf)) != 0) { + if (r != GLOB_NOMATCH) { + fatal("%s line %d: include \"%s\" " + "glob failed", filename, + linenum, arg); + } + /* + * If no entry matched then record a + * placeholder to skip later glob calls. + */ + debug2("%s line %d: no match for %s", + filename, linenum, arg); + item = xcalloc(1, sizeof(*item)); + item->selector = strdup(arg); + TAILQ_INSERT_TAIL(includes, + item, entry); + } + if (gbuf.gl_pathc > INT_MAX) + fatal_f("too many glob results"); + for (n = 0; n < (int)gbuf.gl_pathc; n++) { + debug2("%s line %d: including %s", + filename, linenum, gbuf.gl_pathv[n]); + item = xcalloc(1, sizeof(*item)); + item->selector = strdup(arg); + item->filename = strdup(gbuf.gl_pathv[n]); + if ((item->contents = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + load_server_config(item->filename, + item->contents); + parse_server_config_depth(options, + item->filename, item->contents, + includes, connectinfo, + (*inc_flags & SSHCFG_MATCH_ONLY + ? SSHCFG_MATCH_ONLY : (oactive + ? 0 : SSHCFG_NEVERMATCH)), + activep, depth + 1); + *activep = oactive; + TAILQ_INSERT_TAIL(includes, item, entry); + } + globfree(&gbuf); + free(arg); + } + if (value == 0) { + fatal("%s line %d: Include missing filename argument", + filename, linenum); + } + break; + case sMatch: if (cmdline) fatal("Match directive not supported as a command-line " "option"); - value = match_cfg_line(&cp, linenum, connectinfo); + value = match_cfg_line(&cp, linenum, + (*inc_flags & SSHCFG_NEVERMATCH ? NULL : connectinfo)); if (value < 0) fatal("%s line %d: Bad Match condition", filename, linenum); - *activep = value; + *activep = (*inc_flags & SSHCFG_NEVERMATCH) ? 0 : value; + /* The MATCH_ONLY is applicable only until the first match block */ + *inc_flags &= ~SSHCFG_MATCH_ONLY; break; case sPermitListen: @@ -1969,7 +2172,7 @@ process_server_config_line(ServerOptions *options, char *line, lookup_opcode_name(opcode)); } if (*activep && uvalue == 0) { - array_append(filename, linenum, + opt_array_append(filename, linenum, lookup_opcode_name(opcode), chararrayptr, uintptr, arg2); } @@ -2005,6 +2208,21 @@ process_server_config_line(ServerOptions *options, char *line, charptr = &options->revoked_keys_file; goto parse_filename; + case sSecurityKeyProvider: + charptr = &options->sk_provider; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing file name.", + filename, linenum); + if (*activep && *charptr == NULL) { + *charptr = strcasecmp(arg, "internal") == 0 ? + xstrdup(arg) : derelativise_path(arg); + /* increase optional counter */ + if (intptr != NULL) + *intptr = *intptr + 1; + } + break; + case sIPQoS: arg = strdelim(&cp); if ((value = parse_ipqos(arg)) == -1) @@ -2116,7 +2334,7 @@ process_server_config_line(ServerOptions *options, char *line, value2 = 1; if (!*activep) continue; - array_append(filename, linenum, + opt_array_append(filename, linenum, "AuthenticationMethods", &options->auth_methods, &options->num_auth_methods, arg); @@ -2162,6 +2380,10 @@ process_server_config_line(ServerOptions *options, char *line, goto parse_flag; case sRDomain: +#if !defined(__OpenBSD__) && !defined(HAVE_SYS_SET_PROCESS_RDOMAIN) + fatal("%s line %d: setting RDomain not supported on this " + "platform.", filename, linenum); +#endif charptr = &options->routing_domain; arg = strdelim(&cp); if (!arg || *arg == '\0') @@ -2196,22 +2418,39 @@ process_server_config_line(ServerOptions *options, char *line, return 0; } +int +process_server_config_line(ServerOptions *options, char *line, + const char *filename, int linenum, int *activep, + struct connection_info *connectinfo, struct include_list *includes) +{ + int inc_flags = 0; + + return process_server_config_line_depth(options, line, filename, + linenum, activep, connectinfo, &inc_flags, 0, includes); +} + + /* Reads the server configuration file. */ void load_server_config(const char *filename, struct sshbuf *conf) { + struct stat st; char *line = NULL, *cp; size_t linesize = 0; FILE *f; int r, lineno = 0; - debug2("%s: filename %s", __func__, filename); + debug2_f("filename %s", filename); if ((f = fopen(filename, "r")) == NULL) { perror(filename); exit(1); } sshbuf_reset(conf); + /* grow buffer, so realloc is avoided for large config files */ + if (fstat(fileno(f), &st) == 0 && st.st_size > 0 && + (r = sshbuf_allocate(conf, st.st_size)) != 0) + fatal_fr(r, "allocate"); while (getline(&line, &linesize, f) != -1) { lineno++; /* @@ -2223,23 +2462,24 @@ load_server_config(const char *filename, struct sshbuf *conf) 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)); + fatal_fr(r, "sshbuf_put"); } free(line); if ((r = sshbuf_put_u8(conf, 0)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_put_u8"); fclose(f); - debug2("%s: done config len = %zu", __func__, sshbuf_len(conf)); + debug2_f("done config len = %zu", sshbuf_len(conf)); } void parse_server_match_config(ServerOptions *options, - struct connection_info *connectinfo) + struct include_list *includes, struct connection_info *connectinfo) { ServerOptions mo; initialize_server_options(&mo); - parse_server_config(&mo, "reprocess config", cfg, connectinfo); + parse_server_config(&mo, "reprocess config", cfg, includes, + connectinfo); copy_set_server_options(options, &mo, 0); } @@ -2292,12 +2532,14 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) M_CP_INTOPT(password_authentication); M_CP_INTOPT(gss_authentication); M_CP_INTOPT(pubkey_authentication); + M_CP_INTOPT(pubkey_auth_options); 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(ignore_rhosts); M_CP_INTOPT(allow_tcp_forwarding); M_CP_INTOPT(allow_streamlocal_forwarding); @@ -2382,28 +2624,44 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) #undef M_CP_STROPT #undef M_CP_STRARRAYOPT -void -parse_server_config(ServerOptions *options, const char *filename, - struct sshbuf *conf, struct connection_info *connectinfo) +#define SERVCONF_MAX_DEPTH 16 +static void +parse_server_config_depth(ServerOptions *options, const char *filename, + struct sshbuf *conf, struct include_list *includes, + struct connection_info *connectinfo, int flags, int *activep, int depth) { - int active, linenum, bad_options = 0; + int linenum, bad_options = 0; char *cp, *obuf, *cbuf; - debug2("%s: config %s len %zu", __func__, filename, sshbuf_len(conf)); + if (depth < 0 || depth > SERVCONF_MAX_DEPTH) + fatal("Too many recursive configuration includes"); + + debug2_f("config %s len %zu%s", filename, sshbuf_len(conf), + (flags & SSHCFG_NEVERMATCH ? " [checking syntax only]" : "")); if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL) - fatal("%s: sshbuf_dup_string failed", __func__); - active = connectinfo ? 0 : 1; + fatal_f("sshbuf_dup_string failed"); linenum = 1; while ((cp = strsep(&cbuf, "\n")) != NULL) { - if (process_server_config_line(options, cp, filename, - linenum++, &active, connectinfo) != 0) + if (process_server_config_line_depth(options, cp, + filename, linenum++, activep, connectinfo, &flags, + depth, includes) != 0) bad_options++; } free(obuf); if (bad_options > 0) fatal("%s: terminating, %d bad configuration options", filename, bad_options); +} + +void +parse_server_config(ServerOptions *options, const char *filename, + struct sshbuf *conf, struct include_list *includes, + struct connection_info *connectinfo) +{ + int active = connectinfo ? 0 : 1; + parse_server_config_depth(options, filename, conf, includes, + connectinfo, (connectinfo ? SSHCFG_MATCH_ONLY : 0), &active, 0); process_queued_listen_addrs(options); #ifdef WINDOWS @@ -2492,6 +2750,8 @@ fmt_intarg(ServerOpCodes code, int val) return fmt_multistate_int(val, multistate_tcpfwd); case sAllowStreamLocalForwarding: return fmt_multistate_int(val, multistate_tcpfwd); + case sIgnoreRhosts: + return fmt_multistate_int(val, multistate_ignore_rhosts); case sFingerprintHash: return ssh_digest_alg_name(val); default: @@ -2673,13 +2933,14 @@ dump_config(ServerOptions *o) /* 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(sCiphers, o->ciphers); + dump_cfg_string(sMacs, o->macs); 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(sSecurityKeyProvider, o->sk_provider); dump_cfg_string(sAuthorizedPrincipalsFile, o->authorized_principals_file); dump_cfg_string(sVersionAddendum, *o->version_addendum == '\0' @@ -2689,17 +2950,14 @@ dump_config(ServerOptions *o) 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(sKexAlgorithms, o->kex_algorithms); + dump_cfg_string(sCASignatureAlgorithms, o->ca_sign_algorithms); + dump_cfg_string(sHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos); + dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms); + dump_cfg_string(sPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos); +#if defined(__OpenBSD__) || defined(HAVE_SYS_SET_PROCESS_RDOMAIN) dump_cfg_string(sRDomain, o->routing_domain); +#endif /* string arguments requiring a lookup */ dump_cfg_string(sLogLevel, log_level_name(o->log_level)); @@ -2720,6 +2978,8 @@ dump_config(ServerOptions *o) dump_cfg_strarray(sSetEnv, o->num_setenv, o->setenv); dump_cfg_strarray_oneline(sAuthenticationMethods, o->num_auth_methods, o->auth_methods); + dump_cfg_strarray_oneline(sLogVerbose, + o->num_log_verbose, o->log_verbose); /* other arguments */ for (i = 0; i < o->num_subsystems; i++) @@ -2728,6 +2988,13 @@ dump_config(ServerOptions *o) printf("maxstartups %d:%d:%d\n", o->max_startups_begin, o->max_startups_rate, o->max_startups); + printf("persourcemaxstartups "); + if (o->per_source_max_startups == INT_MAX) + printf("none\n"); + else + printf("%d\n", o->per_source_max_startups); + printf("persourcenetblocksize %d:%d\n", o->per_source_masklen_ipv4, + o->per_source_masklen_ipv6); s = NULL; for (i = 0; tunmode_desc[i].val != -1; i++) { @@ -2761,11 +3028,19 @@ dump_config(ServerOptions *o) } printf("\n"); - if (o->permit_user_env_whitelist == NULL) { + if (o->permit_user_env_allowlist == NULL) { dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); } else { printf("permituserenvironment %s\n", - o->permit_user_env_whitelist); + o->permit_user_env_allowlist); } + printf("pubkeyauthoptions"); + if (o->pubkey_auth_options == 0) + printf(" none"); + if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED) + printf(" touch-required"); + if (o->pubkey_auth_options & PUBKEYAUTH_VERIFY_REQUIRED) + printf(" verify-required"); + printf("\n"); } diff --git a/servconf.h b/servconf.h index 5483da051..4f4fd9ba4 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.140 2019/04/18 18:56:16 dtucker Exp $ */ +/* $OpenBSD: servconf.h,v 1.151 2021/01/26 05:32:21 dtucker Exp $ */ /* * Author: Tatu Ylonen @@ -16,6 +16,8 @@ #ifndef SERVCONF_H #define SERVCONF_H +#include + #define MAX_PORTS 256 /* Max # ports. */ #define MAX_SUBSYSTEMS 256 /* Max # subsystems. */ @@ -36,12 +38,21 @@ #define PERMITOPEN_ANY 0 #define PERMITOPEN_NONE -2 +/* IgnoreRhosts */ +#define IGNORE_RHOSTS_NO 0 +#define IGNORE_RHOSTS_YES 1 +#define IGNORE_RHOSTS_SHOSTS 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" +/* PubkeyAuthOptions flags */ +#define PUBKEYAUTH_TOUCH_REQUIRED (1) +#define PUBKEYAUTH_VERIFY_REQUIRED (1<<1) + struct ssh; struct fwd_perm_list; @@ -107,13 +118,16 @@ typedef struct { struct ForwardOptions fwd_opts; /* forwarding options */ SyslogFacility log_facility; /* Facility for system logging. */ LogLevel log_level; /* Level for system logging. */ + u_int num_log_verbose; /* Verbose log overrides */ + char **log_verbose; 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 *hostbased_accepted_algos; /* Algos 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 */ + char *pubkey_accepted_algos; /* Signature algos allowed for pubkey */ + int pubkey_auth_options; /* -1 or mask of PUBKEYAUTH_* flags */ int kerberos_authentication; /* If true, permit Kerberos * authentication. */ int kerberos_or_local_passwd; /* If true, permit kerberos @@ -135,7 +149,7 @@ typedef struct { 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 */ + char *permit_user_env_allowlist; /* pattern-list of allowed env names */ int compression; /* If true, compression is allowed */ int allow_tcp_forwarding; /* One of FORWARD_* */ int allow_streamlocal_forwarding; /* One of FORWARD_* */ @@ -163,6 +177,9 @@ typedef struct { int max_startups_begin; int max_startups_rate; int max_startups; + int per_source_max_startups; + int per_source_masklen_ipv4; + int per_source_masklen_ipv6; int max_authtries; int max_sessions; char *banner; /* SSH-2 banner message */ @@ -211,6 +228,7 @@ typedef struct { int fingerprint_hash; int expose_userauth_info; u_int64_t timing_secret; + char *sk_provider; } ServerOptions; /* Information about the incoming connection as used by Match */ @@ -225,11 +243,20 @@ struct connection_info { * unspecified */ }; +/* List of included files for re-exec from the parsed configuration */ +struct include_item { + char *selector; + char *filename; + struct sshbuf *contents; + TAILQ_ENTRY(include_item) entry; +}; +TAILQ_HEAD(include_list, include_item); + /* * 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 + * privsep child 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 @@ -244,32 +271,35 @@ struct connection_info { 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(hostbased_accepted_algos); \ + M_CP_STROPT(pubkey_accepted_algos); \ M_CP_STROPT(ca_sign_algorithms); \ M_CP_STROPT(routing_domain); \ - M_CP_STROPT(permit_user_env_whitelist); \ + M_CP_STROPT(permit_user_env_allowlist); \ 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(setenv, num_setenv); \ M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \ M_CP_STRARRAYOPT(permitted_opens, num_permitted_opens); \ M_CP_STRARRAYOPT(permitted_listens, num_permitted_listens); \ + M_CP_STRARRAYOPT(log_verbose, num_log_verbose); \ } while (0) 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 *); + int *, struct connection_info *, struct include_list *includes); 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 *); + struct include_list *includes, struct connection_info *); +void parse_server_match_config(ServerOptions *, + struct include_list *includes, 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); diff --git a/serverloop.c b/serverloop.c index ea468c954..306658cbc 100644 --- a/serverloop.c +++ b/serverloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.c,v 1.216 2019/06/28 13:35:04 deraadt Exp $ */ +/* $OpenBSD: serverloop.c,v 1.225 2021/01/27 10:05:28 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -157,7 +157,7 @@ notify_done(fd_set *readset) if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) while (read(notify_pipe[0], &c, 1) != -1) - debug2("%s: reading", __func__); + debug2_f("reading"); } /*ARGSUSED*/ @@ -184,7 +184,8 @@ client_alive_check(struct ssh *ssh) int r, channel_id; /* timeout, check to see how many we have had */ - if (ssh_packet_inc_alive_timeouts(ssh) > + if (options.client_alive_count_max > 0 && + 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); @@ -200,13 +201,13 @@ client_alive_check(struct ssh *ssh) (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)); + fatal_fr(r, "compose"); } else { channel_request_start(ssh, channel_id, "keepalive@openssh.com", 1); } if ((r = sshpkt_send(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "send"); } /* @@ -252,6 +253,8 @@ wait_until_can_do_something(struct ssh *ssh, max_time_ms = keepalive_ms; client_alive_scheduled = 1; } + if (last_client_time == 0) + last_client_time = monotime(); } #if 0 @@ -329,21 +332,17 @@ process_input(struct ssh *ssh, fd_set *readset, int connection_in) ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); return -1; } else if (len == -1) { - 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. */ - if ((r = ssh_packet_process_incoming(ssh, buf, len)) - != 0) - fatal("%s: ssh_packet_process_incoming: %s", - __func__, ssh_err(r)); + if (errno == EINTR || errno == EAGAIN || + errno != EWOULDBLOCK) + return 0; + verbose("Read error from remote host %s port %d: %s", + ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), + strerror(errno)); + cleanup_exit(255); } + /* Buffer any received data. */ + if ((r = ssh_packet_process_incoming(ssh, buf, len)) != 0) + fatal_fr(r, "ssh_packet_process_incoming"); } return 0; } @@ -358,9 +357,10 @@ process_output(struct ssh *ssh, fd_set *writeset, int connection_out) /* Send any buffered packet data to the client. */ 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)); + if ((r = ssh_packet_write_poll(ssh)) != 0) { + sshpkt_fatal(ssh, r, "%s: ssh_packet_write_poll", + __func__); + } } } @@ -402,15 +402,15 @@ server_loop2(struct ssh *ssh, Authctxt *authctxt) debug("Entering interactive session for SSH2."); - signal(SIGCHLD, sigchld_handler); + ssh_signal(SIGCHLD, sigchld_handler); child_terminated = 0; 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); + ssh_signal(SIGTERM, sigterm_handler); + ssh_signal(SIGINT, sigterm_handler); + ssh_signal(SIGQUIT, sigterm_handler); } notify_setup(); @@ -490,17 +490,17 @@ server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg) (r = sshpkt_get_end(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: parse packet", __func__); if (target_port > 0xFFFF) { - error("%s: invalid target port", __func__); + error_f("invalid target port"); *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; goto out; } if (originator_port > 0xFFFF) { - error("%s: invalid originator port", __func__); + error_f("invalid originator port"); *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; goto out; } - debug("%s: originator %s port %u, target %s port %u", __func__, + debug_f("originator %s port %u, target %s port %u", originator, originator_port, target, target_port); /* XXX fine grained permissions */ @@ -533,7 +533,7 @@ server_request_direct_streamlocal(struct ssh *ssh) int r; if (pw == NULL || !the_authctxt->valid) - fatal("%s: no/invalid user", __func__); + fatal_f("no/invalid user"); if ((r = sshpkt_get_cstring(ssh, &target, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 || @@ -541,11 +541,11 @@ server_request_direct_streamlocal(struct ssh *ssh) (r = sshpkt_get_end(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: parse packet", __func__); if (originator_port > 0xFFFF) { - error("%s: invalid originator port", __func__); + error_f("invalid originator port"); goto out; } - debug("%s: originator %s port %d, target %s", __func__, + debug_f("originator %s port %d, target %s", originator, originator_port, target); /* XXX fine grained permissions */ @@ -593,7 +593,7 @@ server_request_tun(struct ssh *ssh) 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__); + debug_f("invalid tun"); goto done; } if (auth_opts->force_tun_device != -1) { @@ -682,12 +682,10 @@ server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) (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__, + debug_f("ctype %s rchan %u win %u max %u", ctype, rchan, rwindow, rmaxpack); - if (rchan > INT_MAX) { - error("%s: invalid remote channel ID", __func__); - } else if (strcmp(ctype, "session") == 0) { + 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); @@ -697,8 +695,8 @@ server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) c = server_request_tun(ssh); } if (c != NULL) { - debug("%s: confirm %s", __func__, ctype); - c->remote_id = (int)rchan; + debug_f("confirm %s", ctype); + c->remote_id = rchan; c->have_remote_id = 1; c->remote_window = rwindow; c->remote_maxpacket = rmaxpack; @@ -714,7 +712,7 @@ server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) } } } else { - debug("%s: failure %s", __func__, ctype); + debug_f("failure %s", ctype); 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 || @@ -741,7 +739,7 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) size_t blen, slen; if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); kexsigtype = sshkey_type_plain( sshkey_type_from_name(ssh->kex->hostkey_alg)); @@ -750,8 +748,7 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) 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)); + error_fr(r, "parse key"); goto out; } /* @@ -759,8 +756,7 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) * 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)); + error_f("unknown host %s key", sshkey_type(key)); goto out; } /* @@ -769,7 +765,7 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) */ 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); + error_f("can't retrieve hostkey %d", ndx); goto out; } sshbuf_reset(sigbuf); @@ -783,15 +779,14 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) 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 = sshbuf_put_stringb(sigbuf, + ssh->kex->session_id)) != 0 || (r = sshkey_puts(key, sigbuf)) != 0 || (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 || (r = sshbuf_put_string(resp, sig, slen)) != 0) { - error("%s: couldn't prepare signature: %s", - __func__, ssh_err(r)); + error_fr(r, "assemble signature"); goto out; } } @@ -820,19 +815,19 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) memset(&fwd, 0, sizeof(fwd)); if (pw == NULL || !the_authctxt->valid) - fatal("%s: no/invalid user", __func__); + fatal_f("no/invalid user"); 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); + debug_f("rtype %s want_reply %d", rtype, want_reply); /* -R style forwarding */ if (strcmp(rtype, "tcpip-forward") == 0) { 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__, + debug_f("tcpip-forward listen %s port %u", fwd.listen_host, port); if (port <= INT_MAX) fwd.listen_port = (int)port; @@ -852,16 +847,16 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) &allocated_listen_port, &options.fwd_opts); } if ((resp = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); if (allocated_listen_port != 0 && (r = sshbuf_put_u32(resp, allocated_listen_port)) != 0) - fatal("%s: sshbuf_put_u32: %s", __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_put_u32"); } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { 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__); - debug("%s: cancel-tcpip-forward addr %s port %d", __func__, + debug_f("cancel-tcpip-forward addr %s port %d", fwd.listen_host, port); if (port <= INT_MAX) { fwd.listen_port = (int)port; @@ -870,7 +865,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) } else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) { 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__, + debug_f("streamlocal-forward listen path %s", fwd.listen_path); /* check permissions */ @@ -889,7 +884,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) } else if (strcmp(rtype, "cancel-streamlocal-forward@openssh.com") == 0) { 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__, + debug_f("cancel-streamlocal-forward path %s", fwd.listen_path); success = channel_cancel_rport_listener(ssh, &fwd); @@ -945,8 +940,7 @@ server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) success = session_input_channel_req(ssh, c, rtype); if (want_reply && !(c->flags & CHAN_CLOSE_SENT)) { if (!c->have_remote_id) - fatal("%s: channel %d: no remote_id", - __func__, c->self); + fatal_f("channel %d: no remote_id", c->self); if ((r = sshpkt_start(ssh, success ? SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || diff --git a/session.c b/session.c index 7289c46ef..6a79c1382 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.316 2019/06/28 13:35:04 deraadt Exp $ */ +/* $OpenBSD: session.c,v 1.327 2020/12/14 03:13:12 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -56,10 +56,10 @@ #endif #include #include -#include #include #include #include +#include #include #include @@ -256,7 +256,7 @@ display_loginmsg(void) if (sshbuf_len(loginmsg) == 0) return; if ((r = sshbuf_put_u8(loginmsg, 0)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_put_u8"); printf("%s", (char *)sshbuf_ptr(loginmsg)); sshbuf_reset(loginmsg); } @@ -272,16 +272,16 @@ prepare_auth_info_file(struct passwd *pw, struct sshbuf *info) 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)); + error_f("mkstemp: %s", 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)); + error_f("write: %s", strerror(errno)); goto out; } if (close(fd) != 0) { - error("%s: close: %s", __func__, strerror(errno)); + error_f("close: %s", strerror(errno)); goto out; } success = 1; @@ -308,11 +308,10 @@ set_fwdpermit_from_authopts(struct ssh *ssh, const struct sshauthopt *opts) 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__); + fatal_f("internal error: hpdelim"); host = cleanhostname(host); if (cp == NULL || (port = permitopen_port(cp)) < 0) - fatal("%s: internal error: permitopen port", - __func__); + fatal_f("internal error: permitopen port"); channel_add_permission(ssh, FORWARD_USER, FORWARD_LOCAL, host, port); free(tmp); @@ -324,11 +323,10 @@ set_fwdpermit_from_authopts(struct ssh *ssh, const struct sshauthopt *opts) 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__); + fatal_f("internal error: hpdelim"); host = cleanhostname(host); if (cp == NULL || (port = permitopen_port(cp)) < 0) - fatal("%s: internal error: permitlisten port", - __func__); + fatal_f("internal error: permitlisten port"); channel_add_permission(ssh, FORWARD_USER, FORWARD_REMOTE, host, port); free(tmp); @@ -405,18 +403,17 @@ do_exec_no_pty(struct ssh *ssh, Session *s, const char *command) /* Allocate pipes for communicating with the program. */ if (pipe(pin) == -1) { - error("%s: pipe in: %.100s", __func__, strerror(errno)); + error_f("pipe in: %.100s", strerror(errno)); return -1; } if (pipe(pout) == -1) { - error("%s: pipe out: %.100s", __func__, strerror(errno)); + error_f("pipe out: %.100s", strerror(errno)); close(pin[0]); close(pin[1]); return -1; } if (pipe(perr) == -1) { - error("%s: pipe err: %.100s", __func__, - strerror(errno)); + error_f("pipe err: %.100s", strerror(errno)); close(pin[0]); close(pin[1]); close(pout[0]); @@ -431,12 +428,11 @@ do_exec_no_pty(struct ssh *ssh, Session *s, const char *command) /* Uses socket pairs to communicate with the program. */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1) { - error("%s: socketpair #1: %.100s", __func__, strerror(errno)); + error_f("socketpair #1: %.100s", strerror(errno)); return -1; } if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) == -1) { - error("%s: socketpair #2: %.100s", __func__, - strerror(errno)); + error_f("socketpair #2: %.100s", strerror(errno)); close(inout[0]); close(inout[1]); return -1; @@ -448,7 +444,7 @@ do_exec_no_pty(struct ssh *ssh, Session *s, const char *command) /* Fork the child. */ switch ((pid = fork())) { case -1: - error("%s: fork: %.100s", __func__, strerror(errno)); + error_f("fork: %.100s", strerror(errno)); #ifdef USE_PIPES close(pin[0]); close(pin[1]); @@ -583,14 +579,14 @@ do_exec_pty(struct ssh *ssh, Session *s, const char *command) * detect and gracefully fail out-of-fd conditions. */ if ((fdout = dup(ptyfd)) == -1) { - error("%s: dup #1: %s", __func__, strerror(errno)); + error_f("dup #1: %s", strerror(errno)); close(ttyfd); close(ptyfd); return -1; } /* we keep a reference to the pty master */ if ((ptymaster = dup(ptyfd)) == -1) { - error("%s: dup #2: %s", __func__, strerror(errno)); + error_f("dup #2: %s", strerror(errno)); close(ttyfd); close(ptyfd); close(fdout); @@ -600,7 +596,7 @@ do_exec_pty(struct ssh *ssh, Session *s, const char *command) /* Fork the child. */ switch ((pid = fork())) { case -1: - error("%s: fork: %.100s", __func__, strerror(errno)); + error_f("fork: %.100s", strerror(errno)); close(fdout); close(ptymaster); close(ttyfd); @@ -849,12 +845,12 @@ check_quietlogin(Session *s, const char *command) * 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 + * If allowlist 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) + const char *filename, const char *allowlist) { FILE *f; char *line = NULL, *cp, *value; @@ -887,8 +883,8 @@ read_environment_file(char ***env, u_int *envsize, */ *value = '\0'; value++; - if (whitelist != NULL && - match_pattern_list(cp, whitelist, 0) != 1) + if (allowlist != NULL && + match_pattern_list(cp, allowlist, 0) != 1) continue; child_set_env(env, envsize, cp, value); } @@ -930,7 +926,7 @@ read_etc_default_login(char ***env, u_int *envsize, uid_t uid) * interested in. */ read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login", - options.permit_user_env_whitelist); + options.permit_user_env_allowlist); if (tmpenv == NULL) return; @@ -952,9 +948,10 @@ read_etc_default_login(char ***env, u_int *envsize, uid_t uid) } #endif /* HAVE_ETC_DEFAULT_LOGIN */ +#if defined(USE_PAM) || defined(HAVE_CYGWIN) static void -copy_environment_blacklist(char **source, char ***env, u_int *envsize, - const char *blacklist) +copy_environment_denylist(char **source, char ***env, u_int *envsize, + const char *denylist) { char *var_name, *var_val; int i; @@ -970,8 +967,8 @@ copy_environment_blacklist(char **source, char ***env, u_int *envsize, } *var_val++ = '\0'; - if (blacklist == NULL || - match_pattern_list(var_name, blacklist, 0) != 1) { + if (denylist == NULL || + match_pattern_list(var_name, denylist, 0) != 1) { debug3("Copy environment: %s=%s", var_name, var_val); child_set_env(env, envsize, var_name, var_val); } @@ -979,12 +976,15 @@ copy_environment_blacklist(char **source, char ***env, u_int *envsize, free(var_name); } } +#endif /* defined(USE_PAM) || defined(HAVE_CYGWIN) */ -void +#ifdef HAVE_CYGWIN +static void copy_environment(char **source, char ***env, u_int *envsize) { - copy_environment_blacklist(source, env, envsize, NULL); + copy_environment_denylist(source, env, envsize, NULL); } +#endif static char ** do_setup_env(struct ssh *ssh, Session *s, const char *shell) @@ -1019,7 +1019,7 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) #ifdef GSSAPI /* Allow any GSSAPI methods that we've used to alter - * the childs environment as they see fit + * the child's environment as they see fit */ ssh_gssapi_do_child(&env, &envsize); #endif @@ -1093,7 +1093,7 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) if ((cp = getenv("AUTHSTATE")) != NULL) child_set_env(&env, &envsize, "AUTHSTATE", cp); read_environment_file(&env, &envsize, "/etc/environment", - options.permit_user_env_whitelist); + options.permit_user_env_allowlist); } #endif #ifdef KRB5 @@ -1111,12 +1111,12 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) for (n = 0 ; n < auth_opts->nenv; n++) { ocp = xstrdup(auth_opts->env[n]); cp = strchr(ocp, '='); - if (*cp == '=') { + if (cp != NULL) { *cp = '\0'; - /* Apply PermitUserEnvironment whitelist */ - if (options.permit_user_env_whitelist == NULL || + /* Apply PermitUserEnvironment allowlist */ + if (options.permit_user_env_allowlist == NULL || match_pattern_list(ocp, - options.permit_user_env_whitelist, 0) == 1) + options.permit_user_env_allowlist, 0) == 1) child_set_env(&env, &envsize, ocp, cp + 1); } @@ -1126,10 +1126,10 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) /* read $HOME/.ssh/environment. */ if (options.permit_user_env) { - snprintf(buf, sizeof buf, "%.200s/.ssh/environment", - pw->pw_dir); + snprintf(buf, sizeof buf, "%.200s/%s/environment", + pw->pw_dir, _PATH_SSH_USER_DIR); read_environment_file(&env, &envsize, buf, - options.permit_user_env_whitelist); + options.permit_user_env_allowlist); } #ifdef USE_PAM @@ -1144,15 +1144,15 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) * Don't allow PAM-internal env vars to leak * back into the session environment. */ -#define PAM_ENV_BLACKLIST "SSH_AUTH_INFO*,SSH_CONNECTION*" +#define PAM_ENV_DENYLIST "SSH_AUTH_INFO*,SSH_CONNECTION*" p = fetch_pam_child_environment(); - copy_environment_blacklist(p, &env, &envsize, - PAM_ENV_BLACKLIST); + copy_environment_denylist(p, &env, &envsize, + PAM_ENV_DENYLIST); free_pam_environment(p); p = fetch_pam_environment(); - copy_environment_blacklist(p, &env, &envsize, - PAM_ENV_BLACKLIST); + copy_environment_denylist(p, &env, &envsize, + PAM_ENV_DENYLIST); free_pam_environment(p); } #endif /* USE_PAM */ @@ -1208,19 +1208,21 @@ static void do_rc_files(struct ssh *ssh, Session *s, const char *shell) { FILE *f = NULL; - char cmd[1024]; + char *cmd = NULL, *user_rc = NULL; int do_xauth; struct stat st; do_xauth = s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL; + xasprintf(&user_rc, "%s/%s", s->pw->pw_dir, _PATH_SSH_USER_RC); /* 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); + stat(user_rc, &st) >= 0) { + if (xasprintf(&cmd, "%s -c '%s %s'", shell, _PATH_BSHELL, + user_rc) == -1) + fatal_f("xasprintf: %s", strerror(errno)); if (debug_flag) fprintf(stderr, "Running %s\n", cmd); f = popen(cmd, "w"); @@ -1231,7 +1233,7 @@ do_rc_files(struct ssh *ssh, Session *s, const char *shell) pclose(f); } else fprintf(stderr, "Could not run %s\n", - _PATH_SSH_USER_RC); + user_rc); } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) { if (debug_flag) fprintf(stderr, "Running %s %s\n", _PATH_BSHELL, @@ -1256,8 +1258,8 @@ do_rc_files(struct ssh *ssh, Session *s, const char *shell) options.xauth_location, s->auth_display, s->auth_proto, s->auth_data); } - snprintf(cmd, sizeof cmd, "%s -q -", - options.xauth_location); + if (xasprintf(&cmd, "%s -q -", options.xauth_location) == -1) + fatal_f("xasprintf: %s", strerror(errno)); f = popen(cmd, "w"); if (f) { fprintf(f, "remove %s\n", @@ -1271,6 +1273,8 @@ do_rc_files(struct ssh *ssh, Session *s, const char *shell) cmd); } } + free(cmd); + free(user_rc); } static void @@ -1289,11 +1293,8 @@ do_nologin(struct passwd *pw) return; nl = def_nl; #endif - if (stat(nl, &sb) == -1) { - if (nl != def_nl) - free(nl); + if (stat(nl, &sb) == -1) return; - } /* /etc/nologin exists. Print its contents if we can and exit. */ logit("User %.100s not allowed because %s exists", pw->pw_name, nl); @@ -1343,10 +1344,10 @@ safely_chroot(const char *path, uid_t uid) component[cp - path] = '\0'; } - debug3("%s: checking '%s'", __func__, component); + debug3_f("checking '%s'", component); if (stat(component, &st) != 0) - fatal("%s: stat(\"%s\"): %s", __func__, + fatal_f("stat(\"%s\"): %s", component, strerror(errno)); if (st.st_uid != 0 || (st.st_mode & 022) != 0) fatal("bad ownership or modes for chroot " @@ -1364,8 +1365,7 @@ safely_chroot(const char *path, uid_t uid) if (chroot(path) == -1) fatal("chroot(\"%s\"): %s", path, strerror(errno)); if (chdir("/") == -1) - fatal("%s: chdir(/) after chroot: %s", - __func__, strerror(errno)); + fatal_f("chdir(/) after chroot: %s", strerror(errno)); verbose("Changed root directory to \"%s\"", path); } @@ -1508,6 +1508,9 @@ child_close_fds(struct ssh *ssh) */ endpwent(); + /* Stop directing logs to a high-numbered fd before we close it */ + log_redirect_stderr_to(NULL); + /* * 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 @@ -1657,7 +1660,7 @@ do_child(struct ssh *ssh, Session *s, const char *command) do_rc_files(ssh, s, shell); /* restore SIGPIPE for child */ - signal(SIGPIPE, SIG_DFL); + ssh_signal(SIGPIPE, SIG_DFL); if (s->is_subsystem == SUBSYSTEM_INT_SFTP_ERROR) { error("Connection from %s: refusing non-sftp session", @@ -1736,11 +1739,11 @@ do_child(struct ssh *ssh, Session *s, const char *command) void session_unused(int id) { - debug3("%s: session id %d unused", __func__, id); + debug3_f("session id %d unused", 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); + fatal_f("insane session id %d (max %d nalloc %d)", + id, options.max_sessions, sessions_nalloc); } memset(&sessions[id], 0, sizeof(*sessions)); sessions[id].self = id; @@ -1762,13 +1765,13 @@ session_new(void) 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); + debug2_f("allocate (allocated %d max %d)", + 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); + error_f("cannot allocate %d sessions", + sessions_nalloc + 1); return NULL; } sessions = tmp; @@ -1777,16 +1780,14 @@ session_new(void) 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, + fatal_f("insane first_unused %d max %d nalloc %d", + 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); - } + if (s->used) + fatal_f("session %d already used", sessions_first_unused); sessions_first_unused = s->next_unused; s->used = 1; s->next_unused = -1; @@ -2160,35 +2161,33 @@ session_signal_req(struct ssh *ssh, Session *s) if ((r = sshpkt_get_cstring(ssh, &signame, NULL)) != 0 || (r = sshpkt_get_end(ssh)) != 0) { - error("%s: parse packet: %s", __func__, ssh_err(r)); + error_fr(r, "parse"); goto out; } if ((sig = name2sig(signame)) == -1) { - error("%s: unsupported signal \"%s\"", __func__, signame); + error_f("unsupported signal \"%s\"", signame); goto out; } if (s->pid <= 0) { - error("%s: no pid for session %d", __func__, s->self); + error_f("no pid for session %d", s->self); goto out; } if (s->forced || s->is_subsystem) { - error("%s: refusing to send signal %s to %s session", __func__, + error_f("refusing to send signal %s to %s session", signame, s->forced ? "forced-command" : "subsystem"); goto out; } if (!use_privsep || mm_is_monitor()) { - error("%s: session signalling requires privilege separation", - __func__); + error_f("session signalling requires privilege separation"); goto out; } - debug("%s: signal %s, killpg(%ld, %d)", __func__, signame, - (long)s->pid, sig); + debug_f("signal %s, killpg(%ld, %d)", 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, + error_f("killpg(%ld, %d): %s", (long)s->pid, sig, strerror(errno)); goto out; } @@ -2210,7 +2209,7 @@ session_auth_agent_req(struct ssh *ssh, Session *s) 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__); + debug_f("agent forwarding disabled"); return 0; } if (called) { @@ -2228,10 +2227,10 @@ session_input_channel_req(struct ssh *ssh, Channel *c, const char *rtype) Session *s; if ((s = session_by_channel(c->self)) == NULL) { - logit("%s: no session %d req %.100s", __func__, c->self, rtype); + logit_f("no session %d req %.100s", c->self, rtype); return 0; } - debug("%s: session %d req %s", __func__, s->self, rtype); + debug_f("session %d req %s", s->self, rtype); /* * a session is in LARVAL state until a shell, a command @@ -2289,13 +2288,13 @@ void session_pty_cleanup2(Session *s) { if (s == NULL) { - error("%s: no session", __func__); + error_f("no session"); return; } if (s->ttyfd == -1) return; - debug("%s: session %d release %s", __func__, s->self, s->tty); + debug_f("session %d release %s", s->self, s->tty); /* Record that the user has logged out. */ if (s->pid != 0) @@ -2351,10 +2350,10 @@ 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); + debug_f("x11 channel %d missing", id); } else { /* Detach X11 listener */ - debug("%s: detach x11 channel %d", __func__, id); + debug_f("detach x11 channel %d", id); channel_cancel_cleanup(ssh, id); if (c->ostate != CHAN_OUTPUT_CLOSED) chan_mark_dead(ssh, c); @@ -2367,13 +2366,13 @@ session_close_single_x11(struct ssh *ssh, int id, void *arg) Session *s; u_int i; - debug3("%s: channel %d", __func__, id); + debug3_f("channel %d", id); channel_cancel_cleanup(ssh, id); if ((s = session_by_x11_channel(id)) == NULL) - fatal("%s: no x11 channel %d", __func__, id); + fatal_f("no x11 channel %d", id); for (i = 0; s->x11_chanids[i] != -1; i++) { - debug("%s: session %d: closing channel %d", - __func__, s->self, s->x11_chanids[i]); + debug_f("session %d: closing channel %d", + s->self, s->x11_chanids[i]); /* * The channel "id" is already closing, but make sure we * close all of its siblings. @@ -2400,10 +2399,9 @@ session_exit_message(struct ssh *ssh, Session *s, int status) 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); + fatal_f("session %d: no channel %d", s->self, s->chanid); + debug_f("session %d channel %d pid %ld", + s->self, s->chanid, (long)s->pid); if (WIFEXITED(status)) { channel_request_start(ssh, s->chanid, "exit-status", 0); @@ -2427,12 +2425,12 @@ session_exit_message(struct ssh *ssh, Session *s, int status) } /* disconnect channel */ - debug("%s: release channel %d", __func__, s->chanid); + debug_f("release channel %d", 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. + * by session_close_by_channel when the child sessions close their fds. */ channel_register_cleanup(ssh, c->self, session_close_by_channel, 1); @@ -2482,7 +2480,7 @@ 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); + debug_f("no session for pid %ld", (long)pid); return; } if (s->chanid != -1) @@ -2503,13 +2501,12 @@ session_close_by_channel(struct ssh *ssh, int id, void *arg) u_int i; if (s == NULL) { - debug("%s: no session for id %d", __func__, id); + debug_f("no session for id %d", id); return; } - debug("%s: channel %d child %ld", __func__, id, (long)s->pid); + debug_f("channel %d child %ld", id, (long)s->pid); if (s->pid != 0) { - debug("%s: channel %d: has child, ttyfd %d", - __func__, id, s->ttyfd); + debug_f("channel %d: has child, ttyfd %d", id, s->ttyfd); /* * delay detach of session, but release pty, since * the fd's to the child are already closed diff --git a/sftp-client.c b/sftp-client.c index 1a598a5ec..f0af7011a 100644 --- a/sftp-client.c +++ b/sftp-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-client.c,v 1.135 2019/10/04 04:31:59 djm Exp $ */ +/* $OpenBSD: sftp-client.c,v 1.139 2020/12/04 02:41:10 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -140,7 +140,7 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial) int r; if ((r = sshbuf_reserve(m, 4, &p)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "reserve"); if (atomicio6(read, conn->fd_in, p, 4, sftpio, conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) { if (errno == EPIPE || errno == ECONNRESET) @@ -150,7 +150,7 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial) } if ((r = sshbuf_get_u32(m, &msg_len)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_get_u32"); if (msg_len > SFTP_MAX_MSG_LENGTH) { do_log2(initial ? SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_FATAL, "Received message too long %u", msg_len); @@ -159,7 +159,7 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial) } if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "reserve"); if (atomicio6(read, conn->fd_in, p, msg_len, sftpio, conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != msg_len) { @@ -184,11 +184,11 @@ send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s, int r; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); sshbuf_free(msg); @@ -202,12 +202,12 @@ send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, int r; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); sshbuf_free(msg); @@ -222,11 +222,11 @@ get_status(struct sftp_conn *conn, u_int expected_id) int r; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); @@ -235,7 +235,7 @@ get_status(struct sftp_conn *conn, u_int expected_id) SSH2_FXP_STATUS, type); if ((r = sshbuf_get_u32(msg, &status)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); sshbuf_free(msg); debug3("SSH2_FXP_STATUS %u", status); @@ -261,18 +261,18 @@ get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, va_end(args); if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "parse"); 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)); + fatal_fr(r, "parse status"); if (errfmt != NULL) error("%s: %s", errmsg, fx2txt(status)); sshbuf_free(msg); @@ -282,7 +282,7 @@ get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, 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)); + fatal_fr(r, "parse handle"); sshbuf_free(msg); return handle; @@ -298,12 +298,12 @@ get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) static Attrib a; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "parse"); debug3("Received stat reply T:%u I:%u", type, id); if (id != expected_id) @@ -312,7 +312,7 @@ get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) u_int status; if ((r = sshbuf_get_u32(msg, &status)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse status"); if (quiet) debug("Couldn't stat remote file: %s", fx2txt(status)); else @@ -324,7 +324,7 @@ get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) SSH2_FXP_ATTRS, type); } if ((r = decode_attrib(msg, &a)) != 0) { - error("%s: couldn't decode attrib: %s", __func__, ssh_err(r)); + error_fr(r, "decode_attrib"); sshbuf_free(msg); return NULL; } @@ -344,12 +344,12 @@ get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, int r; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "parse"); debug3("Received statvfs reply T:%u I:%u", type, id); if (id != expected_id) @@ -358,7 +358,7 @@ get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, u_int status; if ((r = sshbuf_get_u32(msg, &status)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse status"); if (quiet) debug("Couldn't statvfs: %s", fx2txt(status)); else @@ -382,7 +382,7 @@ get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, (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)); + fatal_fr(r, "parse statvfs"); st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0; st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0; @@ -411,10 +411,11 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, ret->limit_kbps = 0; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "parse"); + send_msg(ret, msg); sshbuf_reset(msg); @@ -423,7 +424,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, /* Expecting a VERSION reply */ if ((r = sshbuf_get_u8(msg, &type)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse type"); if (type != SSH2_FXP_VERSION) { error("Invalid packet back from SSH2_FXP_INIT (type %u)", type); @@ -432,7 +433,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, return(NULL); } if ((r = sshbuf_get_u32(msg, &ret->version)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse version"); debug2("Remote version: %u", ret->version); @@ -445,7 +446,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, 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)); + fatal_fr(r, "parse extension"); if (strcmp(name, "posix-rename@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_POSIX_RENAME; @@ -512,13 +513,13 @@ do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len) int r; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "parse"); send_msg(conn, msg); debug3("Sent message SSH2_FXP_CLOSE I:%u", id); @@ -549,11 +550,11 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, id = conn->msg_id++; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose OPENDIR"); send_msg(conn, msg); handle = get_handle(conn, id, &handle_len, @@ -578,7 +579,7 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, 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)); + fatal_fr(r, "compose READDIR"); send_msg(conn, msg); sshbuf_reset(msg); @@ -587,7 +588,7 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); debug3("Received reply T:%u I:%u", type, id); @@ -598,8 +599,7 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, u_int rstatus; if ((r = sshbuf_get_u32(msg, &rstatus)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "parse status"); debug3("Received SSH2_FXP_STATUS %d", rstatus); if (rstatus == SSH2_FX_EOF) break; @@ -610,9 +610,9 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, SSH2_FXP_NAME, type); if ((r = sshbuf_get_u32(msg, &count)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse count"); if (count > SSHBUF_SIZE_MAX) - fatal("%s: nonsensical number of entries", __func__); + fatal_f("nonsensical number of entries"); if (count == 0) break; debug3("Received %d SSH2_FXP_NAME responses", count); @@ -624,11 +624,9 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, NULL)) != 0 || (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "parse filenames"); if ((r = decode_attrib(msg, &a)) != 0) { - error("%s: couldn't decode attrib: %s", - __func__, ssh_err(r)); + error_fr(r, "couldn't decode attrib"); free(filename); free(longname); goto out; @@ -843,12 +841,12 @@ do_realpath(struct sftp_conn *conn, const char *path) strlen(path)); if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "parse"); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); @@ -857,7 +855,7 @@ do_realpath(struct sftp_conn *conn, const char *path) u_int status; if ((r = sshbuf_get_u32(msg, &status)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse status"); error("Couldn't canonicalize: %s", fx2txt(status)); sshbuf_free(msg); return NULL; @@ -866,14 +864,14 @@ do_realpath(struct sftp_conn *conn, const char *path) SSH2_FXP_NAME, type); if ((r = sshbuf_get_u32(msg, &count)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse count"); 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)); + fatal_fr(r, "parse filename/attrib"); debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename, (unsigned long)a.size); @@ -894,7 +892,7 @@ do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); /* Send rename request */ id = conn->msg_id++; @@ -903,15 +901,15 @@ do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, (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)); + fatal_fr(r, "compose posix-rename"); } 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)); + fatal_fr(r, "compose rename"); } if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 || (r = sshbuf_put_cstring(msg, newpath)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "compose paths"); send_msg(conn, msg); debug3("Sent message %s \"%s\" -> \"%s\"", use_ext ? "posix-rename@openssh.com" : @@ -939,7 +937,7 @@ do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) } if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); /* Send link request */ id = conn->msg_id++; @@ -948,7 +946,7 @@ do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) (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)); + fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"", oldpath, newpath); @@ -975,7 +973,7 @@ do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) } if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); /* Send symlink request */ id = conn->msg_id++; @@ -983,7 +981,7 @@ do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) (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)); + fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, newpath); @@ -1010,13 +1008,13 @@ do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len) /* Send fsync request */ if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message fsync@openssh.com I:%u", id); sshbuf_free(msg); @@ -1043,12 +1041,12 @@ do_readlink(struct sftp_conn *conn, const char *path) send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "parse"); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); @@ -1057,7 +1055,7 @@ do_readlink(struct sftp_conn *conn, const char *path) u_int status; if ((r = sshbuf_get_u32(msg, &status)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse status"); error("Couldn't readlink: %s", fx2txt(status)); sshbuf_free(msg); return(NULL); @@ -1066,14 +1064,14 @@ do_readlink(struct sftp_conn *conn, const char *path) SSH2_FXP_NAME, type); if ((r = sshbuf_get_u32(msg, &count)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse count"); 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)); + fatal_fr(r, "parse filenames/attrib"); debug3("SSH_FXP_READLINK %s -> %s", path, filename); @@ -1101,12 +1099,12 @@ do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, id = conn->msg_id++; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); send_msg(conn, msg); sshbuf_free(msg); @@ -1129,12 +1127,12 @@ do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len, id = conn->msg_id++; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); send_msg(conn, msg); sshbuf_free(msg); @@ -1156,13 +1154,13 @@ do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a) id = conn->msg_id++; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); send_msg(conn, msg); sshbuf_free(msg); @@ -1182,13 +1180,13 @@ send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, int r; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); send_msg(conn, msg); sshbuf_free(msg); } @@ -1242,7 +1240,7 @@ do_download(struct sftp_conn *conn, const char *remote_path, buflen = conn->transfer_buflen; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); attrib_clear(&junk); /* Send empty attributes */ @@ -1253,7 +1251,7 @@ do_download(struct sftp_conn *conn, const char *remote_path, (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)); + fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); @@ -1344,7 +1342,7 @@ do_download(struct sftp_conn *conn, const char *remote_path, 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)); + fatal_fr(r, "parse"); debug3("Received reply T:%u I:%u R:%d", type, id, max_req); /* Find the request in our queue */ @@ -1358,8 +1356,7 @@ do_download(struct sftp_conn *conn, const char *remote_path, switch (type) { case SSH2_FXP_STATUS: if ((r = sshbuf_get_u32(msg, &status)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "parse status"); if (status != SSH2_FX_EOF) read_error = 1; max_req = 0; @@ -1369,8 +1366,7 @@ do_download(struct sftp_conn *conn, const char *remote_path, break; case SSH2_FXP_DATA: if ((r = sshbuf_get_string(msg, &data, &len)) != 0) - fatal("%s: buffer error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "parse data"); debug3("Received data %llu -> %llu", (unsigned long long)req->offset, (unsigned long long)req->offset + len - 1); @@ -1420,7 +1416,7 @@ do_download(struct sftp_conn *conn, const char *remote_path, (unsigned long long)offset, num_req); max_req = 1; - } else if (max_req <= conn->num_requests) { + } else if (max_req < conn->num_requests) { ++max_req; } } @@ -1505,7 +1501,7 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, int i, ret = 0; SFTP_DIRENT **dir_entries; char *filename, *new_src = NULL, *new_dst = NULL; - mode_t mode = 0777; + mode_t mode = 0777, tmpmode = mode; if (depth >= MAX_DIR_DEPTH) { error("Maximum directory depth exceeded: %d levels", depth); @@ -1524,14 +1520,15 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, if (print_flag) mprintf("Retrieving %s\n", src); - if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) + if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { mode = dirattrib->perm & 01777; - else { + tmpmode = mode | (S_IWUSR|S_IXUSR); + } else { debug("Server did not send permissions for " "directory \"%s\"", dst); } - if (mkdir(dst, mode) == -1 && errno != EEXIST) { + if (mkdir(dst, tmpmode) == -1 && errno != EEXIST) { error("mkdir %s: %s", dst, strerror(errno)); return -1; } @@ -1586,6 +1583,10 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, "\"%s\"", dst); } + if (mode != tmpmode && chmod(dst, mode) == -1) + error("Can't set final mode on \"%s\": %s", dst, + strerror(errno)); + free_sftp_dirents(dir_entries); return ret; @@ -1682,7 +1683,7 @@ do_upload(struct sftp_conn *conn, const char *local_path, } if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); /* Send open request */ id = conn->msg_id++; @@ -1692,7 +1693,7 @@ do_upload(struct sftp_conn *conn, const char *local_path, (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)); + fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); @@ -1749,8 +1750,7 @@ do_upload(struct sftp_conn *conn, const char *local_path, 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)); + fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", id, (unsigned long long)offset, len); @@ -1768,16 +1768,14 @@ do_upload(struct sftp_conn *conn, const char *local_path, 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)); + fatal_fr(r, "parse"); 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)); + fatal_fr(r, "parse status"); debug3("SSH2_FXP_STATUS %u", status); /* Find the request in our queue */ @@ -1796,7 +1794,7 @@ do_upload(struct sftp_conn *conn, const char *local_path, } offset += len; if (offset < 0) - fatal("%s: offset < 0", __func__); + fatal_f("offset < 0"); } sshbuf_free(msg); @@ -1841,6 +1839,7 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, char *filename, *new_src = NULL, *new_dst = NULL; struct stat sb; Attrib a, *dirattrib; + u_int32_t saved_perm; if (depth >= MAX_DIR_DEPTH) { error("Maximum directory depth exceeded: %d levels", depth); @@ -1870,8 +1869,11 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, /* * 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. + * the path already existed and is a directory. Ensure we can + * write to the directory we create for the duration of the transfer. */ + saved_perm = a.perm; + a.perm |= (S_IWUSR|S_IXUSR); if (do_mkdir(conn, dst, &a, 0) != 0) { if ((dirattrib = do_stat(conn, dst, 0)) == NULL) return -1; @@ -1880,6 +1882,7 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, return -1; } } + a.perm = saved_perm; if ((dirp = opendir(src)) == NULL) { error("Failed to open dir \"%s\": %s", src, strerror(errno)); @@ -1961,3 +1964,77 @@ path_append(const char *p1, const char *p2) return(ret); } +char * +make_absolute(char *p, const char *pwd) +{ + char *abs_str; + + /* Derelativise */ +#ifdef WINDOWS + /* + * For Windows - given path is absolute when + * - first character is "/" + * - or second character is ":" + * This code is also applicable from a Linux client to Windows target + * Need to follow up with community if this makes sense in common code + */ + char *s1, *s2; + if (!is_absolute_path(p)) { + abs_str = path_append(pwd, p); + free(p); + p = abs_str; + } + + /* Append "/" if needed to the absolute windows path */ + if (p && p[0] != '\0' && p[1] == ':') { + s1 = path_append("/", p); + free(p); + p = s1; + } + + return(p); +#else /* !WINDOWS */ + if (p && !path_absolute(p)) { + abs_str = path_append(pwd, p); + free(p); + return(abs_str); + } else + return(p); +#endif /* !WINDOWS */ +} + +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)); +} + + +int +local_is_dir(const char *path) +{ + struct stat sb; + + /* XXX: report errors? */ + if (stat(path, &sb) == -1) + return(0); + + return(S_ISDIR(sb.st_mode)); +} + +/* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */ +int +globpath_is_dir(const char *pathname) +{ + size_t l = strlen(pathname); + + return l > 0 && pathname[l - 1] == '/'; +} + diff --git a/sftp-client.h b/sftp-client.h index 63a9b8b13..32a24a3c4 100644 --- a/sftp-client.h +++ b/sftp-client.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-client.h,v 1.28 2019/01/16 23:23:45 djm Exp $ */ +/* $OpenBSD: sftp-client.h,v 1.29 2020/12/04 02:41:10 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller @@ -142,4 +142,17 @@ int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int, /* Concatenate paths, taking care of slashes. Caller must free result. */ char *path_append(const char *, const char *); +/* Make absolute path if relative path and CWD is given. Does not modify + * original if the the path is already absolute. */ +char *make_absolute(char *, const char *); + +/* Check if remote path is directory */ +int remote_is_dir(struct sftp_conn *conn, const char *path); + +/* Check if local path is directory */ +int local_is_dir(const char *path); + +/* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */ +int globpath_is_dir(const char *pathname); + #endif diff --git a/sftp-common.c b/sftp-common.c index 677f27d63..3ad57673d 100644 --- a/sftp-common.c +++ b/sftp-common.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-common.c,v 1.31 2018/09/13 15:23:32 millert Exp $ */ +/* $OpenBSD: sftp-common.c,v 1.32 2020/10/18 11:32:02 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Damien Miller. All rights reserved. @@ -136,7 +136,7 @@ decode_attrib(struct sshbuf *b, Attrib *a) u_int i, count; if ((r = sshbuf_get_u32(b, &count)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + return r; for (i = 0; i < count; i++) { if ((r = sshbuf_get_cstring(b, &type, NULL)) != 0 || (r = sshbuf_get_string(b, &data, &dlen)) != 0) diff --git a/sftp-glob.c b/sftp-glob.c index c196c51e5..f573f98f0 100644 --- a/sftp-glob.c +++ b/sftp-glob.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-glob.c,v 1.28 2019/10/02 00:42:30 djm Exp $ */ +/* $OpenBSD: sftp-glob.c,v 1.29 2019/11/13 04:47:52 deraadt Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -25,6 +25,7 @@ #include #include #include +#include #include "xmalloc.h" #include "sftp.h" diff --git a/sftp-server.8 b/sftp-server.8 index c117398e8..f057da3b8 100644 --- a/sftp-server.8 +++ b/sftp-server.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sftp-server.8,v 1.27 2014/12/11 04:16:14 djm Exp $ +.\" $OpenBSD: sftp-server.8,v 1.30 2020/06/22 06:36:40 jmc Exp $ .\" .\" Copyright (c) 2000 Markus Friedl. All rights reserved. .\" @@ -22,12 +22,12 @@ .\" (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: December 11 2014 $ +.Dd $Mdocdate: June 22 2020 $ .Dt SFTP-SERVER 8 .Os .Sh NAME .Nm sftp-server -.Nd SFTP server subsystem +.Nd OpenSSH SFTP server subsystem .Sh SYNOPSIS .Nm sftp-server .Bk -words @@ -35,8 +35,8 @@ .Op Fl d Ar start_directory .Op Fl f Ar log_facility .Op Fl l Ar log_level -.Op Fl P Ar blacklisted_requests -.Op Fl p Ar whitelisted_requests +.Op Fl P Ar denied_requests +.Op Fl p Ar allowed_requests .Op Fl u Ar umask .Ek .Nm @@ -99,20 +99,20 @@ 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. -.It Fl P Ar blacklisted_requests +.It Fl P Ar denied_requests Specify a comma-separated list of SFTP protocol requests that are banned by the server. .Nm -will reply to any blacklisted request with a failure. +will reply to any denied request with a failure. The .Fl 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. -.It Fl p Ar whitelisted_requests +If both denied and allowed lists are specified, then the denied list is +applied before the allowed list. +.It Fl p Ar allowed_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 +All request types that are not on the allowed list will be logged and replied to with a failure message. .Pp Care must be taken when using this feature to ensure that requests made @@ -122,7 +122,7 @@ Query protocol features supported by .Nm . At present the only feature that may be queried is .Dq requests , -which may be used for black or whitelisting (flags +which may be used to deny or allow specific requests (flags .Fl P and .Fl p diff --git a/sftp-server.c b/sftp-server.c index f17856089..88a598a02 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-server.c,v 1.117 2019/07/05 04:55:40 djm Exp $ */ +/* $OpenBSD: sftp-server.c,v 1.122 2021/02/18 00:30:17 djm Exp $ */ /* * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. * @@ -19,6 +19,7 @@ #include #include +#include #ifdef HAVE_SYS_TIME_H # include #endif @@ -53,6 +54,9 @@ char *sftp_realpath(const char *, char *); /* sftp-realpath.c */ +/* Maximum data read that we are willing to accept */ +#define SFTP_MAX_READ_LENGTH (64 * 1024) + /* Our verbosity */ static LogLevel log_level = SYSLOG_LEVEL_ERROR; @@ -74,7 +78,7 @@ static int init_done; static int readonly; /* Requests that are allowed/denied */ -static char *request_whitelist, *request_blacklist; +static char *request_allowlist, *request_denylist; /* portable attributes, etc. */ typedef struct Stat Stat; @@ -110,6 +114,7 @@ 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_limits(u_int32_t id); static void process_extended(u_int32_t id); struct sftp_handler { @@ -152,6 +157,7 @@ static const struct sftp_handler extended_handlers[] = { { "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 }, + { "limits", "limits@openssh.com", 0, process_extended_limits, 1 }, { NULL, NULL, 0, NULL, 0 } }; @@ -164,20 +170,20 @@ request_permitted(const struct sftp_handler *h) 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) { + if (request_denylist != NULL && + ((result = match_list(h->name, request_denylist, NULL))) != NULL) { free(result); - verbose("Refusing blacklisted %s request", h->name); + verbose("Refusing denylisted %s request", h->name); return 0; } - if (request_whitelist != NULL && - ((result = match_list(h->name, request_whitelist, NULL))) != NULL) { + if (request_allowlist != NULL && + ((result = match_list(h->name, request_allowlist, NULL))) != NULL) { free(result); - debug2("Permitting whitelisted %s request", h->name); + debug2("Permitting allowlisted %s request", h->name); return 1; } - if (request_whitelist != NULL) { - verbose("Refusing non-whitelisted %s request", h->name); + if (request_allowlist != NULL) { + verbose("Refusing non-allowlisted %s request", h->name); return 0; } return 1; @@ -489,7 +495,7 @@ send_msg(struct sshbuf *m) int r; if ((r = sshbuf_put_stringb(oqueue, m)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "enqueue"); sshbuf_reset(m); } @@ -522,16 +528,16 @@ send_status(u_int32_t id, u_int32_t status) (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__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); 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)); + fatal_fr(r, "compose message"); } send_msg(msg); sshbuf_free(msg); @@ -543,11 +549,11 @@ send_data_or_handle(char type, u_int32_t id, const u_char *data, int dlen) int r; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); send_msg(msg); sshbuf_free(msg); } @@ -578,17 +584,17 @@ send_names(u_int32_t id, int count, const Stat *stats) int i, r; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); 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)); + fatal_fr(r, "compose filenames/attrib"); } send_msg(msg); sshbuf_free(msg); @@ -602,11 +608,11 @@ send_attrib(u_int32_t id, const Attrib *a) debug("request %u: sent attrib have 0x%x", id, a->flags); if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); send_msg(msg); sshbuf_free(msg); } @@ -622,7 +628,7 @@ send_statvfs(u_int32_t id, struct statvfs *st) flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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 || @@ -636,7 +642,7 @@ send_statvfs(u_int32_t id, struct statvfs *st) (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)); + fatal_fr(r, "compose"); send_msg(msg); sshbuf_free(msg); } @@ -650,10 +656,10 @@ process_init(void) int r; if ((r = sshbuf_get_u32(iqueue, &version)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); verbose("received client version %u", version); if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u8(msg, SSH2_FXP_VERSION)) != 0 || (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0 || /* POSIX rename extension */ @@ -671,9 +677,13 @@ process_init(void) /* fsync extension */ (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ + /* lsetstat extension */ (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 || + (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */ + /* limits extension */ + (r = sshbuf_put_cstring(msg, "limits@openssh.com")) != 0 || (r = sshbuf_put_cstring(msg, "1")) != 0) /* version */ - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "compose"); send_msg(msg); sshbuf_free(msg); } @@ -689,7 +699,7 @@ process_open(u_int32_t id) 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)); + fatal_fr(r, "parse"); debug3("request %u: open flags %d", id, pflags); flags = flags_from_portable(pflags); @@ -731,7 +741,7 @@ 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)); + fatal_fr(r, "parse"); debug3("request %u: close handle %u", id, handle); handle_log_close(handle, NULL); @@ -743,7 +753,7 @@ process_close(u_int32_t id) static void process_read(u_int32_t id) { - u_char buf[64*1024]; + u_char buf[SFTP_MAX_READ_LENGTH]; u_int32_t len; int r, handle, fd, ret, status = SSH2_FX_FAILURE; u_int64_t off; @@ -751,7 +761,7 @@ process_read(u_int32_t id) 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)); + fatal_fr(r, "parse"); debug("request %u: read \"%s\" (handle %d) off %llu len %d", id, handle_to_name(handle), handle, (unsigned long long)off, len); @@ -792,7 +802,7 @@ process_write(u_int32_t id) 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)); + fatal_fr(r, "parse"); debug("request %u: write \"%s\" (handle %d) off %llu len %zu", id, handle_to_name(handle), handle, (unsigned long long)off, len); @@ -804,18 +814,18 @@ process_write(u_int32_t id) if (!(handle_to_flags(handle) & O_APPEND) && lseek(fd, off, SEEK_SET) == -1) { status = errno_to_portable(errno); - error("process_write: seek failed"); + error_f("seek failed"); } else { /* XXX ATOMICIO ? */ ret = write(fd, data, len); if (ret == -1) { - error("process_write: write failed"); + error_f("write: %s", strerror(errno)); 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"); + debug2_f("nothing at all written"); status = SSH2_FX_FAILURE; } } @@ -833,7 +843,7 @@ process_do_stat(u_int32_t id, int do_lstat) int r, status = SSH2_FX_FAILURE; if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); debug3("request %u: %sstat", id, do_lstat ? "l" : ""); verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name); @@ -870,7 +880,7 @@ process_fstat(u_int32_t id) int fd, r, handle, status = SSH2_FX_FAILURE; if ((r = get_handle(iqueue, &handle)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); debug("request %u: fstat \"%s\" (handle %u)", id, handle_to_name(handle), handle); fd = handle_to_fd(handle); @@ -921,7 +931,7 @@ process_setstat(u_int32_t id) if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || (r = decode_attrib(iqueue, &a)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); debug("request %u: setstat name \"%s\"", id, name); if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { @@ -968,7 +978,7 @@ process_fsetstat(u_int32_t id) if ((r = get_handle(iqueue, &handle)) != 0 || (r = decode_attrib(iqueue, &a)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); debug("request %u: fsetstat handle %d", id, handle); fd = handle_to_fd(handle); @@ -1032,7 +1042,7 @@ process_opendir(u_int32_t id) 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)); + fatal_fr(r, "parse"); debug3("request %u: opendir", id); logit("opendir \"%s\"", path); @@ -1063,7 +1073,7 @@ process_readdir(u_int32_t id) int r, handle; if ((r = get_handle(iqueue, &handle)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); debug("request %u: readdir \"%s\" (handle %d)", id, handle_to_name(handle), handle); @@ -1117,7 +1127,7 @@ process_remove(u_int32_t id) int r, status = SSH2_FX_FAILURE; if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); debug3("request %u: remove", id); logit("remove name \"%s\"", name); @@ -1136,7 +1146,7 @@ process_mkdir(u_int32_t id) if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || (r = decode_attrib(iqueue, &a)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm & 07777 : 0777; @@ -1155,7 +1165,7 @@ process_rmdir(u_int32_t id) int r, status; if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); debug3("request %u: rmdir", id); logit("rmdir name \"%s\"", name); @@ -1173,7 +1183,7 @@ process_realpath(u_int32_t id) int r; if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); if (path[0] == '\0') { free(path); @@ -1206,7 +1216,7 @@ process_rename(u_int32_t id) 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)); + fatal_fr(r, "parse"); debug3("request %u: rename", id); logit("rename old \"%s\" new \"%s\"", oldpath, newpath); @@ -1265,7 +1275,7 @@ process_readlink(u_int32_t id) char *path; if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); debug3("request %u: readlink", id); verbose("readlink \"%s\"", path); @@ -1290,7 +1300,7 @@ process_symlink(u_int32_t id) 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)); + fatal_fr(r, "parse"); debug3("request %u: symlink", id); logit("symlink old \"%s\" new \"%s\"", oldpath, newpath); @@ -1310,7 +1320,7 @@ process_extended_posix_rename(u_int32_t id) 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)); + fatal_fr(r, "parse"); debug3("request %u: posix-rename", id); logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath); @@ -1329,7 +1339,7 @@ process_extended_statvfs(u_int32_t id) int r; if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); debug3("request %u: statvfs", id); logit("statvfs \"%s\"", path); @@ -1347,7 +1357,7 @@ process_extended_fstatvfs(u_int32_t id) struct statvfs st; if ((r = get_handle(iqueue, &handle)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); debug("request %u: fstatvfs \"%s\" (handle %u)", id, handle_to_name(handle), handle); if ((fd = handle_to_fd(handle)) < 0) { @@ -1368,7 +1378,7 @@ process_extended_hardlink(u_int32_t id) 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)); + fatal_fr(r, "parse"); debug3("request %u: hardlink", id); logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath); @@ -1385,7 +1395,7 @@ 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)); + fatal_fr(r, "parse"); debug3("request %u: fsync (handle %u)", id, handle); verbose("fsync \"%s\"", handle_to_name(handle)); if ((fd = handle_to_fd(handle)) < 0) @@ -1406,7 +1416,7 @@ process_extended_lsetstat(u_int32_t id) if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || (r = decode_attrib(iqueue, &a)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); debug("request %u: lsetstat name \"%s\"", id, name); if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { @@ -1446,6 +1456,36 @@ process_extended_lsetstat(u_int32_t id) free(name); } +static void +process_extended_limits(u_int32_t id) +{ + struct sshbuf *msg; + int r; + uint64_t nfiles = 0; + struct rlimit rlim; + + debug("request %u: limits", id); + + if (getrlimit(RLIMIT_NOFILE, &rlim) != -1 && rlim.rlim_cur > 5) + nfiles = rlim.rlim_cur - 5; /* stdio(3) + syslog + spare */ + + if ((msg = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 || + (r = sshbuf_put_u32(msg, id)) != 0 || + /* max-packet-length */ + (r = sshbuf_put_u64(msg, SFTP_MAX_MSG_LENGTH)) != 0 || + /* max-read-length */ + (r = sshbuf_put_u64(msg, SFTP_MAX_READ_LENGTH)) != 0 || + /* max-write-length */ + (r = sshbuf_put_u64(msg, SFTP_MAX_MSG_LENGTH - 1024)) != 0 || + /* max-open-handles */ + (r = sshbuf_put_u64(msg, nfiles)) != 0) + fatal_fr(r, "compose"); + send_msg(msg); + sshbuf_free(msg); +} + static void process_extended(u_int32_t id) { @@ -1453,7 +1493,7 @@ process_extended(u_int32_t id) int i, r; if ((r = sshbuf_get_cstring(iqueue, &request, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); for (i = 0; extended_handlers[i].handler != NULL; i++) { if (strcmp(request, extended_handlers[i].ext_name) == 0) { if (!request_permitted(&extended_handlers[i])) @@ -1496,10 +1536,10 @@ process(void) if (buf_len < msg_len + 4) return; if ((r = sshbuf_consume(iqueue, 4)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "consume"); buf_len -= 4; if ((r = sshbuf_get_u8(iqueue, &type)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse type"); switch (type) { case SSH2_FXP_INIT: @@ -1510,14 +1550,14 @@ process(void) 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)); + fatal_fr(r, "parse extended ID"); 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)); + fatal_fr(r, "parse ID"); for (i = 0; handlers[i].handler != NULL; i++) { if (type == handlers[i].type) { if (!request_permitted(&handlers[i])) { @@ -1544,7 +1584,7 @@ process(void) } if (msg_len > consumed && (r = sshbuf_consume(iqueue, msg_len - consumed)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "consume"); } /* Cleanup handler that logs active handles upon normal exit */ @@ -1566,8 +1606,8 @@ sftp_server_usage(void) 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" + "[-l log_level]\n\t[-P denied_requests] " + "[-p allowed_requests] [-u umask]\n" " %s -Q protocol_feature\n", __progname, __progname); exit(1); @@ -1637,14 +1677,14 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) free(cp); break; case 'p': - if (request_whitelist != NULL) + if (request_allowlist != NULL) fatal("Permitted requests already set"); - request_whitelist = xstrdup(optarg); + request_allowlist = xstrdup(optarg); break; case 'P': - if (request_blacklist != NULL) + if (request_denylist != NULL) fatal("Refused requests already set"); - request_blacklist = xstrdup(optarg); + request_denylist = xstrdup(optarg); break; case 'u': errno = 0; @@ -1702,9 +1742,9 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) max = out; if ((iqueue = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((oqueue = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); rset = xcalloc(howmany(max + 1, NFDBITS), sizeof(fd_mask)); wset = xcalloc(howmany(max + 1, NFDBITS), sizeof(fd_mask)); @@ -1731,8 +1771,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) 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)); + fatal_fr(r, "reserve"); olen = sshbuf_len(oqueue); if (olen > 0) @@ -1754,10 +1793,8 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) } else if (len == -1) { 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)); - } + } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) + fatal_fr(r, "sshbuf_put"); } /* send oqueue to stdout */ if (FD_ISSET(out, wset)) { @@ -1765,10 +1802,8 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) if (len == -1) { 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)); - } + } else if ((r = sshbuf_consume(oqueue, len)) != 0) + fatal_fr(r, "consume"); } /* @@ -1780,7 +1815,6 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) if (r == 0) process(); else if (r != SSH_ERR_NO_BUFFER_SPACE) - fatal("%s: sshbuf_check_reserve: %s", - __func__, ssh_err(r)); + fatal_fr(r, "reserve"); } } diff --git a/sftp.1 b/sftp.1 index a52c1cff3..a1a637302 100644 --- a/sftp.1 +++ b/sftp.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: sftp.1,v 1.127 2019/06/19 20:12:44 jmc Exp $ +.\" $OpenBSD: sftp.1,v 1.137 2021/02/12 03:49:09 djm Exp $ .\" .\" Copyright (c) 2001 Damien Miller. All rights reserved. .\" @@ -22,15 +22,15 @@ .\" (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: June 19 2019 $ +.Dd $Mdocdate: February 12 2021 $ .Dt SFTP 1 .Os .Sh NAME .Nm sftp -.Nd secure file transfer program +.Nd OpenSSH secure file transfer .Sh SYNOPSIS .Nm sftp -.Op Fl 46aCfpqrv +.Op Fl 46AaCfNpqrv .Op Fl B Ar buffer_size .Op Fl b Ar batchfile .Op Fl c Ar cipher @@ -104,6 +104,11 @@ to use IPv4 addresses only. Forces .Nm to use IPv6 addresses only. +.It Fl A +Allows forwarding of +.Xr ssh-agent 1 +to the remote system. +The default is not to forward an authentication agent. .It Fl a Attempt to continue interrupted transfers rather than overwriting existing partial or complete copies of files. @@ -197,6 +202,10 @@ This option is directly passed to .Xr ssh 1 . .It Fl l Ar limit Limits the used bandwidth, specified in Kbit/s. +.It Fl N +Disables quiet mode, e.g. to override the implicit quiet mode set by the +.Fl b +flag. .It Fl o Ar ssh_option Can be used to pass options to .Nm ssh @@ -237,8 +246,8 @@ For full details of the options listed below, and their possible values, see .It GSSAPIDelegateCredentials .It HashKnownHosts .It Host +.It HostbasedAcceptedAlgorithms .It HostbasedAuthentication -.It HostbasedKeyTypes .It HostKeyAlgorithms .It HostKeyAlias .It Hostname @@ -249,6 +258,7 @@ For full details of the options listed below, and their possible values, see .It KbdInteractiveAuthentication .It KbdInteractiveDevices .It KexAlgorithms +.It KnownHostsCommand .It LogLevel .It MACs .It NoHostAuthenticationForLocalhost @@ -259,7 +269,7 @@ For full details of the options listed below, and their possible values, see .It PreferredAuthentications .It ProxyCommand .It ProxyJump -.It PubkeyAcceptedKeyTypes +.It PubkeyAcceptedAlgorithms .It PubkeyAuthentication .It RekeyLimit .It SendEnv @@ -339,15 +349,18 @@ 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. +.Pp +If the +.Fl h +flag is specified, then symlinks will not be followed. +Note that this is only supported by servers that implement +the "lsetstat@openssh.com" extension. .It Xo Ic chmod .Op Fl h .Ar mode @@ -357,13 +370,16 @@ 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. +.Pp +If the +.Fl h +flag is specified, then symlinks will not be followed. +Note that this is only supported by servers that implement +the "lsetstat@openssh.com" extension. .It Xo Ic chown .Op Fl h .Ar own @@ -373,15 +389,18 @@ 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. +.Pp +If the +.Fl h +flag is specified, then symlinks will not be followed. +Note that this is only supported by servers that implement +the "lsetstat@openssh.com" extension. .It Xo Ic df .Op Fl hi .Op Ar path @@ -631,7 +650,7 @@ Equivalent to with the .Fl a flag set. -.It Ic rename Ar oldpath Ar newpath +.It Ic rename Ar oldpath newpath Rename remote file from .Ar oldpath to @@ -642,7 +661,7 @@ Delete remote file specified by .It Ic rmdir Ar path Remove remote directory specified by .Ar path . -.It Ic symlink Ar oldpath Ar newpath +.It Ic symlink Ar oldpath newpath Create a symbolic link from .Ar oldpath to diff --git a/sftp.c b/sftp.c index c1d36631d..b7b4bc4f0 100644 --- a/sftp.c +++ b/sftp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp.c,v 1.195 2019/10/02 00:42:30 djm Exp $ */ +/* $OpenBSD: sftp.c,v 1.206 2021/01/08 02:44:14 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -223,9 +223,12 @@ static const struct CMD cmds[] = { static void killchild(int signo) { - if (sshpid > 1) { - kill(sshpid, SIGTERM); - waitpid(sshpid, NULL, 0); + pid_t pid; + + pid = sshpid; + if (pid > 1) { + kill(pid, SIGTERM); + waitpid(pid, NULL, 0); } _exit(1); @@ -418,46 +421,6 @@ path_strip(const char *path, const char *strip) return (xstrdup(path)); } -static char * -make_absolute(char *p, const char *pwd) -{ - char *abs_str; - - /* Derelativise */ -#ifdef WINDOWS - /* - * For Windows - given path is absolute when - * - first character is "/" - * - or second character is ":" - * This code is also applicable from a Linux client to Windows target - * Need to follow up with community if this makes sense in common code - */ - char *s1, *s2; - if (!is_absolute_path(p)) { - abs_str = path_append(pwd, p); - free(p); - p = abs_str; - } - - /* Append "/" if needed to the absolute windows path */ - if (p && p[0] != '\0' && p[1] == ':') { - s1 = path_append("/", p); - free(p); - p = s1; - } - -#else /* !WINDOWS */ - if (p && !path_absolute(p)) { - abs_str = path_append(pwd, p); - free(p); - return(abs_str); - } else - return(p); -#endif /* !WINDOWS */ - return(p); - -} - static int parse_getput_flags(const char *cmd, char **argv, int argc, int *aflag, int *fflag, int *pflag, int *rflag) @@ -666,40 +629,6 @@ parse_no_flags(const char *cmd, char **argv, int argc) 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) @@ -729,7 +658,7 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst, * If multiple matches then dst must be a directory or * unspecified. */ - if (g.gl_matchc > 1 && dst != NULL && !is_dir(dst)) { + if (g.gl_matchc > 1 && dst != NULL && !local_is_dir(dst)) { error("Multiple source paths, but destination " "\"%s\" is not a directory", dst); err = -1; @@ -746,7 +675,7 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst, } if (g.gl_matchc == 1 && dst) { - if (is_dir(dst)) { + if (local_is_dir(dst)) { abs_dst = path_append(dst, filename); } else { abs_dst = xstrdup(dst); @@ -765,7 +694,7 @@ process_get(struct sftp_conn *conn, const char *src, const char *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 (globpath_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) @@ -858,7 +787,7 @@ process_put(struct sftp_conn *conn, const char *src, const char *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 (globpath_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) @@ -999,7 +928,10 @@ sglob_comp(const void *aa, const void *bb) 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, <)); + if (timespeccmp(&as->st_mtim, &bs->st_mtim, ==)) + return 0; + return timespeccmp(&as->st_mtim, &bs->st_mtim, <) ? + rmul : -rmul; #elif defined(HAVE_STRUCT_STAT_ST_MTIME) return (rmul * NCMP(as->st_mtime, bs->st_mtime)); #else @@ -1232,7 +1164,7 @@ undo_glob_escape(char *s) * 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 MAXARGS 128 #define MAXARGLEN 8192 static char ** makeargv(const char *arg, int *argcp, int sloppy, char *lastquote, @@ -1390,7 +1322,7 @@ parse_args(const char **cpp, int *ignore_errors, int *disable_echo, int *aflag, const char *cmd, *cp = *cpp; char *cp2, **argv; int base = 0; - long l; + long long ll; int path1_mandatory = 0, i, cmdnum, optidx, argc; /* Skip leading whitespace */ @@ -1548,16 +1480,16 @@ parse_args(const char **cpp, int *ignore_errors, int *disable_echo, int *aflag, if (argc - optidx < 1) goto need_num_arg; errno = 0; - l = strtol(argv[optidx], &cp2, base); + ll = strtoll(argv[optidx], &cp2, base); if (cp2 == argv[optidx] || *cp2 != '\0' || - ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) || - l < 0) { + ((ll == LLONG_MIN || ll == LLONG_MAX) && errno == ERANGE) || + ll < 0 || ll > UINT32_MAX) { need_num_arg: error("You must supply a numeric argument " "to the %s command.", cmd); return -1; } - *n_arg = l; + *n_arg = ll; if (cmdnum == I_LUMASK) break; /* Get pathname (mandatory) */ @@ -2168,7 +2100,7 @@ complete(EditLine *el, int ch) lf = el_line(el); if (el_get(el, EL_CLIENTDATA, (void**)&complete_ctx) != 0) - fatal("%s: el_get failed", __func__); + fatal_f("el_get failed"); /* Figure out which argument the cursor points to */ cursor = lf->cursor - lf->buffer; @@ -2310,7 +2242,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) interactive = !batchmode && isatty(STDIN_FILENO); err = 0; for (;;) { - signal(SIGINT, SIG_IGN); + ssh_signal(SIGINT, SIG_IGN); if (el == NULL) { if (interactive) @@ -2342,14 +2274,14 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) /* Handle user interrupts gracefully during commands */ interrupted = 0; - signal(SIGINT, cmd_interrupt); + ssh_signal(SIGINT, cmd_interrupt); err = parse_dispatch_command(conn, cmd, &remote_path, startdir, batchmode, !interactive && el == NULL); if (err != 0) break; } - signal(SIGCHLD, SIG_DFL); + ssh_signal(SIGCHLD, SIG_DFL); free(remote_path); free(startdir); free(conn); @@ -2428,20 +2360,20 @@ connect_to_server(char *path, char **args, int *in, int *out) * 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); + ssh_signal(SIGINT, SIG_IGN); + ssh_signal(SIGTERM, SIG_DFL); execvp(path, args); fprintf(stderr, "exec: %s: %s\n", path, strerror(errno)); _exit(1); } -#endif - signal(SIGTERM, killchild); - signal(SIGINT, killchild); - signal(SIGHUP, killchild); - signal(SIGTSTP, suspchild); - signal(SIGTTIN, suspchild); - signal(SIGTTOU, suspchild); - signal(SIGCHLD, sigchld_handler); + + ssh_signal(SIGTERM, killchild); + ssh_signal(SIGINT, killchild); + ssh_signal(SIGHUP, killchild); + ssh_signal(SIGTSTP, suspchild); + ssh_signal(SIGTTIN, suspchild); + ssh_signal(SIGTTOU, suspchild); + ssh_signal(SIGCHLD, sigchld_handler); close(c_in); close(c_out); } @@ -2452,7 +2384,7 @@ usage(void) extern char *__progname; fprintf(stderr, - "usage: %s [-46aCfpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n" + "usage: %s [-46AaCfNpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\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" @@ -2464,9 +2396,9 @@ usage(void) int main(int argc, char **argv) { - int in, out, ch, err, tmp, port = -1; + int in, out, ch, err, tmp, port = -1, noisy = 0; char *host = NULL, *user, *cp, *file2 = NULL; - int debug_level = 0, sshver = 2; + int debug_level = 0; char *file1 = NULL, *sftp_server = NULL; char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; const char *errstr; @@ -2490,7 +2422,6 @@ main(int argc, char **argv) args.list = NULL; addargs(&args, "%s", ssh_program); addargs(&args, "-oForwardX11 no"); - addargs(&args, "-oForwardAgent no"); addargs(&args, "-oPermitLocalCommand no"); addargs(&args, "-oClearAllForwardings yes"); @@ -2498,9 +2429,10 @@ main(int argc, char **argv) infile = stdin; while ((ch = getopt(argc, argv, - "1246afhpqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:")) != -1) { + "1246AafhNpqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:")) != -1) { switch (ch) { /* Passed through to ssh(1) */ + case 'A': case '4': case '6': case 'C': @@ -2534,12 +2466,10 @@ main(int argc, char **argv) debug_level++; break; case '1': - sshver = 1; - if (sftp_server == NULL) - sftp_server = _PATH_SFTP_SERVER; + fatal("SSH protocol v.1 is no longer supported"); break; case '2': - sshver = 2; + /* accept silently */ break; case 'a': global_aflag = 1; @@ -2564,6 +2494,9 @@ main(int argc, char **argv) case 'f': global_fflag = 1; break; + case 'N': + noisy = 1; /* Used to clear quiet mode after getopt */ + break; case 'p': global_pflag = 1; break; @@ -2599,9 +2532,15 @@ main(int argc, char **argv) } } + /* Do this last because we want the user to be able to override it */ + addargs(&args, "-oForwardAgent no"); + if (!isatty(STDERR_FILENO)) showprogress = 0; + if (noisy) + quiet = 0; + log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1); if (sftp_direct == NULL) { @@ -2649,7 +2588,6 @@ main(int argc, char **argv) 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) diff --git a/sk-api.h b/sk-api.h new file mode 100644 index 000000000..74921d4c3 --- /dev/null +++ b/sk-api.h @@ -0,0 +1,98 @@ +/* $OpenBSD: sk-api.h,v 1.12 2021/02/18 02:15:07 djm Exp $ */ +/* + * Copyright (c) 2019 Google LLC + * + * 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 _SK_API_H +#define _SK_API_H 1 + +#include +#ifdef HAVE_STDINT_H +#include +#endif + +/* Flags */ +#define SSH_SK_USER_PRESENCE_REQD 0x01 +#define SSH_SK_USER_VERIFICATION_REQD 0x04 +#define SSH_SK_RESIDENT_KEY 0x20 + +/* Algs */ +#define SSH_SK_ECDSA 0x00 +#define SSH_SK_ED25519 0x01 + +/* Error codes */ +#define SSH_SK_ERR_GENERAL -1 +#define SSH_SK_ERR_UNSUPPORTED -2 +#define SSH_SK_ERR_PIN_REQUIRED -3 +#define SSH_SK_ERR_DEVICE_NOT_FOUND -4 + +struct sk_enroll_response { + uint8_t *public_key; + size_t public_key_len; + uint8_t *key_handle; + size_t key_handle_len; + uint8_t *signature; + size_t signature_len; + uint8_t *attestation_cert; + size_t attestation_cert_len; + uint8_t *authdata; + size_t authdata_len; +}; + +struct sk_sign_response { + uint8_t flags; + uint32_t counter; + uint8_t *sig_r; + size_t sig_r_len; + uint8_t *sig_s; + size_t sig_s_len; +}; + +struct sk_resident_key { + uint32_t alg; + size_t slot; + char *application; + struct sk_enroll_response key; + uint8_t flags; +}; + +struct sk_option { + char *name; + char *value; + uint8_t required; +}; + +#define SSH_SK_VERSION_MAJOR 0x00070000 /* current API version */ +#define SSH_SK_VERSION_MAJOR_MASK 0xffff0000 + +/* Return the version of the middleware API */ +uint32_t sk_api_version(void); + +/* Enroll a U2F key (private key generation) */ +int sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, + const char *application, uint8_t flags, const char *pin, + struct sk_option **options, struct sk_enroll_response **enroll_response); + +/* Sign a challenge */ +int sk_sign(uint32_t alg, const uint8_t *data, size_t data_len, + const char *application, const uint8_t *key_handle, size_t key_handle_len, + uint8_t flags, const char *pin, struct sk_option **options, + struct sk_sign_response **sign_response); + +/* Enumerate all resident keys */ +int sk_load_resident_keys(const char *pin, struct sk_option **options, + struct sk_resident_key ***rks, size_t *nrks); + +#endif /* _SK_API_H */ diff --git a/sk-usbhid.c b/sk-usbhid.c new file mode 100644 index 000000000..c85b9857d --- /dev/null +++ b/sk-usbhid.c @@ -0,0 +1,1262 @@ +/* $OpenBSD: sk-usbhid.c,v 1.29 2021/02/18 02:15:07 djm Exp $ */ +/* + * Copyright (c) 2019 Markus Friedl + * Copyright (c) 2020 Pedro Martelletto + * + * 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_SK_INTERNAL + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SHA2_H +#include +#endif + +#ifdef WITH_OPENSSL +#include +#include +#include +#include +#include +#include +#endif /* WITH_OPENSSL */ + +#include +#include + +/* backwards compat for libfido2 */ +#ifndef HAVE_FIDO_CRED_PROT +#define fido_cred_prot(x) (0) +#endif +#ifndef HAVE_FIDO_CRED_SET_PROT +#define fido_cred_set_prot(x, y) (FIDO_ERR_UNSUPPORTED_OPTION) +#endif +#ifndef HAVE_FIDO_DEV_SUPPORTS_CRED_PROT +#define fido_dev_supports_cred_prot(x) (0) +#endif +#ifndef HAVE_FIDO_DEV_GET_TOUCH_BEGIN +#define fido_dev_get_touch_begin(x) (FIDO_ERR_UNSUPPORTED_OPTION) +#endif +#ifndef HAVE_FIDO_DEV_GET_TOUCH_STATUS +#define fido_dev_get_touch_status(x, y, z) (FIDO_ERR_UNSUPPORTED_OPTION) +#endif +#ifndef FIDO_CRED_PROT_UV_REQUIRED +#define FIDO_CRED_PROT_UV_REQUIRED 0 +#endif +#ifndef FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID +#define FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID 0 +#endif + +#ifndef SK_STANDALONE +# include "log.h" +# include "xmalloc.h" +# include "misc.h" +/* + * If building as part of OpenSSH, then rename exported functions. + * This must be done before including sk-api.h. + */ +# define sk_api_version ssh_sk_api_version +# define sk_enroll ssh_sk_enroll +# define sk_sign ssh_sk_sign +# define sk_load_resident_keys ssh_sk_load_resident_keys +#endif /* !SK_STANDALONE */ + +#include "sk-api.h" + +/* #define SK_DEBUG 1 */ + +#ifdef SK_DEBUG +#define SSH_FIDO_INIT_ARG FIDO_DEBUG +#else +#define SSH_FIDO_INIT_ARG 0 +#endif + +#define MAX_FIDO_DEVICES 8 +#define FIDO_POLL_MS 50 +#define SELECT_MS 15000 +#define POLL_SLEEP_NS 200000000 + +/* Compatibility with OpenSSH 1.0.x */ +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) +#define ECDSA_SIG_get0(sig, pr, ps) \ + do { \ + (*pr) = sig->r; \ + (*ps) = sig->s; \ + } while (0) +#endif + +struct sk_usbhid { + fido_dev_t *dev; + char *path; +}; + +/* Return the version of the middleware API */ +uint32_t sk_api_version(void); + +/* Enroll a U2F key (private key generation) */ +int sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, + const char *application, uint8_t flags, const char *pin, + struct sk_option **options, struct sk_enroll_response **enroll_response); + +/* Sign a challenge */ +int sk_sign(uint32_t alg, const uint8_t *data, size_t data_len, + const char *application, const uint8_t *key_handle, size_t key_handle_len, + uint8_t flags, const char *pin, struct sk_option **options, + struct sk_sign_response **sign_response); + +/* Load resident keys */ +int sk_load_resident_keys(const char *pin, struct sk_option **options, + struct sk_resident_key ***rks, size_t *nrks); + +static void skdebug(const char *func, const char *fmt, ...) + __attribute__((__format__ (printf, 2, 3))); + +static void +skdebug(const char *func, const char *fmt, ...) +{ +#if !defined(SK_STANDALONE) + char *msg; + va_list ap; + + va_start(ap, fmt); + xvasprintf(&msg, fmt, ap); + va_end(ap); + debug("%s: %s", func, msg); + free(msg); +#elif defined(SK_DEBUG) + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "%s: ", func); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); + va_end(ap); +#else + (void)func; /* XXX */ + (void)fmt; /* XXX */ +#endif +} + +uint32_t +sk_api_version(void) +{ + return SSH_SK_VERSION_MAJOR; +} + +static struct sk_usbhid * +sk_open(const char *path) +{ + struct sk_usbhid *sk; + int r; + + if (path == NULL) { + skdebug(__func__, "path == NULL"); + return NULL; + } + if ((sk = calloc(1, sizeof(*sk))) == NULL) { + skdebug(__func__, "calloc sk failed"); + return NULL; + } + if ((sk->path = strdup(path)) == NULL) { + skdebug(__func__, "strdup path failed"); + free(sk); + return NULL; + } + if ((sk->dev = fido_dev_new()) == NULL) { + skdebug(__func__, "fido_dev_new failed"); + free(sk->path); + free(sk); + return NULL; + } + if ((r = fido_dev_open(sk->dev, sk->path)) != FIDO_OK) { + skdebug(__func__, "fido_dev_open %s failed: %s", sk->path, + fido_strerr(r)); + fido_dev_free(&sk->dev); + free(sk->path); + free(sk); + return NULL; + } + return sk; +} + +static void +sk_close(struct sk_usbhid *sk) +{ + if (sk == NULL) + return; + fido_dev_cancel(sk->dev); /* cancel any pending operation */ + fido_dev_close(sk->dev); + fido_dev_free(&sk->dev); + free(sk->path); + free(sk); +} + +static struct sk_usbhid ** +sk_openv(const fido_dev_info_t *devlist, size_t ndevs, size_t *nopen) +{ + const fido_dev_info_t *di; + struct sk_usbhid **skv; + size_t i; + + *nopen = 0; + if ((skv = calloc(ndevs, sizeof(*skv))) == NULL) { + skdebug(__func__, "calloc skv failed"); + return NULL; + } + for (i = 0; i < ndevs; i++) { + if ((di = fido_dev_info_ptr(devlist, i)) == NULL) + skdebug(__func__, "fido_dev_info_ptr failed"); + else if ((skv[*nopen] = sk_open(fido_dev_info_path(di))) == NULL) + skdebug(__func__, "sk_open failed"); + else + (*nopen)++; + } + if (*nopen == 0) { + for (i = 0; i < ndevs; i++) + sk_close(skv[i]); + free(skv); + skv = NULL; + } + + return skv; +} + +static void +sk_closev(struct sk_usbhid **skv, size_t nsk) +{ + size_t i; + + for (i = 0; i < nsk; i++) + sk_close(skv[i]); + free(skv); +} + +static int +sk_touch_begin(struct sk_usbhid **skv, size_t nsk) +{ + size_t i, ok = 0; + int r; + + for (i = 0; i < nsk; i++) + if ((r = fido_dev_get_touch_begin(skv[i]->dev)) != FIDO_OK) + skdebug(__func__, "fido_dev_get_touch_begin %s failed:" + " %s", skv[i]->path, fido_strerr(r)); + else + ok++; + + return ok ? 0 : -1; +} + +static int +sk_touch_poll(struct sk_usbhid **skv, size_t nsk, int *touch, size_t *idx) +{ + struct timespec ts_pause; + size_t npoll, i; + int r; + + ts_pause.tv_sec = 0; + ts_pause.tv_nsec = POLL_SLEEP_NS; + nanosleep(&ts_pause, NULL); + npoll = nsk; + for (i = 0; i < nsk; i++) { + if (skv[i] == NULL) + continue; /* device discarded */ + skdebug(__func__, "polling %s", skv[i]->path); + if ((r = fido_dev_get_touch_status(skv[i]->dev, touch, + FIDO_POLL_MS)) != FIDO_OK) { + skdebug(__func__, "fido_dev_get_touch_status %s: %s", + skv[i]->path, fido_strerr(r)); + sk_close(skv[i]); /* discard device */ + skv[i] = NULL; + if (--npoll == 0) { + skdebug(__func__, "no device left to poll"); + return -1; + } + } else if (*touch) { + *idx = i; + return 0; + } + } + *touch = 0; + return 0; +} + +/* Calculate SHA256(m) */ +static int +sha256_mem(const void *m, size_t mlen, u_char *d, size_t dlen) +{ +#ifdef WITH_OPENSSL + u_int mdlen; +#endif + + if (dlen != 32) + return -1; +#ifdef WITH_OPENSSL + mdlen = dlen; + if (!EVP_Digest(m, mlen, d, &mdlen, EVP_sha256(), NULL)) + return -1; +#else + SHA256Data(m, mlen, d); +#endif + return 0; +} + +/* Check if the specified key handle exists on a given sk. */ +static int +sk_try(const struct sk_usbhid *sk, const char *application, + const uint8_t *key_handle, size_t key_handle_len) +{ + fido_assert_t *assert = NULL; + /* generate an invalid signature on FIDO2 tokens */ + const char *data = ""; + uint8_t message[32]; + int r = FIDO_ERR_INTERNAL; + + if (sha256_mem(data, strlen(data), message, sizeof(message)) != 0) { + skdebug(__func__, "hash message failed"); + goto out; + } + if ((assert = fido_assert_new()) == NULL) { + skdebug(__func__, "fido_assert_new failed"); + goto out; + } + if ((r = fido_assert_set_clientdata_hash(assert, message, + sizeof(message))) != FIDO_OK) { + skdebug(__func__, "fido_assert_set_clientdata_hash: %s", + fido_strerr(r)); + goto out; + } + if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) { + skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r)); + goto out; + } + if ((r = fido_assert_allow_cred(assert, key_handle, + key_handle_len)) != FIDO_OK) { + skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r)); + goto out; + } + if ((r = fido_assert_set_up(assert, FIDO_OPT_FALSE)) != FIDO_OK) { + skdebug(__func__, "fido_assert_up: %s", fido_strerr(r)); + goto out; + } + r = fido_dev_get_assert(sk->dev, assert, NULL); + skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); + if (r == FIDO_ERR_USER_PRESENCE_REQUIRED) { + /* U2F tokens may return this */ + r = FIDO_OK; + } + out: + fido_assert_free(&assert); + + return r != FIDO_OK ? -1 : 0; +} + +static struct sk_usbhid * +sk_select_by_cred(const fido_dev_info_t *devlist, size_t ndevs, + const char *application, const uint8_t *key_handle, size_t key_handle_len) +{ + struct sk_usbhid **skv, *sk; + size_t skvcnt, i; + + if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) { + skdebug(__func__, "sk_openv failed"); + return NULL; + } + if (skvcnt == 1) { + sk = skv[0]; + skv[0] = NULL; + goto out; + } + sk = NULL; + for (i = 0; i < skvcnt; i++) { + if (sk_try(skv[i], application, key_handle, + key_handle_len) == 0) { + sk = skv[i]; + skv[i] = NULL; + skdebug(__func__, "found key in %s", sk->path); + break; + } + } + out: + sk_closev(skv, skvcnt); + return sk; +} + +static struct sk_usbhid * +sk_select_by_touch(const fido_dev_info_t *devlist, size_t ndevs) +{ + struct sk_usbhid **skv, *sk; + struct timeval tv_start, tv_now, tv_delta; + size_t skvcnt, idx; + int touch, ms_remain; + + if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) { + skdebug(__func__, "sk_openv failed"); + return NULL; + } + sk = NULL; + if (skvcnt < 2) { + if (skvcnt == 1) { + /* single candidate */ + sk = skv[0]; + skv[0] = NULL; + } + goto out; + } +#ifndef HAVE_FIDO_DEV_GET_TOUCH_STATUS + skdebug(__func__, "libfido2 version does not support a feature needed for multiple tokens. Please upgrade to >=1.5.0"); + goto out; +#endif + + if (sk_touch_begin(skv, skvcnt) == -1) { + skdebug(__func__, "sk_touch_begin failed"); + goto out; + } + monotime_tv(&tv_start); + do { + if (sk_touch_poll(skv, skvcnt, &touch, &idx) == -1) { + skdebug(__func__, "sk_touch_poll failed"); + goto out; + } + if (touch) { + sk = skv[idx]; + skv[idx] = NULL; + goto out; + } + monotime_tv(&tv_now); + timersub(&tv_now, &tv_start, &tv_delta); + ms_remain = SELECT_MS - tv_delta.tv_sec * 1000 - + tv_delta.tv_usec / 1000; + } while (ms_remain >= FIDO_POLL_MS); + skdebug(__func__, "timeout"); +out: + sk_closev(skv, skvcnt); + return sk; +} + +static struct sk_usbhid * +sk_probe(const char *application, const uint8_t *key_handle, + size_t key_handle_len) +{ + struct sk_usbhid *sk; + fido_dev_info_t *devlist; + size_t ndevs; + int r; + + if ((devlist = fido_dev_info_new(MAX_FIDO_DEVICES)) == NULL) { + skdebug(__func__, "fido_dev_info_new failed"); + return NULL; + } + if ((r = fido_dev_info_manifest(devlist, MAX_FIDO_DEVICES, + &ndevs)) != FIDO_OK) { + skdebug(__func__, "fido_dev_info_manifest failed: %s", + fido_strerr(r)); + fido_dev_info_free(&devlist, MAX_FIDO_DEVICES); + return NULL; + } + skdebug(__func__, "%zu device(s) detected", ndevs); + if (ndevs == 0) { + sk = NULL; + } else if (application != NULL && key_handle != NULL) { + skdebug(__func__, "selecting sk by cred"); + sk = sk_select_by_cred(devlist, ndevs, application, key_handle, + key_handle_len); + } else { + skdebug(__func__, "selecting sk by touch"); + sk = sk_select_by_touch(devlist, ndevs); + } + fido_dev_info_free(&devlist, MAX_FIDO_DEVICES); + return sk; +} + +#ifdef WITH_OPENSSL +/* + * The key returned via fido_cred_pubkey_ptr() is in affine coordinates, + * but the API expects a SEC1 octet string. + */ +static int +pack_public_key_ecdsa(const fido_cred_t *cred, + struct sk_enroll_response *response) +{ + const uint8_t *ptr; + BIGNUM *x = NULL, *y = NULL; + EC_POINT *q = NULL; + EC_GROUP *g = NULL; + int ret = -1; + + response->public_key = NULL; + response->public_key_len = 0; + + if ((x = BN_new()) == NULL || + (y = BN_new()) == NULL || + (g = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL || + (q = EC_POINT_new(g)) == NULL) { + skdebug(__func__, "libcrypto setup failed"); + goto out; + } + if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) { + skdebug(__func__, "fido_cred_pubkey_ptr failed"); + goto out; + } + if (fido_cred_pubkey_len(cred) != 64) { + skdebug(__func__, "bad fido_cred_pubkey_len %zu", + fido_cred_pubkey_len(cred)); + goto out; + } + + if (BN_bin2bn(ptr, 32, x) == NULL || + BN_bin2bn(ptr + 32, 32, y) == NULL) { + skdebug(__func__, "BN_bin2bn failed"); + goto out; + } + if (EC_POINT_set_affine_coordinates_GFp(g, q, x, y, NULL) != 1) { + skdebug(__func__, "EC_POINT_set_affine_coordinates_GFp failed"); + goto out; + } + response->public_key_len = EC_POINT_point2oct(g, q, + POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); + if (response->public_key_len == 0 || response->public_key_len > 2048) { + skdebug(__func__, "bad pubkey length %zu", + response->public_key_len); + goto out; + } + if ((response->public_key = malloc(response->public_key_len)) == NULL) { + skdebug(__func__, "malloc pubkey failed"); + goto out; + } + if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED, + response->public_key, response->public_key_len, NULL) == 0) { + skdebug(__func__, "EC_POINT_point2oct failed"); + goto out; + } + /* success */ + ret = 0; + out: + if (ret != 0 && response->public_key != NULL) { + memset(response->public_key, 0, response->public_key_len); + free(response->public_key); + response->public_key = NULL; + } + EC_POINT_free(q); + EC_GROUP_free(g); + BN_clear_free(x); + BN_clear_free(y); + return ret; +} +#endif /* WITH_OPENSSL */ + +static int +pack_public_key_ed25519(const fido_cred_t *cred, + struct sk_enroll_response *response) +{ + const uint8_t *ptr; + size_t len; + int ret = -1; + + response->public_key = NULL; + response->public_key_len = 0; + + if ((len = fido_cred_pubkey_len(cred)) != 32) { + skdebug(__func__, "bad fido_cred_pubkey_len len %zu", len); + goto out; + } + if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) { + skdebug(__func__, "fido_cred_pubkey_ptr failed"); + goto out; + } + response->public_key_len = len; + if ((response->public_key = malloc(response->public_key_len)) == NULL) { + skdebug(__func__, "malloc pubkey failed"); + goto out; + } + memcpy(response->public_key, ptr, len); + ret = 0; + out: + if (ret != 0) + free(response->public_key); + return ret; +} + +static int +pack_public_key(uint32_t alg, const fido_cred_t *cred, + struct sk_enroll_response *response) +{ + switch(alg) { +#ifdef WITH_OPENSSL + case SSH_SK_ECDSA: + return pack_public_key_ecdsa(cred, response); +#endif /* WITH_OPENSSL */ + case SSH_SK_ED25519: + return pack_public_key_ed25519(cred, response); + default: + return -1; + } +} + +static int +fidoerr_to_skerr(int fidoerr) +{ + switch (fidoerr) { + case FIDO_ERR_UNSUPPORTED_OPTION: + case FIDO_ERR_UNSUPPORTED_ALGORITHM: + return SSH_SK_ERR_UNSUPPORTED; + case FIDO_ERR_PIN_REQUIRED: + case FIDO_ERR_PIN_INVALID: + return SSH_SK_ERR_PIN_REQUIRED; + default: + return -1; + } +} + +static int +check_enroll_options(struct sk_option **options, char **devicep, + uint8_t *user_id, size_t user_id_len) +{ + size_t i; + + if (options == NULL) + return 0; + for (i = 0; options[i] != NULL; i++) { + if (strcmp(options[i]->name, "device") == 0) { + if ((*devicep = strdup(options[i]->value)) == NULL) { + skdebug(__func__, "strdup device failed"); + return -1; + } + skdebug(__func__, "requested device %s", *devicep); + } else if (strcmp(options[i]->name, "user") == 0) { + if (strlcpy(user_id, options[i]->value, user_id_len) >= + user_id_len) { + skdebug(__func__, "user too long"); + return -1; + } + skdebug(__func__, "requested user %s", + (char *)user_id); + } else { + skdebug(__func__, "requested unsupported option %s", + options[i]->name); + if (options[i]->required) { + skdebug(__func__, "unknown required option"); + return -1; + } + } + } + return 0; +} + +int +sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, + const char *application, uint8_t flags, const char *pin, + struct sk_option **options, struct sk_enroll_response **enroll_response) +{ + fido_cred_t *cred = NULL; + const uint8_t *ptr; + uint8_t user_id[32]; + struct sk_usbhid *sk = NULL; + struct sk_enroll_response *response = NULL; + size_t len; + int credprot; + int cose_alg; + int ret = SSH_SK_ERR_GENERAL; + int r; + char *device = NULL; + + fido_init(SSH_FIDO_INIT_ARG); + + if (enroll_response == NULL) { + skdebug(__func__, "enroll_response == NULL"); + goto out; + } + *enroll_response = NULL; + memset(user_id, 0, sizeof(user_id)); + if (check_enroll_options(options, &device, user_id, + sizeof(user_id)) != 0) + goto out; /* error already logged */ + + switch(alg) { +#ifdef WITH_OPENSSL + case SSH_SK_ECDSA: + cose_alg = COSE_ES256; + break; +#endif /* WITH_OPENSSL */ + case SSH_SK_ED25519: + cose_alg = COSE_EDDSA; + break; + default: + skdebug(__func__, "unsupported key type %d", alg); + goto out; + } + if (device != NULL) + sk = sk_open(device); + else + sk = sk_probe(NULL, NULL, 0); + if (sk == NULL) { + skdebug(__func__, "failed to find sk"); + goto out; + } + skdebug(__func__, "using device %s", sk->path); + if ((cred = fido_cred_new()) == NULL) { + skdebug(__func__, "fido_cred_new failed"); + goto out; + } + if ((r = fido_cred_set_type(cred, cose_alg)) != FIDO_OK) { + skdebug(__func__, "fido_cred_set_type: %s", fido_strerr(r)); + goto out; + } + if ((r = fido_cred_set_clientdata_hash(cred, challenge, + challenge_len)) != FIDO_OK) { + skdebug(__func__, "fido_cred_set_clientdata_hash: %s", + fido_strerr(r)); + goto out; + } + if ((r = fido_cred_set_rk(cred, (flags & SSH_SK_RESIDENT_KEY) != 0 ? + FIDO_OPT_TRUE : FIDO_OPT_OMIT)) != FIDO_OK) { + skdebug(__func__, "fido_cred_set_rk: %s", fido_strerr(r)); + goto out; + } + if ((r = fido_cred_set_user(cred, user_id, sizeof(user_id), + "openssh", "openssh", NULL)) != FIDO_OK) { + skdebug(__func__, "fido_cred_set_user: %s", fido_strerr(r)); + goto out; + } + if ((r = fido_cred_set_rp(cred, application, NULL)) != FIDO_OK) { + skdebug(__func__, "fido_cred_set_rp: %s", fido_strerr(r)); + goto out; + } + if ((flags & (SSH_SK_RESIDENT_KEY|SSH_SK_USER_VERIFICATION_REQD)) != 0) { +#if !defined(HAVE_FIDO_DEV_SUPPORTS_CRED_PROT) || \ + !defined(HAVE_FIDO_CRED_SET_PROT) + skdebug(__func__, "libfido2 version does not support a feature required for this operation. Please upgrade to >=1.5.0"); + ret = SSH_SK_ERR_UNSUPPORTED; + goto out; + credprot = 0; (void)credprot; /* avoid warning */ +#endif + if (!fido_dev_supports_cred_prot(sk->dev)) { + skdebug(__func__, "%s does not support credprot, " + "refusing to create unprotected " + "resident/verify-required key", sk->path); + ret = SSH_SK_ERR_UNSUPPORTED; + goto out; + } + if ((flags & SSH_SK_USER_VERIFICATION_REQD)) + credprot = FIDO_CRED_PROT_UV_REQUIRED; + else + credprot = FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID; + + if ((r = fido_cred_set_prot(cred, credprot)) != FIDO_OK) { + skdebug(__func__, "fido_cred_set_prot: %s", + fido_strerr(r)); + ret = fidoerr_to_skerr(r); + goto out; + } + } + if ((r = fido_dev_make_cred(sk->dev, cred, pin)) != FIDO_OK) { + skdebug(__func__, "fido_dev_make_cred: %s", fido_strerr(r)); + ret = fidoerr_to_skerr(r); + goto out; + } + if (fido_cred_x5c_ptr(cred) != NULL) { + if ((r = fido_cred_verify(cred)) != FIDO_OK) { + skdebug(__func__, "fido_cred_verify: %s", + fido_strerr(r)); + goto out; + } + } else { + skdebug(__func__, "self-attested credential"); + if ((r = fido_cred_verify_self(cred)) != FIDO_OK) { + skdebug(__func__, "fido_cred_verify_self: %s", + fido_strerr(r)); + goto out; + } + } + if ((response = calloc(1, sizeof(*response))) == NULL) { + skdebug(__func__, "calloc response failed"); + goto out; + } + if (pack_public_key(alg, cred, response) != 0) { + skdebug(__func__, "pack_public_key failed"); + goto out; + } + if ((ptr = fido_cred_id_ptr(cred)) != NULL) { + len = fido_cred_id_len(cred); + if ((response->key_handle = calloc(1, len)) == NULL) { + skdebug(__func__, "calloc key handle failed"); + goto out; + } + memcpy(response->key_handle, ptr, len); + response->key_handle_len = len; + } + if ((ptr = fido_cred_sig_ptr(cred)) != NULL) { + len = fido_cred_sig_len(cred); + if ((response->signature = calloc(1, len)) == NULL) { + skdebug(__func__, "calloc signature failed"); + goto out; + } + memcpy(response->signature, ptr, len); + response->signature_len = len; + } + if ((ptr = fido_cred_x5c_ptr(cred)) != NULL) { + len = fido_cred_x5c_len(cred); + skdebug(__func__, "attestation cert len=%zu", len); + if ((response->attestation_cert = calloc(1, len)) == NULL) { + skdebug(__func__, "calloc attestation cert failed"); + goto out; + } + memcpy(response->attestation_cert, ptr, len); + response->attestation_cert_len = len; + } + if ((ptr = fido_cred_authdata_ptr(cred)) != NULL) { + len = fido_cred_authdata_len(cred); + skdebug(__func__, "authdata len=%zu", len); + if ((response->authdata = calloc(1, len)) == NULL) { + skdebug(__func__, "calloc authdata failed"); + goto out; + } + memcpy(response->authdata, ptr, len); + response->authdata_len = len; + } + *enroll_response = response; + response = NULL; + ret = 0; + out: + free(device); + if (response != NULL) { + free(response->public_key); + free(response->key_handle); + free(response->signature); + free(response->attestation_cert); + free(response->authdata); + free(response); + } + sk_close(sk); + fido_cred_free(&cred); + return ret; +} + +#ifdef WITH_OPENSSL +static int +pack_sig_ecdsa(fido_assert_t *assert, struct sk_sign_response *response) +{ + ECDSA_SIG *sig = NULL; + const BIGNUM *sig_r, *sig_s; + const unsigned char *cp; + size_t sig_len; + int ret = -1; + + cp = fido_assert_sig_ptr(assert, 0); + sig_len = fido_assert_sig_len(assert, 0); + if ((sig = d2i_ECDSA_SIG(NULL, &cp, sig_len)) == NULL) { + skdebug(__func__, "d2i_ECDSA_SIG failed"); + goto out; + } + ECDSA_SIG_get0(sig, &sig_r, &sig_s); + response->sig_r_len = BN_num_bytes(sig_r); + response->sig_s_len = BN_num_bytes(sig_s); + if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL || + (response->sig_s = calloc(1, response->sig_s_len)) == NULL) { + skdebug(__func__, "calloc signature failed"); + goto out; + } + BN_bn2bin(sig_r, response->sig_r); + BN_bn2bin(sig_s, response->sig_s); + ret = 0; + out: + ECDSA_SIG_free(sig); + if (ret != 0) { + free(response->sig_r); + free(response->sig_s); + response->sig_r = NULL; + response->sig_s = NULL; + } + return ret; +} +#endif /* WITH_OPENSSL */ + +static int +pack_sig_ed25519(fido_assert_t *assert, struct sk_sign_response *response) +{ + const unsigned char *ptr; + size_t len; + int ret = -1; + + ptr = fido_assert_sig_ptr(assert, 0); + len = fido_assert_sig_len(assert, 0); + if (len != 64) { + skdebug(__func__, "bad length %zu", len); + goto out; + } + response->sig_r_len = len; + if ((response->sig_r = calloc(1, response->sig_r_len)) == NULL) { + skdebug(__func__, "calloc signature failed"); + goto out; + } + memcpy(response->sig_r, ptr, len); + ret = 0; + out: + if (ret != 0) { + free(response->sig_r); + response->sig_r = NULL; + } + return ret; +} + +static int +pack_sig(uint32_t alg, fido_assert_t *assert, + struct sk_sign_response *response) +{ + switch(alg) { +#ifdef WITH_OPENSSL + case SSH_SK_ECDSA: + return pack_sig_ecdsa(assert, response); +#endif /* WITH_OPENSSL */ + case SSH_SK_ED25519: + return pack_sig_ed25519(assert, response); + default: + return -1; + } +} + +/* Checks sk_options for sk_sign() and sk_load_resident_keys() */ +static int +check_sign_load_resident_options(struct sk_option **options, char **devicep) +{ + size_t i; + + if (options == NULL) + return 0; + for (i = 0; options[i] != NULL; i++) { + if (strcmp(options[i]->name, "device") == 0) { + if ((*devicep = strdup(options[i]->value)) == NULL) { + skdebug(__func__, "strdup device failed"); + return -1; + } + skdebug(__func__, "requested device %s", *devicep); + } else { + skdebug(__func__, "requested unsupported option %s", + options[i]->name); + if (options[i]->required) { + skdebug(__func__, "unknown required option"); + return -1; + } + } + } + return 0; +} + +int +sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, + const char *application, + const uint8_t *key_handle, size_t key_handle_len, + uint8_t flags, const char *pin, struct sk_option **options, + struct sk_sign_response **sign_response) +{ + fido_assert_t *assert = NULL; + char *device = NULL; + struct sk_usbhid *sk = NULL; + struct sk_sign_response *response = NULL; + uint8_t message[32]; + int ret = SSH_SK_ERR_GENERAL; + int r; + + fido_init(SSH_FIDO_INIT_ARG); + + if (sign_response == NULL) { + skdebug(__func__, "sign_response == NULL"); + goto out; + } + *sign_response = NULL; + if (check_sign_load_resident_options(options, &device) != 0) + goto out; /* error already logged */ + /* hash data to be signed before it goes to the security key */ + if ((r = sha256_mem(data, datalen, message, sizeof(message))) != 0) { + skdebug(__func__, "hash message failed"); + goto out; + } + if (device != NULL) + sk = sk_open(device); + else if (pin != NULL || (flags & SSH_SK_USER_VERIFICATION_REQD)) + sk = sk_probe(NULL, NULL, 0); + else + sk = sk_probe(application, key_handle, key_handle_len); + if (sk == NULL) { + skdebug(__func__, "failed to find sk"); + goto out; + } + if ((assert = fido_assert_new()) == NULL) { + skdebug(__func__, "fido_assert_new failed"); + goto out; + } + if ((r = fido_assert_set_clientdata_hash(assert, message, + sizeof(message))) != FIDO_OK) { + skdebug(__func__, "fido_assert_set_clientdata_hash: %s", + fido_strerr(r)); + goto out; + } + if ((r = fido_assert_set_rp(assert, application)) != FIDO_OK) { + skdebug(__func__, "fido_assert_set_rp: %s", fido_strerr(r)); + goto out; + } + if ((r = fido_assert_allow_cred(assert, key_handle, + key_handle_len)) != FIDO_OK) { + skdebug(__func__, "fido_assert_allow_cred: %s", fido_strerr(r)); + goto out; + } + if ((r = fido_assert_set_up(assert, + (flags & SSH_SK_USER_PRESENCE_REQD) ? + FIDO_OPT_TRUE : FIDO_OPT_FALSE)) != FIDO_OK) { + skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r)); + goto out; + } + if (pin == NULL && (flags & SSH_SK_USER_VERIFICATION_REQD) && + (r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK) { + skdebug(__func__, "fido_assert_set_uv: %s", fido_strerr(r)); + ret = FIDO_ERR_PIN_REQUIRED; + goto out; + } + if ((r = fido_dev_get_assert(sk->dev, assert, pin)) != FIDO_OK) { + skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r)); + ret = fidoerr_to_skerr(r); + goto out; + } + if ((response = calloc(1, sizeof(*response))) == NULL) { + skdebug(__func__, "calloc response failed"); + goto out; + } + response->flags = fido_assert_flags(assert, 0); + response->counter = fido_assert_sigcount(assert, 0); + if (pack_sig(alg, assert, response) != 0) { + skdebug(__func__, "pack_sig failed"); + goto out; + } + *sign_response = response; + response = NULL; + ret = 0; + out: + explicit_bzero(message, sizeof(message)); + free(device); + if (response != NULL) { + free(response->sig_r); + free(response->sig_s); + free(response); + } + sk_close(sk); + fido_assert_free(&assert); + return ret; +} + +static int +read_rks(struct sk_usbhid *sk, const char *pin, + struct sk_resident_key ***rksp, size_t *nrksp) +{ + int ret = SSH_SK_ERR_GENERAL, r = -1; + fido_credman_metadata_t *metadata = NULL; + fido_credman_rp_t *rp = NULL; + fido_credman_rk_t *rk = NULL; + size_t i, j, nrp, nrk; + const fido_cred_t *cred; + struct sk_resident_key *srk = NULL, **tmp; + + if (pin == NULL) { + skdebug(__func__, "no PIN specified"); + ret = SSH_SK_ERR_PIN_REQUIRED; + goto out; + } + if ((metadata = fido_credman_metadata_new()) == NULL) { + skdebug(__func__, "alloc failed"); + goto out; + } + + if ((r = fido_credman_get_dev_metadata(sk->dev, metadata, pin)) != 0) { + if (r == FIDO_ERR_INVALID_COMMAND) { + skdebug(__func__, "device %s does not support " + "resident keys", sk->path); + ret = 0; + goto out; + } + skdebug(__func__, "get metadata for %s failed: %s", + sk->path, fido_strerr(r)); + ret = fidoerr_to_skerr(r); + goto out; + } + skdebug(__func__, "existing %llu, remaining %llu", + (unsigned long long)fido_credman_rk_existing(metadata), + (unsigned long long)fido_credman_rk_remaining(metadata)); + if ((rp = fido_credman_rp_new()) == NULL) { + skdebug(__func__, "alloc rp failed"); + goto out; + } + if ((r = fido_credman_get_dev_rp(sk->dev, rp, pin)) != 0) { + skdebug(__func__, "get RPs for %s failed: %s", + sk->path, fido_strerr(r)); + goto out; + } + nrp = fido_credman_rp_count(rp); + skdebug(__func__, "Device %s has resident keys for %zu RPs", + sk->path, nrp); + + /* Iterate over RP IDs that have resident keys */ + for (i = 0; i < nrp; i++) { + skdebug(__func__, "rp %zu: name=\"%s\" id=\"%s\" hashlen=%zu", + i, fido_credman_rp_name(rp, i), fido_credman_rp_id(rp, i), + fido_credman_rp_id_hash_len(rp, i)); + + /* Skip non-SSH RP IDs */ + if (strncasecmp(fido_credman_rp_id(rp, i), "ssh:", 4) != 0) + continue; + + fido_credman_rk_free(&rk); + if ((rk = fido_credman_rk_new()) == NULL) { + skdebug(__func__, "alloc rk failed"); + goto out; + } + if ((r = fido_credman_get_dev_rk(sk->dev, + fido_credman_rp_id(rp, i), rk, pin)) != 0) { + skdebug(__func__, "get RKs for %s slot %zu failed: %s", + sk->path, i, fido_strerr(r)); + goto out; + } + nrk = fido_credman_rk_count(rk); + skdebug(__func__, "RP \"%s\" has %zu resident keys", + fido_credman_rp_id(rp, i), nrk); + + /* Iterate over resident keys for this RP ID */ + for (j = 0; j < nrk; j++) { + if ((cred = fido_credman_rk(rk, j)) == NULL) { + skdebug(__func__, "no RK in slot %zu", j); + continue; + } + skdebug(__func__, "Device %s RP \"%s\" slot %zu: " + "type %d flags 0x%02x prot 0x%02x", sk->path, + fido_credman_rp_id(rp, i), j, fido_cred_type(cred), + fido_cred_flags(cred), fido_cred_prot(cred)); + + /* build response entry */ + if ((srk = calloc(1, sizeof(*srk))) == NULL || + (srk->key.key_handle = calloc(1, + fido_cred_id_len(cred))) == NULL || + (srk->application = strdup(fido_credman_rp_id(rp, + i))) == NULL) { + skdebug(__func__, "alloc sk_resident_key"); + goto out; + } + + srk->key.key_handle_len = fido_cred_id_len(cred); + memcpy(srk->key.key_handle, fido_cred_id_ptr(cred), + srk->key.key_handle_len); + + switch (fido_cred_type(cred)) { + case COSE_ES256: + srk->alg = SSH_SK_ECDSA; + break; + case COSE_EDDSA: + srk->alg = SSH_SK_ED25519; + break; + default: + skdebug(__func__, "unsupported key type %d", + fido_cred_type(cred)); + goto out; /* XXX free rk and continue */ + } + + if (fido_cred_prot(cred) == FIDO_CRED_PROT_UV_REQUIRED) + srk->flags |= SSH_SK_USER_VERIFICATION_REQD; + + if ((r = pack_public_key(srk->alg, cred, + &srk->key)) != 0) { + skdebug(__func__, "pack public key failed"); + goto out; + } + /* append */ + if ((tmp = recallocarray(*rksp, *nrksp, (*nrksp) + 1, + sizeof(**rksp))) == NULL) { + skdebug(__func__, "alloc rksp"); + goto out; + } + *rksp = tmp; + (*rksp)[(*nrksp)++] = srk; + srk = NULL; + } + } + /* Success */ + ret = 0; + out: + if (srk != NULL) { + free(srk->application); + freezero(srk->key.public_key, srk->key.public_key_len); + freezero(srk->key.key_handle, srk->key.key_handle_len); + freezero(srk, sizeof(*srk)); + } + fido_credman_rp_free(&rp); + fido_credman_rk_free(&rk); + fido_credman_metadata_free(&metadata); + return ret; +} + +int +sk_load_resident_keys(const char *pin, struct sk_option **options, + struct sk_resident_key ***rksp, size_t *nrksp) +{ + int ret = SSH_SK_ERR_GENERAL, r = -1; + size_t i, nrks = 0; + struct sk_resident_key **rks = NULL; + struct sk_usbhid *sk = NULL; + char *device = NULL; + + *rksp = NULL; + *nrksp = 0; + + fido_init(SSH_FIDO_INIT_ARG); + + if (check_sign_load_resident_options(options, &device) != 0) + goto out; /* error already logged */ + if (device != NULL) + sk = sk_open(device); + else + sk = sk_probe(NULL, NULL, 0); + if (sk == NULL) { + skdebug(__func__, "failed to find sk"); + goto out; + } + skdebug(__func__, "trying %s", sk->path); + if ((r = read_rks(sk, pin, &rks, &nrks)) != 0) { + skdebug(__func__, "read_rks failed for %s", sk->path); + ret = r; + goto out; + } + /* success, unless we have no keys but a specific error */ + if (nrks > 0 || ret == SSH_SK_ERR_GENERAL) + ret = 0; + *rksp = rks; + *nrksp = nrks; + rks = NULL; + nrks = 0; + out: + sk_close(sk); + for (i = 0; i < nrks; i++) { + free(rks[i]->application); + freezero(rks[i]->key.public_key, rks[i]->key.public_key_len); + freezero(rks[i]->key.key_handle, rks[i]->key.key_handle_len); + freezero(rks[i], sizeof(*rks[i])); + } + free(rks); + return ret; +} + +#endif /* ENABLE_SK_INTERNAL */ diff --git a/sntrup4591761.c b/sntrup4591761.c deleted file mode 100644 index 61fe2483f..000000000 --- a/sntrup4591761.c +++ /dev/null @@ -1,1083 +0,0 @@ -/* $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 -#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

= 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

= 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 deleted file mode 100644 index e684c3329..000000000 --- a/sntrup4591761.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/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 ' -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/sntrup761.c b/sntrup761.c new file mode 100644 index 000000000..c63e600fb --- /dev/null +++ b/sntrup761.c @@ -0,0 +1,1273 @@ +/* $OpenBSD: sntrup761.c,v 1.5 2021/01/08 02:33:13 dtucker Exp $ */ + +/* + * Public Domain, Authors: + * - Daniel J. Bernstein + * - Chitchanok Chuengsatiansup + * - Tanja Lange + * - Christine van Vredendaal + */ + +#include "includes.h" + +#ifdef USE_SNTRUP761X25519 + +#include +#include "crypto_api.h" + +#define int8 crypto_int8 +#define uint8 crypto_uint8 +#define int16 crypto_int16 +#define uint16 crypto_uint16 +#define int32 crypto_int32 +#define uint32 crypto_uint32 +#define int64 crypto_int64 +#define uint64 crypto_uint64 + +/* from supercop-20201130/crypto_sort/int32/portable4/int32_minmax.inc */ +#define int32_MINMAX(a,b) \ +do { \ + int64_t ab = (int64_t)b ^ (int64_t)a; \ + int64_t c = (int64_t)b - (int64_t)a; \ + c ^= ab & (c ^ b); \ + c >>= 31; \ + c &= ab; \ + a ^= c; \ + b ^= c; \ +} while(0) + +/* from supercop-20201130/crypto_sort/int32/portable4/sort.c */ + + +static void crypto_sort_int32(void *array,long long n) +{ + long long top,p,q,r,i,j; + int32 *x = array; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p >= 1;p >>= 1) { + i = 0; + while (i + 2 * p <= n) { + for (j = i;j < i + p;++j) + int32_MINMAX(x[j],x[j+p]); + i += 2 * p; + } + for (j = i;j < n - p;++j) + int32_MINMAX(x[j],x[j+p]); + + i = 0; + j = 0; + for (q = top;q > p;q >>= 1) { + if (j != i) for (;;) { + if (j == n - q) goto done; + int32 a = x[j + p]; + for (r = q;r > p;r >>= 1) + int32_MINMAX(a,x[j + r]); + x[j + p] = a; + ++j; + if (j == i + p) { + i += 2 * p; + break; + } + } + while (i + p <= n - q) { + for (j = i;j < i + p;++j) { + int32 a = x[j + p]; + for (r = q;r > p;r >>= 1) + int32_MINMAX(a,x[j+r]); + x[j + p] = a; + } + i += 2 * p; + } + /* now i + p > n - q */ + j = i; + while (j < n - q) { + int32 a = x[j + p]; + for (r = q;r > p;r >>= 1) + int32_MINMAX(a,x[j+r]); + x[j + p] = a; + ++j; + } + + done: ; + } + } +} + +/* from supercop-20201130/crypto_sort/uint32/useint32/sort.c */ + +/* can save time by vectorizing xor loops */ +/* can save time by integrating xor loops with int32_sort */ + +static void crypto_sort_uint32(void *array,long long n) +{ + crypto_uint32 *x = array; + long long j; + for (j = 0;j < n;++j) x[j] ^= 0x80000000; + crypto_sort_int32(array,n); + for (j = 0;j < n;++j) x[j] ^= 0x80000000; +} + +/* from supercop-20201130/crypto_kem/sntrup761/ref/uint32.c */ + +/* +CPU division instruction typically takes time depending on x. +This software is designed to take time independent of x. +Time still varies depending on m; user must ensure that m is constant. +Time also varies on CPUs where multiplication is variable-time. +There could be more CPU issues. +There could also be compiler issues. +*/ + +static void uint32_divmod_uint14(uint32 *q,uint16 *r,uint32 x,uint16 m) +{ + uint32 v = 0x80000000; + uint32 qpart; + uint32 mask; + + v /= m; + + /* caller guarantees m > 0 */ + /* caller guarantees m < 16384 */ + /* vm <= 2^31 <= vm+m-1 */ + /* xvm <= 2^31 x <= xvm+x(m-1) */ + + *q = 0; + + qpart = (x*(uint64)v)>>31; + /* 2^31 qpart <= xv <= 2^31 qpart + 2^31-1 */ + /* 2^31 qpart m <= xvm <= 2^31 qpart m + (2^31-1)m */ + /* 2^31 qpart m <= 2^31 x <= 2^31 qpart m + (2^31-1)m + x(m-1) */ + /* 0 <= 2^31 newx <= (2^31-1)m + x(m-1) */ + /* 0 <= newx <= (1-1/2^31)m + x(m-1)/2^31 */ + /* 0 <= newx <= (1-1/2^31)(2^14-1) + (2^32-1)((2^14-1)-1)/2^31 */ + + x -= qpart*m; *q += qpart; + /* x <= 49146 */ + + qpart = (x*(uint64)v)>>31; + /* 0 <= newx <= (1-1/2^31)m + x(m-1)/2^31 */ + /* 0 <= newx <= m + 49146(2^14-1)/2^31 */ + /* 0 <= newx <= m + 0.4 */ + /* 0 <= newx <= m */ + + x -= qpart*m; *q += qpart; + /* x <= m */ + + x -= m; *q += 1; + mask = -(x>>31); + x += mask&(uint32)m; *q += mask; + /* x < m */ + + *r = x; +} + + +static uint16 uint32_mod_uint14(uint32 x,uint16 m) +{ + uint32 q; + uint16 r; + uint32_divmod_uint14(&q,&r,x,m); + return r; +} + +/* from supercop-20201130/crypto_kem/sntrup761/ref/int32.c */ + +static void int32_divmod_uint14(int32 *q,uint16 *r,int32 x,uint16 m) +{ + uint32 uq,uq2; + uint16 ur,ur2; + uint32 mask; + + uint32_divmod_uint14(&uq,&ur,0x80000000+(uint32)x,m); + uint32_divmod_uint14(&uq2,&ur2,0x80000000,m); + ur -= ur2; uq -= uq2; + mask = -(uint32)(ur>>15); + ur += mask&m; uq += mask; + *r = ur; *q = uq; +} + + +static uint16 int32_mod_uint14(int32 x,uint16 m) +{ + int32 q; + uint16 r; + int32_divmod_uint14(&q,&r,x,m); + return r; +} + +/* from supercop-20201130/crypto_kem/sntrup761/ref/paramsmenu.h */ +/* pick one of these three: */ +#define SIZE761 +#undef SIZE653 +#undef SIZE857 + +/* pick one of these two: */ +#define SNTRUP /* Streamlined NTRU Prime */ +#undef LPR /* NTRU LPRime */ + +/* from supercop-20201130/crypto_kem/sntrup761/ref/params.h */ +#ifndef params_H +#define params_H + +/* menu of parameter choices: */ + + +/* what the menu means: */ + +#if defined(SIZE761) +#define p 761 +#define q 4591 +#define Rounded_bytes 1007 +#ifndef LPR +#define Rq_bytes 1158 +#define w 286 +#else +#define w 250 +#define tau0 2156 +#define tau1 114 +#define tau2 2007 +#define tau3 287 +#endif + +#elif defined(SIZE653) +#define p 653 +#define q 4621 +#define Rounded_bytes 865 +#ifndef LPR +#define Rq_bytes 994 +#define w 288 +#else +#define w 252 +#define tau0 2175 +#define tau1 113 +#define tau2 2031 +#define tau3 290 +#endif + +#elif defined(SIZE857) +#define p 857 +#define q 5167 +#define Rounded_bytes 1152 +#ifndef LPR +#define Rq_bytes 1322 +#define w 322 +#else +#define w 281 +#define tau0 2433 +#define tau1 101 +#define tau2 2265 +#define tau3 324 +#endif + +#else +#error "no parameter set defined" +#endif + +#ifdef LPR +#define I 256 +#endif + +#endif + +/* from supercop-20201130/crypto_kem/sntrup761/ref/Decode.h */ +#ifndef Decode_H +#define Decode_H + + +/* Decode(R,s,M,len) */ +/* assumes 0 < M[i] < 16384 */ +/* produces 0 <= R[i] < M[i] */ + +#endif + +/* from supercop-20201130/crypto_kem/sntrup761/ref/Decode.c */ + +static void Decode(uint16 *out,const unsigned char *S,const uint16 *M,long long len) +{ + if (len == 1) { + if (M[0] == 1) + *out = 0; + else if (M[0] <= 256) + *out = uint32_mod_uint14(S[0],M[0]); + else + *out = uint32_mod_uint14(S[0]+(((uint16)S[1])<<8),M[0]); + } + if (len > 1) { + uint16 R2[(len+1)/2]; + uint16 M2[(len+1)/2]; + uint16 bottomr[len/2]; + uint32 bottomt[len/2]; + long long i; + for (i = 0;i < len-1;i += 2) { + uint32 m = M[i]*(uint32) M[i+1]; + if (m > 256*16383) { + bottomt[i/2] = 256*256; + bottomr[i/2] = S[0]+256*S[1]; + S += 2; + M2[i/2] = (((m+255)>>8)+255)>>8; + } else if (m >= 16384) { + bottomt[i/2] = 256; + bottomr[i/2] = S[0]; + S += 1; + M2[i/2] = (m+255)>>8; + } else { + bottomt[i/2] = 1; + bottomr[i/2] = 0; + M2[i/2] = m; + } + } + if (i < len) + M2[i/2] = M[i]; + Decode(R2,S,M2,(len+1)/2); + for (i = 0;i < len-1;i += 2) { + uint32 r = bottomr[i/2]; + uint32 r1; + uint16 r0; + r += bottomt[i/2]*R2[i/2]; + uint32_divmod_uint14(&r1,&r0,r,M[i]); + r1 = uint32_mod_uint14(r1,M[i+1]); /* only needed for invalid inputs */ + *out++ = r0; + *out++ = r1; + } + if (i < len) + *out++ = R2[i/2]; + } +} + +/* from supercop-20201130/crypto_kem/sntrup761/ref/Encode.h */ +#ifndef Encode_H +#define Encode_H + + +/* Encode(s,R,M,len) */ +/* assumes 0 <= R[i] < M[i] < 16384 */ + +#endif + +/* from supercop-20201130/crypto_kem/sntrup761/ref/Encode.c */ + +/* 0 <= R[i] < M[i] < 16384 */ +static void Encode(unsigned char *out,const uint16 *R,const uint16 *M,long long len) +{ + if (len == 1) { + uint16 r = R[0]; + uint16 m = M[0]; + while (m > 1) { + *out++ = r; + r >>= 8; + m = (m+255)>>8; + } + } + if (len > 1) { + uint16 R2[(len+1)/2]; + uint16 M2[(len+1)/2]; + long long i; + for (i = 0;i < len-1;i += 2) { + uint32 m0 = M[i]; + uint32 r = R[i]+R[i+1]*m0; + uint32 m = M[i+1]*m0; + while (m >= 16384) { + *out++ = r; + r >>= 8; + m = (m+255)>>8; + } + R2[i/2] = r; + M2[i/2] = m; + } + if (i < len) { + R2[i/2] = R[i]; + M2[i/2] = M[i]; + } + Encode(out,R2,M2,(len+1)/2); + } +} + +/* from supercop-20201130/crypto_kem/sntrup761/ref/kem.c */ + +#ifdef LPR +#endif + + +/* ----- masks */ + +#ifndef LPR + +/* return -1 if x!=0; else return 0 */ +static int int16_nonzero_mask(int16 x) +{ + uint16 u = x; /* 0, else 1...65535 */ + uint32 v = u; /* 0, else 1...65535 */ + v = -v; /* 0, else 2^32-65535...2^32-1 */ + v >>= 31; /* 0, else 1 */ + return -v; /* 0, else -1 */ +} + +#endif + +/* return -1 if x<0; otherwise return 0 */ +static int int16_negative_mask(int16 x) +{ + uint16 u = x; + u >>= 15; + return -(int) u; + /* alternative with gcc -fwrapv: */ + /* x>>15 compiles to CPU's arithmetic right shift */ +} + +/* ----- arithmetic mod 3 */ + +typedef int8 small; + +/* F3 is always represented as -1,0,1 */ +/* so ZZ_fromF3 is a no-op */ + +/* x must not be close to top int16 */ +static small F3_freeze(int16 x) +{ + return int32_mod_uint14(x+1,3)-1; +} + +/* ----- arithmetic mod q */ + +#define q12 ((q-1)/2) +typedef int16 Fq; +/* always represented as -q12...q12 */ +/* so ZZ_fromFq is a no-op */ + +/* x must not be close to top int32 */ +static Fq Fq_freeze(int32 x) +{ + return int32_mod_uint14(x+q12,q)-q12; +} + +#ifndef LPR + +static Fq Fq_recip(Fq a1) +{ + int i = 1; + Fq ai = a1; + + while (i < q-2) { + ai = Fq_freeze(a1*(int32)ai); + i += 1; + } + return ai; +} + +#endif + +/* ----- Top and Right */ + +#ifdef LPR +#define tau 16 + +static int8 Top(Fq C) +{ + return (tau1*(int32)(C+tau0)+16384)>>15; +} + +static Fq Right(int8 T) +{ + return Fq_freeze(tau3*(int32)T-tau2); +} +#endif + +/* ----- small polynomials */ + +#ifndef LPR + +/* 0 if Weightw_is(r), else -1 */ +static int Weightw_mask(small *r) +{ + int weight = 0; + int i; + + for (i = 0;i < p;++i) weight += r[i]&1; + return int16_nonzero_mask(weight-w); +} + +/* R3_fromR(R_fromRq(r)) */ +static void R3_fromRq(small *out,const Fq *r) +{ + int i; + for (i = 0;i < p;++i) out[i] = F3_freeze(r[i]); +} + +/* h = f*g in the ring R3 */ +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 = F3_freeze(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 = F3_freeze(result+f[j]*g[i-j]); + fg[i] = result; + } + + for (i = p+p-2;i >= p;--i) { + fg[i-p] = F3_freeze(fg[i-p]+fg[i]); + fg[i-p+1] = F3_freeze(fg[i-p+1]+fg[i]); + } + + for (i = 0;i < p;++i) h[i] = fg[i]; +} + +/* returns 0 if recip succeeded; else -1 */ +static int R3_recip(small *out,const small *in) +{ + small f[p+1],g[p+1],v[p+1],r[p+1]; + int i,loop,delta; + int sign,swap,t; + + for (i = 0;i < p+1;++i) v[i] = 0; + for (i = 0;i < p+1;++i) r[i] = 0; + r[0] = 1; + for (i = 0;i < p;++i) f[i] = 0; + f[0] = 1; f[p-1] = f[p] = -1; + for (i = 0;i < p;++i) g[p-1-i] = in[i]; + g[p] = 0; + + delta = 1; + + for (loop = 0;loop < 2*p-1;++loop) { + for (i = p;i > 0;--i) v[i] = v[i-1]; + v[0] = 0; + + sign = -g[0]*f[0]; + swap = int16_negative_mask(-delta) & int16_nonzero_mask(g[0]); + delta ^= swap&(delta^-delta); + delta += 1; + + for (i = 0;i < p+1;++i) { + t = swap&(f[i]^g[i]); f[i] ^= t; g[i] ^= t; + t = swap&(v[i]^r[i]); v[i] ^= t; r[i] ^= t; + } + + for (i = 0;i < p+1;++i) g[i] = F3_freeze(g[i]+sign*f[i]); + for (i = 0;i < p+1;++i) r[i] = F3_freeze(r[i]+sign*v[i]); + + for (i = 0;i < p;++i) g[i] = g[i+1]; + g[p] = 0; + } + + sign = f[0]; + for (i = 0;i < p;++i) out[i] = sign*v[p-1-i]; + + return int16_nonzero_mask(delta); +} + +#endif + +/* ----- polynomials mod q */ + +/* h = f*g in the ring Rq */ +static void Rq_mult_small(Fq *h,const Fq *f,const small *g) +{ + Fq fg[p+p-1]; + Fq result; + int i,j; + + for (i = 0;i < p;++i) { + result = 0; + for (j = 0;j <= i;++j) result = Fq_freeze(result+f[j]*(int32)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 = Fq_freeze(result+f[j]*(int32)g[i-j]); + fg[i] = result; + } + + for (i = p+p-2;i >= p;--i) { + fg[i-p] = Fq_freeze(fg[i-p]+fg[i]); + fg[i-p+1] = Fq_freeze(fg[i-p+1]+fg[i]); + } + + for (i = 0;i < p;++i) h[i] = fg[i]; +} + +#ifndef LPR + +/* h = 3f in Rq */ +static void Rq_mult3(Fq *h,const Fq *f) +{ + int i; + + for (i = 0;i < p;++i) h[i] = Fq_freeze(3*f[i]); +} + +/* out = 1/(3*in) in Rq */ +/* returns 0 if recip succeeded; else -1 */ +static int Rq_recip3(Fq *out,const small *in) +{ + Fq f[p+1],g[p+1],v[p+1],r[p+1]; + int i,loop,delta; + int swap,t; + int32 f0,g0; + Fq scale; + + for (i = 0;i < p+1;++i) v[i] = 0; + for (i = 0;i < p+1;++i) r[i] = 0; + r[0] = Fq_recip(3); + for (i = 0;i < p;++i) f[i] = 0; + f[0] = 1; f[p-1] = f[p] = -1; + for (i = 0;i < p;++i) g[p-1-i] = in[i]; + g[p] = 0; + + delta = 1; + + for (loop = 0;loop < 2*p-1;++loop) { + for (i = p;i > 0;--i) v[i] = v[i-1]; + v[0] = 0; + + swap = int16_negative_mask(-delta) & int16_nonzero_mask(g[0]); + delta ^= swap&(delta^-delta); + delta += 1; + + for (i = 0;i < p+1;++i) { + t = swap&(f[i]^g[i]); f[i] ^= t; g[i] ^= t; + t = swap&(v[i]^r[i]); v[i] ^= t; r[i] ^= t; + } + + f0 = f[0]; + g0 = g[0]; + for (i = 0;i < p+1;++i) g[i] = Fq_freeze(f0*g[i]-g0*f[i]); + for (i = 0;i < p+1;++i) r[i] = Fq_freeze(f0*r[i]-g0*v[i]); + + for (i = 0;i < p;++i) g[i] = g[i+1]; + g[p] = 0; + } + + scale = Fq_recip(f[0]); + for (i = 0;i < p;++i) out[i] = Fq_freeze(scale*(int32)v[p-1-i]); + + return int16_nonzero_mask(delta); +} + +#endif + +/* ----- rounded polynomials mod q */ + +static void Round(Fq *out,const Fq *a) +{ + int i; + for (i = 0;i < p;++i) out[i] = a[i]-F3_freeze(a[i]); +} + +/* ----- sorting to generate short polynomial */ + +static void Short_fromlist(small *out,const uint32 *in) +{ + uint32 L[p]; + int i; + + for (i = 0;i < w;++i) L[i] = in[i]&(uint32)-2; + for (i = w;i < p;++i) L[i] = (in[i]&(uint32)-3)|1; + crypto_sort_uint32(L,p); + for (i = 0;i < p;++i) out[i] = (L[i]&3)-1; +} + +/* ----- underlying hash function */ + +#define Hash_bytes 32 + +/* e.g., b = 0 means out = Hash0(in) */ +static void Hash_prefix(unsigned char *out,int b,const unsigned char *in,int inlen) +{ + unsigned char x[inlen+1]; + unsigned char h[64]; + int i; + + x[0] = b; + for (i = 0;i < inlen;++i) x[i+1] = in[i]; + crypto_hash_sha512(h,x,inlen+1); + for (i = 0;i < 32;++i) out[i] = h[i]; +} + +/* ----- higher-level randomness */ + +static uint32 urandom32(void) +{ + unsigned char c[4]; + uint32 out[4]; + + randombytes(c,4); + out[0] = (uint32)c[0]; + out[1] = ((uint32)c[1])<<8; + out[2] = ((uint32)c[2])<<16; + out[3] = ((uint32)c[3])<<24; + return out[0]+out[1]+out[2]+out[3]; +} + +static void Short_random(small *out) +{ + uint32 L[p]; + int i; + + for (i = 0;i < p;++i) L[i] = urandom32(); + Short_fromlist(out,L); +} + +#ifndef LPR + +static void Small_random(small *out) +{ + int i; + + for (i = 0;i < p;++i) out[i] = (((urandom32()&0x3fffffff)*3)>>30)-1; +} + +#endif + +/* ----- Streamlined NTRU Prime Core */ + +#ifndef LPR + +/* h,(f,ginv) = KeyGen() */ +static void KeyGen(Fq *h,small *f,small *ginv) +{ + small g[p]; + Fq finv[p]; + + for (;;) { + Small_random(g); + if (R3_recip(ginv,g) == 0) break; + } + Short_random(f); + Rq_recip3(finv,f); /* always works */ + Rq_mult_small(h,finv,g); +} + +/* c = Encrypt(r,h) */ +static void Encrypt(Fq *c,const small *r,const Fq *h) +{ + Fq hr[p]; + + Rq_mult_small(hr,h,r); + Round(c,hr); +} + +/* r = Decrypt(c,(f,ginv)) */ +static void Decrypt(small *r,const Fq *c,const small *f,const small *ginv) +{ + Fq cf[p]; + Fq cf3[p]; + small e[p]; + small ev[p]; + int mask; + int i; + + Rq_mult_small(cf,c,f); + Rq_mult3(cf3,cf); + R3_fromRq(e,cf3); + R3_mult(ev,e,ginv); + + mask = Weightw_mask(ev); /* 0 if weight w, else -1 */ + for (i = 0;i < w;++i) r[i] = ((ev[i]^1)&~mask)^1; + for (i = w;i < p;++i) r[i] = ev[i]&~mask; +} + +#endif + +/* ----- NTRU LPRime Core */ + +#ifdef LPR + +/* (G,A),a = KeyGen(G); leaves G unchanged */ +static void KeyGen(Fq *A,small *a,const Fq *G) +{ + Fq aG[p]; + + Short_random(a); + Rq_mult_small(aG,G,a); + Round(A,aG); +} + +/* B,T = Encrypt(r,(G,A),b) */ +static void Encrypt(Fq *B,int8 *T,const int8 *r,const Fq *G,const Fq *A,const small *b) +{ + Fq bG[p]; + Fq bA[p]; + int i; + + Rq_mult_small(bG,G,b); + Round(B,bG); + Rq_mult_small(bA,A,b); + for (i = 0;i < I;++i) T[i] = Top(Fq_freeze(bA[i]+r[i]*q12)); +} + +/* r = Decrypt((B,T),a) */ +static void Decrypt(int8 *r,const Fq *B,const int8 *T,const small *a) +{ + Fq aB[p]; + int i; + + Rq_mult_small(aB,B,a); + for (i = 0;i < I;++i) + r[i] = -int16_negative_mask(Fq_freeze(Right(T[i])-aB[i]+4*w+1)); +} + +#endif + +/* ----- encoding I-bit inputs */ + +#ifdef LPR + +#define Inputs_bytes (I/8) +typedef int8 Inputs[I]; /* passed by reference */ + +static void Inputs_encode(unsigned char *s,const Inputs r) +{ + int i; + for (i = 0;i < Inputs_bytes;++i) s[i] = 0; + for (i = 0;i < I;++i) s[i>>3] |= r[i]<<(i&7); +} + +#endif + +/* ----- Expand */ + +#ifdef LPR + +static const unsigned char aes_nonce[16] = {0}; + +static void Expand(uint32 *L,const unsigned char *k) +{ + int i; + crypto_stream_aes256ctr((unsigned char *) L,4*p,aes_nonce,k); + for (i = 0;i < p;++i) { + uint32 L0 = ((unsigned char *) L)[4*i]; + uint32 L1 = ((unsigned char *) L)[4*i+1]; + uint32 L2 = ((unsigned char *) L)[4*i+2]; + uint32 L3 = ((unsigned char *) L)[4*i+3]; + L[i] = L0+(L1<<8)+(L2<<16)+(L3<<24); + } +} + +#endif + +/* ----- Seeds */ + +#ifdef LPR + +#define Seeds_bytes 32 + +static void Seeds_random(unsigned char *s) +{ + randombytes(s,Seeds_bytes); +} + +#endif + +/* ----- Generator, HashShort */ + +#ifdef LPR + +/* G = Generator(k) */ +static void Generator(Fq *G,const unsigned char *k) +{ + uint32 L[p]; + int i; + + Expand(L,k); + for (i = 0;i < p;++i) G[i] = uint32_mod_uint14(L[i],q)-q12; +} + +/* out = HashShort(r) */ +static void HashShort(small *out,const Inputs r) +{ + unsigned char s[Inputs_bytes]; + unsigned char h[Hash_bytes]; + uint32 L[p]; + + Inputs_encode(s,r); + Hash_prefix(h,5,s,sizeof s); + Expand(L,h); + Short_fromlist(out,L); +} + +#endif + +/* ----- NTRU LPRime Expand */ + +#ifdef LPR + +/* (S,A),a = XKeyGen() */ +static void XKeyGen(unsigned char *S,Fq *A,small *a) +{ + Fq G[p]; + + Seeds_random(S); + Generator(G,S); + KeyGen(A,a,G); +} + +/* B,T = XEncrypt(r,(S,A)) */ +static void XEncrypt(Fq *B,int8 *T,const int8 *r,const unsigned char *S,const Fq *A) +{ + Fq G[p]; + small b[p]; + + Generator(G,S); + HashShort(b,r); + Encrypt(B,T,r,G,A,b); +} + +#define XDecrypt Decrypt + +#endif + +/* ----- encoding small polynomials (including short polynomials) */ + +#define Small_bytes ((p+3)/4) + +/* these are the only functions that rely on p mod 4 = 1 */ + +static void Small_encode(unsigned char *s,const small *f) +{ + small x; + int i; + + for (i = 0;i < p/4;++i) { + x = *f++ + 1; + x += (*f++ + 1)<<2; + x += (*f++ + 1)<<4; + x += (*f++ + 1)<<6; + *s++ = x; + } + x = *f++ + 1; + *s++ = x; +} + +static void Small_decode(small *f,const unsigned char *s) +{ + unsigned char x; + int i; + + for (i = 0;i < p/4;++i) { + x = *s++; + *f++ = ((small)(x&3))-1; x >>= 2; + *f++ = ((small)(x&3))-1; x >>= 2; + *f++ = ((small)(x&3))-1; x >>= 2; + *f++ = ((small)(x&3))-1; + } + x = *s++; + *f++ = ((small)(x&3))-1; +} + +/* ----- encoding general polynomials */ + +#ifndef LPR + +static void Rq_encode(unsigned char *s,const Fq *r) +{ + uint16 R[p],M[p]; + int i; + + for (i = 0;i < p;++i) R[i] = r[i]+q12; + for (i = 0;i < p;++i) M[i] = q; + Encode(s,R,M,p); +} + +static void Rq_decode(Fq *r,const unsigned char *s) +{ + uint16 R[p],M[p]; + int i; + + for (i = 0;i < p;++i) M[i] = q; + Decode(R,s,M,p); + for (i = 0;i < p;++i) r[i] = ((Fq)R[i])-q12; +} + +#endif + +/* ----- encoding rounded polynomials */ + +static void Rounded_encode(unsigned char *s,const Fq *r) +{ + uint16 R[p],M[p]; + int i; + + for (i = 0;i < p;++i) R[i] = ((r[i]+q12)*10923)>>15; + for (i = 0;i < p;++i) M[i] = (q+2)/3; + Encode(s,R,M,p); +} + +static void Rounded_decode(Fq *r,const unsigned char *s) +{ + uint16 R[p],M[p]; + int i; + + for (i = 0;i < p;++i) M[i] = (q+2)/3; + Decode(R,s,M,p); + for (i = 0;i < p;++i) r[i] = R[i]*3-q12; +} + +/* ----- encoding top polynomials */ + +#ifdef LPR + +#define Top_bytes (I/2) + +static void Top_encode(unsigned char *s,const int8 *T) +{ + int i; + for (i = 0;i < Top_bytes;++i) + s[i] = T[2*i]+(T[2*i+1]<<4); +} + +static void Top_decode(int8 *T,const unsigned char *s) +{ + int i; + for (i = 0;i < Top_bytes;++i) { + T[2*i] = s[i]&15; + T[2*i+1] = s[i]>>4; + } +} + +#endif + +/* ----- Streamlined NTRU Prime Core plus encoding */ + +#ifndef LPR + +typedef small Inputs[p]; /* passed by reference */ +#define Inputs_random Short_random +#define Inputs_encode Small_encode +#define Inputs_bytes Small_bytes + +#define Ciphertexts_bytes Rounded_bytes +#define SecretKeys_bytes (2*Small_bytes) +#define PublicKeys_bytes Rq_bytes + +/* pk,sk = ZKeyGen() */ +static void ZKeyGen(unsigned char *pk,unsigned char *sk) +{ + Fq h[p]; + small f[p],v[p]; + + KeyGen(h,f,v); + Rq_encode(pk,h); + Small_encode(sk,f); sk += Small_bytes; + Small_encode(sk,v); +} + +/* C = ZEncrypt(r,pk) */ +static void ZEncrypt(unsigned char *C,const Inputs r,const unsigned char *pk) +{ + Fq h[p]; + Fq c[p]; + Rq_decode(h,pk); + Encrypt(c,r,h); + Rounded_encode(C,c); +} + +/* r = ZDecrypt(C,sk) */ +static void ZDecrypt(Inputs r,const unsigned char *C,const unsigned char *sk) +{ + small f[p],v[p]; + Fq c[p]; + + Small_decode(f,sk); sk += Small_bytes; + Small_decode(v,sk); + Rounded_decode(c,C); + Decrypt(r,c,f,v); +} + +#endif + +/* ----- NTRU LPRime Expand plus encoding */ + +#ifdef LPR + +#define Ciphertexts_bytes (Rounded_bytes+Top_bytes) +#define SecretKeys_bytes Small_bytes +#define PublicKeys_bytes (Seeds_bytes+Rounded_bytes) + +static void Inputs_random(Inputs r) +{ + unsigned char s[Inputs_bytes]; + int i; + + randombytes(s,sizeof s); + for (i = 0;i < I;++i) r[i] = 1&(s[i>>3]>>(i&7)); +} + +/* pk,sk = ZKeyGen() */ +static void ZKeyGen(unsigned char *pk,unsigned char *sk) +{ + Fq A[p]; + small a[p]; + + XKeyGen(pk,A,a); pk += Seeds_bytes; + Rounded_encode(pk,A); + Small_encode(sk,a); +} + +/* c = ZEncrypt(r,pk) */ +static void ZEncrypt(unsigned char *c,const Inputs r,const unsigned char *pk) +{ + Fq A[p]; + Fq B[p]; + int8 T[I]; + + Rounded_decode(A,pk+Seeds_bytes); + XEncrypt(B,T,r,pk,A); + Rounded_encode(c,B); c += Rounded_bytes; + Top_encode(c,T); +} + +/* r = ZDecrypt(C,sk) */ +static void ZDecrypt(Inputs r,const unsigned char *c,const unsigned char *sk) +{ + small a[p]; + Fq B[p]; + int8 T[I]; + + Small_decode(a,sk); + Rounded_decode(B,c); + Top_decode(T,c+Rounded_bytes); + XDecrypt(r,B,T,a); +} + +#endif + +/* ----- confirmation hash */ + +#define Confirm_bytes 32 + +/* h = HashConfirm(r,pk,cache); cache is Hash4(pk) */ +static void HashConfirm(unsigned char *h,const unsigned char *r,const unsigned char *pk,const unsigned char *cache) +{ +#ifndef LPR + unsigned char x[Hash_bytes*2]; + int i; + + Hash_prefix(x,3,r,Inputs_bytes); + for (i = 0;i < Hash_bytes;++i) x[Hash_bytes+i] = cache[i]; +#else + unsigned char x[Inputs_bytes+Hash_bytes]; + int i; + + for (i = 0;i < Inputs_bytes;++i) x[i] = r[i]; + for (i = 0;i < Hash_bytes;++i) x[Inputs_bytes+i] = cache[i]; +#endif + Hash_prefix(h,2,x,sizeof x); +} + +/* ----- session-key hash */ + +/* k = HashSession(b,y,z) */ +static void HashSession(unsigned char *k,int b,const unsigned char *y,const unsigned char *z) +{ +#ifndef LPR + unsigned char x[Hash_bytes+Ciphertexts_bytes+Confirm_bytes]; + int i; + + Hash_prefix(x,3,y,Inputs_bytes); + for (i = 0;i < Ciphertexts_bytes+Confirm_bytes;++i) x[Hash_bytes+i] = z[i]; +#else + unsigned char x[Inputs_bytes+Ciphertexts_bytes+Confirm_bytes]; + int i; + + for (i = 0;i < Inputs_bytes;++i) x[i] = y[i]; + for (i = 0;i < Ciphertexts_bytes+Confirm_bytes;++i) x[Inputs_bytes+i] = z[i]; +#endif + Hash_prefix(k,b,x,sizeof x); +} + +/* ----- Streamlined NTRU Prime and NTRU LPRime */ + +/* pk,sk = KEM_KeyGen() */ +static void KEM_KeyGen(unsigned char *pk,unsigned char *sk) +{ + int i; + + ZKeyGen(pk,sk); sk += SecretKeys_bytes; + for (i = 0;i < PublicKeys_bytes;++i) *sk++ = pk[i]; + randombytes(sk,Inputs_bytes); sk += Inputs_bytes; + Hash_prefix(sk,4,pk,PublicKeys_bytes); +} + +/* c,r_enc = Hide(r,pk,cache); cache is Hash4(pk) */ +static void Hide(unsigned char *c,unsigned char *r_enc,const Inputs r,const unsigned char *pk,const unsigned char *cache) +{ + Inputs_encode(r_enc,r); + ZEncrypt(c,r,pk); c += Ciphertexts_bytes; + HashConfirm(c,r_enc,pk,cache); +} + +/* c,k = Encap(pk) */ +static void Encap(unsigned char *c,unsigned char *k,const unsigned char *pk) +{ + Inputs r; + unsigned char r_enc[Inputs_bytes]; + unsigned char cache[Hash_bytes]; + + Hash_prefix(cache,4,pk,PublicKeys_bytes); + Inputs_random(r); + Hide(c,r_enc,r,pk,cache); + HashSession(k,1,r_enc,c); +} + +/* 0 if matching ciphertext+confirm, else -1 */ +static int Ciphertexts_diff_mask(const unsigned char *c,const unsigned char *c2) +{ + uint16 differentbits = 0; + int len = Ciphertexts_bytes+Confirm_bytes; + + while (len-- > 0) differentbits |= (*c++)^(*c2++); + return (1&((differentbits-1)>>8))-1; +} + +/* k = Decap(c,sk) */ +static void Decap(unsigned char *k,const unsigned char *c,const unsigned char *sk) +{ + const unsigned char *pk = sk + SecretKeys_bytes; + const unsigned char *rho = pk + PublicKeys_bytes; + const unsigned char *cache = rho + Inputs_bytes; + Inputs r; + unsigned char r_enc[Inputs_bytes]; + unsigned char cnew[Ciphertexts_bytes+Confirm_bytes]; + int mask; + int i; + + ZDecrypt(r,c,sk); + Hide(cnew,r_enc,r,pk,cache); + mask = Ciphertexts_diff_mask(c,cnew); + for (i = 0;i < Inputs_bytes;++i) r_enc[i] ^= mask&(r_enc[i]^rho[i]); + HashSession(k,1+mask,r_enc,c); +} + +/* ----- crypto_kem API */ + + +int crypto_kem_sntrup761_keypair(unsigned char *pk,unsigned char *sk) +{ + KEM_KeyGen(pk,sk); + return 0; +} + +int crypto_kem_sntrup761_enc(unsigned char *c,unsigned char *k,const unsigned char *pk) +{ + Encap(c,k,pk); + return 0; +} + +int crypto_kem_sntrup761_dec(unsigned char *k,const unsigned char *c,const unsigned char *sk) +{ + Decap(k,c,sk); + return 0; +} +#endif /* USE_SNTRUP761X25519 */ diff --git a/sntrup761.sh b/sntrup761.sh new file mode 100644 index 000000000..5cd5f92c3 --- /dev/null +++ b/sntrup761.sh @@ -0,0 +1,85 @@ +#!/bin/sh +# $OpenBSD: sntrup761.sh,v 1.5 2021/01/08 02:33:13 dtucker Exp $ +# Placed in the Public Domain. +# +AUTHOR="supercop-20201130/crypto_kem/sntrup761/ref/implementors" +FILES=" + supercop-20201130/crypto_sort/int32/portable4/int32_minmax.inc + supercop-20201130/crypto_sort/int32/portable4/sort.c + supercop-20201130/crypto_sort/uint32/useint32/sort.c + supercop-20201130/crypto_kem/sntrup761/ref/uint32.c + supercop-20201130/crypto_kem/sntrup761/ref/int32.c + supercop-20201130/crypto_kem/sntrup761/ref/paramsmenu.h + supercop-20201130/crypto_kem/sntrup761/ref/params.h + supercop-20201130/crypto_kem/sntrup761/ref/Decode.h + supercop-20201130/crypto_kem/sntrup761/ref/Decode.c + supercop-20201130/crypto_kem/sntrup761/ref/Encode.h + supercop-20201130/crypto_kem/sntrup761/ref/Encode.c + supercop-20201130/crypto_kem/sntrup761/ref/kem.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 ' +echo '#include "crypto_api.h"' +echo +# Map the types used in this code to the ones in crypto_api.h. We use #define +# instead of typedef since some systems have existing intXX types and do not +# permit multiple typedefs even if they do not conflict. +for t in int8 uint8 int16 uint16 int32 uint32 int64 uint64; do + echo "#define $t crypto_${t}" +done +echo +for i in $FILES; do + echo "/* from $i */" + # Changes to all files: + # - remove all includes, we inline everything required. + # - make functions not required elsewhere static. + # - rename the functions we do use. + # - remove unneccesary defines and externs. + sed -e "/#include/d" \ + -e "s/crypto_kem_/crypto_kem_sntrup761_/g" \ + -e "s/^void /static void /g" \ + -e "s/^int16 /static int16 /g" \ + -e "s/^uint16 /static uint16 /g" \ + -e "/^extern /d" \ + -e '/CRYPTO_NAMESPACE/d' \ + -e "/^#define int32 crypto_int32/d" \ + $i | \ + case "$i" in + # Use int64_t for intermediate values in int32_MINMAX to prevent signed + # 32-bit integer overflow when called by crypto_sort_uint32. + */int32_minmax.inc) + sed -e "s/int32 ab = b ^ a/int64_t ab = (int64_t)b ^ (int64_t)a/" \ + -e "s/int32 c = b - a/int64_t c = (int64_t)b - (int64_t)a/" + ;; + */int32/portable4/sort.c) + sed -e "s/void crypto_sort/void crypto_sort_int32/g" + ;; + */uint32/useint32/sort.c) + sed -e "s/void crypto_sort/void crypto_sort_uint32/g" + ;; + # Remove unused function to prevent warning. + */crypto_kem/sntrup761/ref/int32.c) + sed -e '/ int32_div_uint14/,/^}$/d' + ;; + # Remove unused function to prevent warning. + */crypto_kem/sntrup761/ref/uint32.c) + sed -e '/ uint32_div_uint14/,/^}$/d' + ;; + # Default: pass through. + *) + cat + ;; + esac + echo +done diff --git a/srclimit.c b/srclimit.c new file mode 100644 index 000000000..e2446f131 --- /dev/null +++ b/srclimit.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2020 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 "includes.h" + +#include +#include + +#include +#include +#include +#include + +#include "addr.h" +#include "canohost.h" +#include "log.h" +#include "misc.h" +#include "srclimit.h" +#include "xmalloc.h" + +static int max_children, max_persource, ipv4_masklen, ipv6_masklen; + +/* Per connection state, used to enforce unauthenticated connection limit. */ +static struct child_info { + int id; + struct xaddr addr; +} *child; + +void +srclimit_init(int max, int persource, int ipv4len, int ipv6len) +{ + int i; + + max_children = max; + ipv4_masklen = ipv4len; + ipv6_masklen = ipv6len; + max_persource = persource; + if (max_persource == INT_MAX) /* no limit */ + return; + debug("%s: max connections %d, per source %d, masks %d,%d", __func__, + max, persource, ipv4len, ipv6len); + if (max <= 0) + fatal("%s: invalid number of sockets: %d", __func__, max); + child = xcalloc(max_children, sizeof(*child)); + for (i = 0; i < max_children; i++) + child[i].id = -1; +} + +/* returns 1 if connection allowed, 0 if not allowed. */ +int +srclimit_check_allow(int sock, int id) +{ + struct xaddr xa, xb, xmask; + struct sockaddr_storage addr; + socklen_t addrlen = sizeof(addr); + struct sockaddr *sa = (struct sockaddr *)&addr; + int i, bits, first_unused, count = 0; + char xas[NI_MAXHOST]; + + if (max_persource == INT_MAX) /* no limit */ + return 1; + + debug("%s: sock %d id %d limit %d", __func__, sock, id, max_persource); + if (getpeername(sock, sa, &addrlen) != 0) + return 1; /* not remote socket? */ + if (addr_sa_to_xaddr(sa, addrlen, &xa) != 0) + return 1; /* unknown address family? */ + + /* Mask address off address to desired size. */ + bits = xa.af == AF_INET ? ipv4_masklen : ipv6_masklen; + if (addr_netmask(xa.af, bits, &xmask) != 0 || + addr_and(&xb, &xa, &xmask) != 0) { + debug3("%s: invalid mask %d bits", __func__, bits); + return 1; + } + + first_unused = max_children; + /* Count matching entries and find first unused one. */ + for (i = 0; i < max_children; i++) { + if (child[i].id == -1) { + if (i < first_unused) + first_unused = i; + } else if (addr_cmp(&child[i].addr, &xb) == 0) { + count++; + } + } + if (addr_ntop(&xa, xas, sizeof(xas)) != 0) { + debug3("%s: addr ntop failed", __func__); + return 1; + } + debug3("%s: new unauthenticated connection from %s/%d, at %d of %d", + __func__, xas, bits, count, max_persource); + + if (first_unused == max_children) { /* no free slot found */ + debug3("%s: no free slot", __func__); + return 0; + } + if (first_unused < 0 || first_unused >= max_children) + fatal("%s: internal error: first_unused out of range", + __func__); + + if (count >= max_persource) + return 0; + + /* Connection allowed, store masked address. */ + child[first_unused].id = id; + memcpy(&child[first_unused].addr, &xb, sizeof(xb)); + return 1; +} + +void +srclimit_done(int id) +{ + int i; + + if (max_persource == INT_MAX) /* no limit */ + return; + + debug("%s: id %d", __func__, id); + /* Clear corresponding state entry. */ + for (i = 0; i < max_children; i++) { + if (child[i].id == id) { + child[i].id = -1; + return; + } + } +} diff --git a/srclimit.h b/srclimit.h new file mode 100644 index 000000000..6e04f32b3 --- /dev/null +++ b/srclimit.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020 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. + */ +void srclimit_init(int, int, int, int); +int srclimit_check_allow(int, int); +void srclimit_done(int); diff --git a/ssh-add.1 b/ssh-add.1 index d4e1c603b..2786df514 100644 --- a/ssh-add.1 +++ b/ssh-add.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-add.1,v 1.69 2019/01/21 12:53:35 djm Exp $ +.\" $OpenBSD: ssh-add.1,v 1.81 2020/07/14 23:57:01 djm Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -35,16 +35,17 @@ .\" (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: January 21 2019 $ +.Dd $Mdocdate: July 14 2020 $ .Dt SSH-ADD 1 .Os .Sh NAME .Nm ssh-add -.Nd adds private key identities to the authentication agent +.Nd adds private key identities to the OpenSSH authentication agent .Sh SYNOPSIS .Nm ssh-add -.Op Fl cDdkLlqvXx +.Op Fl cDdKkLlqvXx .Op Fl E Ar fingerprint_hash +.Op Fl S Ar provider .Op Fl t Ar life .Op Ar .Nm ssh-add @@ -62,8 +63,10 @@ When run without arguments, it adds the files .Pa ~/.ssh/id_rsa , .Pa ~/.ssh/id_dsa , .Pa ~/.ssh/id_ecdsa , +.Pa ~/.ssh/id_ecdsa_sk , +.Pa ~/.ssh/id_ed25519 , and -.Pa ~/.ssh/id_ed25519 . +.Pa ~/.ssh/id_ed25519_sk . After loading a private key, .Nm will try to load corresponding certificate information from the @@ -110,6 +113,11 @@ If no public key is found at a given path, will append .Pa .pub and retry. +If the argument list consists of +.Dq - +then +.Nm +will read public keys to be removed from standard input. .It Fl E Ar fingerprint_hash Specifies the hash algorithm used when displaying key fingerprints. Valid options are: @@ -121,6 +129,8 @@ The default is .It Fl e Ar pkcs11 Remove keys provided by the PKCS#11 shared library .Ar pkcs11 . +.It Fl K +Load resident keys from a FIDO authenticator. .It Fl k When loading keys into or deleting keys from the agent, process plain private keys only and skip certificates. @@ -131,6 +141,10 @@ by the agent. Lists fingerprints of all identities currently represented by the agent. .It Fl q Be quiet after a successful operation. +.It Fl S Ar provider +Specifies a path to a library that will be used when adding +FIDO authenticator-hosted keys, overriding the default of using the +internal USB HID support. .It Fl s Ar pkcs11 Add keys provided by the PKCS#11 shared library .Ar pkcs11 . @@ -160,7 +174,7 @@ Lock the agent with a password. .El .Sh ENVIRONMENT .Bl -tag -width Ds -.It Ev "DISPLAY" and "SSH_ASKPASS" +.It Ev "DISPLAY", "SSH_ASKPASS" and "SSH_ASKPASS_REQUIRE" If .Nm needs a passphrase, it will read the passphrase from the current @@ -181,25 +195,45 @@ This is particularly useful when calling 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.) +.Pp +.Ev SSH_ASKPASS_REQUIRE +allows further control over the use of an askpass program. +If this variable is set to +.Dq never +then +.Nm +will never attempt to use one. +If it is set to +.Dq prefer , +then +.Nm +will prefer to use the askpass program instead of the TTY when requesting +passwords. +Finally, if the variable is set to +.Dq force , +then the askpass program will be used for all passphrase input regardless +of whether +.Ev DISPLAY +is set. .It Ev SSH_AUTH_SOCK Identifies the path of a .Ux Ns -domain socket used to communicate with the agent. +.It Ev SSH_SK_PROVIDER +Specifies a path to a library that will be used when loading any +FIDO authenticator-hosted keys, overriding the default of using +the built-in USB HID support. .El .Sh FILES -.Bl -tag -width Ds +.Bl -tag -width Ds -compact .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_ecdsa_sk .It Pa ~/.ssh/id_ed25519 -Contains the Ed25519 authentication identity of the user. +.It Pa ~/.ssh/id_ed25519_sk .It Pa ~/.ssh/id_rsa -Contains the RSA authentication identity of the user. +Contains the DSA, ECDSA, authenticator-hosted ECDSA, Ed25519, +authenticator-hosted Ed25519 or RSA authentication identity of the user. .El .Pp Identity files should not be readable by anyone but the user. diff --git a/ssh-add.c b/ssh-add.c index ebfb8a32b..7edb9f9a7 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-add.c,v 1.141 2019/09/06 05:23:55 djm Exp $ */ +/* $OpenBSD: ssh-add.c,v 1.159 2021/01/11 02:12:58 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -66,6 +66,8 @@ #include "misc.h" #include "ssherr.h" #include "digest.h" +#include "ssh-sk.h" +#include "sk-api.h" /* argv0 */ extern char *__progname; @@ -77,9 +79,11 @@ static char *default_files[] = { _PATH_SSH_CLIENT_ID_DSA, #ifdef OPENSSL_HAS_ECC _PATH_SSH_CLIENT_ID_ECDSA, + _PATH_SSH_CLIENT_ID_ECDSA_SK, #endif #endif /* WITH_OPENSSL */ _PATH_SSH_CLIENT_ID_ED25519, + _PATH_SSH_CLIENT_ID_ED25519_SK, _PATH_SSH_CLIENT_ID_XMSS, NULL }; @@ -102,12 +106,59 @@ static void clear_pass(void) { if (pass) { - explicit_bzero(pass, strlen(pass)); - free(pass); + freezero(pass, strlen(pass)); pass = NULL; } } +static int +delete_one(int agent_fd, const struct sshkey *key, const char *comment, + const char *path, int qflag) +{ + int r; + + if ((r = ssh_remove_identity(agent_fd, key)) != 0) { + fprintf(stderr, "Could not remove identity \"%s\": %s\n", + path, ssh_err(r)); + return r; + } + if (!qflag) { + fprintf(stderr, "Identity removed: %s %s (%s)\n", path, + sshkey_type(key), comment); + } + return 0; +} + +static int +delete_stdin(int agent_fd, int qflag) +{ + char *line = NULL, *cp; + size_t linesize = 0; + struct sshkey *key = NULL; + int lnum = 0, r, ret = -1; + + while (getline(&line, &linesize, stdin) != -1) { + lnum++; + sshkey_free(key); + key = NULL; + line[strcspn(line, "\n")] = '\0'; + cp = line + strspn(line, " \t"); + if (*cp == '#' || *cp == '\0') + continue; + if ((key = sshkey_new(KEY_UNSPEC)) == NULL) + fatal_f("sshkey_new"); + if ((r = sshkey_read(key, &cp)) != 0) { + error_r(r, "(stdin):%d: invalid key", lnum); + continue; + } + if (delete_one(agent_fd, key, cp, "(stdin)", qflag) == 0) + ret = 0; + } + sshkey_free(key); + free(line); + return ret; +} + static int delete_file(int agent_fd, const char *filename, int key_only, int qflag) { @@ -115,19 +166,15 @@ delete_file(int agent_fd, const char *filename, int key_only, int qflag) char *certpath = NULL, *comment = NULL; int r, ret = -1; + if (strcmp(filename, "-") == 0) + return delete_stdin(agent_fd, qflag); + 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); - } + if (delete_one(agent_fd, public, comment, filename, qflag) == 0) ret = 0; - } else - fprintf(stderr, "Could not remove identity \"%s\": %s\n", - filename, ssh_err(r)); if (key_only) goto out; @@ -138,8 +185,7 @@ delete_file(int agent_fd, const char *filename, int key_only, int qflag) 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)); + error_r(r, "Failed to load certificate \"%s\"", certpath); goto out; } @@ -147,15 +193,8 @@ delete_file(int agent_fd, const char *filename, int key_only, int qflag) 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); - } + if (delete_one(agent_fd, cert, comment, certpath, qflag) == 0) ret = 0; - } else - fprintf(stderr, "Could not remove identity \"%s\": %s\n", - certpath, ssh_err(r)); out: sshkey_free(cert); @@ -191,7 +230,8 @@ delete_all(int agent_fd, int qflag) } static int -add_file(int agent_fd, const char *filename, int key_only, int qflag) +add_file(int agent_fd, const char *filename, int key_only, int qflag, + const char *skprovider) { struct sshkey *private, *cert; char *comment = NULL; @@ -220,9 +260,7 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag) return -1; } } - if ((keyblob = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); - if ((r = sshkey_load_file(fd, keyblob)) != 0) { + if ((r = sshbuf_load_fd(fd, &keyblob)) != 0) { fprintf(stderr, "Error loading key \"%s\": %s\n", filename, ssh_err(r)); sshbuf_free(keyblob); @@ -310,8 +348,24 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag) ssh_free_identitylist(idlist); } + if (sshkey_is_sk(private)) { + if (skprovider == NULL) { + fprintf(stderr, "Cannot load FIDO key %s " + "without provider\n", filename); + goto out; + } + if ((private->sk_flags & SSH_SK_USER_VERIFICATION_REQD) != 0) { + fprintf(stderr, "FIDO verify-required key %s is not " + "currently supported by ssh-agent\n", filename); + goto out; + } + } else { + /* Don't send provider constraint for other keys */ + skprovider = NULL; + } + if ((r = ssh_add_identity_constrained(agent_fd, private, comment, - lifetime, confirm, maxsign)) == 0) { + lifetime, confirm, maxsign, skprovider)) == 0) { ret = 0; if (!qflag) { fprintf(stderr, "Identity added: %s (%s)\n", @@ -338,8 +392,7 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag) 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)); + error_r(r, "Failed to load certificate \"%s\"", certpath); goto out; } @@ -352,21 +405,21 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag) /* Graft with private bits */ if ((r = sshkey_to_certified(private)) != 0) { - error("%s: sshkey_to_certified: %s", __func__, ssh_err(r)); + error_fr(r, "sshkey_to_certified"); sshkey_free(cert); goto out; } if ((r = sshkey_cert_copy(cert, private)) != 0) { - error("%s: sshkey_cert_copy: %s", __func__, ssh_err(r)); + error_fr(r, "sshkey_cert_copy"); 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)); + lifetime, confirm, maxsign, skprovider)) != 0) { + error_r(r, "Certificate %s (%s) add failed", certpath, + private->cert->key_id); goto out; } /* success */ @@ -429,20 +482,18 @@ test_key(int agent_fd, const char *filename) char data[1024]; if ((r = sshkey_load_public(filename, &key, NULL)) != 0) { - error("Couldn't read public key %s: %s", filename, ssh_err(r)); + error_r(r, "Couldn't read public key %s", filename); 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)); + error_r(r, "Agent signature failed for %s", filename); 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)); + NULL, 0, NULL)) != 0) { + error_r(r, "Signature verification failed for %s", filename); goto done; } /* success */ @@ -511,8 +562,7 @@ lock_agent(int agent_fd, int lock) fprintf(stderr, "Passwords do not match.\n"); passok = 0; } - explicit_bzero(p2, strlen(p2)); - free(p2); + freezero(p2, strlen(p2)); } if (passok) { if ((r = ssh_lock_agent(agent_fd, lock, p1)) == 0) { @@ -523,19 +573,68 @@ lock_agent(int agent_fd, int lock) lock ? "" : "un", ssh_err(r)); } } - explicit_bzero(p1, strlen(p1)); - free(p1); + freezero(p1, strlen(p1)); return (ret); } static int -do_file(int agent_fd, int deleting, int key_only, char *file, int qflag) +load_resident_keys(int agent_fd, const char *skprovider, int qflag) +{ + struct sshkey **keys; + size_t nkeys, i; + int r, ok = 0; + char *fp; + + pass = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN); + if ((r = sshsk_load_resident(skprovider, NULL, pass, + &keys, &nkeys)) != 0) { + error_r(r, "Unable to load resident keys"); + return r; + } + for (i = 0; i < nkeys; i++) { + if ((fp = sshkey_fingerprint(keys[i], + fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + fatal_f("sshkey_fingerprint failed"); + if ((r = ssh_add_identity_constrained(agent_fd, keys[i], "", + lifetime, confirm, maxsign, skprovider)) != 0) { + error("Unable to add key %s %s", + sshkey_type(keys[i]), fp); + free(fp); + ok = r; + continue; + } + if (ok == 0) + ok = 1; + if (!qflag) { + fprintf(stderr, "Resident identity added: %s %s\n", + sshkey_type(keys[i]), fp); + 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"); + } + } + free(fp); + sshkey_free(keys[i]); + } + free(keys); + if (nkeys == 0) + return SSH_ERR_KEY_NOT_FOUND; + return ok == 1 ? 0 : ok; +} + +static int +do_file(int agent_fd, int deleting, int key_only, char *file, int qflag, + const char *skprovider) { 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) + if (add_file(agent_fd, file, key_only, qflag, skprovider) == -1) return -1; } return 0; @@ -544,25 +643,16 @@ do_file(int agent_fd, int deleting, int key_only, char *file, int qflag) 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"); + fprintf(stderr, +"usage: ssh-add [-cDdKkLlqvXx] [-E fingerprint_hash] [-S provider] [-t life]\n" +#ifdef WITH_XMSS +" [-M maxsign] [-m minleft]\n" +#endif +" [file ...]\n" +" ssh-add -s pkcs11\n" +" ssh-add -e pkcs11\n" +" ssh-add -T pubkey ...\n" + ); } int @@ -571,8 +661,8 @@ 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; + char *pkcs11provider = NULL, *skprovider = NULL; + int r, i, ch, deleting = 0, ret = 0, key_only = 0, do_download = 0; int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0; SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; LogLevel log_level = SYSLOG_LEVEL_INFO; @@ -600,7 +690,9 @@ main(int argc, char **argv) exit(2); } - while ((ch = getopt(argc, argv, "vklLcdDTxXE:e:M:m:qs:t:")) != -1) { + skprovider = getenv("SSH_SK_PROVIDER"); + + while ((ch = getopt(argc, argv, "vkKlLcdDTxXE:e:M:m:qs:S:t:")) != -1) { switch (ch) { case 'v': if (log_level == SYSLOG_LEVEL_INFO) @@ -616,6 +708,9 @@ main(int argc, char **argv) case 'k': key_only = 1; break; + case 'K': + do_download = 1; + break; case 'l': case 'L': if (lflag != 0) @@ -656,12 +751,16 @@ main(int argc, char **argv) case 's': pkcs11provider = optarg; break; + case 'S': + skprovider = optarg; + break; case 'e': deleting = 1; pkcs11provider = optarg; break; case 't': - if ((lifetime = convtime(optarg)) == -1) { + if ((lifetime = convtime(optarg)) == -1 || + lifetime < 0 || (u_long)lifetime > UINT32_MAX) { fprintf(stderr, "Invalid lifetime\n"); ret = 1; goto done; @@ -697,6 +796,11 @@ main(int argc, char **argv) goto done; } +#ifdef ENABLE_SK_INTERNAL + if (skprovider == NULL) + skprovider = "internal"; +#endif + argc -= optind; argv += optind; if (Tflag) { @@ -713,6 +817,13 @@ main(int argc, char **argv) ret = 1; goto done; } + if (do_download) { + if (skprovider == NULL) + fatal("Cannot download keys without provider"); + if (load_resident_keys(agent_fd, skprovider, qflag) != 0) + ret = 1; + goto done; + } if (argc == 0) { char buf[PATH_MAX]; struct passwd *pw; @@ -732,7 +843,7 @@ main(int argc, char **argv) if (stat(buf, &st) == -1) continue; if (do_file(agent_fd, deleting, key_only, buf, - qflag) == -1) + qflag, skprovider) == -1) ret = 1; else count++; @@ -742,13 +853,12 @@ main(int argc, char **argv) } else { for (i = 0; i < argc; i++) { if (do_file(agent_fd, deleting, key_only, - argv[i], qflag) == -1) + argv[i], qflag, skprovider) == -1) ret = 1; } } - clear_pass(); - done: + clear_pass(); ssh_close_authentication_socket(agent_fd); return ret; } diff --git a/ssh-agent.1 b/ssh-agent.1 index 83b2b41c8..2cf46160b 100644 --- a/ssh-agent.1 +++ b/ssh-agent.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-agent.1,v 1.64 2016/11/30 06:54:26 jmc Exp $ +.\" $OpenBSD: ssh-agent.1,v 1.72 2020/06/22 05:52:05 djm Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -34,57 +34,37 @@ .\" (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: November 30 2016 $ +.Dd $Mdocdate: June 22 2020 $ .Dt SSH-AGENT 1 .Os .Sh NAME .Nm ssh-agent -.Nd authentication agent +.Nd OpenSSH authentication agent .Sh SYNOPSIS .Nm ssh-agent .Op Fl c | s .Op Fl \&Dd .Op Fl a Ar bind_address .Op Fl E Ar fingerprint_hash -.Op Fl P Ar pkcs11_whitelist +.Op Fl P Ar allowed_providers .Op Fl t Ar life -.Op Ar command Op Ar arg ... +.Nm ssh-agent +.Op Fl a Ar bind_address +.Op Fl E Ar fingerprint_hash +.Op Fl P Ar allowed_providers +.Op Fl t Ar life +.Ar command Op Ar arg ... .Nm ssh-agent .Op Fl c | s .Fl k .Sh DESCRIPTION .Nm -is a program to hold private keys used for public key authentication -(RSA, DSA, ECDSA, Ed25519). -.Nm -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. +is a program to hold private keys used for public key authentication. Through use of environment variables the agent can be located and automatically used for authentication when logging in to other machines using .Xr ssh 1 . .Pp -The agent initially does not have any private keys. -Keys are added using -.Xr ssh 1 -(see -.Cm AddKeysToAgent -in -.Xr ssh_config 5 -for details) -or -.Xr ssh-add 1 . -Multiple identities may be stored in -.Nm -concurrently and -.Xr ssh 1 -will automatically use them if present. -.Xr ssh-add 1 -is also used to remove keys from -.Nm -and to query the keys that are held in one. -.Pp The options are as follows: .Bl -tag -width Ds .It Fl a Ar bind_address @@ -122,18 +102,20 @@ The default is Kill the current agent (given by the .Ev SSH_AGENT_PID environment variable). -.It Fl P Ar pkcs11_whitelist -Specify a pattern-list of acceptable paths for PKCS#11 shared libraries -that may be added using the +.It Fl P Ar allowed_providers +Specify a pattern-list of acceptable paths for PKCS#11 provider and FIDO +authenticator middleware shared libraries that may be used with the +.Fl S +or .Fl s -option to +options to .Xr ssh-add 1 . -The default is to allow loading PKCS#11 libraries from -.Dq /usr/lib/*,/usr/local/lib/* . -PKCS#11 libraries that do not match the whitelist will be refused. +Libraries that do not match the pattern list will be refused. See PATTERNS in .Xr ssh_config 5 for a description of pattern-list syntax. +The default list is +.Dq /usr/lib/*,/usr/local/lib/* . .It Fl s Generate Bourne shell commands on .Dv stdout . @@ -148,64 +130,82 @@ A lifetime specified for an identity with .Xr ssh-add 1 overrides this value. Without this option the default maximum lifetime is forever. -.El -.Pp -If a command line is given, this is executed as a subprocess of the agent. -When the command dies, so does the agent. -.Pp -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. -.Pp -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 -.Cm ssh-agent xterm & . -The second is that the agent prints the needed shell commands (either -.Xr sh 1 -or -.Xr csh 1 -syntax can be generated) which can be evaluated in the calling shell, eg -.Cm eval `ssh-agent -s` -for Bourne-type shells such as -.Xr sh 1 -or -.Xr ksh 1 -and -.Cm eval `ssh-agent -c` -for -.Xr csh 1 -and derivatives. -.Pp -Later -.Xr ssh 1 -looks at these variables and uses them to establish a connection to the agent. -.Pp -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. -.Pp -A -.Ux Ns -domain -socket is created and the name of this socket is stored in the -.Ev 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. -.Pp -The -.Ev SSH_AGENT_PID -environment variable holds the agent's process ID. -.Pp +.It Ar command Op Ar arg ... +If a command (and optional arguments) is given, +this is executed as a subprocess of the agent. The agent exits automatically when the command given on the command line terminates. +.El +.Pp +There are two main ways to get an agent set up. +The first is at the start of an X session, +where all other windows or programs are started as children of the +.Nm +program. +The agent starts a command under which its environment +variables are exported, for example +.Cm ssh-agent xterm & . +When the command terminates, so does the agent. +.Pp +The second method is used for a login session. +When +.Nm +is started, +it prints the shell commands required to set its environment variables, +which in turn can be evaluated in the calling shell, for example +.Cm eval `ssh-agent -s` . +.Pp +In both cases, +.Xr ssh 1 +looks at these environment variables and uses them to establish a connection to the agent. +.Pp +The agent initially does not have any private keys. +Keys are added using +.Xr ssh-add 1 +or by +.Xr ssh 1 +when +.Cm AddKeysToAgent +is set in +.Xr ssh_config 5 . +Multiple identities may be stored in +.Nm +concurrently and +.Xr ssh 1 +will automatically use them if present. +.Xr ssh-add 1 +is also used to remove keys from +.Nm +and to query the keys that are held in one. +.Pp +Connections to +.Nm +may be forwarded from further remote hosts using the +.Fl A +option to +.Xr ssh 1 +(but see the caveats documented therein), +avoiding the need for authentication data to be stored on other machines. +Authentication passphrases and private keys never go over the network: +the connection to the agent is forwarded over SSH remote connections +and the result is returned to the requester, +allowing the user access to their identities anywhere in the network +in a secure fashion. +.Sh ENVIRONMENT +.Bl -tag -width "SSH_AGENT_PID" +.It Ev SSH_AGENT_PID +When +.Nm +starts, it stores the name of the agent's process ID (PID) in this variable. +.It Ev SSH_AUTH_SOCK +When +.Nm +starts, it creates a +.Ux Ns -domain +socket and stores its pathname in this variable. +It is accessible only to the current user, +but is easily abused by root or another instance of the same user. +.El .Sh FILES .Bl -tag -width Ds .It Pa $TMPDIR/ssh-XXXXXXXXXX/agent. @@ -218,6 +218,7 @@ The sockets should get automatically removed when the agent exits. .Xr ssh 1 , .Xr ssh-add 1 , .Xr ssh-keygen 1 , +.Xr ssh_config 5 , .Xr sshd 8 .Sh AUTHORS .An -nosplit diff --git a/ssh-agent.c b/ssh-agent.c index 9c6680a25..58fe6ddf7 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-agent.c,v 1.237 2019/06/28 13:35:04 deraadt Exp $ */ +/* $OpenBSD: ssh-agent.c,v 1.277 2021/02/12 03:14:18 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -41,6 +41,7 @@ #include #include #include +#include #ifdef HAVE_SYS_TIME_H # include #endif @@ -76,6 +77,7 @@ #include "xmalloc.h" #include "ssh.h" +#include "ssh2.h" #include "sshbuf.h" #include "sshkey.h" #include "authfd.h" @@ -85,13 +87,14 @@ #include "digest.h" #include "ssherr.h" #include "match.h" - -#ifdef ENABLE_PKCS11 +#include "msg.h" +#include "ssherr.h" +#include "pathnames.h" #include "ssh-pkcs11.h" -#endif +#include "sk-api.h" -#ifndef DEFAULT_PKCS11_WHITELIST -# define DEFAULT_PKCS11_WHITELIST "/usr/lib*/*,/usr/local/lib*/*" +#ifndef DEFAULT_ALLOWED_PROVIDERS +# define DEFAULT_ALLOWED_PROVIDERS "/usr/lib*/*,/usr/local/lib*/*" #endif /* Maximum accepted message length */ @@ -100,12 +103,12 @@ #define AGENT_RBUF_LEN (4096) typedef enum { - AUTH_UNUSED, - AUTH_SOCKET, - AUTH_CONNECTION + AUTH_UNUSED = 0, + AUTH_SOCKET = 1, + AUTH_CONNECTION = 2, } sock_type; -typedef struct { +typedef struct socket_entry { int fd; sock_type type; struct sshbuf *input; @@ -123,6 +126,7 @@ typedef struct identity { char *provider; time_t death; u_int confirm; + char *sk_provider; } Identity; struct idtable { @@ -146,8 +150,8 @@ pid_t cleanup_pid = 0; char socket_name[PATH_MAX]; char socket_dir[PATH_MAX]; -/* PKCS#11 path whitelist */ -static char *pkcs11_whitelist; +/* Pattern-list of allowed PKCS#11/Security key paths */ +static char *allowed_providers; /* locking */ #define LOCK_SIZE 32 @@ -160,19 +164,23 @@ u_char lock_salt[LOCK_SALT_SIZE]; extern char *__progname; /* Default lifetime in seconds (0 == forever) */ -static long lifetime = 0; +static int lifetime = 0; static int fingerprint_hash = SSH_FP_HASH_DEFAULT; +/* Refuse signing of non-SSH messages for web-origin FIDO keys */ +static int restrict_websafe = 1; + 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); + memset(e, '\0', sizeof(*e)); + e->fd = -1; + e->type = AUTH_UNUSED; } static void @@ -189,6 +197,7 @@ free_identity(Identity *id) sshkey_free(id->key); free(id->provider); free(id->comment); + free(id->sk_provider); free(id); } @@ -207,15 +216,16 @@ lookup_identity(struct sshkey *key) /* Check confirmation of keysign request */ static int -confirm_key(Identity *id) +confirm_key(Identity *id, const char *extra) { 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)) + ask_permission("Allow use of key %s?\nKey fingerprint %s.%s%s", + id->comment, p, + extra == NULL ? "" : "\n", extra == NULL ? "" : extra)) ret = 0; free(p); @@ -230,7 +240,7 @@ send_status(SocketEntry *e, int success) 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)); + fatal_fr(r, "compose"); } /* send list of supported public keys to 'client' */ @@ -241,22 +251,23 @@ process_request_identities(SocketEntry *e) struct sshbuf *msg; int r; + debug2_f("entering"); + if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); 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)); + error_fr(r, "compose key/comment"); continue; } } if ((r = sshbuf_put_stringb(e->output, msg)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "enqueue"); sshbuf_free(msg); } @@ -278,56 +289,213 @@ agent_decode_alg(struct sshkey *key, u_int flags) return NULL; } +/* + * Attempt to parse the contents of a buffer as a SSH publickey userauth + * request, checking its contents for consistency and matching the embedded + * key against the one that is being used for signing. + * Note: does not modify msg buffer. + * Optionally extract the username and session ID from the request. + */ +static int +parse_userauth_request(struct sshbuf *msg, const struct sshkey *expected_key, + char **userp, struct sshbuf **sess_idp) +{ + struct sshbuf *b = NULL, *sess_id = NULL; + char *user = NULL, *service = NULL, *method = NULL, *pkalg = NULL; + int r; + u_char t, sig_follows; + struct sshkey *mkey = NULL; + + if (userp != NULL) + *userp = NULL; + if (sess_idp != NULL) + *sess_idp = NULL; + if ((b = sshbuf_fromb(msg)) == NULL) + fatal_f("sshbuf_fromb"); + + /* SSH userauth request */ + if ((r = sshbuf_froms(b, &sess_id)) != 0) + goto out; + if (sshbuf_len(sess_id) == 0) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((r = sshbuf_get_u8(b, &t)) != 0 || /* SSH2_MSG_USERAUTH_REQUEST */ + (r = sshbuf_get_cstring(b, &user, NULL)) != 0 || /* server user */ + (r = sshbuf_get_cstring(b, &service, NULL)) != 0 || /* service */ + (r = sshbuf_get_cstring(b, &method, NULL)) != 0 || /* method */ + (r = sshbuf_get_u8(b, &sig_follows)) != 0 || /* sig-follows */ + (r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 || /* alg */ + (r = sshkey_froms(b, &mkey)) != 0) /* key */ + goto out; + if (t != SSH2_MSG_USERAUTH_REQUEST || + sig_follows != 1 || + strcmp(service, "ssh-connection") != 0 || + !sshkey_equal(expected_key, mkey) || + sshkey_type_from_name(pkalg) != expected_key->type) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (strcmp(method, "publickey") != 0) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (sshbuf_len(b) != 0) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + /* success */ + r = 0; + debug3_f("well formed userauth"); + if (userp != NULL) { + *userp = user; + user = NULL; + } + if (sess_idp != NULL) { + *sess_idp = sess_id; + sess_id = NULL; + } + out: + sshbuf_free(b); + sshbuf_free(sess_id); + free(user); + free(service); + free(method); + free(pkalg); + sshkey_free(mkey); + return r; +} + +/* + * Attempt to parse the contents of a buffer as a SSHSIG signature request. + * Note: does not modify buffer. + */ +static int +parse_sshsig_request(struct sshbuf *msg) +{ + int r; + struct sshbuf *b; + + if ((b = sshbuf_fromb(msg)) == NULL) + fatal_f("sshbuf_fromb"); + + if ((r = sshbuf_cmp(b, 0, "SSHSIG", 6)) != 0 || + (r = sshbuf_consume(b, 6)) != 0 || + (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* namespace */ + (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || /* reserved */ + (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* hashalg */ + (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0) /* H(msg) */ + goto out; + if (sshbuf_len(b) != 0) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + /* success */ + r = 0; + out: + sshbuf_free(b); + return r; +} + +/* + * This function inspects a message to be signed by a FIDO key that has a + * web-like application string (i.e. one that does not begin with "ssh:". + * It checks that the message is one of those expected for SSH operations + * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges + * for the web. + */ +static int +check_websafe_message_contents(struct sshkey *key, struct sshbuf *data) +{ + if (parse_userauth_request(data, key, NULL, NULL) == 0) { + debug_f("signed data matches public key userauth request"); + return 1; + } + if (parse_sshsig_request(data) == 0) { + debug_f("signed data matches SSHSIG signature request"); + return 1; + } + + /* XXX check CA signature operation */ + + error("web-origin key attempting to sign non-SSH message"); + return 0; +} + /* ssh2 only */ static void process_sign_request2(SocketEntry *e) { - const u_char *data; u_char *signature = NULL; - size_t dlen, slen = 0; + size_t slen = 0; u_int compat = 0, flags; int r, ok = -1; - struct sshbuf *msg; + char *fp = NULL; + struct sshbuf *msg = NULL, *data = NULL; struct sshkey *key = NULL; struct identity *id; + struct notifier_ctx *notifier = NULL; - if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + debug_f("entering"); + + if ((msg = sshbuf_new()) == NULL || (data = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); if ((r = sshkey_froms(e->request, &key)) != 0 || - (r = sshbuf_get_string_direct(e->request, &data, &dlen)) != 0 || + (r = sshbuf_get_stringb(e->request, data)) != 0 || (r = sshbuf_get_u32(e->request, &flags)) != 0) { - error("%s: couldn't parse request: %s", __func__, ssh_err(r)); + error_fr(r, "parse"); goto send; } if ((id = lookup_identity(key)) == NULL) { - verbose("%s: %s key not found", __func__, sshkey_type(key)); + verbose_f("%s key not found", sshkey_type(key)); goto send; } - if (id->confirm && confirm_key(id) != 0) { - verbose("%s: user refused key", __func__); + if (id->confirm && confirm_key(id, NULL) != 0) { + verbose_f("user refused key"); goto send; } + if (sshkey_is_sk(id->key)) { + if (strncmp(id->key->sk_application, "ssh:", 4) != 0 && + !check_websafe_message_contents(key, data)) { + /* error already logged */ + goto send; + } + if ((id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { + if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, + SSH_FP_DEFAULT)) == NULL) + fatal_f("fingerprint failed"); + notifier = notify_start(0, + "Confirm user presence for key %s %s", + sshkey_type(id->key), fp); + } + } + /* XXX support PIN required FIDO keys */ 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)); + sshbuf_ptr(data), sshbuf_len(data), agent_decode_alg(key, flags), + id->sk_provider, NULL, compat)) != 0) { + error_fr(r, "sshkey_sign"); goto send; } /* Success */ ok = 0; send: - sshkey_free(key); + notify_complete(notifier, "User presence confirmed"); + 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)); + fatal_fr(r, "compose"); } else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "compose failure"); if ((r = sshbuf_put_stringb(e->output, msg)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "enqueue"); + sshbuf_free(data); sshbuf_free(msg); + sshkey_free(key); + free(fp); free(signature); } @@ -339,24 +507,24 @@ process_remove_identity(SocketEntry *e) struct sshkey *key = NULL; Identity *id; + debug2_f("entering"); if ((r = sshkey_froms(e->request, &key)) != 0) { - error("%s: get key: %s", __func__, ssh_err(r)); + error_fr(r, "parse key"); goto done; } if ((id = lookup_identity(key)) == NULL) { - debug("%s: key not found", __func__); + debug_f("key not found"); goto done; } /* We have this key, free it. */ if (idtab->nentries < 1) - fatal("%s: internal error: nentries %d", - __func__, idtab->nentries); + fatal_f("internal error: nentries %d", idtab->nentries); TAILQ_REMOVE(&idtab->idlist, id, next); free_identity(id); idtab->nentries--; - sshkey_free(key); success = 1; done: + sshkey_free(key); send_status(e, success); } @@ -365,6 +533,7 @@ process_remove_all_identities(SocketEntry *e) { Identity *id; + debug2_f("entering"); /* Loop over all identities and clear the keys. */ for (id = TAILQ_FIRST(&idtab->idlist); id; id = TAILQ_FIRST(&idtab->idlist)) { @@ -405,68 +574,171 @@ reaper(void) return (deadline - now); } +static int +parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp) +{ + char *ext_name = NULL; + int r; + + if ((r = sshbuf_get_cstring(m, &ext_name, NULL)) != 0) { + error_fr(r, "parse constraint extension"); + goto out; + } + debug_f("constraint ext %s", ext_name); + if (strcmp(ext_name, "sk-provider@openssh.com") == 0) { + if (sk_providerp == NULL) { + error_f("%s not valid here", ext_name); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (*sk_providerp != NULL) { + error_f("%s already set", ext_name); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((r = sshbuf_get_cstring(m, sk_providerp, NULL)) != 0) { + error_fr(r, "parse %s", ext_name); + goto out; + } + } else { + error_f("unsupported constraint \"%s\"", ext_name); + r = SSH_ERR_FEATURE_UNSUPPORTED; + goto out; + } + /* success */ + r = 0; + out: + free(ext_name); + return r; +} + +static int +parse_key_constraints(struct sshbuf *m, struct sshkey *k, time_t *deathp, + u_int *secondsp, int *confirmp, char **sk_providerp) +{ + u_char ctype; + int r; + u_int seconds, maxsign = 0; + + while (sshbuf_len(m)) { + if ((r = sshbuf_get_u8(m, &ctype)) != 0) { + error_fr(r, "parse constraint type"); + goto out; + } + switch (ctype) { + case SSH_AGENT_CONSTRAIN_LIFETIME: + if (*deathp != 0) { + error_f("lifetime already set"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((r = sshbuf_get_u32(m, &seconds)) != 0) { + error_fr(r, "parse lifetime constraint"); + goto out; + } + *deathp = monotime() + seconds; + *secondsp = seconds; + break; + case SSH_AGENT_CONSTRAIN_CONFIRM: + if (*confirmp != 0) { + error_f("confirm already set"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + *confirmp = 1; + break; + case SSH_AGENT_CONSTRAIN_MAXSIGN: + if (k == NULL) { + error_f("maxsign not valid here"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (maxsign != 0) { + error_f("maxsign already set"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((r = sshbuf_get_u32(m, &maxsign)) != 0) { + error_fr(r, "parse maxsign constraint"); + goto out; + } + if ((r = sshkey_enable_maxsign(k, maxsign)) != 0) { + error_fr(r, "enable maxsign"); + goto out; + } + break; + case SSH_AGENT_CONSTRAIN_EXTENSION: + if ((r = parse_key_constraint_extension(m, + sk_providerp)) != 0) + goto out; /* error already logged */ + break; + default: + error_f("Unknown constraint %d", ctype); + r = SSH_ERR_FEATURE_UNSUPPORTED; + goto out; + } + } + /* success */ + r = 0; + out: + return r; +} + static void process_add_identity(SocketEntry *e) { Identity *id; int success = 0, confirm = 0; - u_int seconds, maxsign; - char *comment = NULL; + char *fp, *comment = NULL, *sk_provider = NULL; + char canonical_provider[PATH_MAX]; time_t death = 0; + u_int seconds = 0; struct sshkey *k = NULL; - u_char ctype; int r = SSH_ERR_INTERNAL_ERROR; + debug2_f("entering"); 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; + error_fr(r, "parse"); + goto out; } - if ((r = sshkey_shield_private(k)) != 0) { - error("%s: shield 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; - } + if (parse_key_constraints(e->request, k, &death, &seconds, &confirm, + &sk_provider) != 0) { + error_f("failed to parse constraints"); + sshbuf_reset(e->request); + goto out; } - success = 1; + if (sk_provider != NULL) { + if (!sshkey_is_sk(k)) { + error("Cannot add provider: %s is not an " + "authenticator-hosted key", sshkey_type(k)); + goto out; + } + if (strcasecmp(sk_provider, "internal") == 0) { + debug_f("internal provider"); + } else { + if (realpath(sk_provider, canonical_provider) == NULL) { + verbose("failed provider \"%.100s\": " + "realpath: %s", sk_provider, + strerror(errno)); + goto out; + } + free(sk_provider); + sk_provider = xstrdup(canonical_provider); + if (match_pattern_list(sk_provider, + allowed_providers, 0) != 1) { + error("Refusing add key: " + "provider %s not allowed", sk_provider); + goto out; + } + } + } + if ((r = sshkey_shield_private(k)) != 0) { + error_fr(r, "shield private"); + goto out; + } if (lifetime && !death) death = monotime() + lifetime; if ((id = lookup_identity(k)) == NULL) { @@ -478,12 +750,31 @@ process_add_identity(SocketEntry *e) /* key state might have been updated */ sshkey_free(id->key); free(id->comment); + free(id->sk_provider); } + /* success */ id->key = k; id->comment = comment; id->death = death; id->confirm = confirm; -send: + id->sk_provider = sk_provider; + + if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT, + SSH_FP_DEFAULT)) == NULL) + fatal_f("sshkey_fingerprint failed"); + debug_f("add %s %s \"%.100s\" (life: %u) (confirm: %u) " + "(provider: %s)", sshkey_ssh_name(k), fp, comment, seconds, + confirm, sk_provider == NULL ? "none" : sk_provider); + free(fp); + /* transferred */ + k = NULL; + comment = NULL; + sk_provider = NULL; + success = 1; + out: + free(sk_provider); + free(comment); + sshkey_free(k); send_status(e, success); } @@ -497,13 +788,14 @@ process_lock_agent(SocketEntry *e, int lock) static u_int fail_count = 0; size_t pwlen; + debug2_f("entering"); /* * 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)); + fatal_fr(r, "parse"); if (pwlen == 0) { debug("empty password not supported"); } else if (locked && !lock) { @@ -535,8 +827,7 @@ process_lock_agent(SocketEntry *e, int lock) fatal("bcrypt_pbkdf"); success = 1; } - explicit_bzero(passwd, pwlen); - free(passwd); + freezero(passwd, pwlen); send_status(e, success); } @@ -547,11 +838,11 @@ no_identities(SocketEntry *e) int r; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); sshbuf_free(msg); } @@ -560,77 +851,67 @@ static void process_add_smartcard_key(SocketEntry *e) { char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX]; + char **comments = NULL; int r, i, count = 0, success = 0, confirm = 0; - u_int seconds; + u_int seconds = 0; time_t death = 0; - u_char type; struct sshkey **keys = NULL, *k; Identity *id; + debug2_f("entering"); 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)); + error_fr(r, "parse"); 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 (parse_key_constraints(e->request, NULL, &death, &seconds, &confirm, + NULL) != 0) { + error_f("failed to parse constraints"); + 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) { + if (match_pattern_list(canonical_provider, allowed_providers, 0) != 1) { verbose("refusing PKCS#11 add of \"%.100s\": " - "provider not whitelisted", canonical_provider); + "provider not allowed", canonical_provider); goto send; } - debug("%s: add %.100s", __func__, canonical_provider); + debug_f("add %.100s", canonical_provider); if (lifetime && !death) death = monotime() + lifetime; - count = pkcs11_add_provider(canonical_provider, pin, &keys); + count = pkcs11_add_provider(canonical_provider, pin, &keys, &comments); for (i = 0; i < count; i++) { k = keys[i]; if (lookup_identity(k) == NULL) { id = xcalloc(1, sizeof(Identity)); id->key = k; + keys[i] = NULL; /* transferred */ id->provider = xstrdup(canonical_provider); - id->comment = xstrdup(canonical_provider); /* XXX */ + if (*comments[i] != '\0') { + id->comment = comments[i]; + comments[i] = NULL; /* transferred */ + } else { + id->comment = xstrdup(canonical_provider); + } id->death = death; id->confirm = confirm; TAILQ_INSERT_TAIL(&idtab->idlist, id, next); idtab->nentries++; success = 1; - } else { - sshkey_free(k); } - keys[i] = NULL; + /* XXX update constraints for existing keys */ + sshkey_free(keys[i]); + free(comments[i]); } send: free(pin); free(provider); free(keys); + free(comments); send_status(e, success); } @@ -641,9 +922,10 @@ process_remove_smartcard_key(SocketEntry *e) int r, success = 0; Identity *id, *nxt; + debug2_f("entering"); 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)); + error_fr(r, "parse"); goto send; } free(pin); @@ -654,7 +936,7 @@ process_remove_smartcard_key(SocketEntry *e) goto send; } - debug("%s: remove %.100s", __func__, canonical_provider); + debug_f("remove %.100s", canonical_provider); for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) { nxt = TAILQ_NEXT(id, next); /* Skip file--based keys */ @@ -669,15 +951,17 @@ process_remove_smartcard_key(SocketEntry *e) if (pkcs11_del_provider(canonical_provider) == 0) success = 1; else - error("%s: pkcs11_del_provider failed", __func__); + error_f("pkcs11_del_provider failed"); send: free(provider); send_status(e, success); } #endif /* ENABLE_PKCS11 */ -/* dispatch incoming messages */ - +/* + * dispatch incoming message. + * returns 1 on success, 0 for incomplete messages or -1 on error. + */ static int process_message(u_int socknum) { @@ -687,10 +971,8 @@ process_message(u_int socknum) int r; SocketEntry *e; - if (socknum >= sockets_alloc) { - fatal("%s: socket number %u >= allocated %u", - __func__, socknum, sockets_alloc); - } + if (socknum >= sockets_alloc) + fatal_f("sock %u >= allocated %u", socknum, sockets_alloc); e = &sockets[socknum]; if (sshbuf_len(e->input) < 5) @@ -698,8 +980,8 @@ process_message(u_int socknum) 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); + debug_f("socket %u (fd=%d) message too long %u > %u", + socknum, e->fd, msg_len, AGENT_MAX_LEN); return -1; } if (sshbuf_len(e->input) < msg_len + 4) @@ -711,13 +993,13 @@ process_message(u_int socknum) (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)); + error_fr(r, "parse"); return -1; } - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); } - debug("%s: socket %u (fd=%d) type %d", __func__, socknum, e->fd, type); + debug_f("socket %u (fd=%d) type %d", socknum, e->fd, type); /* check whether agent is locked */ if (locked && type != SSH_AGENTC_UNLOCK) { @@ -731,7 +1013,7 @@ process_message(u_int socknum) /* send a fail message for all other request types */ send_status(e, 0); } - return 0; + return 1; } switch (type) { @@ -775,7 +1057,7 @@ process_message(u_int socknum) send_status(e, 0); break; } - return 0; + return 1; } static void @@ -783,6 +1065,8 @@ new_socket(sock_type type, int fd) { u_int i, old_alloc, new_alloc; + debug_f("type = %s", type == AUTH_CONNECTION ? "CONNECTION" : + (type == AUTH_SOCKET ? "SOCKET" : "UNKNOWN")); set_nonblock(fd); if (fd > max_fd) @@ -791,28 +1075,25 @@ new_socket(sock_type type, int 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__); + if ((sockets[i].input = sshbuf_new()) == NULL || + (sockets[i].output = sshbuf_new()) == NULL || + (sockets[i].request = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); sockets[i].type = type; return; } old_alloc = sockets_alloc; new_alloc = sockets_alloc + 10; - sockets = xreallocarray(sockets, new_alloc, sizeof(sockets[0])); + sockets = xrecallocarray(sockets, old_alloc, 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__); + if ((sockets[old_alloc].input = sshbuf_new()) == NULL || + (sockets[old_alloc].output = sshbuf_new()) == NULL || + (sockets[old_alloc].request = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); sockets[old_alloc].type = type; } @@ -857,16 +1138,20 @@ handle_conn_read(u_int socknum) 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)); + error_f("read error on socket %u (fd %d): %s", + 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)); + fatal_fr(r, "compose"); explicit_bzero(buf, sizeof(buf)); - process_message(socknum); + for (;;) { + if ((r = process_message(socknum)) == -1) + return -1; + else if (r == 0) + break; + } return 0; } @@ -884,14 +1169,13 @@ handle_conn_write(u_int socknum) 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)); + error_f("read error on socket %u (fd %d): %s", + 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)); + fatal_fr(r, "consume"); return 0; } @@ -913,7 +1197,7 @@ after_poll(struct pollfd *pfd, size_t npfd, u_int maxfds) break; } if (socknum >= sockets_alloc) { - error("%s: no socket for fd %d", __func__, pfd[i].fd); + error_f("no socket for fd %d", pfd[i].fd); continue; } /* Process events */ @@ -974,7 +1258,7 @@ prepare_poll(struct pollfd **pfdp, size_t *npfdp, int *timeoutp, u_int maxfds) } if (npfd != *npfdp && (pfd = recallocarray(pfd, *npfdp, npfd, sizeof(*pfd))) == NULL) - fatal("%s: recallocarray failed", __func__); + fatal_f("recallocarray failed"); *pfdp = pfd; *npfdp = npfd; @@ -1003,10 +1287,8 @@ prepare_poll(struct pollfd **pfdp, size_t *npfdp, int *timeoutp, u_int maxfds) (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)); - } + else if (r != SSH_ERR_NO_BUFFER_SPACE) + fatal_fr(r, "reserve"); if (sshbuf_len(sockets[i].output) > 0) pfd[j].events |= POLLOUT; j++; @@ -1035,7 +1317,7 @@ cleanup_socket(void) { if (cleanup_pid != 0 && getpid() != cleanup_pid) return; - debug("%s: cleanup", __func__); + debug_f("cleanup"); if (socket_name[0]) unlink(socket_name); if (socket_dir[0]) @@ -1079,7 +1361,9 @@ 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" + " [-P allowed_providers] [-t life]\n" + " ssh-agent [-a bind_address] [-E fingerprint_hash] [-P allowed_providers]\n" + " [-t life] command [arg ...]\n" " ssh-agent [-c | -s] -k\n"); exit(1); } @@ -1088,7 +1372,7 @@ 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; + int sock, ch, result, saved_errno; char *shell, *format, *pidstr, *agentsocket = NULL; #ifdef HAVE_SETRLIMIT struct rlimit rlim; @@ -1113,13 +1397,15 @@ main(int ac, char **av) platform_disable_tracing(0); /* strict=no */ +#ifdef RLIMIT_NOFILE if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) fatal("%s: getrlimit: %s", __progname, strerror(errno)); +#endif __progname = ssh_get_progname(av[0]); seed_rng(); - while ((ch = getopt(ac, av, "cDdksE:a:P:t:")) != -1) { + while ((ch = getopt(ac, av, "cDdksE:a:O:P:t:")) != -1) { switch (ch) { case 'E': fingerprint_hash = ssh_digest_alg_by_name(optarg); @@ -1134,10 +1420,16 @@ main(int ac, char **av) case 'k': k_flag++; break; + case 'O': + if (strcmp(optarg, "no-restrict-websafe") == 0) + restrict_websafe = 0; + else + fatal("Unknown -O option"); + break; case 'P': - if (pkcs11_whitelist != NULL) + if (allowed_providers != NULL) fatal("-P option already specified"); - pkcs11_whitelist = xstrdup(optarg); + allowed_providers = xstrdup(optarg); break; case 's': if (c_flag) @@ -1173,8 +1465,8 @@ main(int ac, char **av) 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 (allowed_providers == NULL) + allowed_providers = xstrdup(DEFAULT_ALLOWED_PROVIDERS); if (ac == 0 && !c_flag && !s_flag) { shell = getenv("SHELL"); @@ -1300,14 +1592,8 @@ main(int ac, char **av) } (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); - } + if (stdfd_devnull(1, 1, 1) == -1) + error_f("stdfd_devnull failed"); #ifdef HAVE_SETRLIMIT /* deny core dumps, since memory contains unencrypted private keys */ @@ -1329,10 +1615,10 @@ skip: 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); + ssh_signal(SIGPIPE, SIG_IGN); + ssh_signal(SIGINT, (d_flag | D_flag) ? cleanup_handler : SIG_IGN); + ssh_signal(SIGHUP, cleanup_handler); + ssh_signal(SIGTERM, cleanup_handler); if (pledge("stdio rpath cpath unix id proc exec", NULL) == -1) fatal("%s: pledge: %s", __progname, strerror(errno)); diff --git a/ssh-dss.c b/ssh-dss.c index a23c383dc..fddc29cc9 100644 --- a/ssh-dss.c +++ b/ssh-dss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-dss.c,v 1.37 2018/02/07 02:06:51 jsing Exp $ */ +/* $OpenBSD: ssh-dss.c,v 1.39 2020/02/26 13:40:09 jsg Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -200,10 +200,8 @@ ssh_dss_verify(const struct sshkey *key, BN_clear_free(sig_s); sshbuf_free(b); free(ktype); - if (sigblob != NULL) { - explicit_bzero(sigblob, len); - free(sigblob); - } + if (sigblob != NULL) + freezero(sigblob, len); return ret; } #endif /* WITH_OPENSSL */ diff --git a/ssh-ecdsa-sk.c b/ssh-ecdsa-sk.c new file mode 100644 index 000000000..c6927ecb2 --- /dev/null +++ b/ssh-ecdsa-sk.c @@ -0,0 +1,324 @@ +/* $OpenBSD: ssh-ecdsa-sk.c,v 1.8 2020/06/22 23:44:27 djm Exp $ */ +/* + * Copyright (c) 2000 Markus Friedl. All rights reserved. + * Copyright (c) 2010 Damien Miller. All rights reserved. + * Copyright (c) 2019 Google Inc. 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. + */ + +/* #define DEBUG_SK 1 */ + +#include "includes.h" + +#include + +#ifdef WITH_OPENSSL +#include +#include +#include +#include +#endif + +#include +#include /* needed for DEBUG_SK only */ + +#include "openbsd-compat/openssl-compat.h" + +#include "sshbuf.h" +#include "ssherr.h" +#include "digest.h" +#define SSHKEY_INTERNAL +#include "sshkey.h" + +#ifndef OPENSSL_HAS_ECC +/* ARGSUSED */ +int +ssh_ecdsa_sk_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat, + struct sshkey_sig_details **detailsp) +{ + return SSH_ERR_FEATURE_UNSUPPORTED; +} +#else /* OPENSSL_HAS_ECC */ + +/* + * Check FIDO/W3C webauthn signatures clientData field against the expected + * format and prepare a hash of it for use in signature verification. + * + * webauthn signatures do not sign the hash of the message directly, but + * instead sign a JSON-like "clientData" wrapper structure that contains the + * message hash along with a other information. + * + * Fortunately this structure has a fixed format so it is possible to verify + * that the hash of the signed message is present within the clientData + * structure without needing to implement any JSON parsing. + */ +static int +webauthn_check_prepare_hash(const u_char *data, size_t datalen, + const char *origin, const struct sshbuf *wrapper, + uint8_t flags, const struct sshbuf *extensions, + u_char *msghash, size_t msghashlen) +{ + int r = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *chall = NULL, *m = NULL; + + if ((m = sshbuf_new()) == NULL || + (chall = sshbuf_from(data, datalen)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + /* + * Ensure origin contains no quote character and that the flags are + * consistent with what we received + */ + if (strchr(origin, '\"') != NULL || + (flags & 0x40) != 0 /* AD */ || + ((flags & 0x80) == 0 /* ED */) != (sshbuf_len(extensions) == 0)) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + + /* + * Prepare the preamble to clientData that we expect, poking the + * challenge and origin into their canonical positions in the + * structure. The crossOrigin flag and any additional extension + * fields present are ignored. + */ +#define WEBAUTHN_0 "{\"type\":\"webauthn.get\",\"challenge\":\"" +#define WEBAUTHN_1 "\",\"origin\":\"" +#define WEBAUTHN_2 "\"" + if ((r = sshbuf_put(m, WEBAUTHN_0, sizeof(WEBAUTHN_0) - 1)) != 0 || + (r = sshbuf_dtourlb64(chall, m, 0)) != 0 || + (r = sshbuf_put(m, WEBAUTHN_1, sizeof(WEBAUTHN_1) - 1)) != 0 || + (r = sshbuf_put(m, origin, strlen(origin))) != 0 || + (r = sshbuf_put(m, WEBAUTHN_2, sizeof(WEBAUTHN_2) - 1)) != 0) + goto out; +#ifdef DEBUG_SK + fprintf(stderr, "%s: received origin: %s\n", __func__, origin); + fprintf(stderr, "%s: received clientData:\n", __func__); + sshbuf_dump(wrapper, stderr); + fprintf(stderr, "%s: expected clientData premable:\n", __func__); + sshbuf_dump(m, stderr); +#endif + /* Check that the supplied clientData has the preamble we expect */ + if ((r = sshbuf_cmp(wrapper, 0, sshbuf_ptr(m), sshbuf_len(m))) != 0) + goto out; + + /* Prepare hash of clientData */ + if ((r = ssh_digest_buffer(SSH_DIGEST_SHA256, wrapper, + msghash, msghashlen)) != 0) + goto out; + + /* success */ + r = 0; + out: + sshbuf_free(chall); + sshbuf_free(m); + return r; +} + +/* ARGSUSED */ +int +ssh_ecdsa_sk_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat, + struct sshkey_sig_details **detailsp) +{ + ECDSA_SIG *sig = NULL; + BIGNUM *sig_r = NULL, *sig_s = NULL; + u_char sig_flags; + u_char msghash[32], apphash[32], sighash[32]; + u_int sig_counter; + int is_webauthn = 0, ret = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *b = NULL, *sigbuf = NULL, *original_signed = NULL; + struct sshbuf *webauthn_wrapper = NULL, *webauthn_exts = NULL; + char *ktype = NULL, *webauthn_origin = NULL; + struct sshkey_sig_details *details = NULL; +#ifdef DEBUG_SK + char *tmp = NULL; +#endif + + if (detailsp != NULL) + *detailsp = NULL; + if (key == NULL || key->ecdsa == NULL || + sshkey_type_plain(key->type) != KEY_ECDSA_SK || + signature == NULL || signaturelen == 0) + return SSH_ERR_INVALID_ARGUMENT; + + if (key->ecdsa_nid != NID_X9_62_prime256v1) + return SSH_ERR_INTERNAL_ERROR; + + /* fetch signature */ + if ((b = sshbuf_from(signature, signaturelen)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((details = calloc(1, sizeof(*details))) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (strcmp(ktype, "webauthn-sk-ecdsa-sha2-nistp256@openssh.com") == 0) + is_webauthn = 1; + else if (strcmp(ktype, "sk-ecdsa-sha2-nistp256@openssh.com") != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (sshbuf_froms(b, &sigbuf) != 0 || + sshbuf_get_u8(b, &sig_flags) != 0 || + sshbuf_get_u32(b, &sig_counter) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (is_webauthn) { + if (sshbuf_get_cstring(b, &webauthn_origin, NULL) != 0 || + sshbuf_froms(b, &webauthn_wrapper) != 0 || + sshbuf_froms(b, &webauthn_exts) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + } + if (sshbuf_len(b) != 0) { + ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; + goto out; + } + + /* parse signature */ + if (sshbuf_get_bignum2(sigbuf, &sig_r) != 0 || + sshbuf_get_bignum2(sigbuf, &sig_s) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (sshbuf_len(sigbuf) != 0) { + ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; + goto out; + } + +#ifdef DEBUG_SK + fprintf(stderr, "%s: data: (len %zu)\n", __func__, datalen); + /* sshbuf_dump_data(data, datalen, stderr); */ + fprintf(stderr, "%s: sig_r: %s\n", __func__, (tmp = BN_bn2hex(sig_r))); + free(tmp); + fprintf(stderr, "%s: sig_s: %s\n", __func__, (tmp = BN_bn2hex(sig_s))); + free(tmp); + fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n", + __func__, sig_flags, sig_counter); + if (is_webauthn) { + fprintf(stderr, "%s: webauthn origin: %s\n", __func__, + webauthn_origin); + fprintf(stderr, "%s: webauthn_wrapper:\n", __func__); + sshbuf_dump(webauthn_wrapper, stderr); + } +#endif + 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 */ + + /* Reconstruct data that was supposedly signed */ + if ((original_signed = sshbuf_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (is_webauthn) { + if ((ret = webauthn_check_prepare_hash(data, datalen, + webauthn_origin, webauthn_wrapper, sig_flags, webauthn_exts, + msghash, sizeof(msghash))) != 0) + goto out; + } else if ((ret = ssh_digest_memory(SSH_DIGEST_SHA256, data, datalen, + msghash, sizeof(msghash))) != 0) + goto out; + /* Application value is hashed before signature */ + if ((ret = ssh_digest_memory(SSH_DIGEST_SHA256, key->sk_application, + strlen(key->sk_application), apphash, sizeof(apphash))) != 0) + goto out; +#ifdef DEBUG_SK + fprintf(stderr, "%s: hashed application:\n", __func__); + sshbuf_dump_data(apphash, sizeof(apphash), stderr); + fprintf(stderr, "%s: hashed message:\n", __func__); + sshbuf_dump_data(msghash, sizeof(msghash), stderr); +#endif + if ((ret = sshbuf_put(original_signed, + apphash, sizeof(apphash))) != 0 || + (ret = sshbuf_put_u8(original_signed, sig_flags)) != 0 || + (ret = sshbuf_put_u32(original_signed, sig_counter)) != 0 || + (ret = sshbuf_putb(original_signed, webauthn_exts)) != 0 || + (ret = sshbuf_put(original_signed, msghash, sizeof(msghash))) != 0) + goto out; + /* Signature is over H(original_signed) */ + if ((ret = ssh_digest_buffer(SSH_DIGEST_SHA256, original_signed, + sighash, sizeof(sighash))) != 0) + goto out; + details->sk_counter = sig_counter; + details->sk_flags = sig_flags; +#ifdef DEBUG_SK + fprintf(stderr, "%s: signed buf:\n", __func__); + sshbuf_dump(original_signed, stderr); + fprintf(stderr, "%s: signed hash:\n", __func__); + sshbuf_dump_data(sighash, sizeof(sighash), stderr); +#endif + + /* Verify it */ + switch (ECDSA_do_verify(sighash, sizeof(sighash), 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; + } + /* success */ + if (detailsp != NULL) { + *detailsp = details; + details = NULL; + } + out: + explicit_bzero(&sig_flags, sizeof(sig_flags)); + explicit_bzero(&sig_counter, sizeof(sig_counter)); + explicit_bzero(msghash, sizeof(msghash)); + explicit_bzero(sighash, sizeof(msghash)); + explicit_bzero(apphash, sizeof(apphash)); + sshkey_sig_details_free(details); + sshbuf_free(webauthn_wrapper); + sshbuf_free(webauthn_exts); + free(webauthn_origin); + sshbuf_free(original_signed); + 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 /* OPENSSL_HAS_ECC */ diff --git a/ssh-ed25519-sk.c b/ssh-ed25519-sk.c new file mode 100644 index 000000000..4393ca669 --- /dev/null +++ b/ssh-ed25519-sk.c @@ -0,0 +1,163 @@ +/* $OpenBSD: ssh-ed25519-sk.c,v 1.6 2020/10/18 11:32:02 djm Exp $ */ +/* + * Copyright (c) 2019 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. + */ + +/* #define DEBUG_SK 1 */ + +#include "includes.h" + +#define SSHKEY_INTERNAL +#include +#include + +#include "crypto_api.h" + +#include +#include + +#include "log.h" +#include "sshbuf.h" +#include "sshkey.h" +#include "ssherr.h" +#include "ssh.h" +#include "digest.h" + +int +ssh_ed25519_sk_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat, + struct sshkey_sig_details **detailsp) +{ + struct sshbuf *b = NULL; + struct sshbuf *encoded = NULL; + char *ktype = NULL; + const u_char *sigblob; + const u_char *sm; + u_char *m = NULL; + u_char apphash[32]; + u_char msghash[32]; + u_char sig_flags; + u_int sig_counter; + size_t len; + unsigned long long smlen = 0, mlen = 0; + int r = SSH_ERR_INTERNAL_ERROR; + int ret; + struct sshkey_sig_details *details = NULL; + + if (detailsp != NULL) + *detailsp = NULL; + + if (key == NULL || + sshkey_type_plain(key->type) != KEY_ED25519_SK || + key->ed25519_pk == NULL || + signature == NULL || signaturelen == 0) + return SSH_ERR_INVALID_ARGUMENT; + + if ((b = sshbuf_from(signature, signaturelen)) == NULL) + return SSH_ERR_ALLOC_FAIL; + if (sshbuf_get_cstring(b, &ktype, NULL) != 0 || + sshbuf_get_string_direct(b, &sigblob, &len) != 0 || + sshbuf_get_u8(b, &sig_flags) != 0 || + sshbuf_get_u32(b, &sig_counter) != 0) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } +#ifdef DEBUG_SK + fprintf(stderr, "%s: data:\n", __func__); + /* sshbuf_dump_data(data, datalen, stderr); */ + fprintf(stderr, "%s: sigblob:\n", __func__); + sshbuf_dump_data(sigblob, len, stderr); + fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n", + __func__, sig_flags, sig_counter); +#endif + if (strcmp(sshkey_ssh_name_plain(key), ktype) != 0) { + r = SSH_ERR_KEY_TYPE_MISMATCH; + goto out; + } + if (sshbuf_len(b) != 0) { + r = SSH_ERR_UNEXPECTED_TRAILING_DATA; + goto out; + } + if (len > crypto_sign_ed25519_BYTES) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (ssh_digest_memory(SSH_DIGEST_SHA256, key->sk_application, + strlen(key->sk_application), apphash, sizeof(apphash)) != 0 || + ssh_digest_memory(SSH_DIGEST_SHA256, data, datalen, + msghash, sizeof(msghash)) != 0) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } +#ifdef DEBUG_SK + fprintf(stderr, "%s: hashed application:\n", __func__); + sshbuf_dump_data(apphash, sizeof(apphash), stderr); + fprintf(stderr, "%s: hashed message:\n", __func__); + sshbuf_dump_data(msghash, sizeof(msghash), stderr); +#endif + if ((details = calloc(1, sizeof(*details))) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + details->sk_counter = sig_counter; + details->sk_flags = sig_flags; + if ((encoded = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (sshbuf_put(encoded, sigblob, len) != 0 || + sshbuf_put(encoded, apphash, sizeof(apphash)) != 0 || + sshbuf_put_u8(encoded, sig_flags) != 0 || + sshbuf_put_u32(encoded, sig_counter) != 0 || + sshbuf_put(encoded, msghash, sizeof(msghash)) != 0) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } +#ifdef DEBUG_SK + fprintf(stderr, "%s: signed buf:\n", __func__); + sshbuf_dump(encoded, stderr); +#endif + sm = sshbuf_ptr(encoded); + smlen = sshbuf_len(encoded); + mlen = smlen; + if ((m = malloc(smlen)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen, + key->ed25519_pk)) != 0) { + debug2_f("crypto_sign_ed25519_open failed: %d", ret); + } + if (ret != 0 || mlen != smlen - len) { + r = SSH_ERR_SIGNATURE_INVALID; + goto out; + } + /* XXX compare 'm' and 'sm + len' ? */ + /* success */ + r = 0; + if (detailsp != NULL) { + *detailsp = details; + details = NULL; + } + out: + if (m != NULL) + freezero(m, smlen); /* NB mlen may be invalid if r != 0 */ + sshkey_sig_details_free(details); + sshbuf_free(b); + sshbuf_free(encoded); + free(ktype); + return r; +} diff --git a/ssh-ed25519.c b/ssh-ed25519.c index 5163e0297..23419f3c8 100644 --- a/ssh-ed25519.c +++ b/ssh-ed25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-ed25519.c,v 1.7 2016/04/21 06:08:02 djm Exp $ */ +/* $OpenBSD: ssh-ed25519.c,v 1.9 2020/10/18 11:32:02 djm Exp $ */ /* * Copyright (c) 2013 Markus Friedl * @@ -83,10 +83,8 @@ ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, r = 0; out: sshbuf_free(b); - if (sig != NULL) { - explicit_bzero(sig, slen); - free(sig); - } + if (sig != NULL) + freezero(sig, slen); return r; } @@ -142,8 +140,7 @@ ssh_ed25519_verify(const struct sshkey *key, memcpy(sm+len, data, datalen); if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen, key->ed25519_pk)) != 0) { - debug2("%s: crypto_sign_ed25519_open failed: %d", - __func__, ret); + debug2_f("crypto_sign_ed25519_open failed: %d", ret); } if (ret != 0 || mlen != datalen) { r = SSH_ERR_SIGNATURE_INVALID; @@ -153,14 +150,10 @@ ssh_ed25519_verify(const struct sshkey *key, /* success */ r = 0; out: - if (sm != NULL) { - explicit_bzero(sm, smlen); - free(sm); - } - if (m != NULL) { - explicit_bzero(m, smlen); /* NB mlen may be invalid if r != 0 */ - free(m); - } + if (sm != NULL) + freezero(sm, smlen); + if (m != NULL) + freezero(m, smlen); /* NB mlen may be invalid if r != 0 */ sshbuf_free(b); free(ktype); return r; diff --git a/ssh-gss.h b/ssh-gss.h index 36180d07a..a8af117d2 100644 --- a/ssh-gss.h +++ b/ssh-gss.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-gss.h,v 1.14 2018/07/10 09:13:30 djm Exp $ */ +/* $OpenBSD: ssh-gss.h,v 1.15 2021/01/27 10:05:28 djm Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. * @@ -122,7 +122,7 @@ void ssh_gssapi_build_ctx(Gssctxt **); void ssh_gssapi_delete_ctx(Gssctxt **); OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); void ssh_gssapi_buildmic(struct sshbuf *, const char *, - const char *, const char *); + const char *, const char *, const struct sshbuf *); int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); /* In the server */ diff --git a/ssh-keygen.1 b/ssh-keygen.1 index 957d2f0f0..43c8aa2f5 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.171 2019/10/03 17:07:50 jmc Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.212 2020/11/27 10:12:30 dtucker Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -35,27 +35,33 @@ .\" (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: October 3 2019 $ +.Dd $Mdocdate: November 27 2020 $ .Dt SSH-KEYGEN 1 .Os .Sh NAME .Nm ssh-keygen -.Nd authentication key generation, management and conversion +.Nd OpenSSH authentication key utility .Sh SYNOPSIS .Nm ssh-keygen .Op Fl q +.Op Fl a Ar rounds .Op Fl b Ar bits .Op Fl C Ar comment .Op Fl f Ar output_keyfile .Op Fl m Ar format .Op Fl N Ar new_passphrase -.Op Fl t Cm dsa | ecdsa | ed25519 | rsa +.Op Fl O Ar option +.Op Fl t Cm dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa +.Op Fl w Ar provider +.Op Fl Z Ar cipher .Nm ssh-keygen .Fl p +.Op Fl a Ar rounds .Op Fl f Ar keyfile .Op Fl m Ar format .Op Fl N Ar new_passphrase .Op Fl P Ar old_passphrase +.Op Fl Z Ar cipher .Nm ssh-keygen .Fl i .Op Fl f Ar input_keyfile @@ -69,6 +75,7 @@ .Op Fl f Ar input_keyfile .Nm ssh-keygen .Fl c +.Op Fl a Ar rounds .Op Fl C Ar comment .Op Fl f Ar keyfile .Op Fl P Ar passphrase @@ -90,6 +97,10 @@ .Fl H .Op Fl f Ar known_hosts_file .Nm ssh-keygen +.Fl K +.Op Fl a Ar rounds +.Op Fl w Ar provider +.Nm ssh-keygen .Fl R Ar hostname .Op Fl f Ar known_hosts_file .Nm ssh-keygen @@ -97,20 +108,14 @@ .Op Fl g .Op Fl f Ar input_keyfile .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 +.Fl M Cm generate +.Op Fl O Ar option +.Ar output_file .Nm ssh-keygen -.Fl f Ar input_file -.Fl T Ar output_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 +.Fl M Cm screen +.Op Fl f Ar input_file +.Op Fl O Ar option +.Ar output_file .Nm ssh-keygen .Fl I Ar certificate_identity .Fl s Ar ca_key @@ -126,6 +131,7 @@ .Op Fl f Ar input_keyfile .Nm ssh-keygen .Fl A +.Op Fl a Ar rounds .Op Fl f Ar prefix_path .Nm ssh-keygen .Fl k @@ -136,9 +142,14 @@ .Ar .Nm ssh-keygen .Fl Q +.Op Fl l .Fl f Ar krl_file .Ar .Nm ssh-keygen +.Fl Y Cm find-principals +.Fl s Ar signature_file +.Fl f Ar allowed_signers_file +.Nm ssh-keygen .Fl Y Cm check-novalidate .Fl n Ar namespace .Fl s Ar signature_file @@ -188,7 +199,9 @@ 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 +.Pa ~/.ssh/id_ecdsa_sk , +.Pa ~/.ssh/id_ed25519 , +.Pa ~/.ssh/id_ed25519_sk or .Pa ~/.ssh/id_rsa . Additionally, the system administrator may use this to generate host keys, @@ -242,7 +255,9 @@ 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 +After a key is generated, +.Nm +will ask where the keys should be placed to be activated. .Pp The options are as follows: @@ -261,14 +276,12 @@ This is used by 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. +(key derivation function, currently +.Xr bcrypt_pbkdf 3 ) +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. +The default is 16 rounds. .It Fl B Show the bubblebabble digest of specified private or public key file. .It Fl b Ar bits @@ -282,7 +295,7 @@ 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 +ECDSA-SK, Ed25519 and Ed25519-SK keys have a fixed length and the .Fl b flag will be ignored. .It Fl C Ar comment @@ -329,12 +342,6 @@ used in conjunction with the 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 @@ -375,24 +382,12 @@ 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 +Download resident keys from a FIDO authenticator. +Public and private key files will be written to the current directory for +each downloaded key. +If multiple FIDO authenticators are attached, keys will be downloaded from +the first touched authenticator. .It Fl k Generate a KRL file. In this mode, @@ -415,9 +410,26 @@ 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 Cm generate +Generate candidate Diffie-Hellman Group Exchange (DH-GEX) parameters for +eventual use by the +.Sq diffie-hellman-group-exchange-* +key exchange methods. +The numbers generated by this operation must be further screened before +use. +See the +.Sx MODULI GENERATION +section for more information. +.It Fl M Cm screen +Screen candidate parameters for Diffie-Hellman Group Exchange. +This will accept a list of candidate numbers and test that they are +safe (Sophie Germain) primes with acceptable group generators. +The results of this operation may be added to the +.Pa /etc/moduli +file. +See the +.Sx MODULI GENERATION +section for more information. .It Fl m Ar key_format Specify a key format for key generation, the .Fl i @@ -453,13 +465,451 @@ 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. +Specify a key/value option. +These are specific to the operation that +.Nm +has been requested to perform. +.Pp +When signing certificates, one of the options listed in the +.Sx CERTIFICATES +section may be specified here. +.Pp +When performing moduli generation or screening, one of the options +listed in the +.Sx MODULI GENERATION +section may be specified. +.Pp +When generating a key that will be hosted on a FIDO authenticator, +this flag may be used to specify key-specific options. +Those supported at present are: +.Bl -tag -width Ds +.It Cm application +Override the default FIDO application/origin string of +.Dq ssh: . +This may be useful when generating host or domain-specific resident keys. +The specified application string must begin with +.Dq ssh: . +.It Cm challenge Ns = Ns Ar path +Specifies a path to a challenge string that will be passed to the +FIDO token during key generation. +The challenge string may be used as part of an out-of-band +protocol for key enrollment +(a random challenge is used by default). +.It Cm device +Explicitly specify a +.Xr fido 4 +device to use, rather than letting the token middleware select one. +.It Cm no-touch-required +Indicate that the generated private key should not require touch +events (user presence) when making signatures. +Note that +.Xr sshd 8 +will refuse such signatures by default, unless overridden via +an authorized_keys option. +.It Cm resident +Indicate that the key should be stored on the FIDO authenticator itself. +Resident keys may be supported on FIDO2 tokens and typically require that +a PIN be set on the token prior to generation. +Resident keys may be loaded off the token using +.Xr ssh-add 1 . +.It Cm user +A username to be associated with a resident key, +overriding the empty default username. +Specifying a username may be useful when generating multiple resident keys +for the same application name. +.It Cm verify-required +Indicate that this private key should require user verification for +each signature. +Not all FIDO tokens support this option. +Currently PIN authentication is the only supported verification method, +but other methods may be supported in the future. +.It Cm write-attestation Ns = Ns Ar path +May be used at key generation time to record the attestation data +returned from FIDO tokens during key generation. +Please note that this information is potentially sensitive. +By default, this information is discarded. +.El +.Pp +The +.Fl O +option may be specified multiple times. +.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. +If the +.Fl l +option is also specified then the contents of the KRL will be printed. +.It Fl q +Silence +.Nm ssh-keygen . +.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 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 Cm dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa +Specifies the type of key to create. +The possible values are +.Dq dsa , +.Dq ecdsa , +.Dq ecdsa-sk , +.Dq ed25519 , +.Dq ed25519-sk , +or +.Dq rsa . +.Pp +This flag may also be used to specify the desired signature type when +signing certificates using an RSA CA key. +The available RSA signature variants are +.Dq ssh-rsa +(SHA1 signatures, not recommended), +.Dq rsa-sha2-256 , +and +.Dq rsa-sha2-512 +(the default). +.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 expiry 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 provider +Specifies a path to a library that will be used when creating +FIDO authenticator-hosted keys, overriding the default of using +the internal USB HID support. +.It Fl Y Cm find-principals +Find the principal(s) associated with the public key of a signature, +provided using the +.Fl s +flag in an authorized signers file provided using the +.Fl f +flag. +The format of the allowed signers file is documented in the +.Sx ALLOWED SIGNERS +section below. +If one or more matching principals are found, they are returned on +standard output. +.It Fl Y Cm check-novalidate +Checks that a signature generated using +.Nm +.Fl Y Cm sign +has a valid structure. +This does not validate if a signature comes from an authorized signer. +When testing a signature, +.Nm +accepts a message on standard input and a signature namespace using +.Fl n . +A file containing the corresponding signature must also be supplied using the +.Fl s +flag. +Successful testing of the signature is signalled by +.Nm +returning a zero exit status. +.It Fl Y Cm sign +Cryptographically sign a file or some data using a SSH key. +When signing, +.Nm +accepts zero or more files to sign on the command-line - if no files +are specified then +.Nm +will sign data presented on standard input. +Signatures are written to the path of the input file with +.Dq .sig +appended, or to standard output if the message to be signed was read from +standard input. +.Pp +The key used for signing is specified using the +.Fl f +option and may refer to either a private key, or a public key with the private +half available via +.Xr ssh-agent 1 . +An additional signature namespace, used to prevent signature confusion across +different domains of use (e.g. file signing vs email signing) must be provided +via the +.Fl n +flag. +Namespaces are arbitrary strings, and may include: +.Dq file +for file signing, +.Dq email +for email signing. +For custom uses, it is recommended to use names following a +NAMESPACE@YOUR.DOMAIN pattern to generate unambiguous namespaces. +.It Fl Y Cm verify +Request to verify a signature generated using +.Nm +.Fl Y Cm sign +as described above. +When verifying a signature, +.Nm +accepts a message on standard input and a signature namespace using +.Fl n . +A file containing the corresponding signature must also be supplied using the +.Fl s +flag, along with the identity of the signer using +.Fl I +and a list of allowed signers via the +.Fl f +flag. +The format of the allowed signers file is documented in the +.Sx ALLOWED SIGNERS +section below. +A file containing revoked keys can be passed using the +.Fl r +flag. +The revocation file may be a KRL or a one-per-line list of public keys. +Successful verification by an authorized signer is signalled by +.Nm +returning a zero exit status. +.It Fl y +This option will read a private +OpenSSH format file and print an OpenSSH public key to stdout. +.It Fl Z Ar cipher +Specifies the cipher to use for encryption when writing an OpenSSH-format +private key file. +The list of available ciphers may be obtained using +.Qq ssh -Q cipher . +The default is +.Dq aes256-ctr . +.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 M Cm generate +option. +The desired length of the primes may be specified by the +.Fl O Cm bits +option. +For example: +.Pp +.Dl # ssh-keygen -M generate -O bits=2048 moduli-2048.candidates +.Pp +By default, the search for primes begins at a random point in the +desired length range. +This may be overridden using the +.Fl O Cm start +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 M Cm screen +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 -M screen -f moduli-2048.candidates moduli-2048 +.Pp +By default, each candidate will be subjected to 100 primality tests. +This may be overridden using the +.Fl O Cm prime-tests +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 O Cm generator +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. +.Pp +A number of options are available for moduli generation and screening via the +.Fl O +flag: +.Bl -tag -width Ds +.It Ic lines Ns = Ns Ar number +Exit after screening the specified number of lines while performing DH +candidate screening. +.It Ic start-line Ns = Ns Ar line-number +Start screening at the specified line number while performing DH candidate +screening. +.It Ic checkpoint Ns = Ns Ar filename +Write the last line processed to the specified file while performing DH +candidate screening. +This will be used to skip lines in the input file that have already been +processed if the job is restarted. +.It Ic memory Ns = Ns Ar mbytes +Specify the amount of memory to use (in megabytes) when generating +candidate moduli for DH-GEX. +.It Ic start Ns = Ns Ar hex-value +Specify start point (in hex) when generating candidate moduli for DH-GEX. +.It Ic generator Ns = Ns Ar value +Specify desired generator (in decimal) when testing candidate moduli for DH-GEX. +.El +.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. .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 @@ -530,347 +980,33 @@ by .It Ic permit-X11-forwarding Allows X11 forwarding. .Pp +.It Ic no-touch-required +Do not require signatures made using this key include demonstration +of user presence (e.g. by having the user touch the authenticator). +This option only makes sense for the FIDO authenticator algorithms +.Cm ecdsa-sk +and +.Cm ed25519-sk . +.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 | [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 . -.Pp -This flag may also be used to specify the desired signature type when -signing certificates using an RSA CA key. -The available RSA signature variants are -.Dq ssh-rsa -(SHA1 signatures, not recommended), -.Dq rsa-sha2-256 , +.It Ic verify-required +Require signatures made using this key indicate that the user was first +verified. +This option only makes sense for the FIDO authenticator algorithms +.Cm ecdsa-sk and -.Dq rsa-sha2-512 -(the default). -.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 Y Cm sign -Cryptographically sign a file or some data using a SSH key. -When signing, -.Nm -accepts zero or more files to sign on the command-line - if no files -are specified then -.Nm -will sign data presented on standard input. -Signatures are written to the path of the input file with -.Dq .sig -appended, or to standard output if the message to be signed was read from -standard input. -.Pp -The key used for signing is specified using the -.Fl f -option and may refer to either a private key, or a public key with the private -half available via -.Xr ssh-agent 1 . -An additional signature namespace, used to prevent signature confusion across -different domains of use (e.g. file signing vs email signing) must be provided -via the -.Fl n -flag. -Namespaces are arbitrary strings, and may include: -.Dq file -for file signing, -.Dq email -for email signing. -For custom uses, it is recommended to use names following a -NAMESPACE@YOUR.DOMAIN pattern to generate unambiguous namespaces. -.It Fl Y Cm verify -Request to verify a signature generated using -.Nm -.Fl Y Cm sign -as described above. -When verifying a signature, -.Nm -accepts a message on standard input and a signature namespace using -.Fl n . -A file containing the corresponding signature must also be supplied using the -.Fl s -flag, along with the identity of the signer using -.Fl I -and a list of allowed signers via the -.Fl f -flag. -The format of the allowed signers file is documented in the -.Sx ALLOWED SIGNERS -section below. -A file containing revoked keys can be passed using the -.Fl r -flag. -The revocation file may be a KRL or a one-per-line list of public keys. -Successful verification by an authorized signer is signalled by -.Nm -.It Fl Y Cm check-novalidate -Checks that a signature generated using -.Nm -.Fl Y Cm sign -has a valid structure. -This does not validate if a signature comes from an authorized signer. -When testing a signature, -.Nm -accepts a message on standard input and a signature namespace using -.Fl n . -A file containing the corresponding signature must also be supplied using the -.Fl s -flag. -Successful testing of the signature is signalled by -.Nm -returning a zero exit status. -.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. +.Cm ed25519-sk . +Currently PIN authentication is the only supported verification method, +but other methods may be supported in the future. .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. +At present, no standard options are valid for host keys. .Pp Finally, certificates may be defined with a validity lifetime. The @@ -878,7 +1014,7 @@ The 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 +By default, certificates are valid from the .Ux Epoch to the distant future. .Pp @@ -982,13 +1118,13 @@ Empty lines and lines starting with a .Ql # are ignored as comments. .Pp -The principals field is a pattern-list (See PATTERNS in +The principals field is a pattern-list (see PATTERNS in .Xr ssh_config 5 ) consisting of one or more comma-separated USER@DOMAIN identity patterns that are accepted for signing. When verifying, the identity presented via the -.Fl I option -must match a principals pattern in order for the corresponding key to be +.Fl I +option must match a principals pattern in order for the corresponding key to be considered acceptable for verification. .Pp The options (if present) consist of comma-separated option specifications. @@ -1019,14 +1155,23 @@ user1@example.com,user2@example.com ssh-rsa AAAAX1... # A key that is accepted only for file signing. user2@example.com namespaces="file" ssh-ed25519 AAA41... .Ed +.Sh ENVIRONMENT +.Bl -tag -width Ds +.It Ev SSH_SK_PROVIDER +Specifies a path to a library that will be used when loading any +FIDO authenticator-hosted keys, overriding the default of using +the built-in USB HID support. +.El .Sh FILES .Bl -tag -width Ds -compact .It Pa ~/.ssh/id_dsa .It Pa ~/.ssh/id_ecdsa +.It Pa ~/.ssh/id_ecdsa_sk .It Pa ~/.ssh/id_ed25519 +.It Pa ~/.ssh/id_ed25519_sk .It Pa ~/.ssh/id_rsa -Contains the DSA, ECDSA, Ed25519 or RSA -authentication identity of the user. +Contains the DSA, ECDSA, authenticator-hosted ECDSA, Ed25519, +authenticator-hosted 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 @@ -1039,10 +1184,12 @@ 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_ecdsa_sk.pub .It Pa ~/.ssh/id_ed25519.pub +.It Pa ~/.ssh/id_ed25519_sk.pub .It Pa ~/.ssh/id_rsa.pub -Contains the DSA, ECDSA, Ed25519 or RSA -public key for authentication. +Contains the DSA, ECDSA, authenticator-hosted ECDSA, Ed25519, +authenticator-hosted Ed25519 or RSA public key for authentication. The contents of this file should be added to .Pa ~/.ssh/authorized_keys on all machines diff --git a/ssh-keygen.c b/ssh-keygen.c index ea6989755..a7429645e 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.355 2019/10/03 17:07:50 jmc Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.427 2020/12/20 23:36:51 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -63,6 +63,9 @@ #include "utf8.h" #include "authfd.h" #include "sshsig.h" +#include "ssh-sk.h" +#include "sk-api.h" /* XXX for SSH_SK_USER_PRESENCE_REQD; remove */ +#include "cipher.h" #ifdef WITH_OPENSSL # define DEFAULT_KEY_TYPE_NAME "rsa" @@ -118,11 +121,12 @@ 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_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_NO_REQUIRE_USER_PRESENCE (1<<5) #define CERTOPT_DEFAULT (CERTOPT_X_FWD|CERTOPT_AGENT_FWD| \ CERTOPT_PORT_FWD|CERTOPT_PTY|CERTOPT_USER_RC) static u_int32_t certflags_flags = CERTOPT_DEFAULT; @@ -130,13 +134,13 @@ static char *certflags_command = NULL; static char *certflags_src_addr = NULL; /* Arbitrary extensions specified by user */ -struct cert_userext { +struct cert_ext { char *key; char *val; int crit; }; -static struct cert_userext *cert_userext; -static size_t ncert_userext; +static struct cert_ext *cert_ext; +static size_t ncert_ext; /* Conversion to/from various formats */ enum { @@ -150,16 +154,16 @@ static char *key_type_name = NULL; /* Load key from this PKCS#11 provider */ static char *pkcs11provider = NULL; +/* FIDO/U2F provider to use */ +static char *sk_provider = NULL; + /* Format for writing private keys */ static int private_key_format = SSHKEY_PRIVATE_OPENSSH; /* Cipher for new-format private keys */ static char *openssh_format_cipher = NULL; -/* - * Number of KDF rounds to derive new format keys / - * number of primality trials when screening moduli. - */ +/* Number of KDF rounds to derive new format keys. */ static int rounds = 0; /* argv0 */ @@ -181,7 +185,7 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) fatal("unknown key type %s", key_type_name); if (*bitsp == 0) { #ifdef WITH_OPENSSL - u_int nid; + int nid; switch(type) { case KEY_DSA: @@ -216,10 +220,11 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) break; case KEY_ECDSA: if (sshkey_ecdsa_bits_to_nid(*bitsp) == -1) - fatal("Invalid ECDSA key length: valid lengths are " #ifdef OPENSSL_HAS_NISTP521 + fatal("Invalid ECDSA key length: valid lengths are " "256, 384 or 521 bits"); #else + fatal("Invalid ECDSA key length: valid lengths are " "256 or 384 bits"); #endif } @@ -269,6 +274,10 @@ ask_filename(struct passwd *pw, const char *prompt) case KEY_ECDSA: name = _PATH_SSH_CLIENT_ID_ECDSA; break; + case KEY_ECDSA_SK_CERT: + case KEY_ECDSA_SK: + name = _PATH_SSH_CLIENT_ID_ECDSA_SK; + break; #endif case KEY_RSA_CERT: case KEY_RSA: @@ -278,6 +287,10 @@ ask_filename(struct passwd *pw, const char *prompt) case KEY_ED25519_CERT: name = _PATH_SSH_CLIENT_ID_ED25519; break; + case KEY_ED25519_SK: + case KEY_ED25519_SK_CERT: + name = _PATH_SSH_CLIENT_ID_ED25519_SK; + break; case KEY_XMSS: case KEY_XMSS_CERT: name = _PATH_SSH_CLIENT_ID_XMSS; @@ -310,16 +323,15 @@ load_identity(const char *filename, char **commentp) if ((r = sshkey_load_private(filename, "", &prv, commentp)) == 0) return prv; if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) - fatal("Load key \"%s\": %s", filename, ssh_err(r)); + fatal_r(r, "Load key \"%s\"", filename); if (identity_passphrase) pass = xstrdup(identity_passphrase); else pass = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN); r = sshkey_load_private(filename, pass, &prv, commentp); - explicit_bzero(pass, strlen(pass)); - free(pass); + freezero(pass, strlen(pass)); if (r != 0) - fatal("Load key \"%s\": %s", filename, ssh_err(r)); + fatal_r(r, "Load key \"%s\"", filename); return prv; } @@ -337,11 +349,11 @@ do_convert_to_ssh2(struct passwd *pw, struct sshkey *k) int r; if ((b = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshkey_putb(k, b)) != 0) - fatal("key_to_blob failed: %s", ssh_err(r)); + fatal_fr(r, "put key"); if ((b64 = sshbuf_dtob64_string(b, 1)) == NULL) - fatal("%s: sshbuf_dtob64_string failed", __func__); + fatal_f("sshbuf_dtob64_string failed"); /* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */ snprintf(comment, sizeof(comment), @@ -378,7 +390,7 @@ do_convert_to_pkcs8(struct sshkey *k) break; #endif default: - fatal("%s: unsupported key type %s", __func__, sshkey_type(k)); + fatal_f("unsupported key type %s", sshkey_type(k)); } exit(0); } @@ -391,8 +403,18 @@ do_convert_to_pem(struct sshkey *k) if (!PEM_write_RSAPublicKey(stdout, k->rsa)) fatal("PEM_write_RSAPublicKey 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)); + fatal_f("unsupported key type %s", sshkey_type(k)); } exit(0); } @@ -421,7 +443,7 @@ do_convert_to(struct passwd *pw) do_convert_to_pem(k); break; default: - fatal("%s: unknown key format %d", __func__, convert_format); + fatal_f("unknown key format %d", convert_format); } exit(0); } @@ -437,15 +459,15 @@ buffer_get_bignum_bits(struct sshbuf *b, BIGNUM *value) int r; if ((r = sshbuf_get_u32(b, &bignum_bits)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); 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)); + fatal_f("input buffer too small: need %d have %zu", + bytes, sshbuf_len(b)); if (BN_bin2bn(sshbuf_ptr(b), bytes, value) == NULL) - fatal("%s: BN_bin2bn failed", __func__); + fatal_f("BN_bin2bn failed"); if ((r = sshbuf_consume(b, bytes)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "consume"); } static struct sshkey * @@ -464,7 +486,7 @@ do_convert_private_ssh2(struct sshbuf *b) BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL; if ((r = sshbuf_get_u32(b, &magic)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse magic"); if (magic != SSH_COM_PRIVATE_KEY_MAGIC) { error("bad magic 0x%x != 0x%x", magic, @@ -477,7 +499,7 @@ do_convert_private_ssh2(struct sshbuf *b) (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)); + fatal_fr(r, "parse"); debug("ignore (%d %d %d %d)", i1, i2, i3, i4); if (strcmp(cipher, "none") != 0) { error("unsupported cipher %s", cipher); @@ -506,24 +528,24 @@ do_convert_private_ssh2(struct sshbuf *b) (dsa_g = BN_new()) == NULL || (dsa_pub_key = BN_new()) == NULL || (dsa_priv_key = BN_new()) == NULL) - fatal("%s: BN_new", __func__); + fatal_f("BN_new"); 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__); + fatal_f("DSA_set0_pqg failed"); 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__); + fatal_f("DSA_set0_key failed"); 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)); + fatal_fr(r, "parse RSA"); e = e1; debug("e %lx", e); if (e < 30) { @@ -535,7 +557,7 @@ do_convert_private_ssh2(struct sshbuf *b) debug("e %lx", e); } if ((rsa_e = BN_new()) == NULL) - fatal("%s: BN_new", __func__); + fatal_f("BN_new"); if (!BN_set_word(rsa_e, e)) { BN_clear_free(rsa_e); sshkey_free(key); @@ -546,30 +568,32 @@ do_convert_private_ssh2(struct sshbuf *b) (rsa_p = BN_new()) == NULL || (rsa_q = BN_new()) == NULL || (rsa_iqmp = BN_new()) == NULL) - fatal("%s: BN_new", __func__); + fatal_f("BN_new"); 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__); + fatal_f("RSA_set0_key failed"); 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__); + fatal_f("RSA_set0_factors failed"); 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)); + fatal_fr(r, "generate RSA parameters"); BN_clear_free(rsa_iqmp); break; } rlen = sshbuf_len(b); if (rlen != 0) - error("%s: remaining bytes in key blob %d", __func__, rlen); + error_f("remaining bytes in key blob %d", rlen); /* 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) { + if (sshkey_sign(key, &sig, &slen, data, sizeof(data), + NULL, NULL, NULL, 0) != 0 || + sshkey_verify(key, sig, slen, data, sizeof(data), + NULL, 0, NULL) != 0) { sshkey_free(key); free(sig); return NULL; @@ -646,11 +670,13 @@ do_convert_from_ssh2(struct passwd *pw, struct sshkey **k, int *private) (encoded[len-3] == '=')) encoded[len-3] = '\0'; if ((r = sshbuf_b64tod(buf, encoded)) != 0) - fatal("%s: base64 decoding failed: %s", __func__, ssh_err(r)); - if (*private) - *k = do_convert_private_ssh2(buf); - else if ((r = sshkey_fromb(buf, k)) != 0) - fatal("decode blob failed: %s", ssh_err(r)); + fatal_fr(r, "base64 decode"); + if (*private) { + if ((*k = do_convert_private_ssh2(buf)) == NULL) + fatal_f("private key conversion failed"); + } else if ((r = sshkey_fromb(buf, k)) != 0) + fatal_fr(r, "parse key"); + sshbuf_free(buf); fclose(fp); } @@ -663,7 +689,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private) 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__, + fatal_f("%s is not a recognised public key format", identity_file); } fclose(fp); @@ -690,7 +716,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private) break; #endif default: - fatal("%s: unsupported pubkey type %d", __func__, + fatal_f("unsupported pubkey type %d", EVP_PKEY_base_id(pubkey)); } EVP_PKEY_free(pubkey); @@ -713,7 +739,7 @@ do_convert_from_pem(struct sshkey **k, int *private) fclose(fp); return; } - fatal("%s: unrecognised raw private key format", __func__); + fatal_f("unrecognised raw private key format"); } static void @@ -739,7 +765,7 @@ do_convert_from(struct passwd *pw) do_convert_from_pem(&k, &private); break; default: - fatal("%s: unknown key format %d", __func__, convert_format); + fatal_f("unknown key format %d", convert_format); } if (!private) { @@ -764,8 +790,7 @@ do_convert_from(struct passwd *pw) NULL, 0, NULL, NULL); break; default: - fatal("%s: unsupported key type %s", __func__, - sshkey_type(k)); + fatal_f("unsupported key type %s", sshkey_type(k)); } } @@ -790,11 +815,15 @@ do_print_public(struct passwd *pw) fatal("%s: %s", identity_file, strerror(errno)); prv = load_identity(identity_file, &comment); if ((r = sshkey_write(prv, stdout)) != 0) - error("sshkey_write failed: %s", ssh_err(r)); - sshkey_free(prv); + fatal_fr(r, "write key"); if (comment != NULL && *comment != '\0') fprintf(stdout, " %s", comment); fprintf(stdout, "\n"); + if (sshkey_is_sk(prv)) { + debug("sk_application: \"%s\", sk_flags 0x%02x", + prv->sk_application, prv->sk_flags); + } + sshkey_free(prv); free(comment); exit(0); } @@ -807,13 +836,13 @@ do_download(struct passwd *pw) int i, nkeys; enum sshkey_fp_rep rep; int fptype; - char *fp, *ra; + char *fp, *ra, **comments = NULL; fptype = print_bubblebabble ? SSH_DIGEST_SHA1 : fingerprint_hash; rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT; pkcs11_init(1); - nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys); + nkeys = pkcs11_add_provider(pkcs11provider, NULL, &keys, &comments); if (nkeys <= 0) fatal("cannot read public key from pkcs11"); for (i = 0; i < nkeys; i++) { @@ -822,7 +851,7 @@ do_download(struct passwd *pw) ra = sshkey_fingerprint(keys[i], fingerprint_hash, SSH_FP_RANDOMART); if (fp == NULL || ra == NULL) - fatal("%s: sshkey_fingerprint fail", __func__); + fatal_f("sshkey_fingerprint fail"); printf("%u %s %s (PKCS11 key)\n", sshkey_size(keys[i]), fp, sshkey_type(keys[i])); if (log_level_get() >= SYSLOG_LEVEL_VERBOSE) @@ -831,10 +860,13 @@ do_download(struct passwd *pw) free(fp); } else { (void) sshkey_write(keys[i], stdout); /* XXX check */ - fprintf(stdout, "\n"); + fprintf(stdout, "%s%s\n", + *(comments[i]) == '\0' ? "" : " ", comments[i]); } + free(comments[i]); sshkey_free(keys[i]); } + free(comments); free(keys); pkcs11_terminate(); exit(0); @@ -870,7 +902,7 @@ fingerprint_one_key(const struct sshkey *public, const char *comment) 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__); + fatal_f("sshkey_fingerprint failed"); mprintf("%u %s %s (%s)\n", sshkey_size(public), fp, comment ? comment : "no comment", sshkey_type(public)); if (log_level_get() >= SYSLOG_LEVEL_VERBOSE) @@ -884,22 +916,25 @@ fingerprint_private(const char *path) { struct stat st; char *comment = NULL; - struct sshkey *public = NULL; + struct sshkey *privkey = NULL, *pubkey = NULL; int r; if (stat(identity_file, &st) == -1) 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_public(path, &pubkey, &comment)) != 0) + debug_r(r, "load public \"%s\"", path); + if (pubkey == NULL || comment == NULL || *comment == '\0') { + free(comment); 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); - } + &privkey, &comment)) != 0) + debug_r(r, "load private \"%s\"", path); } + if (pubkey == NULL && privkey == NULL) + fatal("%s is not a key file.", path); - fingerprint_one_key(public, comment); - sshkey_free(public); + fingerprint_one_key(pubkey == NULL ? privkey : pubkey, comment); + sshkey_free(pubkey); + sshkey_free(privkey); free(comment); } @@ -1027,7 +1062,6 @@ do_gen_all_hostkeys(struct passwd *pw) 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; @@ -1065,26 +1099,25 @@ do_gen_all_hostkeys(struct passwd *pw) 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", + error("Could not save your private key in %s: %s", prv_tmp, strerror(errno)); goto failnext; } - close(fd); /* just using mkstemp() to generate/reserve a name */ + (void)close(fd); /* just using mkstemp() to 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)); + error_r(r, "sshkey_generate failed"); goto failnext; } if ((r = sshkey_from_private(private, &public)) != 0) - fatal("sshkey_from_private failed: %s", ssh_err(r)); + fatal_fr(r, "sshkey_from_private"); snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname); if ((r = sshkey_save_private(private, prv_tmp, "", comment, private_key_format, openssh_format_cipher, rounds)) != 0) { - error("Saving key \"%s\" failed: %s", - prv_tmp, ssh_err(r)); + error_r(r, "Saving key \"%s\" failed", prv_tmp); goto failnext; } if ((fd = mkstemp(pub_tmp)) == -1) { @@ -1094,25 +1127,10 @@ do_gen_all_hostkeys(struct passwd *pw) } (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)); + (void)close(fd); + if ((r = sshkey_save_public(public, pub_tmp, comment)) != 0) { + error_r(r, "Unable to save public key to %s", + identity_file); goto failnext; } @@ -1246,10 +1264,11 @@ known_hosts_find_delete(struct hostkey_foreach_line *l, void *_ctx) ra = sshkey_fingerprint(l->key, fingerprint_hash, SSH_FP_RANDOMART); if (fp == NULL || ra == NULL) - fatal("%s: sshkey_fingerprint failed", - __func__); - mprintf("%s %s %s %s\n", ctx->host, - sshkey_type(l->key), fp, l->comment); + fatal_f("sshkey_fingerprint failed"); + mprintf("%s %s %s%s%s\n", ctx->host, + sshkey_type(l->key), fp, + l->comment[0] ? " " : "", + l->comment); if (log_level_get() >= SYSLOG_LEVEL_VERBOSE) printf("%s\n", ra); free(ra); @@ -1277,6 +1296,7 @@ do_known_hosts(struct passwd *pw, const char *name, int find_host, int r, fd, oerrno, inplace = 0; struct known_hosts_ctx ctx; u_int foreach_options; + struct stat sb; if (!have_identity) { cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid); @@ -1286,6 +1306,8 @@ do_known_hosts(struct passwd *pw, const char *name, int find_host, free(cp); have_identity = 1; } + if (stat(identity_file, &sb) != 0) + fatal("Cannot stat %s: %s", identity_file, strerror(errno)); memset(&ctx, 0, sizeof(ctx)); ctx.out = stdout; @@ -1312,6 +1334,7 @@ do_known_hosts(struct passwd *pw, const char *name, int find_host, unlink(tmp); fatal("fdopen: %s", strerror(oerrno)); } + fchmod(fd, sb.st_mode & 0644); inplace = 1; } /* XXX support identity_file == "-" for stdin */ @@ -1319,10 +1342,10 @@ do_known_hosts(struct passwd *pw, const char *name, int find_host, 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) { + foreach_options, 0)) != 0) { if (inplace) unlink(tmp); - fatal("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r)); + fatal_fr(r, "hostkeys_foreach"); } if (inplace) @@ -1396,13 +1419,12 @@ do_change_passphrase(struct passwd *pw) RP_ALLOW_STDIN); r = sshkey_load_private(identity_file, old_passphrase, &private, &comment); - explicit_bzero(old_passphrase, strlen(old_passphrase)); - free(old_passphrase); + freezero(old_passphrase, strlen(old_passphrase)); if (r != 0) goto badkey; } else if (r != 0) { badkey: - fatal("Failed to load key %s: %s", identity_file, ssh_err(r)); + fatal_r(r, "Failed to load key %s", identity_file); } if (comment) mprintf("Key has comment '%s'\n", comment); @@ -1428,24 +1450,20 @@ do_change_passphrase(struct passwd *pw) exit(1); } /* Destroy the other copy. */ - explicit_bzero(passphrase2, strlen(passphrase2)); - free(passphrase2); + freezero(passphrase2, strlen(passphrase2)); } /* Save the file using the new passphrase. */ if ((r = sshkey_save_private(private, identity_file, passphrase1, comment, private_key_format, openssh_format_cipher, rounds)) != 0) { - error("Saving key \"%s\" failed: %s.", - identity_file, ssh_err(r)); - explicit_bzero(passphrase1, strlen(passphrase1)); - free(passphrase1); + error_r(r, "Saving key \"%s\" failed", identity_file); + freezero(passphrase1, strlen(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); + freezero(passphrase1, strlen(passphrase1)); sshkey_free(private); /* Destroys contents */ free(comment); @@ -1466,15 +1484,14 @@ do_print_resource_record(struct passwd *pw, char *fname, char *hname, int r; if (fname == NULL) - fatal("%s: no filename", __func__); + fatal_f("no filename"); if (stat(fname, &st) == -1) { 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)); + fatal_r(r, "Failed to read v2 public key from \"%s\"", fname); export_dns_rr(hname, public, stdout, print_generic); sshkey_free(public); free(comment); @@ -1491,8 +1508,7 @@ do_change_comment(struct passwd *pw, const char *identity_comment) struct sshkey *private; struct sshkey *public; struct stat st; - FILE *f; - int r, fd; + int r; if (!have_identity) ask_filename(pw, "Enter file in which the key is"); @@ -1502,8 +1518,7 @@ do_change_comment(struct passwd *pw, const char *identity_comment) &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)); + fatal_r(r, "Cannot load private key \"%s\"", identity_file); else { if (identity_passphrase) passphrase = xstrdup(identity_passphrase); @@ -1515,10 +1530,9 @@ do_change_comment(struct passwd *pw, const char *identity_comment) /* 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)); + freezero(passphrase, strlen(passphrase)); + fatal_r(r, "Cannot load private key \"%s\"", + identity_file); } } @@ -1559,33 +1573,21 @@ do_change_comment(struct passwd *pw, const char *identity_comment) if ((r = sshkey_save_private(private, identity_file, passphrase, new_comment, private_key_format, openssh_format_cipher, rounds)) != 0) { - error("Saving key \"%s\" failed: %s", - identity_file, ssh_err(r)); - explicit_bzero(passphrase, strlen(passphrase)); - free(passphrase); + error_r(r, "Saving key \"%s\" failed", identity_file); + freezero(passphrase, strlen(passphrase)); sshkey_free(private); free(comment); exit(1); } - explicit_bzero(passphrase, strlen(passphrase)); - free(passphrase); + freezero(passphrase, strlen(passphrase)); if ((r = sshkey_from_private(private, &public)) != 0) - fatal("sshkey_from_private failed: %s", ssh_err(r)); + fatal_fr(r, "sshkey_from_private"); 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)); + if ((r = sshkey_save_public(public, identity_file, new_comment)) != 0) + fatal_r(r, "Unable to save public key to %s", identity_file); sshkey_free(public); - fprintf(f, " %s\n", new_comment); - fclose(f); - free(comment); if (strlen(new_comment) > 0) @@ -1597,31 +1599,32 @@ do_change_comment(struct passwd *pw, const char *identity_comment) } static void -add_flag_option(struct sshbuf *c, const char *name) +cert_ext_add(const char *key, const char *value, int iscrit) { - 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)); + cert_ext = xreallocarray(cert_ext, ncert_ext + 1, sizeof(*cert_ext)); + cert_ext[ncert_ext].key = xstrdup(key); + cert_ext[ncert_ext].val = value == NULL ? NULL : xstrdup(value); + cert_ext[ncert_ext].crit = iscrit; + ncert_ext++; } -static void -add_string_option(struct sshbuf *c, const char *name, const char *value) +/* qsort(3) comparison function for certificate extensions */ +static int +cert_ext_cmp(const void *_a, const void *_b) { - struct sshbuf *b; + const struct cert_ext *a = (const struct cert_ext *)_a; + const struct cert_ext *b = (const struct cert_ext *)_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); + if (a->crit != b->crit) + return (a->crit < b->crit) ? -1 : 1; + if ((r = strcmp(a->key, b->key)) != 0) + return r; + if ((a->val == NULL) != (b->val == NULL)) + return (a->val == NULL) ? -1 : 1; + if (a->val != NULL && (r = strcmp(a->val, b->val)) != 0) + return r; + return 0; } #define OPTIONS_CRITICAL 1 @@ -1629,41 +1632,62 @@ add_string_option(struct sshbuf *c, const char *name, const char *value) static void prepare_options_buf(struct sshbuf *c, int which) { + struct sshbuf *b; size_t i; + int r; + const struct cert_ext *ext; + if ((b = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); 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))) + for (i = 0; i < ncert_ext; i++) { + ext = &cert_ext[i]; + if ((ext->crit && (which & OPTIONS_EXTENSIONS)) || + (!ext->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); + if (ext->val == NULL) { + /* flag option */ + debug3_f("%s", ext->key); + if ((r = sshbuf_put_cstring(c, ext->key)) != 0 || + (r = sshbuf_put_string(c, NULL, 0)) != 0) + fatal_fr(r, "prepare flag"); + } else { + /* key/value option */ + debug3_f("%s=%s", ext->key, ext->val); + sshbuf_reset(b); + if ((r = sshbuf_put_cstring(c, ext->key)) != 0 || + (r = sshbuf_put_cstring(b, ext->val)) != 0 || + (r = sshbuf_put_stringb(c, b)) != 0) + fatal_fr(r, "prepare k/v"); } } + sshbuf_free(b); +} + +static void +finalise_cert_exts(void) +{ + /* critical options */ + if (certflags_command != NULL) + cert_ext_add("force-command", certflags_command, 1); + if (certflags_src_addr != NULL) + cert_ext_add("source-address", certflags_src_addr, 1); + /* extensions */ + if ((certflags_flags & CERTOPT_X_FWD) != 0) + cert_ext_add("permit-X11-forwarding", NULL, 0); + if ((certflags_flags & CERTOPT_AGENT_FWD) != 0) + cert_ext_add("permit-agent-forwarding", NULL, 0); + if ((certflags_flags & CERTOPT_PORT_FWD) != 0) + cert_ext_add("permit-port-forwarding", NULL, 0); + if ((certflags_flags & CERTOPT_PTY) != 0) + cert_ext_add("permit-pty", NULL, 0); + if ((certflags_flags & CERTOPT_USER_RC) != 0) + cert_ext_add("permit-user-rc", NULL, 0); + if ((certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0) + cert_ext_add("no-touch-required", NULL, 0); + /* order lexically by key */ + if (ncert_ext > 0) + qsort(cert_ext, ncert_ext, sizeof(*cert_ext), cert_ext_cmp); } static struct sshkey * @@ -1674,11 +1698,11 @@ load_pkcs11_key(char *path) 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)); + fatal_r(r, "Couldn't load CA public key \"%s\"", path); - nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase, &keys); - debug3("%s: %d keys", __func__, nkeys); + nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase, + &keys, NULL); + debug3_f("%d keys", nkeys); if (nkeys <= 0) fatal("cannot read public key from pkcs11"); for (i = 0; i < nkeys; i++) { @@ -1700,7 +1724,8 @@ load_pkcs11_key(char *path) static int agent_signer(struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, - const char *alg, u_int compat, void *ctx) + const char *alg, const char *provider, const char *pin, + u_int compat, void *ctx) { int *agent_fdp = (int *)ctx; @@ -1713,13 +1738,14 @@ 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; + int r, i, found, agent_fd = -1; u_int n; struct sshkey *ca, *public; - char valid[64], *otmp, *tmp, *cp, *out, *comment, **plist = NULL; - FILE *f; + char valid[64], *otmp, *tmp, *cp, *out, *comment; + char *ca_fp = NULL, **plist = NULL, *pin = NULL; struct ssh_identitylist *agent_ids; size_t j; + struct notifier_ctx *notifier = NULL; #ifdef ENABLE_PKCS11 pkcs11_init(1); @@ -1736,13 +1762,11 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, * agent. */ if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0) - fatal("Cannot load CA public key %s: %s", - tmp, ssh_err(r)); + fatal_r(r, "Cannot load CA public key %s", tmp); if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) - fatal("Cannot use public key for CA signature: %s", - ssh_err(r)); + fatal_r(r, "Cannot use public key for CA signature"); if ((r = ssh_fetch_identitylist(agent_fd, &agent_ids)) != 0) - fatal("Retrieve agent key list: %s", ssh_err(r)); + fatal_r(r, "Retrieve agent key list"); found = 0; for (j = 0; j < agent_ids->nkeys; j++) { if (sshkey_equal(ca, agent_ids->keys[j])) { @@ -1757,15 +1781,27 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, } else { /* CA key is assumed to be a private key on the filesystem */ ca = load_identity(tmp, NULL); + if (sshkey_is_sk(ca) && + (ca->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) { + if ((pin = read_passphrase("Enter PIN for CA key: ", + RP_ALLOW_STDIN)) == NULL) + fatal_f("couldn't read PIN"); + } } 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); + if (key_type_name != NULL) { + if (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); + } + } else if (ca->type == KEY_RSA) { + /* Default to a good signature algorithm */ + key_type_name = "rsa-sha2-512"; } + ca_fp = sshkey_fingerprint(ca, fingerprint_hash, SSH_FP_DEFAULT); + finalise_cert_exts(); for (i = 0; i < argc; i++) { /* Split list of principals */ n = 0; @@ -1784,18 +1820,14 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, 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)); + fatal_r(r, "load pubkey \"%s\"", tmp); + if (sshkey_is_cert(public)) + fatal_f("key \"%s\" type %s cannot be certified", + 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)); + fatal_r(r, "Could not upgrade key %s to certificate", tmp); public->cert->type = cert_key_type; public->cert->serial = (u_int64_t)cert_serial; public->cert->key_id = xstrdup(cert_key_id); @@ -1808,17 +1840,25 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, OPTIONS_EXTENSIONS); if ((r = sshkey_from_private(ca, &public->cert->signature_key)) != 0) - fatal("sshkey_from_private (ca key): %s", ssh_err(r)); + fatal_r(r, "sshkey_from_private (ca key)"); 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)); + key_type_name, sk_provider, NULL, agent_signer, + &agent_fd)) != 0) + fatal_r(r, "Couldn't certify %s via agent", tmp); } else { - if ((sshkey_certify(public, ca, key_type_name)) != 0) - fatal("Couldn't certify key %s: %s", - tmp, ssh_err(r)); + if (sshkey_is_sk(ca) && + (ca->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { + notifier = notify_start(0, + "Confirm user presence for key %s %s", + sshkey_type(ca), ca_fp); + } + r = sshkey_certify(public, ca, key_type_name, + sk_provider, pin); + notify_complete(notifier, "User presence confirmed"); + if (r != 0) + fatal_r(r, "Couldn't certify key %s", tmp); } if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0) @@ -1826,16 +1866,10 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, 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 ((r = sshkey_save_public(public, out, comment)) != 0) { + fatal_r(r, "Unable to save public key to %s", + identity_file); + } if (!quiet) { sshkey_format_cert_validity(public->cert, @@ -1854,6 +1888,9 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, if (cert_serial_autoinc) cert_serial++; } + if (pin != NULL) + freezero(pin, strlen(pin)); + free(ca_fp); #ifdef ENABLE_PKCS11 pkcs11_terminate(); #endif @@ -1952,6 +1989,10 @@ add_cert_option(char *opt) certflags_flags &= ~CERTOPT_USER_RC; else if (strcasecmp(opt, "permit-user-rc") == 0) certflags_flags |= CERTOPT_USER_RC; + else if (strcasecmp(opt, "touch-required") == 0) + certflags_flags &= ~CERTOPT_NO_REQUIRE_USER_PRESENCE; + else if (strcasecmp(opt, "no-touch-required") == 0) + certflags_flags |= CERTOPT_NO_REQUIRE_USER_PRESENCE; else if (strncasecmp(opt, "force-command=", 14) == 0) { val = opt + 14; if (*val == '\0') @@ -1973,13 +2014,8 @@ add_cert_option(char *opt) 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++; + cert_ext_add(val, cp, iscrit); + free(val); } else fatal("Unsupported certificate option \"%s\"", opt); } @@ -1987,39 +2023,42 @@ add_cert_option(char *opt) static void show_options(struct sshbuf *optbuf, int in_critical) { - char *name, *arg; + char *name, *arg, *hex; struct sshbuf *options, *option = NULL; int r; if ((options = sshbuf_fromb(optbuf)) == NULL) - fatal("%s: sshbuf_fromb failed", __func__); + fatal_f("sshbuf_fromb failed"); 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)); + fatal_fr(r, "parse option"); 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)) + strcmp(name, "permit-user-rc") == 0 || + strcmp(name, "no-touch-required") == 0)) { printf("\n"); - else if (in_critical && + } 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)); + fatal_fr(r, "parse critical"); printf(" %s\n", arg); free(arg); - } else { - printf(" UNKNOWN OPTION (len %zu)\n", - sshbuf_len(option)); + } else if (sshbuf_len(option) > 0) { + hex = sshbuf_dtob16(option); + printf(" UNKNOWN OPTION: %s (len %zu)\n", + hex, sshbuf_len(option)); sshbuf_reset(option); - } + free(hex); + } else + printf(" UNKNOWN FLAG OPTION\n"); free(name); if (sshbuf_len(option) != 0) fatal("Option corrupt: extra data at end"); @@ -2038,7 +2077,7 @@ print_cert(struct sshkey *key) 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__); + fatal_f("sshkey_fingerprint fail"); sshkey_format_cert_validity(key->cert, valid, sizeof(valid)); printf(" Type: %s %s certificate\n", sshkey_ssh_name(key), @@ -2111,8 +2150,7 @@ do_show_cert(struct passwd *pw) 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)); + error_r(r, "%s:%lu: invalid key", path, lnum); continue; } if (!sshkey_is_cert(key)) { @@ -2136,19 +2174,14 @@ static void load_krl(const char *path, struct ssh_krl **krlp) { struct sshbuf *krlbuf; - int r, fd; + int r; - 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); + if ((r = sshbuf_load_file(path, &krlbuf)) != 0) + fatal_r(r, "Unable to load KRL %s", path); /* XXX check sigs */ if ((r = ssh_krl_from_blob(krlbuf, krlp, NULL, 0)) != 0 || *krlp == NULL) - fatal("Invalid KRL file: %s", ssh_err(r)); + fatal_r(r, "Invalid KRL file %s", path); sshbuf_free(krlbuf); } @@ -2177,9 +2210,9 @@ hash_to_blob(const char *cp, u_char **blobp, size_t *lenp, tmp[tlen] = '\0'; } if ((b = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshbuf_b64tod(b, tmp)) != 0) - fatal("%s:%lu: decode hash failed: %s", file, lnum, ssh_err(r)); + fatal_r(r, "%s:%lu: decode hash failed", file, lnum); free(tmp); *lenp = sshbuf_len(b); *blobp = xmalloc(*lenp); @@ -2265,8 +2298,7 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, } if (ssh_krl_revoke_cert_by_serial_range(krl, ca, serial, serial2) != 0) { - fatal("%s: revoke serial failed", - __func__); + fatal_f("revoke serial failed"); } } else if (strncasecmp(cp, "id:", 3) == 0) { if (ca == NULL && !wild_ca) { @@ -2276,12 +2308,14 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, 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__); + fatal_f("revoke key ID failed"); } 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); + if (r != 0) + fatal_fr(r, "revoke key failed"); } else { if (strncasecmp(cp, "key:", 4) == 0) { cp += 4; @@ -2303,8 +2337,7 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, 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)); + fatal_r(r, "%s:%lu: invalid key", path, lnum); if (was_explicit_key) r = ssh_krl_revoke_key_explicit(krl, key); else if (was_sha1) { @@ -2324,8 +2357,7 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, } else r = ssh_krl_revoke_key(krl, key); if (r != 0) - fatal("%s: revoke key failed: %s", - __func__, ssh_err(r)); + fatal_fr(r, "revoke key failed"); freezero(blob, blen); blob = NULL; blen = 0; @@ -2346,7 +2378,7 @@ do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path, struct ssh_krl *krl; struct stat sb; struct sshkey *ca = NULL; - int fd, i, r, wild_ca = 0; + int i, r, wild_ca = 0; char *tmp; struct sshbuf *kbuf; @@ -2365,8 +2397,7 @@ do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path, 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)); + fatal_r(r, "Cannot load CA public key %s", tmp); free(tmp); } } @@ -2388,19 +2419,15 @@ do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path, 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)) + if ((r = sshbuf_write_file(identity_file, kbuf)) != 0) 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) +do_check_krl(struct passwd *pw, int print_krl, int argc, char **argv) { int i, r, ret = 0; char *comment; @@ -2410,10 +2437,11 @@ do_check_krl(struct passwd *pw, int argc, char **argv) if (*identity_file == '\0') fatal("KRL checking requires an input file"); load_krl(identity_file, &krl); + if (print_krl) + krl_dump(krl, stdout); 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)); + fatal_r(r, "Cannot load public key %s", argv[i]); r = ssh_krl_check_key(krl, k); printf("%s%s%s%s: %s\n", argv[i], *comment ? " (" : "", comment, *comment ? ")" : "", @@ -2437,7 +2465,7 @@ load_sign_key(const char *keypath, const struct sshkey *pubkey) int r; /* - * If passed a public key filename, then try to locate the correponding + * If passed a public key filename, then try to locate the corresponding * private key. This lets us specify certificates on the command-line * and have ssh-keygen find the appropriate private key. */ @@ -2447,8 +2475,8 @@ load_sign_key(const char *keypath, const struct sshkey *pubkey) strcmp(privpath + plen - slen, suffixes[i]) != 0) continue; privpath[plen - slen] = '\0'; - debug("%s: %s looks like a public key, using private key " - "path %s instead", __func__, keypath, privpath); + debug_f("%s looks like a public key, using private key " + "path %s instead", keypath, privpath); } if ((privkey = load_identity(privpath, NULL)) == NULL) { error("Couldn't load identity %s", keypath); @@ -2465,12 +2493,11 @@ load_sign_key(const char *keypath, const struct sshkey *pubkey) * it capable of signing. */ if ((r = sshkey_to_certified(privkey)) != 0) { - error("%s: sshkey_to_certified: %s", __func__, - ssh_err(r)); + error_fr(r, "sshkey_to_certified"); goto done; } if ((r = sshkey_cert_copy(pubkey, privkey)) != 0) { - error("%s: sshkey_cert_copy: %s", __func__, ssh_err(r)); + error_fr(r, "sshkey_cert_copy"); goto done; } } @@ -2489,8 +2516,8 @@ sign_one(struct sshkey *signkey, const char *filename, int fd, { struct sshbuf *sigbuf = NULL, *abuf = NULL; int r = SSH_ERR_INTERNAL_ERROR, wfd = -1, oerrno; - char *wfile = NULL; - char *asig = NULL; + char *wfile = NULL, *asig = NULL, *fp = NULL; + char *pin = NULL, *prompt = NULL; if (!quiet) { if (fd == STDIN_FILENO) @@ -2498,17 +2525,34 @@ sign_one(struct sshkey *signkey, const char *filename, int fd, else fprintf(stderr, "Signing file %s\n", filename); } - if ((r = sshsig_sign_fd(signkey, NULL, fd, sig_namespace, - &sigbuf, signer, signer_ctx)) != 0) { - error("Signing %s failed: %s", filename, ssh_err(r)); + if (signer == NULL && sshkey_is_sk(signkey)) { + if ((signkey->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) { + xasprintf(&prompt, "Enter PIN for %s key: ", + sshkey_type(signkey)); + if ((pin = read_passphrase(prompt, + RP_ALLOW_STDIN)) == NULL) + fatal_f("couldn't read PIN"); + } + if ((signkey->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { + if ((fp = sshkey_fingerprint(signkey, fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) + fatal_f("fingerprint failed"); + fprintf(stderr, "Confirm user presence for key %s %s\n", + sshkey_type(signkey), fp); + free(fp); + } + } + if ((r = sshsig_sign_fd(signkey, NULL, sk_provider, pin, + fd, sig_namespace, &sigbuf, signer, signer_ctx)) != 0) { + error_r(r, "Signing %s failed", filename); goto out; } if ((r = sshsig_armor(sigbuf, &abuf)) != 0) { - error("%s: sshsig_armor: %s", __func__, ssh_err(r)); + error_fr(r, "sshsig_armor"); goto out; } if ((asig = sshbuf_dup_string(abuf)) == NULL) { - error("%s: buffer error", __func__); + error_f("buffer error"); r = SSH_ERR_ALLOC_FAIL; goto out; } @@ -2547,7 +2591,10 @@ sign_one(struct sshkey *signkey, const char *filename, int fd, r = 0; out: free(wfile); + free(prompt); free(asig); + if (pin != NULL) + freezero(pin, strlen(pin)); sshbuf_free(abuf); sshbuf_free(sigbuf); if (wfd != -1) @@ -2556,7 +2603,7 @@ sign_one(struct sshkey *signkey, const char *filename, int fd, } static int -sign(const char *keypath, const char *sig_namespace, int argc, char **argv) +sig_sign(const char *keypath, const char *sig_namespace, int argc, char **argv) { int i, fd = -1, r, ret = -1; int agent_fd = -1; @@ -2572,17 +2619,17 @@ sign(const char *keypath, const char *sig_namespace, int argc, char **argv) } if ((r = sshkey_load_public(keypath, &pubkey, NULL)) != 0) { - error("Couldn't load public key %s: %s", keypath, ssh_err(r)); + error_r(r, "Couldn't load public key %s", keypath); goto done; } if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) - debug("Couldn't get agent socket: %s", ssh_err(r)); + debug_r(r, "Couldn't get agent socket"); else { if ((r = ssh_agent_has_key(agent_fd, pubkey)) == 0) signer = agent_signer; else - debug("Couldn't find key in agent: %s", ssh_err(r)); + debug_r(r, "Couldn't find key in agent"); } if (signer == NULL) { @@ -2627,52 +2674,50 @@ done: } static int -verify(const char *signature, const char *sig_namespace, const char *principal, - const char *allowed_keys, const char *revoked_keys) +sig_verify(const char *signature, const char *sig_namespace, + const char *principal, const char *allowed_keys, const char *revoked_keys) { - int r, ret = -1, sigfd = -1; + int r, ret = -1; struct sshbuf *sigbuf = NULL, *abuf = NULL; struct sshkey *sign_key = NULL; char *fp = NULL; + struct sshkey_sig_details *sig_details = NULL; - if ((abuf = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new() failed", __func__); - - if ((sigfd = open(signature, O_RDONLY)) < 0) { - error("Couldn't open signature file %s", signature); + memset(&sig_details, 0, sizeof(sig_details)); + if ((r = sshbuf_load_file(signature, &abuf)) != 0) { + error_r(r, "Couldn't read signature file"); goto done; } - if ((r = sshkey_load_file(sigfd, abuf)) != 0) { - error("Couldn't read signature file: %s", ssh_err(r)); - goto done; - } if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) { - error("%s: sshsig_armor: %s", __func__, ssh_err(r)); - return r; + error_fr(r, "sshsig_armor"); + goto done; } if ((r = sshsig_verify_fd(sigbuf, STDIN_FILENO, sig_namespace, - &sign_key)) != 0) + &sign_key, &sig_details)) != 0) goto done; /* sshsig_verify() prints error */ if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash, SSH_FP_DEFAULT)) == NULL) - fatal("%s: sshkey_fingerprint failed", __func__); + fatal_f("sshkey_fingerprint failed"); debug("Valid (unverified) signature from key %s", fp); + if (sig_details != NULL) { + debug2_f("signature details: counter = %u, flags = 0x%02x", + sig_details->sk_counter, sig_details->sk_flags); + } free(fp); fp = NULL; if (revoked_keys != NULL) { if ((r = sshkey_check_revoked(sign_key, revoked_keys)) != 0) { - debug3("sshkey_check_revoked failed: %s", ssh_err(r)); + debug3_fr(r, "sshkey_check_revoked"); goto done; } } - if (allowed_keys != NULL && - (r = sshsig_check_allowed_keys(allowed_keys, sign_key, - principal, sig_namespace)) != 0) { - debug3("sshsig_check_allowed_keys failed: %s", ssh_err(r)); + if (allowed_keys != NULL && (r = sshsig_check_allowed_keys(allowed_keys, + sign_key, principal, sig_namespace)) != 0) { + debug3_fr(r, "sshsig_check_allowed_keys"); goto done; } /* success */ @@ -2681,10 +2726,8 @@ done: if (!quiet) { if (ret == 0) { if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash, - SSH_FP_DEFAULT)) == NULL) { - fatal("%s: sshkey_fingerprint failed", - __func__); - } + SSH_FP_DEFAULT)) == NULL) + fatal_f("sshkey_fingerprint failed"); if (principal == NULL) { printf("Good \"%s\" signature with %s key %s\n", sig_namespace, sshkey_type(sign_key), fp); @@ -2698,27 +2741,341 @@ done: printf("Could not verify signature.\n"); } } - if (sigfd != -1) - close(sigfd); sshbuf_free(sigbuf); sshbuf_free(abuf); sshkey_free(sign_key); + sshkey_sig_details_free(sig_details); free(fp); return ret; } +static int +sig_find_principals(const char *signature, const char *allowed_keys) { + int r, ret = -1; + struct sshbuf *sigbuf = NULL, *abuf = NULL; + struct sshkey *sign_key = NULL; + char *principals = NULL, *cp, *tmp; + + if ((r = sshbuf_load_file(signature, &abuf)) != 0) { + error_r(r, "Couldn't read signature file"); + goto done; + } + if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) { + error_fr(r, "sshsig_armor"); + goto done; + } + if ((r = sshsig_get_pubkey(sigbuf, &sign_key)) != 0) { + error_fr(r, "sshsig_get_pubkey"); + goto done; + } + if ((r = sshsig_find_principals(allowed_keys, sign_key, + &principals)) != 0) { + error_fr(r, "sshsig_get_principal"); + goto done; + } + ret = 0; +done: + if (ret == 0 ) { + /* Emit matching principals one per line */ + tmp = principals; + while ((cp = strsep(&tmp, ",")) != NULL && *cp != '\0') + puts(cp); + } else { + fprintf(stderr, "No principal matched.\n"); + } + sshbuf_free(sigbuf); + sshbuf_free(abuf); + sshkey_free(sign_key); + free(principals); + return ret; +} + +static void +do_moduli_gen(const char *out_file, char **opts, size_t nopts) +{ +#ifdef WITH_OPENSSL + /* Moduli generation/screening */ + u_int32_t memory = 0; + BIGNUM *start = NULL; + int moduli_bits = 0; + FILE *out; + size_t i; + const char *errstr; + + /* Parse options */ + for (i = 0; i < nopts; i++) { + if (strncmp(opts[i], "memory=", 7) == 0) { + memory = (u_int32_t)strtonum(opts[i]+7, 1, + UINT_MAX, &errstr); + if (errstr) { + fatal("Memory limit is %s: %s", + errstr, opts[i]+7); + } + } else if (strncmp(opts[i], "start=", 6) == 0) { + /* XXX - also compare length against bits */ + if (BN_hex2bn(&start, opts[i]+6) == 0) + fatal("Invalid start point."); + } else if (strncmp(opts[i], "bits=", 5) == 0) { + moduli_bits = (int)strtonum(opts[i]+5, 1, + INT_MAX, &errstr); + if (errstr) { + fatal("Invalid number: %s (%s)", + opts[i]+12, errstr); + } + } else { + fatal("Option \"%s\" is unsupported for moduli " + "generation", opts[i]); + } + } + + if ((out = fopen(out_file, "w")) == NULL) { + fatal("Couldn't open modulus candidate file \"%s\": %s", + out_file, strerror(errno)); + } + setvbuf(out, NULL, _IOLBF, 0); + + if (moduli_bits == 0) + moduli_bits = DEFAULT_BITS; + if (gen_candidates(out, memory, moduli_bits, start) != 0) + fatal("modulus candidate generation failed"); +#else /* WITH_OPENSSL */ + fatal("Moduli generation is not supported"); +#endif /* WITH_OPENSSL */ +} + +static void +do_moduli_screen(const char *out_file, char **opts, size_t nopts) +{ +#ifdef WITH_OPENSSL + /* Moduli generation/screening */ + char *checkpoint = NULL; + u_int32_t generator_wanted = 0; + unsigned long start_lineno = 0, lines_to_process = 0; + int prime_tests = 0; + FILE *out, *in = stdin; + size_t i; + const char *errstr; + + /* Parse options */ + for (i = 0; i < nopts; i++) { + if (strncmp(opts[i], "lines=", 6) == 0) { + lines_to_process = strtoul(opts[i]+6, NULL, 10); + } else if (strncmp(opts[i], "start-line=", 11) == 0) { + start_lineno = strtoul(opts[i]+11, NULL, 10); + } else if (strncmp(opts[i], "checkpoint=", 11) == 0) { + checkpoint = xstrdup(opts[i]+11); + } else if (strncmp(opts[i], "generator=", 10) == 0) { + generator_wanted = (u_int32_t)strtonum( + opts[i]+10, 1, UINT_MAX, &errstr); + if (errstr != NULL) { + fatal("Generator invalid: %s (%s)", + opts[i]+10, errstr); + } + } else if (strncmp(opts[i], "prime-tests=", 12) == 0) { + prime_tests = (int)strtonum(opts[i]+12, 1, + INT_MAX, &errstr); + if (errstr) { + fatal("Invalid number: %s (%s)", + opts[i]+12, errstr); + } + } else { + fatal("Option \"%s\" is unsupported for moduli " + "screening", opts[i]); + } + } + + 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)); + } + } + + if ((out = fopen(out_file, "a")) == NULL) { + fatal("Couldn't open moduli file \"%s\": %s", + out_file, strerror(errno)); + } + setvbuf(out, NULL, _IOLBF, 0); + if (prime_test(in, out, prime_tests == 0 ? 100 : prime_tests, + generator_wanted, checkpoint, + start_lineno, lines_to_process) != 0) + fatal("modulus screening failed"); +#else /* WITH_OPENSSL */ + fatal("Moduli screening is not supported"); +#endif /* WITH_OPENSSL */ +} + +static char * +private_key_passphrase(void) +{ + char *passphrase1, *passphrase2; + + /* 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. + */ + freezero(passphrase1, strlen(passphrase1)); + freezero(passphrase2, strlen(passphrase2)); + printf("Passphrases do not match. Try again.\n"); + goto passphrase_again; + } + /* Clear the other copy of the passphrase. */ + freezero(passphrase2, strlen(passphrase2)); + } + return passphrase1; +} + +static const char * +skip_ssh_url_preamble(const char *s) +{ + if (strncmp(s, "ssh://", 6) == 0) + return s + 6; + else if (strncmp(s, "ssh:", 4) == 0) + return s + 4; + return s; +} + +static int +do_download_sk(const char *skprovider, const char *device) +{ + struct sshkey **keys; + size_t nkeys, i; + int r, ret = -1; + char *fp, *pin = NULL, *pass = NULL, *path, *pubpath; + const char *ext; + + if (skprovider == NULL) + fatal("Cannot download keys without provider"); + + pin = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN); + if (!quiet) { + printf("You may need to touch your authenticator " + "to authorize key download.\n"); + } + if ((r = sshsk_load_resident(skprovider, device, pin, + &keys, &nkeys)) != 0) { + if (pin != NULL) + freezero(pin, strlen(pin)); + error_r(r, "Unable to load resident keys"); + return -1; + } + if (nkeys == 0) + logit("No keys to download"); + if (pin != NULL) + freezero(pin, strlen(pin)); + + for (i = 0; i < nkeys; i++) { + if (keys[i]->type != KEY_ECDSA_SK && + keys[i]->type != KEY_ED25519_SK) { + error("Unsupported key type %s (%d)", + sshkey_type(keys[i]), keys[i]->type); + continue; + } + if ((fp = sshkey_fingerprint(keys[i], + fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + fatal_f("sshkey_fingerprint failed"); + debug_f("key %zu: %s %s %s (flags 0x%02x)", i, + sshkey_type(keys[i]), fp, keys[i]->sk_application, + keys[i]->sk_flags); + ext = skip_ssh_url_preamble(keys[i]->sk_application); + xasprintf(&path, "id_%s_rk%s%s", + keys[i]->type == KEY_ECDSA_SK ? "ecdsa_sk" : "ed25519_sk", + *ext == '\0' ? "" : "_", ext); + + /* If the file already exists, ask the user to confirm. */ + if (!confirm_overwrite(path)) { + free(path); + break; + } + + /* Save the key with the application string as the comment */ + if (pass == NULL) + pass = private_key_passphrase(); + if ((r = sshkey_save_private(keys[i], path, pass, + keys[i]->sk_application, private_key_format, + openssh_format_cipher, rounds)) != 0) { + error_r(r, "Saving key \"%s\" failed", path); + free(path); + break; + } + if (!quiet) { + printf("Saved %s key%s%s to %s\n", + sshkey_type(keys[i]), + *ext != '\0' ? " " : "", + *ext != '\0' ? keys[i]->sk_application : "", + path); + } + + /* Save public key too */ + xasprintf(&pubpath, "%s.pub", path); + free(path); + if ((r = sshkey_save_public(keys[i], pubpath, + keys[i]->sk_application)) != 0) { + error_r(r, "Saving public key \"%s\" failed", pubpath); + free(pubpath); + break; + } + free(pubpath); + } + + if (i >= nkeys) + ret = 0; /* success */ + if (pass != NULL) + freezero(pass, strlen(pass)); + for (i = 0; i < nkeys; i++) + sshkey_free(keys[i]); + free(keys); + return ret; +} + +static void +save_attestation(struct sshbuf *attest, const char *path) +{ + mode_t omask; + int r; + + if (path == NULL) + return; /* nothing to do */ + if (attest == NULL || sshbuf_len(attest) == 0) + fatal("Enrollment did not return attestation data"); + omask = umask(077); + r = sshbuf_write_file(path, attest); + umask(omask); + if (r != 0) + fatal_r(r, "Unable to write attestation data \"%s\"", path); + if (!quiet) + printf("Your FIDO attestation certificate has been saved in " + "%s\n", path); +} + static void usage(void) { fprintf(stderr, - "usage: ssh-keygen [-q] [-b bits] [-C comment] [-f output_keyfile] [-m format]\n" - " [-N new_passphrase] [-t dsa | ecdsa | ed25519 | rsa]\n" - " ssh-keygen -p [-f keyfile] [-m format] [-N new_passphrase]\n" - " [-P old_passphrase]\n" + "usage: ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile]\n" + " [-m format] [-N new_passphrase] [-O option]\n" + " [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]\n" + " [-w provider] [-Z cipher]\n" + " ssh-keygen -p [-a rounds] [-f keyfile] [-m format] [-N new_passphrase]\n" + " [-P old_passphrase] [-Z cipher]\n" " ssh-keygen -i [-f input_keyfile] [-m key_format]\n" " ssh-keygen -e [-f input_keyfile] [-m key_format]\n" " ssh-keygen -y [-f input_keyfile]\n" - " ssh-keygen -c [-C comment] [-f keyfile] [-P passphrase]\n" + " ssh-keygen -c [-a rounds] [-C comment] [-f keyfile] [-P passphrase]\n" " ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]\n" " ssh-keygen -B [-f input_keyfile]\n"); #ifdef ENABLE_PKCS11 @@ -2728,25 +3085,26 @@ usage(void) fprintf(stderr, " ssh-keygen -F hostname [-lv] [-f known_hosts_file]\n" " ssh-keygen -H [-f known_hosts_file]\n" + " ssh-keygen -K [-a rounds] [-w provider]\n" " ssh-keygen -R hostname [-f known_hosts_file]\n" " ssh-keygen -r hostname [-g] [-f input_keyfile]\n" #ifdef WITH_OPENSSL - " ssh-keygen -G output_file [-v] [-b bits] [-M memory] [-S start_point]\n" - " ssh-keygen -f input_file -T output_file [-v] [-a rounds] [-J num_lines]\n" - " [-j start_line] [-K checkpt] [-W generator]\n" + " ssh-keygen -M generate [-O option] output_file\n" + " ssh-keygen -M screen [-f input_file] [-O option] output_file\n" #endif " ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider]\n" " [-n principals] [-O option] [-V validity_interval]\n" " [-z serial_number] file ...\n" " ssh-keygen -L [-f input_keyfile]\n" - " ssh-keygen -A [-f prefix_path]\n" + " ssh-keygen -A [-a rounds] [-f prefix_path]\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" + " ssh-keygen -Q [-l] -f krl_file [file ...]\n" + " ssh-keygen -Y find-principals -s signature_file -f allowed_signers_file\n" " ssh-keygen -Y check-novalidate -n namespace -s signature_file\n" " ssh-keygen -Y sign -f key_file -n namespace file ...\n" " ssh-keygen -Y verify -f allowed_signers_file -I signer_identity\n" - " -n namespace -s signature_file [-r revocation_file]\n"); + " -n namespace -s signature_file [-r revocation_file]\n"); exit(1); } @@ -2756,32 +3114,28 @@ usage(void) int main(int argc, char **argv) { - char dotsshdir[PATH_MAX], comment[1024], *passphrase1, *passphrase2; + char comment[1024], *passphrase; char *rr_hostname = NULL, *ep, *fp, *ra; struct sshkey *private, *public; struct passwd *pw; - struct stat st; - int r, opt, type, fd; + int r, opt, type; 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; + int do_gen_candidates = 0, do_screen_candidates = 0, download_sk = 0; unsigned long long cert_serial = 0; - char *identity_comment = NULL, *ca_key_path = NULL; + char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL; + char *sk_application = NULL, *sk_device = NULL, *sk_user = NULL; + char *sk_attestation_path = NULL; + struct sshbuf *challenge = NULL, *attest = NULL; + size_t i, nopts = 0; u_int32_t bits = 0; - FILE *f; + uint8_t sk_flags = SSH_SK_USER_PRESENCE_REQD; const char *errstr; int log_level = SYSLOG_LEVEL_INFO; char *sign_op = NULL; -#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; @@ -2804,10 +3158,12 @@ main(int argc, char **argv) if (gethostname(hostname, sizeof(hostname)) == -1) fatal("gethostname: %s", strerror(errno)); - /* Remaining characters: dw */ - while ((opt = getopt(argc, argv, "ABHLQUXceghiklopquvxy" - "C:D:E:F:G:I:J:K:M:N:O:P:R:S:T:V:W:Y:Z:" - "a:b:f:g:j:m:n:r:s:t:z:")) != -1) { + sk_provider = getenv("SSH_SK_PROVIDER"); + + /* Remaining characters: dGjJSTWx */ + while ((opt = getopt(argc, argv, "ABHKLQUXceghiklopquvy" + "C:D:E:F:I:M:N:O:P:R:V:Y:Z:" + "a:b:f:g:m:n:r:s:t:w:z:")) != -1) { switch (opt) { case 'A': gen_all_hostkeys = 1; @@ -2885,6 +3241,9 @@ main(int argc, char **argv) case 'g': print_generic = 1; break; + case 'K': + download_sk = 1; + break; case 'P': identity_passphrase = optarg; break; @@ -2895,10 +3254,15 @@ main(int argc, char **argv) check_krl = 1; break; case 'O': - add_cert_option(optarg); + opts = xrecallocarray(opts, nopts, nopts + 1, + sizeof(*opts)); + opts[nopts++] = xstrdup(optarg); break; case 'Z': openssh_format_cipher = optarg; + if (cipher_by_name(openssh_format_cipher) == NULL) + fatal("Invalid OpenSSH-format cipher '%s'", + openssh_format_cipher); break; case 'C': identity_comment = optarg; @@ -2907,7 +3271,6 @@ main(int argc, char **argv) quiet = 1; break; case 'e': - case 'x': /* export key */ convert_to = 1; break; @@ -2965,6 +3328,9 @@ main(int argc, char **argv) case 'Y': sign_op = optarg; break; + case 'w': + sk_provider = optarg; + break; case 'z': errno = 0; if (*optarg == '+') { @@ -2976,56 +3342,25 @@ main(int argc, char **argv) (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); + if (strcmp(optarg, "generate") == 0) + do_gen_candidates = 1; + else if (strcmp(optarg, "screen") == 0) + do_screen_candidates = 1; + else + fatal("Unsupported moduli option %s", 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(); } } +#ifdef ENABLE_SK_INTERNAL + if (sk_provider == NULL) + sk_provider = "internal"; +#endif + /* reinit */ log_init(argv[0], log_level, SYSLOG_FACILITY_USER, 1); @@ -3033,27 +3368,47 @@ main(int argc, char **argv) argc -= optind; if (sign_op != NULL) { - if (cert_principals == NULL || *cert_principals == '\0') { - error("Too few arguments for sign/verify: " - "missing namespace"); - exit(1); - } - if (strncmp(sign_op, "sign", 4) == 0) { + if (strncmp(sign_op, "find-principals", 15) == 0) { + if (ca_key_path == NULL) { + error("Too few arguments for find-principals:" + "missing signature file"); + exit(1); + } + if (!have_identity) { + error("Too few arguments for find-principals:" + "missing allowed keys file"); + exit(1); + } + return sig_find_principals(ca_key_path, identity_file); + } else if (strncmp(sign_op, "sign", 4) == 0) { + if (cert_principals == NULL || + *cert_principals == '\0') { + error("Too few arguments for sign: " + "missing namespace"); + exit(1); + } if (!have_identity) { error("Too few arguments for sign: " "missing key"); exit(1); } - return sign(identity_file, cert_principals, argc, argv); + return sig_sign(identity_file, cert_principals, + argc, argv); } else if (strncmp(sign_op, "check-novalidate", 16) == 0) { if (ca_key_path == NULL) { error("Too few arguments for check-novalidate: " "missing signature file"); exit(1); } - return verify(ca_key_path, cert_principals, - NULL, NULL, NULL); + return sig_verify(ca_key_path, cert_principals, + NULL, NULL, NULL); } else if (strncmp(sign_op, "verify", 6) == 0) { + if (cert_principals == NULL || + *cert_principals == '\0') { + error("Too few arguments for verify: " + "missing namespace"); + exit(1); + } if (ca_key_path == NULL) { error("Too few arguments for verify: " "missing signature file"); @@ -3069,9 +3424,10 @@ main(int argc, char **argv) "missing principal ID"); exit(1); } - return verify(ca_key_path, cert_principals, + return sig_verify(ca_key_path, cert_principals, cert_key_id, identity_file, rr_hostname); } + error("Unsupported operation for -Y: \"%s\"", sign_op); usage(); /* NOTREACHED */ } @@ -3081,7 +3437,8 @@ main(int argc, char **argv) error("Too few arguments."); usage(); } - } else if (argc > 0 && !gen_krl && !check_krl) { + } else if (argc > 0 && !gen_krl && !check_krl && + !do_gen_candidates && !do_screen_candidates) { error("Too many arguments."); usage(); } @@ -3099,12 +3456,14 @@ main(int argc, char **argv) return (0); } if (check_krl) { - do_check_krl(pw, argc, argv); + do_check_krl(pw, print_fingerprint, argc, argv); return (0); } if (ca_key_path != NULL) { if (cert_key_id == NULL) fatal("Must specify key id (-I) when certifying"); + for (i = 0; i < nopts; i++) + add_cert_option(opts[i]); do_ca_sign(pw, ca_key_path, prefer_agent, cert_serial, cert_serial_autoinc, argc, argv); } @@ -3116,6 +3475,17 @@ main(int argc, char **argv) } if (pkcs11provider != NULL) do_download(pw); + if (download_sk) { + for (i = 0; i < nopts; i++) { + if (strncasecmp(opts[i], "device=", 7) == 0) { + sk_device = xstrdup(opts[i] + 7); + } else { + fatal("Option \"%s\" is unsupported for " + "FIDO authenticator download", opts[i]); + } + } + return do_download_sk(sk_provider, sk_device); + } if (print_fingerprint || print_bubblebabble) do_fingerprint(pw); if (change_passphrase) @@ -3165,47 +3535,20 @@ main(int argc, char **argv) } } -#ifdef WITH_OPENSSL + if (do_gen_candidates || do_screen_candidates) { + if (argc <= 0) + fatal("No output file specified"); + else if (argc > 1) + fatal("Too many output files specified"); + } 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); + do_moduli_gen(argv[0], opts, nopts); + 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); + do_moduli_screen(argv[0], opts, nopts); + return 0; } -#endif if (gen_all_hostkeys) { do_gen_all_hostkeys(pw); @@ -3221,61 +3564,105 @@ main(int argc, char **argv) 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"); + switch (type) { + case KEY_ECDSA_SK: + case KEY_ED25519_SK: + for (i = 0; i < nopts; i++) { + if (strcasecmp(opts[i], "no-touch-required") == 0) { + sk_flags &= ~SSH_SK_USER_PRESENCE_REQD; + } else if (strcasecmp(opts[i], "verify-required") == 0) { + sk_flags |= SSH_SK_USER_VERIFICATION_REQD; + } else if (strcasecmp(opts[i], "resident") == 0) { + sk_flags |= SSH_SK_RESIDENT_KEY; + } else if (strncasecmp(opts[i], "device=", 7) == 0) { + sk_device = xstrdup(opts[i] + 7); + } else if (strncasecmp(opts[i], "user=", 5) == 0) { + sk_user = xstrdup(opts[i] + 5); + } else if (strncasecmp(opts[i], "challenge=", 10) == 0) { + if ((r = sshbuf_load_file(opts[i] + 10, + &challenge)) != 0) { + fatal_r(r, "Unable to load FIDO " + "enrollment challenge \"%s\"", + opts[i] + 10); + } + } else if (strncasecmp(opts[i], + "write-attestation=", 18) == 0) { + sk_attestation_path = opts[i] + 18; + } else if (strncasecmp(opts[i], + "application=", 12) == 0) { + sk_application = xstrdup(opts[i] + 12); + if (strncmp(sk_application, "ssh:", 4) != 0) { + fatal("FIDO application string must " + "begin with \"ssh:\""); + } + } else { + fatal("Option \"%s\" is unsupported for " + "FIDO authenticator enrollment", opts[i]); + } + } + if (!quiet) { + printf("You may need to touch your authenticator " + "to authorize key generation.\n"); + } + if ((attest = sshbuf_new()) == NULL) + fatal("sshbuf_new failed"); + if ((sk_flags & + (SSH_SK_USER_VERIFICATION_REQD|SSH_SK_RESIDENT_KEY))) { + passphrase = read_passphrase("Enter PIN for " + "authenticator: ", RP_ALLOW_STDIN); + } else { + passphrase = NULL; + } + for (i = 0 ; ; i++) { + fflush(stdout); + r = sshsk_enroll(type, sk_provider, sk_device, + sk_application == NULL ? "ssh:" : sk_application, + sk_user, sk_flags, passphrase, challenge, + &private, attest); + if (r == 0) + break; + if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) + fatal_r(r, "Key enrollment failed"); + else if (passphrase != NULL) { + error("PIN incorrect"); + freezero(passphrase, strlen(passphrase)); + passphrase = NULL; + } + if (i >= 3) + fatal("Too many incorrect PINs"); + passphrase = read_passphrase("Enter PIN for " + "authenticator: ", RP_ALLOW_STDIN); + if (!quiet) { + printf("You may need to touch your " + "authenticator (again) to authorize " + "key generation.\n"); + } + } + if (passphrase != NULL) { + freezero(passphrase, strlen(passphrase)); + passphrase = NULL; + } + break; + default: + if ((r = sshkey_generate(type, bits, &private)) != 0) + fatal("sshkey_generate failed"); + break; + } if ((r = sshkey_from_private(private, &public)) != 0) - fatal("sshkey_from_private failed: %s\n", ssh_err(r)); + fatal_r(r, "sshkey_from_private"); 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) == -1) { - if (errno != ENOENT) { - error("Could not stat %s: %s", dotsshdir, - strerror(errno)); - } else if (mkdir(dotsshdir, 0700) == -1) { - error("Could not create directory '%s': %s", - dotsshdir, strerror(errno)); - } else if (!quiet) - printf("Created directory '%s'.\n", dotsshdir); - } - } + hostfile_create_user_ssh_dir(identity_file, !quiet); + /* If the file already exists, ask the user to confirm. */ if (!confirm_overwrite(identity_file)) 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); - } + /* Determine the passphrase for the private key */ + passphrase = private_key_passphrase(); if (identity_comment) { strlcpy(comment, identity_comment, sizeof(comment)); } else { @@ -3284,35 +3671,23 @@ passphrase_again: } /* Save the key with the given passphrase and comment. */ - if ((r = sshkey_save_private(private, identity_file, passphrase1, + if ((r = sshkey_save_private(private, identity_file, passphrase, comment, private_key_format, openssh_format_cipher, rounds)) != 0) { - error("Saving key \"%s\" failed: %s", - identity_file, ssh_err(r)); - explicit_bzero(passphrase1, strlen(passphrase1)); - free(passphrase1); + error_r(r, "Saving key \"%s\" failed", identity_file); + freezero(passphrase, strlen(passphrase)); exit(1); } - /* Clear the passphrase. */ - explicit_bzero(passphrase1, strlen(passphrase1)); - free(passphrase1); - - /* Clear the private key and the random number generator. */ + freezero(passphrase, strlen(passphrase)); sshkey_free(private); - if (!quiet) - printf("Your identification has been saved in %s.\n", identity_file); + 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 ((r = sshkey_save_public(public, identity_file, comment)) != 0) + fatal_r(r, "Unable to save public key to %s", identity_file); if (!quiet) { fp = sshkey_fingerprint(public, fingerprint_hash, @@ -3321,7 +3696,7 @@ passphrase_again: SSH_FP_RANDOMART); if (fp == NULL || ra == NULL) fatal("sshkey_fingerprint failed"); - printf("Your public key has been saved in %s.\n", + printf("Your public key has been saved in %s\n", identity_file); printf("The key fingerprint is:\n"); printf("%s %s\n", fp, comment); @@ -3331,6 +3706,11 @@ passphrase_again: free(fp); } + if (sk_attestation_path != NULL) + save_attestation(attest, sk_attestation_path); + + sshbuf_free(attest); sshkey_free(public); + exit(0); } diff --git a/ssh-keyscan.1 b/ssh-keyscan.1 index f3d7a4078..f9df75d42 100644 --- a/ssh-keyscan.1 +++ b/ssh-keyscan.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keyscan.1,v 1.44 2018/03/05 07:03:18 jmc Exp $ +.\" $OpenBSD: ssh-keyscan.1,v 1.45 2019/11/30 07:07:59 jmc Exp $ .\" .\" Copyright 1995, 1996 by David Mazieres . .\" @@ -6,12 +6,12 @@ .\" permitted provided that due credit is given to the author and the .\" OpenBSD project by leaving this copyright notice intact. .\" -.Dd $Mdocdate: March 5 2018 $ +.Dd $Mdocdate: November 30 2019 $ .Dt SSH-KEYSCAN 1 .Os .Sh NAME .Nm ssh-keyscan -.Nd gather SSH public keys +.Nd gather SSH public keys from servers .Sh SYNOPSIS .Nm ssh-keyscan .Op Fl 46cDHv diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 5de0508d0..7abbcbff5 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.130 2019/09/06 05:23:55 djm Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.139 2021/01/27 09:26:54 djm Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -61,12 +61,14 @@ int ssh_port = SSH_DEFAULT_PORT; #define KT_ECDSA (1<<2) #define KT_ED25519 (1<<3) #define KT_XMSS (1<<4) +#define KT_ECDSA_SK (1<<5) +#define KT_ED25519_SK (1<<6) #define KT_MIN KT_DSA -#define KT_MAX KT_XMSS +#define KT_MAX KT_ED25519_SK int get_cert = 0; -int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519; +int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519|KT_ECDSA_SK|KT_ED25519_SK; int hash_hosts = 0; /* Hash hostname on output */ @@ -259,6 +261,16 @@ keygrab_ssh2(con *c) "ecdsa-sha2-nistp384," "ecdsa-sha2-nistp521"; break; + case KT_ECDSA_SK: + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? + "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" : + "sk-ecdsa-sha2-nistp256@openssh.com"; + break; + case KT_ED25519_SK: + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? + "sk-ssh-ed25519-cert-v01@openssh.com" : + "sk-ssh-ed25519@openssh.com"; + break; default: fatal("unknown key type %d", c->c_keytype); break; @@ -281,7 +293,7 @@ keygrab_ssh2(con *c) # endif #endif c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; - c->c_ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client; + c->c_ssh->kex->kex[KEX_KEM_SNTRUP761X25519_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 @@ -355,7 +367,7 @@ tcpconnect(char *host) continue; } if (set_nonblock(s) == -1) - fatal("%s: set_nonblock(%d)", __func__, s); + fatal_f("set_nonblock(%d)", s); if (connect(s, ai->ai_addr, ai->ai_addrlen) == -1 && errno != EINPROGRESS) error("connect (`%s'): %s", host, strerror(errno)); @@ -389,7 +401,7 @@ conalloc(char *iname, char *oname, int keytype) if (fdcon[s].c_status) fatal("conalloc: attempt to reuse fdno %d", s); - debug3("%s: oname %s kt %d", __func__, oname, keytype); + debug3_f("oname %s kt %d", oname, keytype); fdcon[s].c_fd = s; fdcon[s].c_status = CS_CON; fdcon[s].c_namebase = namebase; @@ -510,11 +522,10 @@ congreet(int s) 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 */ + c->c_ssh->compat = 0; 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; + compat_banner(c->c_ssh, remote_version); if (!ssh2_capable(remote_major, remote_minor)) { debug("%s doesn't support ssh2", c->c_name); confree(s); @@ -572,16 +583,9 @@ conloop(void) 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 + if (c && timercmp(&c->c_tv, &now, >)) + timersub(&c->c_tv, &now, &seltime); + else timerclear(&seltime); r = xcalloc(read_wait_nfdset, sizeof(fd_mask)); @@ -604,8 +608,7 @@ conloop(void) 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))) { + while (c && timercmp(&c->c_tv, &now, <)) { int s = c->c_fd; c = TAILQ_NEXT(c, c_link); @@ -631,14 +634,15 @@ do_host(char *host) } void -fatal(const char *fmt,...) +sshfatal(const char *file, const char *func, int line, int showfunc, + LogLevel level, const char *suffix, const char *fmt, ...) { va_list args; va_start(args, fmt); - do_log(SYSLOG_LEVEL_FATAL, fmt, args); + sshlogv(file, func, line, showfunc, level, suffix, fmt, args); va_end(args); - exit(255); + cleanup_exit(255); } static void @@ -735,6 +739,12 @@ main(int argc, char **argv) case KEY_XMSS: get_keytypes |= KT_XMSS; break; + case KEY_ED25519_SK: + get_keytypes |= KT_ED25519_SK; + break; + case KEY_ECDSA_SK: + get_keytypes |= KT_ECDSA_SK; + break; case KEY_UNSPEC: default: fatal("Unknown key type \"%s\"", tname); @@ -776,8 +786,7 @@ main(int argc, char **argv) if (argv[j] == NULL) fp = stdin; else if ((fp = fopen(argv[j], "r")) == NULL) - fatal("%s: %s: %s", __progname, argv[j], - strerror(errno)); + fatal("%s: %s: %s", __progname, argv[j], strerror(errno)); while (getline(&line, &linesize, fp) != -1) { /* Chomp off trailing whitespace and comments */ @@ -799,8 +808,7 @@ main(int argc, char **argv) } if (ferror(fp)) - fatal("%s: %s: %s", __progname, argv[j], - strerror(errno)); + fatal("%s: %s: %s", __progname, argv[j], strerror(errno)); fclose(fp); } diff --git a/ssh-keysign.8 b/ssh-keysign.8 index 19b0dbc53..73b62397c 100644 --- a/ssh-keysign.8 +++ b/ssh-keysign.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keysign.8,v 1.15 2016/02/17 07:38:19 jmc Exp $ +.\" $OpenBSD: ssh-keysign.8,v 1.16 2019/11/30 07:07:59 jmc Exp $ .\" .\" Copyright (c) 2002 Markus Friedl. All rights reserved. .\" @@ -22,12 +22,12 @@ .\" (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: February 17 2016 $ +.Dd $Mdocdate: November 30 2019 $ .Dt SSH-KEYSIGN 8 .Os .Sh NAME .Nm ssh-keysign -.Nd ssh helper program for host-based authentication +.Nd OpenSSH helper for host-based authentication .Sh SYNOPSIS .Nm .Sh DESCRIPTION diff --git a/ssh-keysign.c b/ssh-keysign.c index 6cfd5b46c..907162dc7 100644 --- a/ssh-keysign.c +++ b/ssh-keysign.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keysign.c,v 1.61 2019/10/02 00:42:30 djm Exp $ */ +/* $OpenBSD: ssh-keysign.c,v 1.66 2020/12/17 23:10:27 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * @@ -78,33 +78,33 @@ valid_request(struct passwd *pw, char *host, struct sshkey **ret, fail = 0; if ((b = sshbuf_from(data, datalen)) == NULL) - fatal("%s: sshbuf_from failed", __func__); + fatal_f("sshbuf_from failed"); /* 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)); + fatal_fr(r, "parse session ID"); if (len != 20 && len != 32) fail++; if ((r = sshbuf_get_u8(b, &type)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse type"); 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)); + fatal_fr(r, "parse user"); /* service */ if ((r = sshbuf_get_cstring(b, &p, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse service"); 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)); + fatal_fr(r, "parse method"); if (strcmp("hostbased", p) != 0) fail++; free(p); @@ -112,13 +112,13 @@ valid_request(struct passwd *pw, char *host, struct sshkey **ret, /* 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)); + fatal_fr(r, "parse pk"); 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)); + error_fr(r, "decode key"); fail++; } else if (key->type != pktype) fail++; @@ -127,8 +127,8 @@ valid_request(struct passwd *pw, char *host, struct sshkey **ret, /* 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); + fatal_fr(r, "parse hostname"); + debug2_f("check expect chost %s got %s", host, p); if (strlen(host) != len - 1) fail++; else if (p[len - 1] != '.') @@ -139,7 +139,7 @@ valid_request(struct passwd *pw, char *host, struct sshkey **ret, /* local user */ if ((r = sshbuf_get_cstring(b, &luser, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse luser"); if (strcmp(pw->pw_name, luser) != 0) fail++; @@ -150,7 +150,7 @@ valid_request(struct passwd *pw, char *host, struct sshkey **ret, fail++; sshbuf_free(b); - debug3("%s: fail %d", __func__, fail); + debug3_f("fail %d", fail); if (fail) sshkey_free(key); @@ -207,7 +207,7 @@ main(int argc, char **argv) initialize_options(&options); (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "", &options, 0, NULL); - fill_default_options(&options); + (void)fill_default_options(&options); if (options.enable_ssh_keysign != 1) fatal("ssh-keysign not enabled in %s", _PATH_HOST_CONFIG_FILE); @@ -228,7 +228,7 @@ main(int argc, char **argv) NULL, &key, NULL); close(key_fd[i]); if (r != 0) - debug("parse key %d: %s", i, ssh_err(r)); + debug_r(r, "parse key %d", i); else if (key != NULL) { keys[i] = key; found = 1; @@ -243,22 +243,23 @@ main(int argc, char **argv) if ((b = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __progname); if (ssh_msg_recv(STDIN_FILENO, b) < 0) - fatal("ssh_msg_recv failed"); + fatal("%s: ssh_msg_recv failed", __progname); if ((r = sshbuf_get_u8(b, &rver)) != 0) - fatal("%s: buffer error: %s", __progname, ssh_err(r)); + fatal_r(r, "%s: buffer error", __progname); if (rver != version) - fatal("bad version: received %d, expected %d", rver, version); + fatal("%s: bad version: received %d, expected %d", + __progname, rver, version); if ((r = sshbuf_get_u32(b, (u_int *)&fd)) != 0) - fatal("%s: buffer error: %s", __progname, ssh_err(r)); + fatal_r(r, "%s: buffer error", __progname); if (fd < 0 || fd == STDIN_FILENO || fd == STDOUT_FILENO) - fatal("bad fd = %d", fd); + fatal("%s: bad fd = %d", __progname, fd); if ((host = get_local_name(fd)) == NULL) - fatal("cannot get local name for fd"); + fatal("%s: cannot get local name for fd", __progname); if ((r = sshbuf_get_string(b, &data, &dlen)) != 0) - fatal("%s: buffer error: %s", __progname, ssh_err(r)); + fatal_r(r, "%s: buffer error", __progname); if (valid_request(pw, host, &key, data, dlen) < 0) - fatal("not a valid request"); + fatal("%s: not a valid request", __progname); free(host); found = 0; @@ -273,21 +274,21 @@ main(int argc, char **argv) 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", + fatal("%s: no matching hostkey found for key %s %s", __progname, 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)); + if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, + NULL, NULL, NULL, 0)) != 0) + fatal_r(r, "%s: sshkey_sign failed", __progname); 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)); + fatal_r(r, "%s: buffer error", __progname); if (ssh_msg_send(STDOUT_FILENO, version, b) == -1) - fatal("ssh_msg_send failed"); + fatal("%s: ssh_msg_send failed", __progname); return (0); } diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c index e7860de89..e72473694 100644 --- a/ssh-pkcs11-client.c +++ b/ssh-pkcs11-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11-client.c,v 1.15 2019/01/21 12:53:35 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11-client.c,v 1.17 2020/10/18 11:32:02 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * Copyright (c) 2014 Pedro Martelletto. All rights reserved. @@ -65,7 +65,7 @@ send_msg(struct sshbuf *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)); + fatal_fr(r, "consume"); } static int @@ -93,11 +93,11 @@ recv_msg(struct sshbuf *m) return (0); /* XXX */ } if ((r = sshbuf_put(m, buf, l)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_put"); len -= l; } if ((r = sshbuf_get_u8(m, &c)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse type"); return c; } @@ -127,29 +127,29 @@ rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding) goto fail; key = sshkey_new(KEY_UNSPEC); if (key == NULL) { - error("%s: sshkey_new failed", __func__); + error_f("sshkey_new failed"); 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)); + error_fr(r, "encode key"); goto fail; } if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); 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)); + fatal_fr(r, "parse"); if (slen <= (size_t)RSA_size(rsa)) { memcpy(to, signature, slen); ret = slen; @@ -178,13 +178,13 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, nid = sshkey_ecdsa_key_to_nid(ec); if (nid < 0) { - error("%s: couldn't get curve nid", __func__); + error_f("couldn't get curve nid"); goto fail; } key = sshkey_new(KEY_UNSPEC); if (key == NULL) { - error("%s: sshkey_new failed", __func__); + error_f("sshkey_new failed"); goto fail; } key->ecdsa = ec; @@ -193,22 +193,22 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, EC_KEY_up_ref(ec); if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) { - error("%s: sshkey_to_blob: %s", __func__, ssh_err(r)); + error_fr(r, "encode key"); goto fail; } if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); 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)); + fatal_fr(r, "parse"); cp = signature; ret = d2i_ECDSA_SIG(NULL, &cp, slen); free(signature); @@ -238,7 +238,7 @@ wrap_key(struct sshkey *k) EC_KEY_set_method(k->ecdsa, helper_ecdsa); #endif /* HAVE_EC_KEY_METHOD_NEW */ else - fatal("%s: unknown key type", __func__); + fatal_f("unknown key type"); } static int @@ -260,10 +260,10 @@ pkcs11_start_helper_methods(void) #endif /* HAVE_EC_KEY_METHOD_NEW */ if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL) - fatal("%s: RSA_meth_dup failed", __func__); + fatal_f("RSA_meth_dup failed"); if (!RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper") || !RSA_meth_set_priv_enc(helper_rsa, rsa_encrypt)) - fatal("%s: failed to prepare method", __func__); + fatal_f("failed to prepare method"); return (0); } @@ -300,7 +300,7 @@ pkcs11_start_helper(void) helper = getenv("SSH_PKCS11_HELPER"); if (helper == NULL || strlen(helper) == 0) helper = _PATH_SSH_PKCS11_HELPER; - debug("%s: starting %s %s", __func__, helper, + debug_f("starting %s %s", helper, verbosity == NULL ? "" : verbosity); execlp(helper, helper, verbosity, (char *)NULL); fprintf(stderr, "exec: %s: %s\n", helper, strerror(errno)); @@ -312,11 +312,13 @@ pkcs11_start_helper(void) } int -pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp) +pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, + char ***labelsp) { struct sshkey *k; int r, type; u_char *blob; + char *label; size_t blen; u_int nkeys, i; struct sshbuf *msg; @@ -325,29 +327,34 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp) return (-1); if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); send_msg(msg); sshbuf_reset(msg); 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)); + fatal_fr(r, "parse nkeys"); *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); + if (labelsp) + *labelsp = xcalloc(nkeys, sizeof(char *)); 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)); + (r = sshbuf_get_cstring(msg, &label, NULL)) != 0) + fatal_fr(r, "parse key"); if ((r = sshkey_from_blob(blob, blen, &k)) != 0) - fatal("%s: bad key: %s", __func__, ssh_err(r)); + fatal_fr(r, "decode key"); wrap_key(k); (*keysp)[i] = k; + if (labelsp) + (*labelsp)[i] = label; + else + free(label); free(blob); } } else if (type == SSH2_AGENT_FAILURE) { @@ -367,11 +374,11 @@ pkcs11_del_provider(char *name) struct sshbuf *msg; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose"); send_msg(msg); sshbuf_reset(msg); diff --git a/ssh-pkcs11-helper.8 b/ssh-pkcs11-helper.8 index ba5c30fa0..6a592b1f3 100644 --- a/ssh-pkcs11-helper.8 +++ b/ssh-pkcs11-helper.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-pkcs11-helper.8,v 1.5 2019/01/21 12:53:35 djm Exp $ +.\" $OpenBSD: ssh-pkcs11-helper.8,v 1.6 2019/11/30 07:07:59 jmc Exp $ .\" .\" Copyright (c) 2010 Markus Friedl. All rights reserved. .\" @@ -14,12 +14,12 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: January 21 2019 $ +.Dd $Mdocdate: November 30 2019 $ .Dt SSH-PKCS11-HELPER 8 .Os .Sh NAME .Nm ssh-pkcs11-helper -.Nd ssh-agent helper program for PKCS#11 support +.Nd OpenSSH helper for PKCS#11 support .Sh SYNOPSIS .Nm .Op Fl v diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c index 3bcc2440b..a9a6fe381 100644 --- a/ssh-pkcs11-helper.c +++ b/ssh-pkcs11-helper.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11-helper.c,v 1.21 2019/09/06 05:23:55 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11-helper.c,v 1.24 2020/10/18 11:32:02 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -26,7 +26,9 @@ #include #include +#ifdef HAVE_POLL_H #include +#endif #include #include #include @@ -48,7 +50,7 @@ struct pkcs11_keyinfo { struct sshkey *key; - char *providername; + char *providername, *label; TAILQ_ENTRY(pkcs11_keyinfo) next; }; @@ -61,13 +63,14 @@ struct sshbuf *iqueue; struct sshbuf *oqueue; static void -add_key(struct sshkey *k, char *name) +add_key(struct sshkey *k, char *name, char *label) { struct pkcs11_keyinfo *ki; ki = xcalloc(1, sizeof(*ki)); ki->providername = xstrdup(name); ki->key = k; + ki->label = xstrdup(label); TAILQ_INSERT_TAIL(&pkcs11_keylist, ki, next); } @@ -81,6 +84,7 @@ del_keys_by_name(char *name) if (!strcmp(ki->providername, name)) { TAILQ_REMOVE(&pkcs11_keylist, ki, next); free(ki->providername); + free(ki->label); sshkey_free(ki->key); free(ki); } @@ -94,7 +98,7 @@ lookup_key(struct sshkey *k) struct pkcs11_keyinfo *ki; TAILQ_FOREACH(ki, &pkcs11_keylist, next) { - debug("check %p %s", ki, ki->providername); + debug("check %p %s %s", ki, ki->providername, ki->label); if (sshkey_equal(k, ki->key)) return (ki->key); } @@ -107,7 +111,7 @@ send_msg(struct sshbuf *m) int r; if ((r = sshbuf_put_stringb(oqueue, m)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "enqueue"); } static void @@ -119,37 +123,35 @@ process_add(void) u_char *blob; size_t blen; struct sshbuf *msg; + char **labels = NULL; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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) { + fatal_fr(r, "parse"); + if ((nkeys = pkcs11_add_provider(name, pin, &keys, &labels)) > 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)); + fatal_fr(r, "compose"); 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)); + debug_fr(r, "encode key"); 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)); + (r = sshbuf_put_cstring(msg, labels[i])) != 0) + fatal_fr(r, "compose key"); free(blob); - add_key(keys[i], name); + add_key(keys[i], name, labels[i]); + free(labels[i]); } - } 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); + } else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0 || + (r = sshbuf_put_u32(msg, -nkeys)) != 0) + fatal_fr(r, "compose"); + free(labels); + free(keys); /* keys themselves are transferred to pkcs11_keylist */ free(pin); free(name); send_msg(msg); @@ -164,14 +166,14 @@ process_del(void) int r; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "parse"); 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)); + fatal_fr(r, "compose"); free(pin); free(name); send_msg(msg); @@ -191,10 +193,10 @@ process_sign(void) 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)); + fatal_fr(r, "parse"); if ((r = sshkey_from_blob(blob, blen, &key)) != 0) - error("%s: sshkey_from_blob: %s", __func__, ssh_err(r)); + fatal_fr(r, "decode key"); else { if ((found = lookup_key(key)) != NULL) { #ifdef WITH_OPENSSL @@ -220,26 +222,25 @@ process_sign(void) if (ret != 0) ok = 0; else - error("%s: ECDSA_sign" - " returns %d", __func__, ret); + error_f("ECDSA_sign returned %d", ret); slen = xslen; #endif /* OPENSSL_HAS_ECC */ } else - error("%s: don't know how to sign with key " - "type %d", __func__, (int)key->type); + error_f("don't know how to sign with key " + "type %d", (int)key->type); #endif /* WITH_OPENSSL */ } sshkey_free(key); } if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "compose response"); } else { if ((r = sshbuf_put_u8(msg, SSH2_AGENT_FAILURE)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "compose failure response"); } free(data); free(blob); @@ -271,7 +272,7 @@ process(void) return; if ((r = sshbuf_consume(iqueue, 4)) != 0 || (r = sshbuf_get_u8(iqueue, &type)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse type/len"); buf_len -= 4; switch (type) { case SSH_AGENTC_ADD_SMARTCARD_KEY: @@ -302,7 +303,7 @@ process(void) } if (msg_len > consumed) { if ((r = sshbuf_consume(iqueue, msg_len - consumed)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "consume"); } } @@ -317,7 +318,7 @@ cleanup_exit(int i) int main(int argc, char **argv) { - int r, ch, in, out, max, log_stderr = 0; + int r, ch, in, out, log_stderr = 0; ssize_t len; SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; LogLevel log_level = SYSLOG_LEVEL_ERROR; @@ -353,16 +354,10 @@ main(int argc, char **argv) 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__); + fatal_f("sshbuf_new failed"); if ((oqueue = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); while (1) { memset(pfd, 0, sizeof(pfd)); @@ -378,7 +373,7 @@ main(int argc, char **argv) (r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0) pfd[0].events = POLLIN; else if (r != SSH_ERR_NO_BUFFER_SPACE) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "reserve"); if (sshbuf_len(oqueue) > 0) pfd[1].events = POLLOUT; @@ -398,10 +393,8 @@ main(int argc, char **argv) } 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)); - } + } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) + fatal_fr(r, "sshbuf_put"); } /* send oqueue to stdout */ if ((pfd[1].revents & (POLLOUT|POLLHUP)) != 0) { @@ -410,10 +403,8 @@ main(int argc, char **argv) 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)); - } + } else if ((r = sshbuf_consume(oqueue, len)) != 0) + fatal_fr(r, "consume"); } /* @@ -424,7 +415,7 @@ main(int argc, char **argv) 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)); + fatal_fr(r, "reserve"); } } diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c index 09f1ea347..844aa9fff 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11.c,v 1.46 2019/10/01 10:22:53 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11.c,v 1.52 2020/11/22 22:38:26 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * Copyright (c) 2014 Pedro Martelletto. All rights reserved. @@ -46,6 +46,7 @@ #include "misc.h" #include "sshkey.h" #include "ssh-pkcs11.h" +#include "digest.h" #include "xmalloc.h" struct pkcs11_slotinfo { @@ -84,10 +85,9 @@ ossl_error(const char *msg) { unsigned long e; - error("%s: %s", __func__, msg); + error_f("%s", msg); while ((e = ERR_get_error()) != 0) - error("%s: libcrypto error: %.100s", __func__, - ERR_error_string(e, NULL)); + error_f("libcrypto error: %s", ERR_error_string(e, NULL)); } #endif /* HAVE_EC_KEY_METHOD_NEW */ @@ -202,7 +202,7 @@ pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, { struct pkcs11_key *k11 = ptr; - debug("%s: parent %p ptr %p idx %d", __func__, parent, ptr, idx); + debug_f("parent %p ptr %p idx %d", parent, ptr, idx); if (k11 == NULL) return; if (k11->provider) @@ -263,7 +263,7 @@ pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si, 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__); + debug_f("no pin specified"); return (-1); /* bail out */ } } @@ -271,9 +271,24 @@ pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si, (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); + + switch (rv) { + case CKR_OK: + case CKR_USER_ALREADY_LOGGED_IN: + /* success */ + break; + case CKR_PIN_LEN_RANGE: + error("PKCS#11 login failed: PIN length out of range"); + return -1; + case CKR_PIN_INCORRECT: + error("PKCS#11 login failed: PIN incorrect"); + return -1; + case CKR_PIN_LOCKED: + error("PKCS#11 login failed: PIN locked"); + return -1; + default: + error("PKCS#11 login failed: error %lu", rv); + return -1; } si->logged_in = 1; return (0); @@ -322,8 +337,8 @@ pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj, return (-1); } *val = flag != 0; - debug("%s: provider %p slot %lu object %lu: attrib %lu = %d", - __func__, k11->provider, k11->slotidx, obj, type, *val); + debug_f("provider %p slot %lu object %lu: attrib %lu = %d", + k11->provider, k11->slotidx, obj, type, *val); return (0); } @@ -392,7 +407,7 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) 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__); + debug_f("always-auth key"); if (pkcs11_login(k11, CKU_CONTEXT_SPECIFIC) < 0) { error("login failed for always-auth key"); return (-1); @@ -460,7 +475,7 @@ pkcs11_rsa_start_wrapper(void) 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__); + error_f("setup pkcs11 method failed"); return (-1); } return (0); @@ -546,7 +561,7 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, goto done; } if (!ECDSA_SIG_set0(ret, r, s)) { - error("%s: ECDSA_SIG_set0 failed", __func__); + error_f("ECDSA_SIG_set0 failed"); ECDSA_SIG_free(ret); ret = NULL; goto done; @@ -868,7 +883,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, goto fail; } if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL)) - fatal("%s: set key", __func__); + fatal_f("set key"); rsa_n = rsa_e = NULL; /* transferred */ if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa)) @@ -893,15 +908,16 @@ fail: return (key); } -static struct sshkey * +static int pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - CK_OBJECT_HANDLE *obj) + CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp) { CK_ATTRIBUTE cert_attr[3]; CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; X509 *x509 = NULL; + X509_NAME *x509_name = NULL; EVP_PKEY *evp; RSA *rsa = NULL; #ifdef OPENSSL_HAS_ECC @@ -912,7 +928,11 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, #ifdef HAVE_EC_KEY_METHOD_NEW int nid; #endif - const u_char *cp; + const u_char *cp; + char *subject = NULL; + + *keyp = NULL; + *labelp = NULL; memset(&cert_attr, 0, sizeof(cert_attr)); cert_attr[0].type = CKA_ID; @@ -926,7 +946,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); - return (NULL); + return -1; } /* @@ -937,7 +957,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, if (cert_attr[1].ulValueLen == 0 || cert_attr[2].ulValueLen == 0) { error("invalid attribute length"); - return (NULL); + return -1; } /* allocate buffers for attributes */ @@ -949,44 +969,45 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); - goto fail; + goto out; } - x509 = X509_new(); - if (x509 == NULL) { - error("x509_new failed"); - goto fail; - } + /* Decode DER-encoded cert subject */ + cp = cert_attr[2].pValue; + if ((x509_name = d2i_X509_NAME(NULL, &cp, + cert_attr[1].ulValueLen)) == NULL || + (subject = X509_NAME_oneline(x509_name, NULL, 0)) == NULL) + subject = xstrdup("invalid subject"); + X509_NAME_free(x509_name); cp = cert_attr[2].pValue; - if (d2i_X509(&x509, &cp, cert_attr[2].ulValueLen) == NULL) { + if ((x509 = d2i_X509(NULL, &cp, cert_attr[2].ulValueLen)) == NULL) { error("d2i_x509 failed"); - goto fail; + goto out; } - evp = X509_get_pubkey(x509); - if (evp == NULL) { + if ((evp = X509_get_pubkey(x509)) == NULL) { error("X509_get_pubkey failed"); - goto fail; + goto out; } if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) { if (EVP_PKEY_get0_RSA(evp) == NULL) { error("invalid x509; no rsa key"); - goto fail; + goto out; } if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) { error("RSAPublicKey_dup failed"); - goto fail; + goto out; } if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa)) - goto fail; + goto out; key = sshkey_new(KEY_UNSPEC); if (key == NULL) { error("sshkey_new failed"); - goto fail; + goto out; } key->rsa = rsa; @@ -997,26 +1018,26 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, } 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; + goto out; } if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) { error("EC_KEY_dup failed"); - goto fail; + goto out; } nid = sshkey_ecdsa_key_to_nid(ec); if (nid < 0) { error("couldn't get curve nid"); - goto fail; + goto out; } if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec)) - goto fail; + goto out; key = sshkey_new(KEY_UNSPEC); if (key == NULL) { error("sshkey_new failed"); - goto fail; + goto out; } key->ecdsa = ec; @@ -1025,10 +1046,11 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, key->flags |= SSHKEY_FLAG_EXT; ec = NULL; /* now owned by key */ #endif /* HAVE_EC_KEY_METHOD_NEW */ - } else + } else { error("unknown certificate key type"); - -fail: + goto out; + } + out: for (i = 0; i < 3; i++) free(cert_attr[i].pValue); X509_free(x509); @@ -1036,8 +1058,14 @@ fail: #ifdef OPENSSL_HAS_ECC EC_KEY_free(ec); #endif - - return (key); + if (key == NULL) { + free(subject); + return -1; + } + /* success */ + *keyp = key; + *labelp = subject; + return 0; } #if 0 @@ -1051,6 +1079,22 @@ have_rsa_key(const RSA *rsa) } #endif +static void +note_key(struct pkcs11_provider *p, CK_ULONG slotidx, const char *context, + struct sshkey *key) +{ + char *fp; + + if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, + SSH_FP_DEFAULT)) == NULL) { + error_f("sshkey_fingerprint failed"); + return; + } + debug2("%s: provider %s slot %lu: %s %s", context, p->name, + (u_long)slotidx, sshkey_type(key), fp); + free(fp); +} + /* * lookup certificates for token in slot identified by slotidx, * add 'wrapped' public keys to the 'keysp' array and increment nkeys. @@ -1058,7 +1102,7 @@ have_rsa_key(const RSA *rsa) */ static int pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, - struct sshkey ***keysp, int *nkeys) + struct sshkey ***keysp, char ***labelsp, int *nkeys) { struct sshkey *key = NULL; CK_OBJECT_CLASS key_class; @@ -1069,6 +1113,7 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE obj; CK_ULONG n = 0; int ret = -1; + char *label; memset(&key_attr, 0, sizeof(key_attr)); memset(&obj, 0, sizeof(obj)); @@ -1110,28 +1155,35 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, goto fail; } + key = NULL; + label = NULL; switch (ck_cert_type) { case CKC_X_509: - key = pkcs11_fetch_x509_pubkey(p, slotidx, &obj); + if (pkcs11_fetch_x509_pubkey(p, slotidx, &obj, + &key, &label) != 0) { + error("failed to fetch key"); + continue; + } break; default: - /* XXX print key type? */ - key = NULL; - error("skipping unsupported certificate type"); - } - - if (key == NULL) { - error("failed to fetch key"); + error("skipping unsupported certificate type %lu", + ck_cert_type); continue; } - + note_key(p, slotidx, __func__, key); if (pkcs11_key_included(keysp, nkeys, key)) { + debug2_f("key already included");; sshkey_free(key); } else { /* expand key array and add key */ *keysp = xrecallocarray(*keysp, *nkeys, *nkeys + 1, sizeof(struct sshkey *)); (*keysp)[*nkeys] = key; + if (labelsp != NULL) { + *labelsp = xrecallocarray(*labelsp, *nkeys, + *nkeys + 1, sizeof(char *)); + (*labelsp)[*nkeys] = xstrdup((char *)label); + } *nkeys = *nkeys + 1; debug("have %d keys", *nkeys); } @@ -1155,11 +1207,11 @@ fail: */ static int pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, - struct sshkey ***keysp, int *nkeys) + struct sshkey ***keysp, char ***labelsp, int *nkeys) { struct sshkey *key = NULL; CK_OBJECT_CLASS key_class; - CK_ATTRIBUTE key_attr[1]; + CK_ATTRIBUTE key_attr[2]; CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; @@ -1186,6 +1238,7 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, while (1) { CK_KEY_TYPE ck_key_type; + CK_UTF8CHAR label[256]; rv = f->C_FindObjects(session, &obj, 1, &n); if (rv != CKR_OK) { @@ -1200,13 +1253,18 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, key_attr[0].type = CKA_KEY_TYPE; key_attr[0].pValue = &ck_key_type; key_attr[0].ulValueLen = sizeof(ck_key_type); + key_attr[1].type = CKA_LABEL; + key_attr[1].pValue = &label; + key_attr[1].ulValueLen = sizeof(label) - 1; - rv = f->C_GetAttributeValue(session, obj, key_attr, 1); + rv = f->C_GetAttributeValue(session, obj, key_attr, 2); if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto fail; } + label[key_attr[1].ulValueLen] = '\0'; + switch (ck_key_type) { case CKK_RSA: key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj); @@ -1226,14 +1284,20 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, error("failed to fetch key"); continue; } - + note_key(p, slotidx, __func__, key); if (pkcs11_key_included(keysp, nkeys, key)) { + debug2_f("key already included");; sshkey_free(key); } else { /* expand key array and add key */ *keysp = xrecallocarray(*keysp, *nkeys, *nkeys + 1, sizeof(struct sshkey *)); (*keysp)[*nkeys] = key; + if (labelsp != NULL) { + *labelsp = xrecallocarray(*labelsp, *nkeys, + *nkeys + 1, sizeof(char *)); + (*labelsp)[*nkeys] = xstrdup((char *)label); + } *nkeys = *nkeys + 1; debug("have %d keys", *nkeys); } @@ -1309,7 +1373,7 @@ pkcs11_rsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, 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); + error_f("key generation failed: error 0x%lx", rv); *err = rv; return NULL; } @@ -1388,12 +1452,12 @@ pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, break; } if (!ec_curve_infos[i].name) { - error("%s: invalid key size %lu", __func__, bits); + error_f("invalid key size %lu", bits); return NULL; } if (pkcs11_decode_hex(ec_curve_infos[i].oid_encoded, &ecparams, &ecparams_size) == -1) { - error("%s: invalid oid", __func__); + error_f("invalid oid"); return NULL; } @@ -1426,7 +1490,7 @@ pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, 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); + error_f("key generation failed: error 0x%lx", rv); *err = rv; return NULL; } @@ -1440,7 +1504,8 @@ pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, * keyp is provided, fetch keys. */ static int -pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, +pkcs11_register_provider(char *provider_id, char *pin, + struct sshkey ***keyp, char ***labelsp, struct pkcs11_provider **providerp, CK_ULONG user) { int nkeys, need_finalize = 0; @@ -1459,10 +1524,11 @@ pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, if (keyp != NULL) *keyp = NULL; + if (labelsp != NULL) + *labelsp = NULL; if (pkcs11_provider_lookup(provider_id) != NULL) { - debug("%s: provider already registered: %s", - __func__, provider_id); + debug_f("provider already registered: %s", provider_id); goto fail; } /* open shared pkcs11-library */ @@ -1511,8 +1577,7 @@ pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, goto fail; } if (p->nslots == 0) { - debug("%s: provider %s returned no slots", __func__, - provider_id); + debug_f("provider %s returned no slots", provider_id); ret = -SSH_PKCS11_ERR_NO_SLOTS; goto fail; } @@ -1531,13 +1596,12 @@ pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, 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); + "failed: %lu", provider_id, (u_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); + debug2_f("ignoring uninitialised token in " + "provider %s slot %lu", provider_id, (u_long)i); continue; } rmspace(token->label, sizeof(token->label)); @@ -1556,8 +1620,8 @@ pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 || keyp == NULL) continue; - pkcs11_fetch_keys(p, i, keyp, &nkeys); - pkcs11_fetch_certs(p, i, keyp, &nkeys); + pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); + pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); if (nkeys == 0 && !p->slotinfo[i].logged_in && pkcs11_interactive) { /* @@ -1569,8 +1633,8 @@ pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, error("login failed"); continue; } - pkcs11_fetch_keys(p, i, keyp, &nkeys); - pkcs11_fetch_certs(p, i, keyp, &nkeys); + pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); + pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); } } @@ -1593,6 +1657,8 @@ fail: } if (handle) dlclose(handle); + if (ret > 0) + ret = -1; return (ret); } @@ -1601,12 +1667,14 @@ fail: * fails if provider already exists */ int -pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp) +pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp, + char ***labelsp) { struct pkcs11_provider *p = NULL; int nkeys; - nkeys = pkcs11_register_provider(provider_id, pin, keyp, &p, CKU_USER); + nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp, + &p, CKU_USER); /* no keys found or some other error, de-register provider */ if (nkeys <= 0 && p != NULL) { @@ -1615,8 +1683,7 @@ pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp) pkcs11_provider_unref(p); } if (nkeys == 0) - debug("%s: provider %s returned no keys", __func__, - provider_id); + debug_f("provider %s returned no keys", provider_id); return (nkeys); } @@ -1637,11 +1704,10 @@ pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label, *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); + debug_f("provider \"%s\" available", provider_id); + else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, NULL, + &p, CKU_SO)) < 0) { + debug_f("could not register provider %s", provider_id); goto out; } else reset_provider = 1; @@ -1652,7 +1718,7 @@ pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label, 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); + debug_f("could not supply SO pin: %lu", rv); reset_pin = 0; } else reset_pin = 1; @@ -1661,20 +1727,20 @@ pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label, 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__); + debug_f("failed to generate RSA key"); 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__); + debug_f("failed to generate ECDSA key"); goto out; } break; default: *err = SSH_PKCS11_ERR_GENERIC; - debug("%s: unknown type %d", __func__, type); + debug_f("unknown type %d", type); goto out; } @@ -1709,10 +1775,10 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx, *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, + debug_f("using provider \"%s\"", provider_id); + } else if (pkcs11_register_provider(provider_id, pin, NULL, NULL, &p, CKU_SO) < 0) { - debug("%s: could not register provider %s", __func__, + debug_f("could not register provider %s", provider_id); goto out; } else @@ -1724,7 +1790,7 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx, 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); + debug_f("could not supply SO pin: %lu", rv); reset_pin = 0; } else reset_pin = 1; @@ -1738,8 +1804,8 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx, 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); + debug_f("could not destroy private key 0x%hhx", + keyid); *err = rv; goto out; } @@ -1760,8 +1826,8 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx, 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); + debug_f("could not get key type of public key 0x%hhx", + keyid); *err = rv; key_type = -1; } @@ -1771,8 +1837,7 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx, 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); + debug_f("could not destroy public key 0x%hhx", keyid); *err = rv; goto out; } @@ -1806,7 +1871,8 @@ pkcs11_init(int interactive) } int -pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp) +pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp, + char ***labelsp) { error("%s: dlopen() not supported", __func__); return (-1); diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h index b9038450d..81f1d7c5d 100644 --- a/ssh-pkcs11.h +++ b/ssh-pkcs11.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11.h,v 1.5 2019/01/20 22:51:37 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11.h,v 1.6 2020/01/25 00:03:36 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -24,7 +24,7 @@ int pkcs11_init(int); void pkcs11_terminate(void); -int pkcs11_add_provider(char *, char *, struct sshkey ***); +int pkcs11_add_provider(char *, char *, struct sshkey ***, char ***); int pkcs11_del_provider(char *); #ifdef WITH_PKCS11_KEYGEN struct sshkey * diff --git a/ssh-sk-client.c b/ssh-sk-client.c new file mode 100644 index 000000000..3102a2c99 --- /dev/null +++ b/ssh-sk-client.c @@ -0,0 +1,448 @@ +/* $OpenBSD: ssh-sk-client.c,v 1.8 2020/10/18 11:32:02 djm Exp $ */ +/* + * Copyright (c) 2019 Google LLC + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "includes.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "ssherr.h" +#include "sshbuf.h" +#include "sshkey.h" +#include "msg.h" +#include "digest.h" +#include "pathnames.h" +#include "ssh-sk.h" +#include "misc.h" + +/* #define DEBUG_SK 1 */ + +static int +start_helper(int *fdp, pid_t *pidp, void (**osigchldp)(int)) +{ + void (*osigchld)(int); + int oerrno, pair[2]; + pid_t pid; + char *helper, *verbosity = NULL; + + *fdp = -1; + *pidp = 0; + *osigchldp = SIG_DFL; + + helper = getenv("SSH_SK_HELPER"); + if (helper == NULL || strlen(helper) == 0) + helper = _PATH_SSH_SK_HELPER; + if (access(helper, X_OK) != 0) { + oerrno = errno; + error_f("helper \"%s\" unusable: %s", helper, strerror(errno)); + errno = oerrno; + return SSH_ERR_SYSTEM_ERROR; + } +#ifdef DEBUG_SK + verbosity = "-vvv"; +#endif + + /* Start helper */ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { + error("socketpair: %s", strerror(errno)); + return SSH_ERR_SYSTEM_ERROR; + } + osigchld = ssh_signal(SIGCHLD, SIG_DFL); + if ((pid = fork()) == -1) { + oerrno = errno; + error("fork: %s", strerror(errno)); + close(pair[0]); + close(pair[1]); + ssh_signal(SIGCHLD, osigchld); + errno = oerrno; + return SSH_ERR_SYSTEM_ERROR; + } + if (pid == 0) { + if ((dup2(pair[1], STDIN_FILENO) == -1) || + (dup2(pair[1], STDOUT_FILENO) == -1)) { + error_f("dup2: %s", strerror(errno)); + _exit(1); + } + close(pair[0]); + close(pair[1]); + closefrom(STDERR_FILENO + 1); + debug_f("starting %s %s", helper, + verbosity == NULL ? "" : verbosity); + execlp(helper, helper, verbosity, (char *)NULL); + error_f("execlp: %s", strerror(errno)); + _exit(1); + } + close(pair[1]); + + /* success */ + debug3_f("started pid=%ld", (long)pid); + *fdp = pair[0]; + *pidp = pid; + *osigchldp = osigchld; + return 0; +} + +static int +reap_helper(pid_t pid) +{ + int status, oerrno; + + debug3_f("pid=%ld", (long)pid); + + errno = 0; + while (waitpid(pid, &status, 0) == -1) { + if (errno == EINTR) { + errno = 0; + continue; + } + oerrno = errno; + error_f("waitpid: %s", strerror(errno)); + errno = oerrno; + return SSH_ERR_SYSTEM_ERROR; + } + if (!WIFEXITED(status)) { + error_f("helper exited abnormally"); + return SSH_ERR_AGENT_FAILURE; + } else if (WEXITSTATUS(status) != 0) { + error_f("helper exited with non-zero exit status"); + return SSH_ERR_AGENT_FAILURE; + } + return 0; +} + +static int +client_converse(struct sshbuf *msg, struct sshbuf **respp, u_int type) +{ + int oerrno, fd, r2, ll, r = SSH_ERR_INTERNAL_ERROR; + u_int rtype, rerr; + pid_t pid; + u_char version; + void (*osigchld)(int); + struct sshbuf *req = NULL, *resp = NULL; + *respp = NULL; + + if ((r = start_helper(&fd, &pid, &osigchld)) != 0) + return r; + + if ((req = sshbuf_new()) == NULL || (resp = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + /* Request preamble: type, log_on_stderr, log_level */ + ll = log_level_get(); + if ((r = sshbuf_put_u32(req, type)) != 0 || + (r = sshbuf_put_u8(req, log_is_on_stderr() != 0)) != 0 || + (r = sshbuf_put_u32(req, ll < 0 ? 0 : ll)) != 0 || + (r = sshbuf_putb(req, msg)) != 0) { + error_fr(r, "compose"); + goto out; + } + if ((r = ssh_msg_send(fd, SSH_SK_HELPER_VERSION, req)) != 0) { + error_fr(r, "send"); + goto out; + } + if ((r = ssh_msg_recv(fd, resp)) != 0) { + error_fr(r, "receive"); + goto out; + } + if ((r = sshbuf_get_u8(resp, &version)) != 0) { + error_fr(r, "parse version"); + goto out; + } + if (version != SSH_SK_HELPER_VERSION) { + error_f("unsupported version: got %u, expected %u", + version, SSH_SK_HELPER_VERSION); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((r = sshbuf_get_u32(resp, &rtype)) != 0) { + error_fr(r, "parse message type"); + goto out; + } + if (rtype == SSH_SK_HELPER_ERROR) { + if ((r = sshbuf_get_u32(resp, &rerr)) != 0) { + error_fr(r, "parse"); + goto out; + } + debug_f("helper returned error -%u", rerr); + /* OpenSSH error values are negative; encoded as -err on wire */ + if (rerr == 0 || rerr >= INT_MAX) + r = SSH_ERR_INTERNAL_ERROR; + else + r = -(int)rerr; + goto out; + } else if (rtype != type) { + error_f("helper returned incorrect message type %u, " + "expecting %u", rtype, type); + r = SSH_ERR_INTERNAL_ERROR; + goto out; + } + /* success */ + r = 0; + out: + oerrno = errno; + close(fd); + if ((r2 = reap_helper(pid)) != 0) { + if (r == 0) { + r = r2; + oerrno = errno; + } + } + if (r == 0) { + *respp = resp; + resp = NULL; + } + sshbuf_free(req); + sshbuf_free(resp); + ssh_signal(SIGCHLD, osigchld); + errno = oerrno; + return r; + +} + +int +sshsk_sign(const char *provider, struct sshkey *key, + u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, + u_int compat, const char *pin) +{ + int oerrno, r = SSH_ERR_INTERNAL_ERROR; + char *fp = NULL; + struct sshbuf *kbuf = NULL, *req = NULL, *resp = NULL; + + *sigp = NULL; + *lenp = 0; + +#ifndef ENABLE_SK + return SSH_ERR_KEY_TYPE_UNKNOWN; +#endif + + if ((kbuf = sshbuf_new()) == NULL || + (req = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + + if ((r = sshkey_private_serialize(key, kbuf)) != 0) { + error_fr(r, "encode key"); + goto out; + } + if ((r = sshbuf_put_stringb(req, kbuf)) != 0 || + (r = sshbuf_put_cstring(req, provider)) != 0 || + (r = sshbuf_put_string(req, data, datalen)) != 0 || + (r = sshbuf_put_cstring(req, NULL)) != 0 || /* alg */ + (r = sshbuf_put_u32(req, compat)) != 0 || + (r = sshbuf_put_cstring(req, pin)) != 0) { + error_fr(r, "compose"); + goto out; + } + + if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, + SSH_FP_DEFAULT)) == NULL) { + error_f("sshkey_fingerprint failed"); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = client_converse(req, &resp, SSH_SK_HELPER_SIGN)) != 0) + goto out; + + if ((r = sshbuf_get_string(resp, sigp, lenp)) != 0) { + error_fr(r, "parse signature"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (sshbuf_len(resp) != 0) { + error_f("trailing data in response"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + /* success */ + r = 0; + out: + oerrno = errno; + if (r != 0) { + freezero(*sigp, *lenp); + *sigp = NULL; + *lenp = 0; + } + sshbuf_free(kbuf); + sshbuf_free(req); + sshbuf_free(resp); + errno = oerrno; + return r; +} + +int +sshsk_enroll(int type, const char *provider_path, const char *device, + const char *application, const char *userid, uint8_t flags, + const char *pin, struct sshbuf *challenge_buf, + struct sshkey **keyp, struct sshbuf *attest) +{ + int oerrno, r = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *kbuf = NULL, *abuf = NULL, *req = NULL, *resp = NULL; + struct sshkey *key = NULL; + + *keyp = NULL; + if (attest != NULL) + sshbuf_reset(attest); + +#ifndef ENABLE_SK + return SSH_ERR_KEY_TYPE_UNKNOWN; +#endif + + if (type < 0) + return SSH_ERR_INVALID_ARGUMENT; + + if ((abuf = sshbuf_new()) == NULL || + (kbuf = sshbuf_new()) == NULL || + (req = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + + if ((r = sshbuf_put_u32(req, (u_int)type)) != 0 || + (r = sshbuf_put_cstring(req, provider_path)) != 0 || + (r = sshbuf_put_cstring(req, device)) != 0 || + (r = sshbuf_put_cstring(req, application)) != 0 || + (r = sshbuf_put_cstring(req, userid)) != 0 || + (r = sshbuf_put_u8(req, flags)) != 0 || + (r = sshbuf_put_cstring(req, pin)) != 0 || + (r = sshbuf_put_stringb(req, challenge_buf)) != 0) { + error_fr(r, "compose"); + goto out; + } + + if ((r = client_converse(req, &resp, SSH_SK_HELPER_ENROLL)) != 0) + goto out; + + if ((r = sshbuf_get_stringb(resp, kbuf)) != 0 || + (r = sshbuf_get_stringb(resp, abuf)) != 0) { + error_fr(r, "parse"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (sshbuf_len(resp) != 0) { + error_f("trailing data in response"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((r = sshkey_private_deserialize(kbuf, &key)) != 0) { + error_fr(r, "encode"); + goto out; + } + if (attest != NULL && (r = sshbuf_putb(attest, abuf)) != 0) { + error_fr(r, "encode attestation information"); + goto out; + } + + /* success */ + r = 0; + *keyp = key; + key = NULL; + out: + oerrno = errno; + sshkey_free(key); + sshbuf_free(kbuf); + sshbuf_free(abuf); + sshbuf_free(req); + sshbuf_free(resp); + errno = oerrno; + return r; +} + +int +sshsk_load_resident(const char *provider_path, const char *device, + const char *pin, struct sshkey ***keysp, size_t *nkeysp) +{ + int oerrno, r = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *kbuf = NULL, *req = NULL, *resp = NULL; + struct sshkey *key = NULL, **keys = NULL, **tmp; + size_t i, nkeys = 0; + + *keysp = NULL; + *nkeysp = 0; + + if ((resp = sshbuf_new()) == NULL || + (kbuf = sshbuf_new()) == NULL || + (req = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + + if ((r = sshbuf_put_cstring(req, provider_path)) != 0 || + (r = sshbuf_put_cstring(req, device)) != 0 || + (r = sshbuf_put_cstring(req, pin)) != 0) { + error_fr(r, "compose"); + goto out; + } + + if ((r = client_converse(req, &resp, SSH_SK_HELPER_LOAD_RESIDENT)) != 0) + goto out; + + while (sshbuf_len(resp) != 0) { + /* key, comment */ + if ((r = sshbuf_get_stringb(resp, kbuf)) != 0 || + (r = sshbuf_get_cstring(resp, NULL, NULL)) != 0) { + error_fr(r, "parse signature"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((r = sshkey_private_deserialize(kbuf, &key)) != 0) { + error_fr(r, "decode key"); + goto out; + } + if ((tmp = recallocarray(keys, nkeys, nkeys + 1, + sizeof(*keys))) == NULL) { + error_f("recallocarray keys failed"); + goto out; + } + debug_f("keys[%zu]: %s %s", nkeys, sshkey_type(key), + key->sk_application); + keys = tmp; + keys[nkeys++] = key; + key = NULL; + } + + /* success */ + r = 0; + *keysp = keys; + *nkeysp = nkeys; + keys = NULL; + nkeys = 0; + out: + oerrno = errno; + for (i = 0; i < nkeys; i++) + sshkey_free(keys[i]); + free(keys); + sshkey_free(key); + sshbuf_free(kbuf); + sshbuf_free(req); + sshbuf_free(resp); + errno = oerrno; + return r; +} diff --git a/ssh-sk-helper.8 b/ssh-sk-helper.8 new file mode 100644 index 000000000..3c53da1ec --- /dev/null +++ b/ssh-sk-helper.8 @@ -0,0 +1,66 @@ +.\" $OpenBSD: ssh-sk-helper.8,v 1.3 2019/12/21 20:22:34 naddy 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: December 21 2019 $ +.Dt SSH-SK-HELPER 8 +.Os +.Sh NAME +.Nm ssh-sk-helper +.Nd OpenSSH helper for FIDO authenticator support +.Sh SYNOPSIS +.Nm +.Op Fl v +.Sh DESCRIPTION +.Nm +is used by +.Xr ssh-agent 1 +to access keys provided by a FIDO authenticator. +.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 6.7 . +.Sh AUTHORS +.An Damien Miller Aq Mt djm@openbsd.org diff --git a/ssh-sk-helper.c b/ssh-sk-helper.c new file mode 100644 index 000000000..21a08919d --- /dev/null +++ b/ssh-sk-helper.c @@ -0,0 +1,364 @@ +/* $OpenBSD: ssh-sk-helper.c,v 1.11 2020/10/18 11:32:02 djm Exp $ */ +/* + * Copyright (c) 2019 Google LLC + * + * 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. + */ + +/* + * This is a tiny program used to isolate the address space used for + * security key middleware signing operations from ssh-agent. It is similar + * to ssh-pkcs11-helper.c but considerably simpler as the operations for + * security keys are stateless. + * + * Please crank SSH_SK_HELPER_VERSION in sshkey.h for any incompatible + * protocol changes. + */ + +#include "includes.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "xmalloc.h" +#include "log.h" +#include "sshkey.h" +#include "authfd.h" +#include "misc.h" +#include "sshbuf.h" +#include "msg.h" +#include "uidswap.h" +#include "sshkey.h" +#include "ssherr.h" +#include "ssh-sk.h" + +#ifdef ENABLE_SK +extern char *__progname; + +static struct sshbuf *reply_error(int r, char *fmt, ...) + __attribute__((__format__ (printf, 2, 3))); + +static struct sshbuf * +reply_error(int r, char *fmt, ...) +{ + char *msg; + va_list ap; + struct sshbuf *resp; + + va_start(ap, fmt); + xvasprintf(&msg, fmt, ap); + va_end(ap); + debug("%s: %s", __progname, msg); + free(msg); + + if (r >= 0) + fatal_f("invalid error code %d", r); + + if ((resp = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __progname); + if (sshbuf_put_u32(resp, SSH_SK_HELPER_ERROR) != 0 || + sshbuf_put_u32(resp, (u_int)-r) != 0) + fatal("%s: buffer error", __progname); + return resp; +} + +/* If the specified string is zero length, then free it and replace with NULL */ +static void +null_empty(char **s) +{ + if (s == NULL || *s == NULL || **s != '\0') + return; + + free(*s); + *s = NULL; +} + +static struct sshbuf * +process_sign(struct sshbuf *req) +{ + int r = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *resp, *kbuf; + struct sshkey *key = NULL; + uint32_t compat; + const u_char *message; + u_char *sig = NULL; + size_t msglen, siglen = 0; + char *provider = NULL, *pin = NULL; + + if ((r = sshbuf_froms(req, &kbuf)) != 0 || + (r = sshbuf_get_cstring(req, &provider, NULL)) != 0 || + (r = sshbuf_get_string_direct(req, &message, &msglen)) != 0 || + (r = sshbuf_get_cstring(req, NULL, NULL)) != 0 || /* alg */ + (r = sshbuf_get_u32(req, &compat)) != 0 || + (r = sshbuf_get_cstring(req, &pin, NULL)) != 0) + fatal_r(r, "%s: parse", __progname); + if (sshbuf_len(req) != 0) + fatal("%s: trailing data in request", __progname); + + if ((r = sshkey_private_deserialize(kbuf, &key)) != 0) + fatal_r(r, "%s: Unable to parse private key", __progname); + if (!sshkey_is_sk(key)) { + fatal("%s: Unsupported key type %s", + __progname, sshkey_ssh_name(key)); + } + + debug_f("ready to sign with key %s, provider %s: " + "msg len %zu, compat 0x%lx", sshkey_type(key), + provider, msglen, (u_long)compat); + + null_empty(&pin); + + if ((r = sshsk_sign(provider, key, &sig, &siglen, + message, msglen, compat, pin)) != 0) { + resp = reply_error(r, "Signing failed: %s", ssh_err(r)); + goto out; + } + + if ((resp = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __progname); + + if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_SIGN)) != 0 || + (r = sshbuf_put_string(resp, sig, siglen)) != 0) + fatal_r(r, "%s: compose", __progname); + out: + sshkey_free(key); + sshbuf_free(kbuf); + free(provider); + if (sig != NULL) + freezero(sig, siglen); + if (pin != NULL) + freezero(pin, strlen(pin)); + return resp; +} + +static struct sshbuf * +process_enroll(struct sshbuf *req) +{ + int r; + u_int type; + char *provider, *application, *pin, *device, *userid; + uint8_t flags; + struct sshbuf *challenge, *attest, *kbuf, *resp; + struct sshkey *key; + + if ((attest = sshbuf_new()) == NULL || + (kbuf = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __progname); + + if ((r = sshbuf_get_u32(req, &type)) != 0 || + (r = sshbuf_get_cstring(req, &provider, NULL)) != 0 || + (r = sshbuf_get_cstring(req, &device, NULL)) != 0 || + (r = sshbuf_get_cstring(req, &application, NULL)) != 0 || + (r = sshbuf_get_cstring(req, &userid, NULL)) != 0 || + (r = sshbuf_get_u8(req, &flags)) != 0 || + (r = sshbuf_get_cstring(req, &pin, NULL)) != 0 || + (r = sshbuf_froms(req, &challenge)) != 0) + fatal_r(r, "%s: parse", __progname); + if (sshbuf_len(req) != 0) + fatal("%s: trailing data in request", __progname); + + if (type > INT_MAX) + fatal("%s: bad type %u", __progname, type); + if (sshbuf_len(challenge) == 0) { + sshbuf_free(challenge); + challenge = NULL; + } + null_empty(&device); + null_empty(&userid); + null_empty(&pin); + + if ((r = sshsk_enroll((int)type, provider, device, application, userid, + flags, pin, challenge, &key, attest)) != 0) { + resp = reply_error(r, "Enrollment failed: %s", ssh_err(r)); + goto out; + } + + if ((resp = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __progname); + if ((r = sshkey_private_serialize(key, kbuf)) != 0) + fatal_r(r, "%s: encode key", __progname); + if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_ENROLL)) != 0 || + (r = sshbuf_put_stringb(resp, kbuf)) != 0 || + (r = sshbuf_put_stringb(resp, attest)) != 0) + fatal_r(r, "%s: compose", __progname); + + out: + sshkey_free(key); + sshbuf_free(kbuf); + sshbuf_free(attest); + sshbuf_free(challenge); + free(provider); + free(application); + if (pin != NULL) + freezero(pin, strlen(pin)); + + return resp; +} + +static struct sshbuf * +process_load_resident(struct sshbuf *req) +{ + int r; + char *provider, *pin, *device; + struct sshbuf *kbuf, *resp; + struct sshkey **keys = NULL; + size_t nkeys = 0, i; + + if ((kbuf = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __progname); + + if ((r = sshbuf_get_cstring(req, &provider, NULL)) != 0 || + (r = sshbuf_get_cstring(req, &device, NULL)) != 0 || + (r = sshbuf_get_cstring(req, &pin, NULL)) != 0) + fatal_r(r, "%s: parse", __progname); + if (sshbuf_len(req) != 0) + fatal("%s: trailing data in request", __progname); + + null_empty(&device); + null_empty(&pin); + + if ((r = sshsk_load_resident(provider, device, pin, + &keys, &nkeys)) != 0) { + resp = reply_error(r, " sshsk_load_resident failed: %s", + ssh_err(r)); + goto out; + } + + if ((resp = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __progname); + + if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_LOAD_RESIDENT)) != 0) + fatal_r(r, "%s: compose", __progname); + + for (i = 0; i < nkeys; i++) { + debug_f("key %zu %s %s", i, sshkey_type(keys[i]), + keys[i]->sk_application); + sshbuf_reset(kbuf); + if ((r = sshkey_private_serialize(keys[i], kbuf)) != 0) + fatal_r(r, "%s: encode key", __progname); + if ((r = sshbuf_put_stringb(resp, kbuf)) != 0 || + (r = sshbuf_put_cstring(resp, "")) != 0) /* comment */ + fatal_r(r, "%s: compose key", __progname); + } + + out: + for (i = 0; i < nkeys; i++) + sshkey_free(keys[i]); + free(keys); + sshbuf_free(kbuf); + free(provider); + if (pin != NULL) + freezero(pin, strlen(pin)); + return resp; +} + +int +main(int argc, char **argv) +{ + SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; + LogLevel log_level = SYSLOG_LEVEL_ERROR; + struct sshbuf *req, *resp; + int in, out, ch, r, vflag = 0; + u_int rtype, ll = 0; + uint8_t version, log_stderr = 0; + + sanitise_stdfd(); + log_init(__progname, log_level, log_facility, log_stderr); + + while ((ch = getopt(argc, argv, "v")) != -1) { + switch (ch) { + case 'v': + vflag = 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, vflag); + + /* + * Rearrange our file descriptors a little; we don't trust the + * providers not to fiddle with stdin/out. + */ + closefrom(STDERR_FILENO + 1); + if ((in = dup(STDIN_FILENO)) == -1 || (out = dup(STDOUT_FILENO)) == -1) + fatal("%s: dup: %s", __progname, strerror(errno)); + close(STDIN_FILENO); + close(STDOUT_FILENO); + sanitise_stdfd(); /* resets to /dev/null */ + + if ((req = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __progname); + if (ssh_msg_recv(in, req) < 0) + fatal("ssh_msg_recv failed"); + close(in); + debug_f("received message len %zu", sshbuf_len(req)); + + if ((r = sshbuf_get_u8(req, &version)) != 0) + fatal_r(r, "%s: parse version", __progname); + if (version != SSH_SK_HELPER_VERSION) { + fatal("unsupported version: received %d, expected %d", + version, SSH_SK_HELPER_VERSION); + } + + if ((r = sshbuf_get_u32(req, &rtype)) != 0 || + (r = sshbuf_get_u8(req, &log_stderr)) != 0 || + (r = sshbuf_get_u32(req, &ll)) != 0) + fatal_r(r, "%s: parse", __progname); + + if (!vflag && log_level_name((LogLevel)ll) != NULL) + log_init(__progname, (LogLevel)ll, log_facility, log_stderr); + + switch (rtype) { + case SSH_SK_HELPER_SIGN: + resp = process_sign(req); + break; + case SSH_SK_HELPER_ENROLL: + resp = process_enroll(req); + break; + case SSH_SK_HELPER_LOAD_RESIDENT: + resp = process_load_resident(req); + break; + default: + fatal("%s: unsupported request type %u", __progname, rtype); + } + sshbuf_free(req); + debug_f("reply len %zu", sshbuf_len(resp)); + + if (ssh_msg_send(out, SSH_SK_HELPER_VERSION, resp) == -1) + fatal("ssh_msg_send failed"); + sshbuf_free(resp); + close(out); + + return (0); +} +#else /* ENABLE_SK */ +#include + +int +main(int argc, char **argv) +{ + fprintf(stderr, "ssh-sk-helper: disabled at compile time\n"); + return -1; +} +#endif /* ENABLE_SK */ diff --git a/ssh-sk.c b/ssh-sk.c new file mode 100644 index 000000000..d254e77f9 --- /dev/null +++ b/ssh-sk.c @@ -0,0 +1,826 @@ +/* $OpenBSD: ssh-sk.c,v 1.35 2021/02/26 00:16:58 djm Exp $ */ +/* + * Copyright (c) 2019 Google LLC + * + * 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 DEBUG_SK 1 */ + +#include "includes.h" + +#ifdef ENABLE_SK + +#include +#include +#ifdef HAVE_STDINT_H +# include +#endif +#include +#include + +#ifdef WITH_OPENSSL +#include +#include +#endif /* WITH_OPENSSL */ + +#include "log.h" +#include "misc.h" +#include "sshbuf.h" +#include "sshkey.h" +#include "ssherr.h" +#include "digest.h" + +#include "ssh-sk.h" +#include "sk-api.h" +#include "crypto_api.h" + +struct sshsk_provider { + char *path; + void *dlhandle; + + /* Return the version of the middleware API */ + uint32_t (*sk_api_version)(void); + + /* Enroll a U2F key (private key generation) */ + int (*sk_enroll)(int alg, const uint8_t *challenge, + size_t challenge_len, const char *application, uint8_t flags, + const char *pin, struct sk_option **opts, + struct sk_enroll_response **enroll_response); + + /* Sign a challenge */ + int (*sk_sign)(int alg, const uint8_t *message, size_t message_len, + const char *application, + const uint8_t *key_handle, size_t key_handle_len, + uint8_t flags, const char *pin, struct sk_option **opts, + struct sk_sign_response **sign_response); + + /* Enumerate resident keys */ + int (*sk_load_resident_keys)(const char *pin, struct sk_option **opts, + struct sk_resident_key ***rks, size_t *nrks); +}; + +/* Built-in version */ +int ssh_sk_enroll(int alg, const uint8_t *challenge, + size_t challenge_len, const char *application, uint8_t flags, + const char *pin, struct sk_option **opts, + struct sk_enroll_response **enroll_response); +int ssh_sk_sign(int alg, const uint8_t *message, size_t message_len, + const char *application, + const uint8_t *key_handle, size_t key_handle_len, + uint8_t flags, const char *pin, struct sk_option **opts, + struct sk_sign_response **sign_response); +int ssh_sk_load_resident_keys(const char *pin, struct sk_option **opts, + struct sk_resident_key ***rks, size_t *nrks); + +static void +sshsk_free(struct sshsk_provider *p) +{ + if (p == NULL) + return; + free(p->path); + if (p->dlhandle != NULL) + dlclose(p->dlhandle); + free(p); +} + +static struct sshsk_provider * +sshsk_open(const char *path) +{ + struct sshsk_provider *ret = NULL; + uint32_t version; + + if (path == NULL || *path == '\0') { + error("No FIDO SecurityKeyProvider specified"); + return NULL; + } + if ((ret = calloc(1, sizeof(*ret))) == NULL) { + error_f("calloc failed"); + return NULL; + } + if ((ret->path = strdup(path)) == NULL) { + error_f("strdup failed"); + goto fail; + } + /* Skip the rest if we're using the linked in middleware */ + if (strcasecmp(ret->path, "internal") == 0) { +#ifdef ENABLE_SK_INTERNAL + ret->sk_enroll = ssh_sk_enroll; + ret->sk_sign = ssh_sk_sign; + ret->sk_load_resident_keys = ssh_sk_load_resident_keys; +#else + error("internal security key support not enabled"); +#endif + return ret; + } + if ((ret->dlhandle = dlopen(path, RTLD_NOW)) == NULL) { + error("Provider \"%s\" dlopen failed: %s", path, dlerror()); + goto fail; + } + if ((ret->sk_api_version = dlsym(ret->dlhandle, + "sk_api_version")) == NULL) { + error("Provider \"%s\" dlsym(sk_api_version) failed: %s", + path, dlerror()); + goto fail; + } + version = ret->sk_api_version(); + debug_f("provider %s implements version 0x%08lx", ret->path, + (u_long)version); + if ((version & SSH_SK_VERSION_MAJOR_MASK) != SSH_SK_VERSION_MAJOR) { + error("Provider \"%s\" implements unsupported " + "version 0x%08lx (supported: 0x%08lx)", + path, (u_long)version, (u_long)SSH_SK_VERSION_MAJOR); + goto fail; + } + if ((ret->sk_enroll = dlsym(ret->dlhandle, "sk_enroll")) == NULL) { + error("Provider %s dlsym(sk_enroll) failed: %s", + path, dlerror()); + goto fail; + } + if ((ret->sk_sign = dlsym(ret->dlhandle, "sk_sign")) == NULL) { + error("Provider \"%s\" dlsym(sk_sign) failed: %s", + path, dlerror()); + goto fail; + } + if ((ret->sk_load_resident_keys = dlsym(ret->dlhandle, + "sk_load_resident_keys")) == NULL) { + error("Provider \"%s\" dlsym(sk_load_resident_keys) " + "failed: %s", path, dlerror()); + goto fail; + } + /* success */ + return ret; +fail: + sshsk_free(ret); + return NULL; +} + +static void +sshsk_free_enroll_response(struct sk_enroll_response *r) +{ + if (r == NULL) + return; + freezero(r->key_handle, r->key_handle_len); + freezero(r->public_key, r->public_key_len); + freezero(r->signature, r->signature_len); + freezero(r->attestation_cert, r->attestation_cert_len); + freezero(r->authdata, r->authdata_len); + freezero(r, sizeof(*r)); +} + +static void +sshsk_free_sign_response(struct sk_sign_response *r) +{ + if (r == NULL) + return; + freezero(r->sig_r, r->sig_r_len); + freezero(r->sig_s, r->sig_s_len); + freezero(r, sizeof(*r)); +} + +#ifdef WITH_OPENSSL +/* Assemble key from response */ +static int +sshsk_ecdsa_assemble(struct sk_enroll_response *resp, struct sshkey **keyp) +{ + struct sshkey *key = NULL; + struct sshbuf *b = NULL; + EC_POINT *q = NULL; + int r; + + *keyp = NULL; + if ((key = sshkey_new(KEY_ECDSA_SK)) == NULL) { + error_f("sshkey_new failed"); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + key->ecdsa_nid = NID_X9_62_prime256v1; + if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL || + (q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL || + (b = sshbuf_new()) == NULL) { + error_f("allocation failed"); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_put_string(b, + resp->public_key, resp->public_key_len)) != 0) { + error_fr(r, "sshbuf_put_string"); + goto out; + } + if ((r = sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa))) != 0) { + error_fr(r, "parse"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa), q) != 0) { + error("Authenticator returned invalid ECDSA key"); + r = 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 */ + error_f("allocation failed"); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + /* success */ + *keyp = key; + key = NULL; /* transferred */ + r = 0; + out: + EC_POINT_free(q); + sshkey_free(key); + sshbuf_free(b); + return r; +} +#endif /* WITH_OPENSSL */ + +static int +sshsk_ed25519_assemble(struct sk_enroll_response *resp, struct sshkey **keyp) +{ + struct sshkey *key = NULL; + int r; + + *keyp = NULL; + if (resp->public_key_len != ED25519_PK_SZ) { + error_f("invalid size: %zu", resp->public_key_len); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((key = sshkey_new(KEY_ED25519_SK)) == NULL) { + error_f("sshkey_new failed"); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((key->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { + error_f("malloc failed"); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + memcpy(key->ed25519_pk, resp->public_key, ED25519_PK_SZ); + /* success */ + *keyp = key; + key = NULL; /* transferred */ + r = 0; + out: + sshkey_free(key); + return r; +} + +static int +sshsk_key_from_response(int alg, const char *application, uint8_t flags, + struct sk_enroll_response *resp, struct sshkey **keyp) +{ + struct sshkey *key = NULL; + int r = SSH_ERR_INTERNAL_ERROR; + + *keyp = NULL; + + /* Check response validity */ + if (resp->public_key == NULL || resp->key_handle == NULL) { + error_f("sk_enroll response invalid"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + switch (alg) { +#ifdef WITH_OPENSSL + case SSH_SK_ECDSA: + if ((r = sshsk_ecdsa_assemble(resp, &key)) != 0) + goto out; + break; +#endif /* WITH_OPENSSL */ + case SSH_SK_ED25519: + if ((r = sshsk_ed25519_assemble(resp, &key)) != 0) + goto out; + break; + default: + error_f("unsupported algorithm %d", alg); + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + key->sk_flags = flags; + if ((key->sk_key_handle = sshbuf_new()) == NULL || + (key->sk_reserved = sshbuf_new()) == NULL) { + error_f("allocation failed"); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((key->sk_application = strdup(application)) == NULL) { + error_f("strdup application failed"); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_put(key->sk_key_handle, resp->key_handle, + resp->key_handle_len)) != 0) { + error_fr(r, "put key handle"); + goto out; + } + /* success */ + r = 0; + *keyp = key; + key = NULL; + out: + sshkey_free(key); + return r; +} + +static int +skerr_to_ssherr(int skerr) +{ + switch (skerr) { + case SSH_SK_ERR_UNSUPPORTED: + return SSH_ERR_FEATURE_UNSUPPORTED; + case SSH_SK_ERR_PIN_REQUIRED: + return SSH_ERR_KEY_WRONG_PASSPHRASE; + case SSH_SK_ERR_DEVICE_NOT_FOUND: + return SSH_ERR_DEVICE_NOT_FOUND; + case SSH_SK_ERR_GENERAL: + default: + return SSH_ERR_INVALID_FORMAT; + } +} + +static void +sshsk_free_options(struct sk_option **opts) +{ + size_t i; + + if (opts == NULL) + return; + for (i = 0; opts[i] != NULL; i++) { + free(opts[i]->name); + free(opts[i]->value); + free(opts[i]); + } + free(opts); +} + +static int +sshsk_add_option(struct sk_option ***optsp, size_t *noptsp, + const char *name, const char *value, uint8_t required) +{ + struct sk_option **opts = *optsp; + size_t nopts = *noptsp; + + if ((opts = recallocarray(opts, nopts, nopts + 2, /* extra for NULL */ + sizeof(*opts))) == NULL) { + error_f("array alloc failed"); + return SSH_ERR_ALLOC_FAIL; + } + *optsp = opts; + *noptsp = nopts + 1; + if ((opts[nopts] = calloc(1, sizeof(**opts))) == NULL) { + error_f("alloc failed"); + return SSH_ERR_ALLOC_FAIL; + } + if ((opts[nopts]->name = strdup(name)) == NULL || + (opts[nopts]->value = strdup(value)) == NULL) { + error_f("alloc failed"); + return SSH_ERR_ALLOC_FAIL; + } + opts[nopts]->required = required; + return 0; +} + +static int +make_options(const char *device, const char *user_id, + struct sk_option ***optsp) +{ + struct sk_option **opts = NULL; + size_t nopts = 0; + int r, ret = SSH_ERR_INTERNAL_ERROR; + + if (device != NULL && + (r = sshsk_add_option(&opts, &nopts, "device", device, 0)) != 0) { + ret = r; + goto out; + } + if (user_id != NULL && + (r = sshsk_add_option(&opts, &nopts, "user", user_id, 0)) != 0) { + ret = r; + goto out; + } + /* success */ + *optsp = opts; + opts = NULL; + nopts = 0; + ret = 0; + out: + sshsk_free_options(opts); + return ret; +} + + +static int +fill_attestation_blob(const struct sk_enroll_response *resp, + struct sshbuf *attest) +{ + int r; + + if (attest == NULL) + return 0; /* nothing to do */ + if ((r = sshbuf_put_cstring(attest, "ssh-sk-attest-v01")) != 0 || + (r = sshbuf_put_string(attest, + resp->attestation_cert, resp->attestation_cert_len)) != 0 || + (r = sshbuf_put_string(attest, + resp->signature, resp->signature_len)) != 0 || + (r = sshbuf_put_string(attest, + resp->authdata, resp->authdata_len)) != 0 || + (r = sshbuf_put_u32(attest, 0)) != 0 || /* resvd flags */ + (r = sshbuf_put_string(attest, NULL, 0)) != 0 /* resvd */) { + error_fr(r, "compose"); + return r; + } + /* success */ + return 0; +} + +int +sshsk_enroll(int type, const char *provider_path, const char *device, + const char *application, const char *userid, uint8_t flags, + const char *pin, struct sshbuf *challenge_buf, + struct sshkey **keyp, struct sshbuf *attest) +{ + struct sshsk_provider *skp = NULL; + struct sshkey *key = NULL; + u_char randchall[32]; + const u_char *challenge; + size_t challenge_len; + struct sk_enroll_response *resp = NULL; + struct sk_option **opts = NULL; + int r = SSH_ERR_INTERNAL_ERROR; + int alg; + + debug_f("provider \"%s\", device \"%s\", application \"%s\", " + "userid \"%s\", flags 0x%02x, challenge len %zu%s", + provider_path, device, application, userid, flags, + challenge_buf == NULL ? 0 : sshbuf_len(challenge_buf), + (pin != NULL && *pin != '\0') ? " with-pin" : ""); + + *keyp = NULL; + if (attest) + sshbuf_reset(attest); + + if ((r = make_options(device, userid, &opts)) != 0) + goto out; + + switch (type) { +#ifdef WITH_OPENSSL + case KEY_ECDSA_SK: + alg = SSH_SK_ECDSA; + break; +#endif /* WITH_OPENSSL */ + case KEY_ED25519_SK: + alg = SSH_SK_ED25519; + break; + default: + error_f("unsupported key type"); + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if (provider_path == NULL) { + error_f("missing provider"); + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if (application == NULL || *application == '\0') { + error_f("missing application"); + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if (challenge_buf == NULL) { + debug_f("using random challenge"); + arc4random_buf(randchall, sizeof(randchall)); + challenge = randchall; + challenge_len = sizeof(randchall); + } else if (sshbuf_len(challenge_buf) == 0) { + error("Missing enrollment challenge"); + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } else { + challenge = sshbuf_ptr(challenge_buf); + challenge_len = sshbuf_len(challenge_buf); + debug3_f("using explicit challenge len=%zd", challenge_len); + } + if ((skp = sshsk_open(provider_path)) == NULL) { + r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */ + goto out; + } + /* XXX validate flags? */ + /* enroll key */ + if ((r = skp->sk_enroll(alg, challenge, challenge_len, application, + flags, pin, opts, &resp)) != 0) { + debug_f("provider \"%s\" failure %d", provider_path, r); + r = skerr_to_ssherr(r); + goto out; + } + + if ((r = sshsk_key_from_response(alg, application, flags, + resp, &key)) != 0) + goto out; + + /* Optionally fill in the attestation information */ + if ((r = fill_attestation_blob(resp, attest)) != 0) + goto out; + + /* success */ + *keyp = key; + key = NULL; /* transferred */ + r = 0; + out: + sshsk_free_options(opts); + sshsk_free(skp); + sshkey_free(key); + sshsk_free_enroll_response(resp); + explicit_bzero(randchall, sizeof(randchall)); + return r; +} + +#ifdef WITH_OPENSSL +static int +sshsk_ecdsa_sig(struct sk_sign_response *resp, struct sshbuf *sig) +{ + struct sshbuf *inner_sig = NULL; + int r = SSH_ERR_INTERNAL_ERROR; + + /* Check response validity */ + if (resp->sig_r == NULL || resp->sig_s == NULL) { + error_f("sk_sign response invalid"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((inner_sig = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + /* Prepare and append inner signature object */ + if ((r = sshbuf_put_bignum2_bytes(inner_sig, + resp->sig_r, resp->sig_r_len)) != 0 || + (r = sshbuf_put_bignum2_bytes(inner_sig, + resp->sig_s, resp->sig_s_len)) != 0) { + error_fr(r, "compose inner"); + goto out; + } + if ((r = sshbuf_put_stringb(sig, inner_sig)) != 0 || + (r = sshbuf_put_u8(sig, resp->flags)) != 0 || + (r = sshbuf_put_u32(sig, resp->counter)) != 0) { + error_fr(r, "compose"); + goto out; + } +#ifdef DEBUG_SK + fprintf(stderr, "%s: sig_r:\n", __func__); + sshbuf_dump_data(resp->sig_r, resp->sig_r_len, stderr); + fprintf(stderr, "%s: sig_s:\n", __func__); + sshbuf_dump_data(resp->sig_s, resp->sig_s_len, stderr); + fprintf(stderr, "%s: inner:\n", __func__); + sshbuf_dump(inner_sig, stderr); +#endif + r = 0; + out: + sshbuf_free(inner_sig); + return r; +} +#endif /* WITH_OPENSSL */ + +static int +sshsk_ed25519_sig(struct sk_sign_response *resp, struct sshbuf *sig) +{ + int r = SSH_ERR_INTERNAL_ERROR; + + /* Check response validity */ + if (resp->sig_r == NULL) { + error_f("sk_sign response invalid"); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((r = sshbuf_put_string(sig, + resp->sig_r, resp->sig_r_len)) != 0 || + (r = sshbuf_put_u8(sig, resp->flags)) != 0 || + (r = sshbuf_put_u32(sig, resp->counter)) != 0) { + error_fr(r, "compose"); + goto out; + } +#ifdef DEBUG_SK + fprintf(stderr, "%s: sig_r:\n", __func__); + sshbuf_dump_data(resp->sig_r, resp->sig_r_len, stderr); +#endif + r = 0; + out: + return r; +} + +int +sshsk_sign(const char *provider_path, struct sshkey *key, + u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, + u_int compat, const char *pin) +{ + struct sshsk_provider *skp = NULL; + int r = SSH_ERR_INTERNAL_ERROR; + int type, alg; + struct sk_sign_response *resp = NULL; + struct sshbuf *inner_sig = NULL, *sig = NULL; + struct sk_option **opts = NULL; + + debug_f("provider \"%s\", key %s, flags 0x%02x%s", + provider_path, sshkey_type(key), key->sk_flags, + (pin != NULL && *pin != '\0') ? " with-pin" : ""); + + if (sigp != NULL) + *sigp = NULL; + if (lenp != NULL) + *lenp = 0; + type = sshkey_type_plain(key->type); + switch (type) { +#ifdef WITH_OPENSSL + case KEY_ECDSA_SK: + alg = SSH_SK_ECDSA; + break; +#endif /* WITH_OPENSSL */ + case KEY_ED25519_SK: + alg = SSH_SK_ED25519; + break; + default: + return SSH_ERR_INVALID_ARGUMENT; + } + if (provider_path == NULL || + key->sk_key_handle == NULL || + key->sk_application == NULL || *key->sk_application == '\0') { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if ((skp = sshsk_open(provider_path)) == NULL) { + r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */ + goto out; + } +#ifdef DEBUG_SK + fprintf(stderr, "%s: sk_flags = 0x%02x, sk_application = \"%s\"\n", + __func__, key->sk_flags, key->sk_application); + fprintf(stderr, "%s: sk_key_handle:\n", __func__); + sshbuf_dump(key->sk_key_handle, stderr); +#endif + if ((r = skp->sk_sign(alg, data, datalen, key->sk_application, + sshbuf_ptr(key->sk_key_handle), sshbuf_len(key->sk_key_handle), + key->sk_flags, pin, opts, &resp)) != 0) { + debug_f("sk_sign failed with code %d", r); + r = skerr_to_ssherr(r); + goto out; + } + /* Assemble signature */ + if ((sig = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_put_cstring(sig, sshkey_ssh_name_plain(key))) != 0) { + error_fr(r, "compose outer"); + goto out; + } + switch (type) { +#ifdef WITH_OPENSSL + case KEY_ECDSA_SK: + if ((r = sshsk_ecdsa_sig(resp, sig)) != 0) + goto out; + break; +#endif /* WITH_OPENSSL */ + case KEY_ED25519_SK: + if ((r = sshsk_ed25519_sig(resp, sig)) != 0) + goto out; + break; + } +#ifdef DEBUG_SK + fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n", + __func__, resp->flags, resp->counter); + fprintf(stderr, "%s: data to sign:\n", __func__); + sshbuf_dump_data(data, datalen, stderr); + fprintf(stderr, "%s: sigbuf:\n", __func__); + sshbuf_dump(sig, stderr); +#endif + if (sigp != NULL) { + if ((*sigp = malloc(sshbuf_len(sig))) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + memcpy(*sigp, sshbuf_ptr(sig), sshbuf_len(sig)); + } + if (lenp != NULL) + *lenp = sshbuf_len(sig); + /* success */ + r = 0; + out: + sshsk_free_options(opts); + sshsk_free(skp); + sshsk_free_sign_response(resp); + sshbuf_free(sig); + sshbuf_free(inner_sig); + return r; +} + +static void +sshsk_free_sk_resident_keys(struct sk_resident_key **rks, size_t nrks) +{ + size_t i; + + if (nrks == 0 || rks == NULL) + return; + for (i = 0; i < nrks; i++) { + free(rks[i]->application); + freezero(rks[i]->key.key_handle, rks[i]->key.key_handle_len); + freezero(rks[i]->key.public_key, rks[i]->key.public_key_len); + freezero(rks[i]->key.signature, rks[i]->key.signature_len); + freezero(rks[i]->key.attestation_cert, + rks[i]->key.attestation_cert_len); + freezero(rks[i], sizeof(**rks)); + } + free(rks); +} + +int +sshsk_load_resident(const char *provider_path, const char *device, + const char *pin, struct sshkey ***keysp, size_t *nkeysp) +{ + struct sshsk_provider *skp = NULL; + int r = SSH_ERR_INTERNAL_ERROR; + struct sk_resident_key **rks = NULL; + size_t i, nrks = 0, nkeys = 0; + struct sshkey *key = NULL, **keys = NULL, **tmp; + uint8_t flags; + struct sk_option **opts = NULL; + + debug_f("provider \"%s\"%s", provider_path, + (pin != NULL && *pin != '\0') ? ", have-pin": ""); + + if (keysp == NULL || nkeysp == NULL) + return SSH_ERR_INVALID_ARGUMENT; + *keysp = NULL; + *nkeysp = 0; + + if ((r = make_options(device, NULL, &opts)) != 0) + goto out; + if ((skp = sshsk_open(provider_path)) == NULL) { + r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */ + goto out; + } + if ((r = skp->sk_load_resident_keys(pin, opts, &rks, &nrks)) != 0) { + error("Provider \"%s\" returned failure %d", provider_path, r); + r = skerr_to_ssherr(r); + goto out; + } + for (i = 0; i < nrks; i++) { + debug3_f("rk %zu: slot = %zu, alg = %d, application = \"%s\"", + i, rks[i]->slot, rks[i]->alg, rks[i]->application); + /* XXX need better filter here */ + if (strncmp(rks[i]->application, "ssh:", 4) != 0) + continue; + switch (rks[i]->alg) { + case SSH_SK_ECDSA: + case SSH_SK_ED25519: + break; + default: + continue; + } + flags = SSH_SK_USER_PRESENCE_REQD|SSH_SK_RESIDENT_KEY; + if ((rks[i]->flags & SSH_SK_USER_VERIFICATION_REQD)) + flags |= SSH_SK_USER_VERIFICATION_REQD; + if ((r = sshsk_key_from_response(rks[i]->alg, + rks[i]->application, flags, &rks[i]->key, &key)) != 0) + goto out; + if ((tmp = recallocarray(keys, nkeys, nkeys + 1, + sizeof(*tmp))) == NULL) { + error_f("recallocarray failed"); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + keys = tmp; + keys[nkeys++] = key; + key = NULL; + /* XXX synthesise comment */ + } + /* success */ + *keysp = keys; + *nkeysp = nkeys; + keys = NULL; + nkeys = 0; + r = 0; + out: + sshsk_free_options(opts); + sshsk_free(skp); + sshsk_free_sk_resident_keys(rks, nrks); + sshkey_free(key); + if (nkeys != 0) { + for (i = 0; i < nkeys; i++) + sshkey_free(keys[i]); + free(keys); + } + return r; +} + +#endif /* ENABLE_SK */ diff --git a/ssh-sk.h b/ssh-sk.h new file mode 100644 index 000000000..0f566bbc3 --- /dev/null +++ b/ssh-sk.h @@ -0,0 +1,69 @@ +/* $OpenBSD: ssh-sk.h,v 1.10 2020/01/10 23:43:26 djm Exp $ */ +/* + * Copyright (c) 2019 Google LLC + * + * 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 _SSH_SK_H +#define _SSH_SK_H 1 + +struct sshbuf; +struct sshkey; +struct sk_option; + +/* Version of protocol expected from ssh-sk-helper */ +#define SSH_SK_HELPER_VERSION 5 + +/* ssh-sk-helper messages */ +#define SSH_SK_HELPER_ERROR 0 /* Only valid H->C */ +#define SSH_SK_HELPER_SIGN 1 +#define SSH_SK_HELPER_ENROLL 2 +#define SSH_SK_HELPER_LOAD_RESIDENT 3 + +/* + * Enroll (generate) a new security-key hosted private key of given type + * via the specified provider middleware. + * If challenge_buf is NULL then a random 256 bit challenge will be used. + * + * Returns 0 on success or a ssherr.h error code on failure. + * + * If successful and the attest_data buffer is not NULL then attestation + * information is placed there. + */ +int sshsk_enroll(int type, const char *provider_path, const char *device, + const char *application, const char *userid, uint8_t flags, + const char *pin, struct sshbuf *challenge_buf, + struct sshkey **keyp, struct sshbuf *attest); + +/* + * Calculate an ECDSA_SK or ED25519_SK signature using the specified key + * and provider middleware. + * + * Returns 0 on success or a ssherr.h error code on failure. + */ +int sshsk_sign(const char *provider_path, struct sshkey *key, + u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, + u_int compat, const char *pin); + +/* + * Enumerates and loads all SSH-compatible resident keys from a security + * key. + * + * Returns 0 on success or a ssherr.h error code on failure. + */ +int sshsk_load_resident(const char *provider_path, const char *device, + const char *pin, struct sshkey ***keysp, size_t *nkeysp); + +#endif /* _SSH_SK_H */ + diff --git a/ssh-xmss.c b/ssh-xmss.c index 4c734fd7d..7bd3a96a3 100644 --- a/ssh-xmss.c +++ b/ssh-xmss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-xmss.c,v 1.1 2018/02/23 15:58:38 markus Exp $*/ +/* $OpenBSD: ssh-xmss.c,v 1.4 2020/10/19 22:49:23 dtucker Exp $*/ /* * Copyright (c) 2017 Stefan-Lukas Gazdag. * Copyright (c) 2017 Markus Friedl. @@ -62,7 +62,7 @@ ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, smlen = slen = datalen + required_siglen; if ((sig = malloc(slen)) == NULL) return SSH_ERR_ALLOC_FAIL; - if ((r = sshkey_xmss_get_state(key, error)) != 0) + if ((r = sshkey_xmss_get_state(key, 1)) != 0) goto out; if ((ret = xmss_sign(key->xmss_sk, sshkey_xmss_bds_state(key), sig, &smlen, data, datalen, sshkey_xmss_params(key))) != 0 || smlen <= datalen) { @@ -90,7 +90,7 @@ ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, /* success */ r = 0; out: - if ((ret = sshkey_xmss_update_state(key, error)) != 0) { + if ((ret = sshkey_xmss_update_state(key, 1)) != 0) { /* discard signature since we cannot update the state */ if (r == 0 && sigp != NULL && *sigp != NULL) { explicit_bzero(*sigp, len); @@ -103,10 +103,8 @@ ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, r = ret; } sshbuf_free(b); - if (sig != NULL) { - explicit_bzero(sig, slen); - free(sig); - } + if (sig != NULL) + freezero(sig, slen); return r; } @@ -166,8 +164,7 @@ ssh_xmss_verify(const struct sshkey *key, memcpy(sm+len, data, datalen); if ((ret = xmss_sign_open(m, &mlen, sm, smlen, key->xmss_pk, sshkey_xmss_params(key))) != 0) { - debug2("%s: crypto_sign_xmss_open failed: %d", - __func__, ret); + debug2_f("xmss_sign_open failed: %d", ret); } if (ret != 0 || mlen != datalen) { r = SSH_ERR_SIGNATURE_INVALID; @@ -177,14 +174,10 @@ ssh_xmss_verify(const struct sshkey *key, /* success */ r = 0; out: - if (sm != NULL) { - explicit_bzero(sm, smlen); - free(sm); - } - if (m != NULL) { - explicit_bzero(m, smlen); /* NB mlen may be invalid if r != 0 */ - free(m); - } + if (sm != NULL) + freezero(sm, smlen); + if (m != NULL) + freezero(m, smlen); sshbuf_free(b); free(ktype); return r; diff --git a/ssh.1 b/ssh.1 index 424d6c3e8..0a01767ed 100644 --- a/ssh.1 +++ b/ssh.1 @@ -33,13 +33,13 @@ .\" (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.403 2019/06/12 11:31:50 jmc Exp $ -.Dd $Mdocdate: June 12 2019 $ +.\" $OpenBSD: ssh.1,v 1.419 2021/02/15 20:43:15 markus Exp $ +.Dd $Mdocdate: February 15 2021 $ .Dt SSH 1 .Os .Sh NAME .Nm ssh -.Nd OpenSSH SSH client (remote login program) +.Nd OpenSSH remote login client .Sh SYNOPSIS .Nm ssh .Op Fl 46AaCfGgKkMNnqsTtVvXxYy @@ -110,7 +110,8 @@ Forces to use IPv6 addresses only. .Pp .It Fl A -Enables forwarding of the authentication agent connection. +Enables forwarding of connections from an authentication agent such as +.Xr ssh-agent 1 . This can also be specified on a per-host basis in a configuration file. .Pp Agent forwarding should be enabled with caution. @@ -121,6 +122,9 @@ 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 safer alternative may be to use a jump host +(see +.Fl J ) . .Pp .It Fl a Disables forwarding of the authentication agent connection. @@ -229,6 +233,9 @@ the system-wide configuration file will be ignored. The default for the per-user configuration file is .Pa ~/.ssh/config . +If set to +.Dq none , +no configuration files will be read. .Pp .It Fl f Requests @@ -279,7 +286,9 @@ public key authentication is read. The default is .Pa ~/.ssh/id_dsa , .Pa ~/.ssh/id_ecdsa , -.Pa ~/.ssh/id_ed25519 +.Pa ~/.ssh/id_ecdsa_sk , +.Pa ~/.ssh/id_ed25519 , +.Pa ~/.ssh/id_ed25519_sk and .Pa ~/.ssh/id_rsa . Identity files may also be specified on @@ -500,8 +509,8 @@ For full details of the options listed below, and their possible values, see .It GSSAPIDelegateCredentials .It HashKnownHosts .It Host +.It HostbasedAcceptedAlgorithms .It HostbasedAuthentication -.It HostbasedKeyTypes .It HostKeyAlgorithms .It HostKeyAlias .It Hostname @@ -512,6 +521,7 @@ For full details of the options listed below, and their possible values, see .It KbdInteractiveAuthentication .It KbdInteractiveDevices .It KexAlgorithms +.It KnownHostsCommand .It LocalCommand .It LocalForward .It LogLevel @@ -521,13 +531,14 @@ For full details of the options listed below, and their possible values, see .It NumberOfPasswordPrompts .It PasswordAuthentication .It PermitLocalCommand +.It PermitRemoteOpen .It PKCS11Provider .It Port .It PreferredAuthentications .It ProxyCommand .It ProxyJump .It ProxyUseFdpass -.It PubkeyAcceptedKeyTypes +.It PubkeyAcceptedAlgorithms .It PubkeyAuthentication .It RekeyLimit .It RemoteCommand @@ -579,10 +590,18 @@ flag), (certificate key types), .Ar key-plain (non-certificate key types), +.Ar key-sig +(all key types and signature algorithms), .Ar protocol-version (supported SSH protocol versions), and .Ar sig (supported signature algorithms). +Alternatively, any keyword from +.Xr ssh_config 5 +or +.Xr sshd_config 5 +that takes an algorithm list may be used as an alias for the corresponding +query_option. .Pp .It Fl q Quiet mode. @@ -826,7 +845,7 @@ 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 +on the remote machine, the user is non-root and the user names are the same on both sides, or if the files .Pa ~/.rhosts or @@ -896,8 +915,12 @@ This stores the private key in (DSA), .Pa ~/.ssh/id_ecdsa (ECDSA), +.Pa ~/.ssh/id_ecdsa_sk +(authenticator-hosted ECDSA), .Pa ~/.ssh/id_ed25519 (Ed25519), +.Pa ~/.ssh/id_ed25519_sk +(authenticator-hosted Ed25519), or .Pa ~/.ssh/id_rsa (RSA) @@ -906,8 +929,12 @@ and stores the public key in (DSA), .Pa ~/.ssh/id_ecdsa.pub (ECDSA), +.Pa ~/.ssh/id_ecdsa_sk.pub +(authenticator-hosted ECDSA), .Pa ~/.ssh/id_ed25519.pub (Ed25519), +.Pa ~/.ssh/id_ed25519_sk.pub +(authenticator-hosted Ed25519), or .Pa ~/.ssh/id_rsa.pub (RSA) @@ -1384,6 +1411,25 @@ or related script. may be necessary to redirect the input from .Pa /dev/null to make this work.) +.It Ev SSH_ASKPASS_REQUIRE +Allows further control over the use of an askpass program. +If this variable is set to +.Dq never +then +.Nm +will never attempt to use one. +If it is set to +.Dq prefer , +then +.Nm +will prefer to use the askpass program instead of the TTY when requesting +passwords. +Finally, if the variable is set to +.Dq force , +then the askpass program will be used for all passphrase input regardless +of whether +.Ev DISPLAY +is set. .It Ev SSH_AUTH_SOCK Identifies the path of a .Ux Ns -domain @@ -1484,7 +1530,9 @@ above. .Pp .It Pa ~/.ssh/id_dsa .It Pa ~/.ssh/id_ecdsa +.It Pa ~/.ssh/id_ecdsa_sk .It Pa ~/.ssh/id_ed25519 +.It Pa ~/.ssh/id_ed25519_sk .It Pa ~/.ssh/id_rsa Contains the private key for authentication. These files @@ -1498,7 +1546,9 @@ 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_ecdsa_sk.pub .It Pa ~/.ssh/id_ed25519.pub +.It Pa ~/.ssh/id_ed25519_sk.pub .It Pa ~/.ssh/id_rsa.pub Contains the public key for authentication. These files are not diff --git a/ssh.c b/ssh.c index f77844456..8750368ac 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.507 2019/09/13 04:27:35 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.552 2021/02/23 00:05:31 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -16,7 +16,7 @@ * 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 + * Modified to work with SSLeay by Niels Provos * in Canada (German citizen). * * Redistribution and use in source and binary forms, with or without @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include @@ -85,7 +86,6 @@ #include "canohost.h" #include "compat.h" #include "cipher.h" -#include "digest.h" #include "packet.h" #include "sshbuf.h" #include "channels.h" @@ -137,11 +137,11 @@ int stdin_null_flag = 0; /* * Flag indicating that the current process should be backgrounded and - * a new slave launched in the foreground for ControlPersist. + * a new mux-client launched in the foreground for ControlPersist. */ int need_controlpersist_detach = 0; -/* Copies of flags for ControlPersist foreground slave */ +/* Copies of flags for ControlPersist foreground mux-client */ int ostdin_null_flag, ono_shell_flag, otty_flag, orequest_tty; /* @@ -167,9 +167,11 @@ char *config = NULL; */ 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; +/* + * A config can specify a path to forward, overriding SSH_AUTH_SOCK. If this is + * not NULL, forward the socket at this path instead. + */ +char *forward_agent_sock_path = NULL; /* socket address the host resolves to */ struct sockaddr_storage hostaddr; @@ -184,7 +186,7 @@ struct sshbuf *command; int subsystem_flag = 0; /* # of replies received for global requests */ -static int remote_forward_confirms_received = 0; +static int forward_confirms_pending = -1; /* mux.c */ extern int muxserver_sock; @@ -207,8 +209,8 @@ usage(void) exit(255); } -static int ssh_session2(struct ssh *, struct passwd *); -static void load_public_identity_files(struct passwd *); +static int ssh_session2(struct ssh *, const struct ssh_conn_info *); +static void load_public_identity_files(const struct ssh_conn_info *); static void main_sigchld_handler(int); /* ~/ expand a list of paths. NB. assumes path[n] is heap-allocated. */ @@ -225,6 +227,39 @@ tilde_expand_paths(char **paths, u_int num_paths) } } +/* + * Expands the set of percent_expand options used by the majority of keywords + * in the client that support percent expansion. + * Caller must free returned string. + */ +static char * +default_client_percent_expand(const char *str, + const struct ssh_conn_info *cinfo) +{ + return percent_expand(str, + DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo), + (char *)NULL); +} + +/* + * Expands the set of percent_expand options used by the majority of keywords + * AND perform environment variable substitution. + * Caller must free returned string. + */ +static char * +default_client_percent_dollar_expand(const char *str, + const struct ssh_conn_info *cinfo) +{ + char *ret; + + ret = percent_dollar_expand(str, + DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo), + (char *)NULL); + if (ret == NULL) + fatal("invalid environment variable expansion"); + return ret; +} + /* * Attempt to resolve a host name / port to a set of addresses and * optionally return any CNAMEs encountered along the way. @@ -241,6 +276,8 @@ resolve_host(const char *name, int port, int logerr, char *cname, size_t clen) if (port <= 0) port = default_ssh_port(); + if (cname != NULL) + *cname = '\0'; snprintf(strport, sizeof strport, "%d", port); memset(&hints, 0, sizeof(hints)); @@ -258,8 +295,8 @@ resolve_host(const char *name, int port, int logerr, char *cname, size_t clen) } 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); + error_f("host \"%s\" cname \"%s\" too long (max %lu)", + name, res->ai_canonname, (u_long)clen); if (clen > 0) *cname = '\0'; } @@ -323,29 +360,27 @@ resolve_addr(const char *name, int port, char *caddr, size_t clen) 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)); + debug2_f("could not resolve name %.100s as address: %s", + name, ssh_gai_strerror(gaierr)); return NULL; } if (res == NULL) { - debug("%s: getaddrinfo %.100s returned no addresses", - __func__, name); + debug_f("getaddrinfo %.100s returned no addresses", name); return NULL; } if (res->ai_next != NULL) { - debug("%s: getaddrinfo %.100s returned multiple addresses", - __func__, name); + debug_f("getaddrinfo %.100s returned multiple addresses", 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)); + debug_f("Could not format address for name %.100s: %s", + 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); + error_f("host \"%s\" addr \"%s\" too long (max %lu)", + name, addr, (u_long)clen); if (clen > 0) *caddr = '\0'; fail: @@ -378,7 +413,7 @@ check_follow_cname(int direct, char **namep, const char *cname) if (!direct && options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS) return 0; - debug3("%s: check \"%s\" CNAME \"%s\"", __func__, *namep, cname); + debug3_f("check \"%s\" CNAME \"%s\"", *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 || @@ -412,10 +447,10 @@ resolve_canonicalize(char **hostp, int port) */ if ((addrs = resolve_addr(*hostp, port, newname, sizeof(newname))) != NULL) { - debug2("%s: hostname %.100s is address", __func__, *hostp); + debug2_f("hostname %.100s is address", *hostp); if (strcasecmp(*hostp, newname) != 0) { - debug2("%s: canonicalised address \"%s\" => \"%s\"", - __func__, *hostp, newname); + debug2_f("canonicalised address \"%s\" => \"%s\"", + *hostp, newname); free(*hostp); *hostp = xstrdup(newname); } @@ -428,8 +463,7 @@ resolve_canonicalize(char **hostp, int port) * attempts at canonicalisation. */ if (is_addr_fast(*hostp)) { - debug("%s: hostname %.100s is an unrecognised address", - __func__, *hostp); + debug_f("hostname %.100s is an unrecognised address", *hostp); return NULL; } @@ -448,7 +482,7 @@ resolve_canonicalize(char **hostp, int port) /* If domain name is anchored, then resolve it now */ if ((*hostp)[strlen(*hostp) - 1] == '.') { - debug3("%s: name is fully qualified", __func__); + debug3_f("name is fully qualified"); fullhost = xstrdup(*hostp); if ((addrs = resolve_host(fullhost, port, 0, newname, sizeof(newname))) != NULL) @@ -464,17 +498,15 @@ resolve_canonicalize(char **hostp, int port) ndots++; } if (ndots > options.canonicalize_max_dots) { - debug3("%s: not canonicalizing hostname \"%s\" (max dots %d)", - __func__, *hostp, options.canonicalize_max_dots); + debug3_f("not canonicalizing hostname \"%s\" (max dots %d)", + *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); + debug3_f("attempting \"%s\" => \"%s\"", *hostp, fullhost); if ((addrs = resolve_host(fullhost, port, 0, newname, sizeof(newname))) == NULL) { free(fullhost); @@ -495,7 +527,7 @@ resolve_canonicalize(char **hostp, int port) 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); + debug2_f("host %s not found in any suffix", *hostp); return NULL; } @@ -511,14 +543,14 @@ check_load(int r, const char *path, const char *message) break; case SSH_ERR_INTERNAL_ERROR: case SSH_ERR_ALLOC_FAIL: - fatal("load %s \"%s\": %s", message, path, ssh_err(r)); + fatal_r(r, "load %s \"%s\"", message, path); case SSH_ERR_SYSTEM_ERROR: /* Ignore missing files */ if (errno == ENOENT) break; /* FALLTHROUGH */ default: - error("load %s \"%s\": %s", message, path, ssh_err(r)); + error_r(r, "load %s \"%s\"", message, path); break; } } @@ -587,6 +619,25 @@ set_addrinfo_port(struct addrinfo *addrs, int port) } } +static void +ssh_conn_info_free(struct ssh_conn_info *cinfo) +{ + if (cinfo == NULL) + return; + free(cinfo->conn_hash_hex); + free(cinfo->shorthost); + free(cinfo->uidstr); + free(cinfo->keyalias); + free(cinfo->thishost); + free(cinfo->host_arg); + free(cinfo->portstr); + free(cinfo->remhost); + free(cinfo->remuser); + free(cinfo->homedir); + free(cinfo->locuser); + free(cinfo); +} + /* * Main program for the ssh client. */ @@ -596,16 +647,17 @@ 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, want_final_pass = 0; - char *p, *cp, *line, *argv0, buf[PATH_MAX], *logfile; - char cname[NI_MAXHOST]; + char *p, *cp, *line, *argv0, *logfile, *host_arg; + char cname[NI_MAXHOST], thishost[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]; + size_t n, len; + u_int j; + struct ssh_conn_info *cinfo = NULL; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); @@ -739,13 +791,16 @@ main(int ac, char **av) break; case 'Q': cp = NULL; - if (strcmp(optarg, "cipher") == 0) + if (strcmp(optarg, "cipher") == 0 || + strcasecmp(optarg, "Ciphers") == 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) + else if (strcmp(optarg, "mac") == 0 || + strcasecmp(optarg, "MACs") == 0) cp = mac_alg_list('\n'); - else if (strcmp(optarg, "kex") == 0) + else if (strcmp(optarg, "kex") == 0 || + strcasecmp(optarg, "KexAlgorithms") == 0) cp = kex_alg_list('\n'); else if (strcmp(optarg, "key") == 0) cp = sshkey_alg_list(0, 0, 0, '\n'); @@ -753,14 +808,28 @@ main(int ac, char **av) 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, "key-sig") == 0 || + strcasecmp(optarg, "PubkeyAcceptedKeyTypes") == 0 || /* deprecated name */ + strcasecmp(optarg, "PubkeyAcceptedAlgorithms") == 0 || + strcasecmp(optarg, "HostKeyAlgorithms") == 0 || + strcasecmp(optarg, "HostbasedKeyTypes") == 0 || /* deprecated name */ + strcasecmp(optarg, "HostbasedAcceptedKeyTypes") == 0 || /* deprecated name */ + strcasecmp(optarg, "HostbasedAcceptedAlgorithms") == 0) + cp = sshkey_alg_list(0, 0, 1, '\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) { + else if (strcmp(optarg, "compression") == 0) { + cp = xstrdup(compression_alg_list(0)); + len = strlen(cp); + for (n = 0; n < len; n++) + if (cp[n] == ',') + cp[n] = '\n'; + } else if (strcmp(optarg, "help") == 0) { cp = xstrdup( - "cipher\ncipher-auth\nkex\nkey\n" - "key-cert\nkey-plain\nmac\n" + "cipher\ncipher-auth\ncompression\nkex\n" + "key\nkey-cert\nkey-plain\nkey-sig\nmac\n" "protocol-version\nsig"); } if (cp == NULL) @@ -831,13 +900,7 @@ main(int ac, char **av) break; case 'V': fprintf(stderr, "%s, %s\n", - SSH_RELEASE, -#ifdef WITH_OPENSSL - OpenSSL_version(OPENSSL_VERSION) -#else - "without OpenSSL" -#endif - ); + SSH_RELEASE, SSH_OPENSSL_VERSION); if (opt == 'V') exit(0); break; @@ -963,7 +1026,11 @@ main(int ac, char **av) break; case 'C': +#ifdef WITH_ZLIB options.compression = 1; +#else + error("Compression not supported, disabling."); +#endif break; case 'N': no_shell_flag = 1; @@ -1074,8 +1141,7 @@ main(int ac, char **av) 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)); + fatal_fr(r, "buffer error"); } } @@ -1095,13 +1161,7 @@ main(int ac, char **av) !use_syslog); if (debug_flag) - logit("%s, %s", SSH_RELEASE, -#ifdef WITH_OPENSSL - OpenSSL_version(OPENSSL_VERSION) -#else - "without OpenSSL" -#endif - ); + logit("%s, %s", SSH_RELEASE, SSH_OPENSSL_VERSION); /* Parse the configuration files */ process_config_files(host_arg, pw, 0, &want_final_pass); @@ -1184,14 +1244,29 @@ main(int ac, char **av) } /* Fill configuration defaults. */ - fill_default_options(&options); + if (fill_default_options(&options) != 0) + cleanup_exit(255); + + if (options.user == NULL) + options.user = xstrdup(pw->pw_name); /* * If ProxyJump option specified, then construct a ProxyCommand now. */ if (options.jump_host != NULL) { char port_s[8]; - const char *sshbin = argv0; + const char *jumpuser = options.jump_user, *sshbin = argv0; + int port = options.port, jumpport = options.jump_port; + + if (port <= 0) + port = default_ssh_port(); + if (jumpport <= 0) + jumpport = default_ssh_port(); + if (jumpuser == NULL) + jumpuser = options.user; + if (strcmp(options.jump_host, host) == 0 && port == jumpport && + strcmp(options.user, jumpuser) == 0) + fatal("jumphost loop via %s", options.jump_host); #ifndef WINDOWS /* TODO - implement "acesss" in posix layer and enable this */ /* @@ -1247,11 +1322,21 @@ main(int ac, char **av) 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.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK) { + if (options.control_persist && options.control_path != NULL) { + debug("UpdateHostKeys=ask is incompatible with " + "ControlPersist; disabling"); + options.update_hostkeys = 0; + } else if (sshbuf_len(command) != 0 || + options.remote_command != NULL || + options.request_tty == REQUEST_TTY_NO) { + debug("UpdateHostKeys=ask is incompatible with " + "remote command execution; disabling"); + options.update_hostkeys = 0; + } else if (options.log_level < SYSLOG_LEVEL_INFO) { + /* no point logging anything; user won't see it */ + options.update_hostkeys = 0; + } } if (options.connection_attempts <= 0) fatal("Invalid number of ConnectionAttempts"); @@ -1267,6 +1352,8 @@ main(int ac, char **av) /* reinit */ log_init(argv0, options.log_level, options.log_facility, !use_syslog); + for (j = 0; j < options.num_log_verbose; j++) + log_verbose_add(options.log_verbose[j]); if (options.request_tty == REQUEST_TTY_YES || options.request_tty == REQUEST_TTY_FORCE) @@ -1289,27 +1376,25 @@ main(int ac, char **av) tty_flag = 0; } - if (options.user == NULL) - options.user = xstrdup(pw->pw_name); - /* Set up strings used to percent_expand() arguments */ + cinfo = xcalloc(1, sizeof(*cinfo)); 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", + cinfo->thishost = xstrdup(thishost); + thishost[strcspn(thishost, ".")] = '\0'; + cinfo->shorthost = xstrdup(thishost); + xasprintf(&cinfo->portstr, "%d", options.port); + xasprintf(&cinfo->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)); + cinfo->keyalias = xstrdup(options.host_key_alias ? + options.host_key_alias : host_arg); + cinfo->conn_hash_hex = ssh_connection_hash(cinfo->thishost, host, + cinfo->portstr, options.user); + cinfo->host_arg = xstrdup(host_arg); + cinfo->remhost = xstrdup(host); + cinfo->remuser = xstrdup(options.user); + cinfo->homedir = xstrdup(pw->pw_dir); + cinfo->locuser = xstrdup(pw->pw_name); /* * Expand tokens in arguments. NB. LocalCommand is expanded later, @@ -1319,48 +1404,141 @@ main(int ac, char **av) 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); + options.remote_command = default_client_percent_expand(cp, + cinfo); 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)); + fatal_fr(r, "buffer error"); } 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); + options.control_path = default_client_percent_dollar_expand(cp, + cinfo); free(cp); } + if (options.identity_agent != NULL) { + p = tilde_expand_filename(options.identity_agent, getuid()); + cp = default_client_percent_dollar_expand(p, cinfo); + free(p); + free(options.identity_agent); + options.identity_agent = cp; + } + + if (options.forward_agent_sock_path != NULL) { + p = tilde_expand_filename(options.forward_agent_sock_path, + getuid()); + cp = default_client_percent_dollar_expand(p, cinfo); + free(p); + free(options.forward_agent_sock_path); + options.forward_agent_sock_path = cp; + if (stat(options.forward_agent_sock_path, &st) != 0) { + error("Cannot forward agent socket path \"%s\": %s", + options.forward_agent_sock_path, strerror(errno)); + if (options.exit_on_forward_failure) + cleanup_exit(255); + } + } + + if (options.num_system_hostfiles > 0 && + strcasecmp(options.system_hostfiles[0], "none") == 0) { + if (options.num_system_hostfiles > 1) + fatal("Invalid GlobalKnownHostsFiles: \"none\" " + "appears with other entries"); + free(options.system_hostfiles[0]); + options.system_hostfiles[0] = NULL; + options.num_system_hostfiles = 0; + } + + if (options.num_user_hostfiles > 0 && + strcasecmp(options.user_hostfiles[0], "none") == 0) { + if (options.num_user_hostfiles > 1) + fatal("Invalid UserKnownHostsFiles: \"none\" " + "appears with other entries"); + free(options.user_hostfiles[0]); + options.user_hostfiles[0] = NULL; + options.num_user_hostfiles = 0; + } + for (j = 0; j < options.num_user_hostfiles; j++) { + if (options.user_hostfiles[j] == NULL) + continue; + cp = tilde_expand_filename(options.user_hostfiles[j], getuid()); + p = default_client_percent_dollar_expand(cp, cinfo); + if (strcmp(options.user_hostfiles[j], p) != 0) + debug3("expanded UserKnownHostsFile '%s' -> " + "'%s'", options.user_hostfiles[j], p); + free(options.user_hostfiles[j]); + free(cp); + options.user_hostfiles[j] = p; + } + + for (i = 0; i < options.num_local_forwards; i++) { + if (options.local_forwards[i].listen_path != NULL) { + cp = options.local_forwards[i].listen_path; + p = options.local_forwards[i].listen_path = + default_client_percent_expand(cp, cinfo); + if (strcmp(cp, p) != 0) + debug3("expanded LocalForward listen path " + "'%s' -> '%s'", cp, p); + free(cp); + } + if (options.local_forwards[i].connect_path != NULL) { + cp = options.local_forwards[i].connect_path; + p = options.local_forwards[i].connect_path = + default_client_percent_expand(cp, cinfo); + if (strcmp(cp, p) != 0) + debug3("expanded LocalForward connect path " + "'%s' -> '%s'", cp, p); + free(cp); + } + } + + for (i = 0; i < options.num_remote_forwards; i++) { + if (options.remote_forwards[i].listen_path != NULL) { + cp = options.remote_forwards[i].listen_path; + p = options.remote_forwards[i].listen_path = + default_client_percent_expand(cp, cinfo); + if (strcmp(cp, p) != 0) + debug3("expanded RemoteForward listen path " + "'%s' -> '%s'", cp, p); + free(cp); + } + if (options.remote_forwards[i].connect_path != NULL) { + cp = options.remote_forwards[i].connect_path; + p = options.remote_forwards[i].connect_path = + default_client_percent_expand(cp, cinfo); + if (strcmp(cp, p) != 0) + debug3("expanded RemoteForward connect path " + "'%s' -> '%s'", cp, p); + free(cp); + } + } + if (config_test) { dump_client_config(&options, host); exit(0); } + /* Expand SecurityKeyProvider if it refers to an environment variable */ + if (options.sk_provider != NULL && *options.sk_provider == '$' && + strlen(options.sk_provider) > 1) { + if ((cp = getenv(options.sk_provider + 1)) == NULL) { + debug("Authenticator provider %s did not resolve; " + "disabling", options.sk_provider); + free(options.sk_provider); + options.sk_provider = NULL; + } else { + debug2("resolved SecurityKeyProvider %s => %s", + options.sk_provider, cp); + free(options.sk_provider); + options.sk_provider = xstrdup(cp); + } + } + if (muxclient_command != 0 && options.control_path == NULL) fatal("No ControlPath specified for \"-O\" command"); if (options.control_path != NULL) { @@ -1383,11 +1561,14 @@ main(int ac, char **av) cleanup_exit(255); /* resolve_host logs the error */ } - timeout_ms = options.connection_timeout * 1000; + if (options.connection_timeout >= INT_MAX/1000) + timeout_ms = INT_MAX; + else + timeout_ms = options.connection_timeout * 1000; /* Open a connection to the remote host. */ - if (ssh_connect(ssh, host_arg, host, addrs, &hostaddr, options.port, - options.address_family, options.connection_attempts, + if (ssh_connect(ssh, host, host_arg, addrs, &hostaddr, options.port, + options.connection_attempts, &timeout_ms, options.tcp_keep_alive) != 0) exit(255); @@ -1415,13 +1596,13 @@ main(int ac, char **av) /* XXX check errors? */ #define L_PUBKEY(p,o) do { \ if ((o) >= sensitive_data.nkeys) \ - fatal("%s pubkey out of array bounds", __func__); \ + fatal_f("pubkey out of array bounds"); \ 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__); \ + fatal_f("cert out of array bounds"); \ check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), p, "cert"); \ } while (0) @@ -1439,24 +1620,8 @@ main(int ac, char **av) } } - /* 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) == -1) { -#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); + load_public_identity_files(cinfo); /* optionally set the SSH_AUTHSOCKET_ENV_NAME variable */ if (options.identity_agent && @@ -1464,24 +1629,9 @@ main(int ac, char **av) 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] == '$') { + cp = options.identity_agent; + /* legacy (limited) format */ + if (cp[0] == '$' && cp[1] != '{') { if (!valid_env_name(cp + 1)) { fatal("Invalid IdentityAgent " "environment variable name %s", cp); @@ -1494,7 +1644,22 @@ main(int ac, char **av) /* identity_agent specifies a path directly */ setenv(SSH_AUTHSOCKET_ENV_NAME, cp, 1); } + } + } + + if (options.forward_agent && options.forward_agent_sock_path != NULL) { + cp = options.forward_agent_sock_path; + if (cp[0] == '$') { + if (!valid_env_name(cp + 1)) { + fatal("Invalid ForwardAgent environment variable name %s", cp); + } + if ((p = getenv(cp + 1)) != NULL) + forward_agent_sock_path = p; + else + options.forward_agent = 0; free(cp); + } else { + forward_agent_sock_path = cp; } } @@ -1503,12 +1668,12 @@ main(int ac, char **av) 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); + ssh_signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ + ssh_signal(SIGCHLD, main_sigchld_handler); /* Log into the remote system. Never returns if the login fails. */ ssh_login(ssh, &sensitive_data, host, (struct sockaddr *)&hostaddr, - options.port, pw, timeout_ms); + options.port, pw, timeout_ms, cinfo); if (ssh_packet_connection_is_on_socket(ssh)) { verbose("Authenticated to %s ([%s]:%d).", host, @@ -1543,7 +1708,8 @@ main(int ac, char **av) } skip_connect: - exit_status = ssh_session2(ssh, pw); + exit_status = ssh_session2(ssh, cinfo); + ssh_conn_info_free(cinfo); ssh_packet_close(ssh); if (options.control_path != NULL && muxserver_sock != -1) @@ -1559,9 +1725,8 @@ static void control_persist_detach(void) { pid_t pid; - int devnull, keep_stderr; - debug("%s: backgrounding master process", __func__); + debug_f("backgrounding master process"); /* * master (current process) into the background, and make the @@ -1569,13 +1734,13 @@ control_persist_detach(void) */ switch ((pid = fork())) { case -1: - fatal("%s: fork: %s", __func__, strerror(errno)); + fatal_f("fork: %s", 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); + /* Parent: set up mux client to connect to backgrounded master */ + debug2_f("background process is %ld", (long)pid); stdin_null_flag = ostdin_null_flag; options.request_tty = orequest_tty; tty_flag = otty_flag; @@ -1586,18 +1751,8 @@ control_persist_detach(void) /* 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); - } + if (stdfd_devnull(1, 1, !(log_is_on_stderr() && debug_flag)) == -1) + error_f("stdfd_devnull failed"); daemon(1, 1); setproctitle("%s [mux]", options.control_path); } @@ -1612,6 +1767,23 @@ fork_postauth(void) fork_after_authentication_flag = 0; if (daemon(1, 1) == -1) fatal("daemon() failed: %.200s", strerror(errno)); + if (stdfd_devnull(1, 1, !(log_is_on_stderr() && debug_flag)) == -1) + error_f("stdfd_devnull failed"); +} + +static void +forwarding_success(void) +{ + if (forward_confirms_pending == -1) + return; + if (--forward_confirms_pending == 0) { + debug_f("all expected forwarding replies received"); + if (fork_after_authentication_flag) + fork_postauth(); + } else { + debug2_f("%d expected forwarding replies remaining", + forward_confirms_pending); + } } /* Callback for remote forward global requests */ @@ -1633,7 +1805,7 @@ ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) if (rfwd->listen_path == NULL && rfwd->listen_port == 0) { if (type == SSH2_MSG_REQUEST_SUCCESS) { if ((r = sshpkt_get_u32(ssh, &port)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse packet"); if (port > 65535) { error("Invalid allocated port %u for remote " "forward to %s:%d", port, @@ -1673,11 +1845,7 @@ ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) "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(); - } + forwarding_success(); } static void @@ -1694,6 +1862,19 @@ ssh_stdio_confirm(struct ssh *ssh, int id, int success, void *arg) fatal("stdio forwarding failed"); } +static void +ssh_tun_confirm(struct ssh *ssh, int id, int success, void *arg) +{ + if (!success) { + error("Tunnel forwarding failed"); + if (options.exit_on_forward_failure) + cleanup_exit(255); + } + + debug_f("tunnel forward established, id=%d", id); + forwarding_success(); +} + static void ssh_init_stdio_forwarding(struct ssh *ssh) { @@ -1703,7 +1884,7 @@ ssh_init_stdio_forwarding(struct ssh *ssh) if (options.stdio_forward_host == NULL) return; - debug3("%s: %s:%d", __func__, options.stdio_forward_host, + debug3_f("%s:%d", options.stdio_forward_host, options.stdio_forward_port); if ((in = dup(STDIN_FILENO)) == -1 || @@ -1711,17 +1892,60 @@ ssh_init_stdio_forwarding(struct ssh *ssh) 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__); + fatal_f("channel_connect_stdio_fwd failed"); 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_forward_permissions(struct ssh *ssh, const char *what, char **opens, + u_int num_opens) +{ + u_int i; + int port; + char *addr, *arg, *oarg, ch; + int where = FORWARD_LOCAL; + + 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]); + ch = '\0'; + addr = hpdelim2(&arg, &ch); + if (addr == NULL || ch == '/') + fatal_f("missing host in %s", what); + addr = cleanhostname(addr); + if (arg == NULL || ((port = permitopen_port(arg)) < 0)) + fatal_f("bad port number in %s", what); + /* Send it to channels layer */ + channel_add_permission(ssh, FORWARD_ADM, + where, addr, port); + free(oarg); + } +} + static void ssh_init_forwarding(struct ssh *ssh, char **ifname) { int success = 0; int i; + ssh_init_forward_permissions(ssh, "permitremoteopen", + options.permitted_remote_opens, + options.num_permitted_remote_opens); + + if (options.exit_on_forward_failure) + forward_confirms_pending = 0; /* track pending requests */ /* Initiate local TCP/IP port forwardings. */ for (i = 0; i < options.num_local_forwards; i++) { debug("Local connections to %.200s:%d forwarded to remote " @@ -1757,32 +1981,33 @@ ssh_init_forwarding(struct ssh *ssh, char **ifname) options.remote_forwards[i].connect_path : options.remote_forwards[i].connect_host, options.remote_forwards[i].connect_port); - options.remote_forwards[i].handle = + if ((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 { + &options.remote_forwards[i])) >= 0) { client_register_global_confirm( ssh_confirm_remote_forward, &options.remote_forwards[i]); - } + forward_confirms_pending++; + } else if (options.exit_on_forward_failure) + fatal("Could not request remote forwarding."); + else + logit("Warning: Could not request remote forwarding."); } /* 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."); - } + options.tun_remote, ssh_tun_confirm, NULL)) != NULL) + forward_confirms_pending++; + else if (options.exit_on_forward_failure) + fatal("Could not request tunnel forwarding."); + else + error("Could not request tunnel forwarding."); + } + if (forward_confirms_pending > 0) { + debug_f("expecting replies for %d forwards", + forward_confirms_pending); } } @@ -1796,8 +2021,7 @@ check_agent_present(void) 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)); + debug_r(r, "ssh_get_authentication_socket"); } } } @@ -1834,7 +2058,7 @@ ssh_session2_setup(struct ssh *ssh, int id, int success, void *arg) debug("Requesting authentication agent forwarding."); channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0); if ((r = sshpkt_send(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "send packet"); } /* Tell the packet module whether this is an interactive session. */ @@ -1882,7 +2106,7 @@ ssh_session2_open(struct ssh *ssh) window, packetmax, CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); - debug3("%s: channel_new: %d", __func__, c->self); + debug3_f("channel_new: %d", c->self); channel_send_open(ssh, c->self); if (!no_shell_flag) @@ -1893,9 +2117,9 @@ ssh_session2_open(struct ssh *ssh) } static int -ssh_session2(struct ssh *ssh, struct passwd *pw) +ssh_session2(struct ssh *ssh, const struct ssh_conn_info *cinfo) { - int r, devnull, id = -1; + int r, id = -1; char *cp, *tun_fwd_ifname = NULL; /* XXX should be pre-session */ @@ -1908,16 +2132,7 @@ ssh_session2(struct ssh *ssh, struct passwd *pw) 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, + DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo), "T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname, (char *)NULL); debug3("expanded LocalCommand: %s", options.local_command); @@ -1931,9 +2146,9 @@ ssh_session2(struct ssh *ssh, struct passwd *pw) /* * 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. + * client attach as a control client. * NB. we must save copies of the flags that we override for - * the backgrounding, since we defer attachment of the slave until + * the backgrounding, since we defer attachment of the client until * after the connection is fully established (in particular, * async rfwd replies have been received for ExitOnForwardFailure). */ @@ -1966,14 +2181,14 @@ ssh_session2(struct ssh *ssh, struct passwd *pw) /* If we don't expect to open a new session, then disallow it */ if (options.control_master == SSHCTL_MASTER_NO && - (datafellows & SSH_NEW_OPENSSH)) { + (ssh->compat & SSH_NEW_OPENSSH)) { debug("Requesting no-more-sessions@openssh.com"); 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)); + fatal_fr(r, "send packet"); } /* Execute a local command */ @@ -1987,15 +2202,8 @@ ssh_session2(struct ssh *ssh, struct passwd *pw) * 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) == -1) - fatal("%s: dup2() stdout failed", __func__); - if (devnull > STDERR_FILENO) - close(devnull); - } + if (!need_controlpersist_detach && stdfd_devnull(0, 1, 0) == -1) + error_f("stdfd_devnull failed"); /* * If requested and we are not interested in replies to remote @@ -2016,7 +2224,7 @@ ssh_session2(struct ssh *ssh, struct passwd *pw) /* Loads all IdentityFile and CertificateFile keys */ static void -load_public_identity_files(struct passwd *pw) +load_public_identity_files(const struct ssh_conn_info *cinfo) { char *filename, *cp; struct sshkey *public; @@ -2029,7 +2237,8 @@ load_public_identity_files(struct passwd *pw) struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; #ifdef ENABLE_PKCS11 - struct sshkey **keys; + struct sshkey **keys = NULL; + char **comments = NULL; int nkeys; #endif /* PKCS11 */ @@ -2048,18 +2257,19 @@ load_public_identity_files(struct passwd *pw) options.num_identity_files < SSH_MAX_IDENTITY_FILES && (pkcs11_init(!options.batch_mode) == 0) && (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL, - &keys)) > 0) { + &keys, &comments)) > 0) { for (i = 0; i < nkeys; i++) { if (n_ids >= SSH_MAX_IDENTITY_FILES) { sshkey_free(keys[i]); + free(comments[i]); continue; } identity_keys[n_ids] = keys[i]; - identity_files[n_ids] = - xstrdup(options.pkcs11_provider); /* XXX */ + identity_files[n_ids] = comments[i]; /* transferred */ n_ids++; } free(keys); + free(comments); } #endif /* ENABLE_PKCS11 */ for (i = 0; i < options.num_identity_files; i++) { @@ -2070,9 +2280,7 @@ load_public_identity_files(struct passwd *pw) 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); + filename = default_client_percent_dollar_expand(cp, cinfo); free(cp); check_load(sshkey_load_public(filename, &public, NULL), filename, "pubkey"); @@ -2102,8 +2310,8 @@ load_public_identity_files(struct passwd *pw) continue; } if (!sshkey_is_cert(public)) { - debug("%s: key %s type %s is not a certificate", - __func__, cp, sshkey_type(public)); + debug_f("key %s type %s is not a certificate", + cp, sshkey_type(public)); sshkey_free(public); free(cp); continue; @@ -2117,18 +2325,11 @@ load_public_identity_files(struct passwd *pw) } if (options.num_certificate_files > SSH_MAX_CERTIFICATE_FILES) - fatal("%s: too many certificates", __func__); + fatal_f("too many certificates"); 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); + filename = default_client_percent_dollar_expand(cp, cinfo); free(cp); check_load(sshkey_load_public(filename, &public, NULL), @@ -2142,8 +2343,8 @@ load_public_identity_files(struct passwd *pw) continue; } if (!sshkey_is_cert(public)) { - debug("%s: key %s type %s is not a certificate", - __func__, filename, sshkey_type(public)); + debug_f("key %s type %s is not a certificate", + filename, sshkey_type(public)); sshkey_free(public); free(filename); continue; diff --git a/ssh.h b/ssh.h index dda6f617e..8110c0602 100644 --- a/ssh.h +++ b/ssh.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.h,v 1.89 2018/12/27 03:25:25 djm Exp $ */ +/* $OpenBSD: ssh.h,v 1.90 2020/07/14 23:57:01 djm Exp $ */ /* * Author: Tatu Ylonen @@ -67,6 +67,11 @@ */ #define SSH_ASKPASS_ENV "SSH_ASKPASS" +/* + * Environment variable to control whether or not askpass is used. + */ +#define SSH_ASKPASS_REQUIRE_ENV "SSH_ASKPASS_REQUIRE" + /* * 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. diff --git a/ssh2.h b/ssh2.h index f2e37c96a..32ddae89b 100644 --- a/ssh2.h +++ b/ssh2.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh2.h,v 1.18 2016/05/04 14:22:33 markus Exp $ */ +/* $OpenBSD: ssh2.h,v 1.19 2020/11/19 23:05:05 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -25,7 +25,7 @@ */ /* - * draft-ietf-secsh-architecture-05.txt + * RFC4251: * * Transport layer protocol: * diff --git a/ssh_api.c b/ssh_api.c index 03dac0982..bceff0f0c 100644 --- a/ssh_api.c +++ b/ssh_api.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh_api.c,v 1.18 2019/09/13 04:36:43 dtucker Exp $ */ +/* $OpenBSD: ssh_api.c,v 1.26 2021/01/27 10:05:28 djm Exp $ */ /* * Copyright (c) 2012 Markus Friedl. All rights reserved. * @@ -54,19 +54,16 @@ int _ssh_host_key_sign(struct ssh *, struct sshkey *, struct sshkey *, */ int use_privsep = 0; int mm_sshkey_sign(struct sshkey *, u_char **, u_int *, - u_char *, u_int, char *, u_int); + const u_char *, u_int, const char *, const char *, const char *, u_int); #ifdef WITH_OPENSSL DH *mm_choose_dh(int, int, int); #endif -/* 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) + const u_char *data, u_int datalen, const char *alg, + const char *sk_provider, const char *sk_pin, u_int compat) { return (-1); } @@ -121,7 +118,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) # endif #endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_server; - ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; + ssh->kex->kex[KEX_KEM_SNTRUP761X25519_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; @@ -139,7 +136,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) # endif #endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; - ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client; + ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; ssh->kex->verify_host_key =&_ssh_verify_host_key; } *sshp = ssh; @@ -151,7 +148,9 @@ ssh_free(struct ssh *ssh) { struct key_entry *k; - ssh_packet_close(ssh); + if (ssh == NULL) + return; + /* * we've only created the public keys variants in case we * are a acting as a server. @@ -166,8 +165,7 @@ ssh_free(struct ssh *ssh) TAILQ_REMOVE(&ssh->private_keys, k, next); free(k); } - if (ssh->kex) - kex_free(ssh->kex); + ssh_packet_close(ssh); free(ssh); } @@ -357,7 +355,7 @@ _ssh_read_banner(struct ssh *ssh, struct sshbuf *banner) if (sshbuf_len(banner) >= 4 && memcmp(sshbuf_ptr(banner), "SSH-", 4) == 0) break; - debug("%s: %.*s", __func__, (int)sshbuf_len(banner), + debug_f("%.*s", (int)sshbuf_len(banner), sshbuf_ptr(banner)); /* Accept lines before banner only on client */ if (ssh->kex->server || ++n > SSH_MAX_PRE_BANNER_LINES) { @@ -390,7 +388,7 @@ _ssh_read_banner(struct ssh *ssh, struct sshbuf *banner) debug("Remote protocol version %d.%d, remote software version %.100s", remote_major, remote_minor, remote_version); - ssh->compat = compat_datafellows(remote_version); + compat_banner(ssh, remote_version); if (remote_major == 1 && remote_minor == 99) { remote_major = 2; remote_minor = 0; @@ -470,9 +468,9 @@ _ssh_host_public_key(int type, int nid, struct ssh *ssh) { struct key_entry *k; - debug3("%s: need %d", __func__, type); + debug3_f("need %d", type); TAILQ_FOREACH(k, &ssh->public_keys, next) { - debug3("%s: check %s", __func__, sshkey_type(k->key)); + debug3_f("check %s", sshkey_type(k->key)); if (k->key->type == type && (type != KEY_ECDSA || k->key->ecdsa_nid == nid)) return (k->key); @@ -485,9 +483,9 @@ _ssh_host_private_key(int type, int nid, struct ssh *ssh) { struct key_entry *k; - debug3("%s: need %d", __func__, type); + debug3_f("need %d", type); TAILQ_FOREACH(k, &ssh->private_keys, next) { - debug3("%s: check %s", __func__, sshkey_type(k->key)); + debug3_f("check %s", sshkey_type(k->key)); if (k->key->type == type && (type != KEY_ECDSA || k->key->ecdsa_nid == nid)) return (k->key); @@ -500,9 +498,9 @@ _ssh_verify_host_key(struct sshkey *hostkey, struct ssh *ssh) { struct key_entry *k; - debug3("%s: need %s", __func__, sshkey_type(hostkey)); + debug3_f("need %s", sshkey_type(hostkey)); TAILQ_FOREACH(k, &ssh->public_keys, next) { - debug3("%s: check %s", __func__, sshkey_type(k->key)); + debug3_f("check %s", sshkey_type(k->key)); if (sshkey_equal_public(hostkey, k->key)) return (0); /* ok */ } @@ -548,8 +546,8 @@ _ssh_order_hostkeyalgs(struct ssh *ssh) } } if (*replace != '\0') { - debug2("%s: orig/%d %s", __func__, ssh->kex->server, orig); - debug2("%s: replace/%d %s", __func__, ssh->kex->server, replace); + debug2_f("orig/%d %s", ssh->kex->server, orig); + debug2_f("replace/%d %s", ssh->kex->server, replace); free(orig); proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = replace; replace = NULL; /* owned by proposal */ @@ -568,5 +566,5 @@ _ssh_host_key_sign(struct ssh *ssh, struct sshkey *privkey, const u_char *data, size_t dlen, const char *alg) { return sshkey_sign(privkey, signature, slen, data, dlen, - alg, ssh->compat); + alg, NULL, NULL, ssh->compat); } diff --git a/ssh_config b/ssh_config index 5e8ef548b..842ea866c 100644 --- a/ssh_config +++ b/ssh_config @@ -1,4 +1,4 @@ -# $OpenBSD: ssh_config,v 1.34 2019/02/04 02:39:42 dtucker Exp $ +# $OpenBSD: ssh_config,v 1.35 2020/07/17 03:43:42 dtucker Exp $ # This is the ssh client system-wide configuration file. See # ssh_config(5) for more information. This file provides defaults for @@ -43,3 +43,4 @@ # VisualHostKey no # ProxyCommand ssh -q -W %h:%p gateway.example.com # RekeyLimit 1G 1h +# UserKnownHostsFile ~/.ssh/known_hosts.d/%k diff --git a/ssh_config.5 b/ssh_config.5 index 02a87892d..f81191890 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -33,13 +33,13 @@ .\" (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.304 2019/09/13 04:52:34 djm Exp $ -.Dd $Mdocdate: September 13 2019 $ +.\" $OpenBSD: ssh_config.5,v 1.349 2021/02/28 22:56:30 dtucker Exp $ +.Dd $Mdocdate: February 28 2021 $ .Dt SSH_CONFIG 5 .Os .Sh NAME .Nm ssh_config -.Nd OpenSSH SSH client configuration files +.Nd OpenSSH client configuration file .Sh DESCRIPTION .Xr ssh 1 obtains configuration data from the following sources in @@ -245,13 +245,22 @@ option was specified to If this option is set to .Cm no , no keys are added to the agent. +Alternately, this option may be specified as a time interval +using the format described in the +.Sx TIME FORMATS +section of +.Xr sshd_config 5 +to specify the key's lifetime in +.Xr ssh-agent 1 , +after which it will automatically be removed. The argument must be -.Cm yes , -.Cm confirm , -.Cm ask , -or .Cm no -(the default). +(the default), +.Cm yes , +.Cm confirm +(optionally followed by a time interval), +.Cm ask +or a time interval. .It Cm AddressFamily Specifies which address family to use when connecting. Valid arguments are @@ -264,9 +273,11 @@ Valid arguments are .It Cm BatchMode If set to .Cm yes , -passphrase/password querying will be disabled. +user interaction such as password prompts and host key confirmation requests +will be disabled. This option is useful in scripts and other batch jobs where no user -is present to supply the password. +is present to interact with +.Xr ssh 1 . The argument must be .Cm yes or @@ -361,8 +372,8 @@ 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 +ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384, +ecdsa-sha2-nistp521,rsa-sha2-512,rsa-sha2-256,ssh-rsa .Ed .Pp .Xr ssh 1 @@ -381,13 +392,17 @@ flag to via .Xr ssh-agent 1 , or via a -.Cm PKCS11Provider . +.Cm PKCS11Provider +or +.Cm SecurityKeyProvider . .Pp Arguments to .Cm CertificateFile -may use the tilde syntax to refer to a user's home directory -or the tokens described in the +may use the tilde syntax to refer to a user's home directory, +the tokens described in the .Sx TOKENS +section and environment variables as described in the +.Sx ENVIRONMENT VARIABLES section. .Pp It is possible to have multiple certificate files specified in @@ -406,7 +421,6 @@ or .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 @@ -417,7 +431,8 @@ and will add addresses of destination hosts to in the process, regardless of the setting of .Cm StrictHostKeyChecking . If the option is set to -.Cm no , +.Cm no +(the default), the check will not be executed. .It Cm Ciphers Specifies the ciphers allowed and their order of preference. @@ -547,9 +562,11 @@ section above or the string 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 +may use the tilde syntax to refer to a user's home directory, +the tokens described in the .Sx TOKENS +section and environment variables as described in the +.Sx ENVIRONMENT VARIABLES section. It is recommended that any .Cm ControlPath @@ -564,7 +581,8 @@ 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 , +.Cm no +(the default), 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 @@ -667,11 +685,14 @@ and .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 +The argument may be +.Cm yes , .Cm no -(the default). +(the default), +an explicit path to an agent socket or the name of an environment variable +(beginning with +.Sq $ ) +in which to find the path. .Pp Agent forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host @@ -771,14 +792,53 @@ 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. +but they do not visually reveal identifying information if the +file's contents are 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 HostbasedAcceptedAlgorithms +Specifies the signature algorithms that will be used for hostbased +authentication as a comma-separated list of patterns. +Alternately if the specified list begins with a +.Sq + +character, then the specified signature algorithms will be appended +to the default set instead of replacing them. +If the specified list begins with a +.Sq - +character, then the specified signature algorithms (including wildcards) +will be removed from the default set instead of replacing them. +If the specified list begins with a +.Sq ^ +character, then the specified signature algorithms will be placed +at the head of the default set. +The default for this option is: +.Bd -literal -offset 3n +ssh-ed25519-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, +sk-ssh-ed25519-cert-v01@openssh.com, +sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +rsa-sha2-512-cert-v01@openssh.com, +rsa-sha2-256-cert-v01@openssh.com, +ssh-rsa-cert-v01@openssh.com, +ssh-ed25519, +ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +sk-ssh-ed25519@openssh.com, +sk-ecdsa-sha2-nistp256@openssh.com, +rsa-sha2-512,rsa-sha2-256,ssh-rsa +.Ed +.Pp +The +.Fl Q +option of +.Xr ssh 1 +may be used to list supported signature algorithms. +This was formerly named HostbasedKeyTypes. .It Cm HostbasedAuthentication Specifies whether to try rhosts based authentication with public key authentication. @@ -787,70 +847,44 @@ The argument must be 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 list begins with a -.Sq + -character, then the specified key types will be appended to the default set -instead of replacing them. -If the specified list begins with a -.Sq - -character, then the specified key types (including wildcards) will be removed -from the default set instead of replacing them. -If the specified list begins with a -.Sq ^ -character, then the specified key types will be placed at the head of the -default set. -The default for this option is: -.Bd -literal -offset 3n -ecdsa-sha2-nistp256-cert-v01@openssh.com, -ecdsa-sha2-nistp384-cert-v01@openssh.com, -ecdsa-sha2-nistp521-cert-v01@openssh.com, -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 +Specifies the host key signature algorithms that the client wants to use in order of preference. Alternately if the specified list begins with a .Sq + -character, then the specified key types will be appended to the default set -instead of replacing them. +character, then the specified signature algorithms will be appended to +the default set instead of replacing them. If the specified list begins with a .Sq - -character, then the specified key types (including wildcards) will be removed -from the default set instead of replacing them. +character, then the specified signature algorithms (including wildcards) +will be removed from the default set instead of replacing them. If the specified list begins with a .Sq ^ -character, then the specified key types will be placed at the head of the -default set. +character, then the specified signature algorithms will be placed +at the head of the default set. The default for this option is: .Bd -literal -offset 3n +ssh-ed25519-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, -rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com, +sk-ssh-ed25519-cert-v01@openssh.com, +sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +rsa-sha2-512-cert-v01@openssh.com, +rsa-sha2-256-cert-v01@openssh.com, ssh-rsa-cert-v01@openssh.com, +ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa +sk-ecdsa-sha2-nistp256@openssh.com, +sk-ssh-ed25519@openssh.com, +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 . +The list of available signature algorithms may also be obtained using +.Qq ssh -Q HostKeyAlgorithms . .It Cm HostKeyAlias Specifies an alias that should be used instead of the real host name when looking up or saving the host key @@ -883,6 +917,8 @@ even if .Xr ssh-agent 1 or a .Cm PKCS11Provider +or +.Cm SecurityKeyProvider offers more identities. The argument to this keyword must be .Cm yes @@ -914,17 +950,21 @@ 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 +may use the tilde syntax to refer to a user's home directory, +the tokens described in the .Sx TOKENS +section and environment variables as described in the +.Sx ENVIRONMENT VARIABLES section. .It Cm IdentityFile -Specifies a file from which the user's DSA, ECDSA, Ed25519 or RSA authentication -identity is read. +Specifies a file from which the user's DSA, ECDSA, authenticator-hosted ECDSA, +Ed25519, authenticator-hosted Ed25519 or RSA authentication identity is read. The default is .Pa ~/.ssh/id_dsa , .Pa ~/.ssh/id_ecdsa , -.Pa ~/.ssh/id_ed25519 +.Pa ~/.ssh/id_ecdsa_sk , +.Pa ~/.ssh/id_ed25519 , +.Pa ~/.ssh/id_ed25519_sk and .Pa ~/.ssh/id_rsa . Additionally, any identities represented by the authentication agent @@ -982,6 +1022,7 @@ Multiple pathnames may be specified and each pathname may contain wildcards and, for user configurations, shell-like .Sq ~ references to user home directories. +Wildcards will be expanded and processed in lexical order. Files without absolute paths are assumed to be in .Pa ~/.ssh if included in a user configuration file or @@ -1018,6 +1059,7 @@ Accepted values are .Cm cs6 , .Cm cs7 , .Cm ef , +.Cm le , .Cm lowdelay , .Cm throughput , .Cm reliability , @@ -1074,12 +1116,36 @@ 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 +diffie-hellman-group14-sha256 .Ed .Pp The list of available key exchange algorithms may also be obtained using .Qq ssh -Q kex . +.It Cm KnownHostsCommand +Specifies a command to use to obtain a list of host keys, in addition to +those listed in +.Cm UserKnownHostsFile +and +.Cm GlobalKnownHostsFile . +This command is executed after the files have been read. +It may write host key lines to standard output in identical format to the +usual files (described in the +.Sx VERIFYING HOST KEYS +section in +.Xr ssh 1 ) . +Arguments to +.Cm KnownHostsCommand +accept the tokens described in the +.Sx TOKENS +section. +The command may be invoked multiple times per connection: once when preparing +the preference list of host key algorithms to use, again to obtain the +host key for the requested host name and, if +.Cm CheckHostIP +is enabled, one more time to obtain the host key matching the server's +address. +If the command exits abnormally or returns a non-zero exit status then the +connection is terminated. .It Cm LocalCommand Specifies a command to execute on the local machine after successfully connecting to the server. @@ -1103,12 +1169,15 @@ 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 +The first argument specifies the listener and may be .Sm off .Oo Ar bind_address : Oc Ar port .Sm on -and the second argument must be -.Ar host : Ns Ar hostport . +or a Unix domain socket path. +The second argument is the destination and may be +.Ar host : Ns Ar hostport +or a Unix domain socket path if the remote host supports it. +.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. @@ -1127,6 +1196,11 @@ 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. +Unix domain socket paths may use the tokens described in the +.Sx TOKENS +section and environment variables as described in the +.Sx ENVIRONMENT VARIABLES +section. .It Cm LogLevel Gives the verbosity level that is used when logging messages from .Xr ssh 1 . @@ -1135,6 +1209,23 @@ 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 LogVerbose +Specify one or more overrides to LogLevel. +An override consists of a pattern lists that matches the source file, function +and line number to force detailed logging for. +For example, an override pattern of: +.Bd -literal -offset indent +kex.c:*:1000,*:kex_exchange_identification():*,packet.c:* +.Ed +.Pp +would enable detailed logging for line 1000 of +.Pa kex.c , +everything in the +.Fn kex_exchange_identification +function, and all code in the +.Pa packet.c +file. +This option is intended for debugging and no overrides are enabled by default. .It Cm MACs Specifies the MAC (message authentication code) algorithms in order of preference. @@ -1199,6 +1290,42 @@ The argument must be or .Cm no (the default). +.It Cm PermitRemoteOpen +Specifies the destinations to which remote TCP port forwarding is permitted when +.Cm RemoteForward +is used as a SOCKS proxy. +The forwarding specification must be one of the following forms: +.Pp +.Bl -item -offset indent -compact +.It +.Cm PermitRemoteOpen +.Sm off +.Ar host : port +.Sm on +.It +.Cm PermitRemoteOpen +.Sm off +.Ar IPv4_addr : port +.Sm on +.It +.Cm PermitRemoteOpen +.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. +Otherwise, no pattern matching or address lookups are performed on supplied +names. .It Cm PKCS11Provider Specifies which PKCS#11 provider to use or .Cm none @@ -1279,6 +1406,9 @@ connection to the specified .Cm ProxyJump host and then establishing a TCP forwarding to the ultimate target from there. +Setting the host to +.Cm none +disables this option entirely. .Pp Note that this option will compete with the .Cm ProxyCommand @@ -1298,35 +1428,41 @@ will pass a connected file descriptor back to 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. +.It Cm PubkeyAcceptedAlgorithms +Specifies the signature algorithms that will be used for public key +authentication as a comma-separated list of patterns. If the specified list begins with a .Sq + -character, then the key types after it will be appended to the default +character, then the algorithms after it will be appended to the default instead of replacing it. If the specified list begins with a .Sq - -character, then the specified key types (including wildcards) will be removed +character, then the specified algorithms (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with a .Sq ^ -character, then the specified key types will be placed at the head of the +character, then the specified algorithms will be placed at the head of the default set. The default for this option is: .Bd -literal -offset 3n +ssh-ed25519-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, -rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com, +sk-ssh-ed25519-cert-v01@openssh.com, +sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +rsa-sha2-512-cert-v01@openssh.com, +rsa-sha2-256-cert-v01@openssh.com, ssh-rsa-cert-v01@openssh.com, +ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa +sk-ssh-ed25519@openssh.com, +sk-ecdsa-sha2-nistp256@openssh.com, +rsa-sha2-512,rsa-sha2-256,ssh-rsa .Ed .Pp -The list of available key types may also be obtained using -.Qq ssh -Q key . +The list of available signature algorithms may also be obtained using +.Qq ssh -Q PubkeyAcceptedAlgorithms . .It Cm PubkeyAuthentication Specifies whether to try public key authentication. The argument to this keyword must be @@ -1336,7 +1472,7 @@ 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 +session key is renegotiated, optionally followed by 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 , @@ -1374,20 +1510,30 @@ 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 +The first argument is the listening specification and may be .Sm off .Oo Ar bind_address : Oc Ar port .Sm on +or, if the remote host supports it, a Unix domain socket path. If forwarding to a specific destination then the second argument must be -.Ar host : Ns Ar hostport , +.Ar host : Ns Ar hostport +or a Unix domain socket path, otherwise if no destination argument is specified then the remote forwarding will be established as a SOCKS proxy. +When acting as a SOCKS proxy the destination of the connection can be +restricted by +.Cm PermitRemoteOpen . .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. +Unix domain socket paths may use the tokens described in the +.Sx TOKENS +section and environment variables as described in the +.Sx ENVIRONMENT VARIABLES +section. .Pp If the .Ar port @@ -1437,6 +1583,15 @@ 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 SecurityKeyProvider +Specifies a path to a library that will be used when loading any +FIDO authenticator-hosted keys, overriding the default of using +the built-in USB HID support. +.Pp +If the specified value begins with a +.Sq $ +character, then it will be treated as an environment variable containing +the path to the library. .It Cm SendEnv Specifies what variables from the local .Xr environ 7 @@ -1642,13 +1797,30 @@ after authentication has completed and add them to The argument must be .Cm yes , .Cm no -(the default) or +or .Cm ask . -Enabling this option allows learning alternate hostkeys for a server +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. +.Pp Additional hostkeys are only accepted if the key used to authenticate the -host was already trusted or explicitly accepted by the user. +host was already trusted or explicitly accepted by the user, the host was +authenticated via +.Cm UserKnownHostsFile +(i.e. not +.Cm GlobalKnownHostsFile ) +and the host was authenticated using a plain key and not a certificate. +.Pp +.Cm UpdateHostKeys +is enabled by default if the user has not overridden the default +.Cm UserKnownHostsFile +setting and has not enabled +.Cm VerifyHostKeyDNS , +otherwise +.Cm UpdateHostKeys +will be set to +.Cm no . +.Pp If .Cm UpdateHostKeys is set to @@ -1671,6 +1843,12 @@ 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. +Each filename may use tilde notation to refer to the user's home directory, +the tokens described in the +.Sx TOKENS +section and environment variables as described in the +.Sx ENVIRONMENT VARIABLES +section. The default is .Pa ~/.ssh/known_hosts , .Pa ~/.ssh/known_hosts2 . @@ -1773,10 +1951,34 @@ A literal Hash of %l%h%p%r. .It %d Local user's home directory. +.It %f +The fingerprint of the server's host key. +.It %H +The +.Pa known_hosts +hostname or address that is being searched for. .It %h The remote hostname. +.It \%%I +A string describing the reason for a +.Cm KnownHostsCommand +execution: either +.Cm ADDRESS +when looking up a host by address (only when +.Cm CheckHostIP +is enabled), +.Cm HOSTNAME +when searching by hostname, or +.Cm ORDER +when preparing the host key algorithm preference list to use for the +destination host. .It %i The local user ID. +.It %K +The base64 encoded host key. +.It %k +The host key alias if specified, otherwise the orignal remote hostname given +on the command line. .It %L The local hostname. .It %l @@ -1796,35 +1998,61 @@ network interface assigned if tunnel forwarding was requested, or .Qq NONE otherwise. +.It %t +The type of the server host key, e.g. +.Cm ssh-ed25519 .It %u The local username. .El .Pp -.Cm Match exec -accepts the tokens %%, %h, %i, %L, %l, %n, %p, %r, and %u. +.Cm CertificateFile , +.Cm ControlPath , +.Cm IdentityAgent , +.Cm IdentityFile , +.Cm KnownHostsCommand , +.Cm LocalForward , +.Cm Match exec , +.Cm RemoteCommand , +.Cm RemoteForward , +and +.Cm UserKnownHostsFile +accept the tokens %%, %C, %d, %h, %i, %k, %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. +.Cm KnownHostsCommand +additionally accepts the tokens %f, %H, %I, %K and %t. .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. +accepts all tokens. .Pp .Cm ProxyCommand accepts the tokens %%, %h, %n, %p, and %r. +.Sh ENVIRONMENT VARIABLES +Arguments to some keywords can be expanded at runtime from environment +variables on the client by enclosing them in +.Ic ${} , +for example +.Ic ${HOME}/.ssh +would refer to the user's .ssh directory. +If a specified environment variable does not exist then an error will be +returned and the setting for that keyword will be ignored. .Pp -.Cm RemoteCommand -accepts the tokens %%, %C, %d, %h, %i, %l, %n, %p, %r, and %u. +The keywords +.Cm CertificateFile , +.Cm ControlPath , +.Cm IdentityAgent , +.Cm IdentityFile +.Cm KnownHostsCommand , +and +.Cm UserKnownHostsFile +support environment variables. +The keywords +.Cm LocalForward +and +.Cm RemoteForward +support environment variables only for Unix domain socket paths. .Sh FILES .Bl -tag -width Ds .It Pa ~/.ssh/config diff --git a/sshbuf-getput-basic.c b/sshbuf-getput-basic.c index d401a7265..9803fb5ed 100644 --- a/sshbuf-getput-basic.c +++ b/sshbuf-getput-basic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshbuf-getput-basic.c,v 1.9 2019/09/06 04:53:27 djm Exp $ */ +/* $OpenBSD: sshbuf-getput-basic.c,v 1.11 2020/06/05 03:25:35 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -338,6 +338,8 @@ sshbuf_put(struct sshbuf *buf, const void *v, size_t len) int sshbuf_putb(struct sshbuf *buf, const struct sshbuf *v) { + if (v == NULL) + return 0; return sshbuf_put(buf, sshbuf_ptr(v), sshbuf_len(v)); } @@ -535,6 +537,9 @@ sshbuf_put_cstring(struct sshbuf *buf, const char *v) int sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v) { + if (v == NULL) + return sshbuf_put_string(buf, NULL, 0); + return sshbuf_put_string(buf, sshbuf_ptr(v), sshbuf_len(v)); } diff --git a/sshbuf-getput-crypto.c b/sshbuf-getput-crypto.c index 3dd1e1446..2e61d3bcd 100644 --- a/sshbuf-getput-crypto.c +++ b/sshbuf-getput-crypto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshbuf-getput-crypto.c,v 1.7 2019/01/21 09:54:11 djm Exp $ */ +/* $OpenBSD: sshbuf-getput-crypto.c,v 1.8 2019/11/15 06:00:20 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -23,6 +23,7 @@ #include #include +#ifdef WITH_OPENSSL #include #ifdef OPENSSL_HAS_ECC # include @@ -153,23 +154,17 @@ 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); + NULL, 0, NULL)) > SSHBUF_MAX_ECPOINT) { return SSH_ERR_INVALID_ARGUMENT; } if (EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED, - d, len, bn_ctx) != len) { - BN_CTX_free(bn_ctx); + d, len, NULL) != len) { 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; @@ -182,4 +177,4 @@ sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v) EC_KEY_get0_group(v)); } #endif /* OPENSSL_HAS_ECC */ - +#endif /* WITH_OPENSSL */ diff --git a/sshbuf-io.c b/sshbuf-io.c new file mode 100644 index 000000000..13ef40e7d --- /dev/null +++ b/sshbuf-io.c @@ -0,0 +1,117 @@ +/* $OpenBSD: sshbuf-io.c,v 1.2 2020/01/25 23:28:06 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. + */ + +#include "includes.h" + +#include +#include + +#include +#include +#include +#include + +#include "ssherr.h" +#include "sshbuf.h" +#include "atomicio.h" + +/* Load a file from a fd into a buffer */ +int +sshbuf_load_fd(int fd, struct sshbuf **blobp) +{ + u_char buf[4096]; + size_t len; + struct stat st; + int r; + struct sshbuf *blob; + + *blobp = NULL; + + if (fstat(fd, &st) == -1) + return SSH_ERR_SYSTEM_ERROR; + if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && + st.st_size > SSHBUF_SIZE_MAX) + return SSH_ERR_INVALID_FORMAT; + if ((blob = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + for (;;) { + if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) { + if (errno == EPIPE) + break; + r = SSH_ERR_SYSTEM_ERROR; + goto out; + } + if ((r = sshbuf_put(blob, buf, len)) != 0) + goto out; + if (sshbuf_len(blob) > SSHBUF_SIZE_MAX) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + } + if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && + st.st_size != (off_t)sshbuf_len(blob)) { + r = SSH_ERR_FILE_CHANGED; + goto out; + } + /* success */ + *blobp = blob; + blob = NULL; /* transferred */ + r = 0; + out: + explicit_bzero(buf, sizeof(buf)); + sshbuf_free(blob); + return r; +} + +int +sshbuf_load_file(const char *path, struct sshbuf **bufp) +{ + int r, fd, oerrno; + + *bufp = NULL; + if ((fd = open(path, O_RDONLY)) == -1) + return SSH_ERR_SYSTEM_ERROR; + if ((r = sshbuf_load_fd(fd, bufp)) != 0) + goto out; + /* success */ + r = 0; + out: + oerrno = errno; + close(fd); + if (r != 0) + errno = oerrno; + return r; +} + +int +sshbuf_write_file(const char *path, struct sshbuf *buf) +{ + int fd, oerrno; + + if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) + return SSH_ERR_SYSTEM_ERROR; + if (atomicio(vwrite, fd, sshbuf_mutable_ptr(buf), + sshbuf_len(buf)) != sshbuf_len(buf) || close(fd) != 0) { + oerrno = errno; + close(fd); + unlink(path); + errno = oerrno; + return SSH_ERR_SYSTEM_ERROR; + } + return 0; +} + diff --git a/sshbuf-misc.c b/sshbuf-misc.c index a73f008b0..afaab8d61 100644 --- a/sshbuf-misc.c +++ b/sshbuf-misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshbuf-misc.c,v 1.11 2019/07/30 05:04:49 djm Exp $ */ +/* $OpenBSD: sshbuf-misc.c,v 1.16 2020/06/22 05:54:10 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -63,7 +63,7 @@ sshbuf_dump_data(const void *s, size_t len, FILE *f) } void -sshbuf_dump(struct sshbuf *buf, FILE *f) +sshbuf_dump(const struct sshbuf *buf, FILE *f) { fprintf(f, "buffer %p len = %zu\n", buf, sshbuf_len(buf)); sshbuf_dump_data(sshbuf_ptr(buf), sshbuf_len(buf), f); @@ -156,20 +156,60 @@ sshbuf_b64tod(struct sshbuf *buf, const char *b64) if ((p = malloc(plen)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((nlen = b64_pton(b64, p, plen)) < 0) { - explicit_bzero(p, plen); - free(p); + freezero(p, plen); return SSH_ERR_INVALID_FORMAT; } if ((r = sshbuf_put(buf, p, nlen)) < 0) { - explicit_bzero(p, plen); - free(p); + freezero(p, plen); return r; } - explicit_bzero(p, plen); - free(p); + freezero(p, plen); return 0; } +int +sshbuf_dtourlb64(const struct sshbuf *d, struct sshbuf *b64, int wrap) +{ + int r = SSH_ERR_INTERNAL_ERROR; + u_char *p; + struct sshbuf *b = NULL; + size_t i, l; + + if ((b = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + /* Encode using regular base64; we'll transform it once done */ + if ((r = sshbuf_dtob64(d, b, wrap)) != 0) + goto out; + /* remove padding from end of encoded string*/ + for (;;) { + l = sshbuf_len(b); + if (l <= 1 || sshbuf_ptr(b) == NULL) { + r = SSH_ERR_INTERNAL_ERROR; + goto out; + } + if (sshbuf_ptr(b)[l - 1] != '=') + break; + if ((r = sshbuf_consume_end(b, 1)) != 0) + goto out; + } + /* Replace characters with rfc4648 equivalents */ + l = sshbuf_len(b); + if ((p = sshbuf_mutable_ptr(b)) == NULL) { + r = SSH_ERR_INTERNAL_ERROR; + goto out; + } + for (i = 0; i < l; i++) { + if (p[i] == '+') + p[i] = '-'; + else if (p[i] == '/') + p[i] = '_'; + } + r = sshbuf_putb(b64, b); + out: + sshbuf_free(b); + return r; +} + char * sshbuf_dup_string(struct sshbuf *buf) { diff --git a/sshbuf.c b/sshbuf.c index adfddf775..368ba7980 100644 --- a/sshbuf.c +++ b/sshbuf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshbuf.c,v 1.13 2018/11/16 06:10:29 djm Exp $ */ +/* $OpenBSD: sshbuf.c,v 1.15 2020/02/26 13:40:09 jsg Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -42,7 +42,7 @@ sshbuf_check_sanity(const struct sshbuf *buf) buf->off > buf->size)) { /* Do not try to recover from corrupted buffer internals */ SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); - signal(SIGSEGV, SIG_DFL); + ssh_signal(SIGSEGV, SIG_DFL); raise(SIGSEGV); return SSH_ERR_INTERNAL_ERROR; } @@ -164,8 +164,7 @@ sshbuf_free(struct sshbuf *buf) explicit_bzero(buf->d, buf->alloc); free(buf->d); } - explicit_bzero(buf, sizeof(*buf)); - free(buf); + freezero(buf, sizeof(*buf)); } void diff --git a/sshbuf.h b/sshbuf.h index ebd64b10e..2ad0e61be 100644 --- a/sshbuf.h +++ b/sshbuf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshbuf.h,v 1.18 2019/09/06 05:23:55 djm Exp $ */ +/* $OpenBSD: sshbuf.h,v 1.23 2020/06/22 05:54:10 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -140,7 +140,7 @@ 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. + * optional dpp parameter or a negative SSH_ERR_* error code on failure. */ int sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp); @@ -187,7 +187,7 @@ int sshbuf_peek_u8(const struct sshbuf *buf, size_t offset, u_char *valp); /* - * Functions to poke values into an exisiting buffer (e.g. a length header + * Functions to poke values into an existing buffer (e.g. a length header * to a packet). The destination bytes must already exist in the buffer. */ int sshbuf_poke_u64(struct sshbuf *buf, size_t offset, u_int64_t val); @@ -242,7 +242,7 @@ int sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v); #endif /* WITH_OPENSSL */ /* Dump the contents of the buffer in a human-readable format */ -void sshbuf_dump(struct sshbuf *buf, FILE *f); +void sshbuf_dump(const 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); @@ -253,6 +253,8 @@ char *sshbuf_dtob16(struct sshbuf *buf); /* Encode the contents of the buffer as base64 */ char *sshbuf_dtob64_string(const struct sshbuf *buf, int wrap); int sshbuf_dtob64(const struct sshbuf *d, struct sshbuf *b64, int wrap); +/* RFC4648 "base64url" encoding variant */ +int sshbuf_dtourlb64(const struct sshbuf *d, struct sshbuf *b64, int wrap); /* Decode base64 data and append it to the buffer */ int sshbuf_b64tod(struct sshbuf *buf, const char *b64); @@ -291,6 +293,22 @@ sshbuf_find(const struct sshbuf *b, size_t start_offset, */ char *sshbuf_dup_string(struct sshbuf *buf); +/* + * Fill a buffer from a file descriptor or filename. Both allocate the + * buffer for the caller. + */ +int sshbuf_load_fd(int, struct sshbuf **) + __attribute__((__nonnull__ (2))); +int sshbuf_load_file(const char *, struct sshbuf **) + __attribute__((__nonnull__ (2))); + +/* + * Write a buffer to a path, creating/truncating as needed (mode 0644, + * subject to umask). The buffer contents are not modified. + */ +int sshbuf_write_file(const char *path, struct sshbuf *buf) + __attribute__((__nonnull__ (2))); + /* Macros for decoding/encoding integers */ #define PEEK_U64(p) \ (((u_int64_t)(((const u_char *)(p))[0]) << 56) | \ diff --git a/sshconnect.c b/sshconnect.c index c35b34f19..cf4a42f08 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.319 2019/09/13 04:31:19 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.350 2021/01/26 00:49:30 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -30,6 +30,7 @@ #include #include #include +#include #include #ifdef HAVE_PATHS_H #include @@ -39,9 +40,9 @@ #include #endif #include -#include #include #include +#include #include #include #ifdef HAVE_IFADDRS_H @@ -89,11 +90,14 @@ expand_proxy_command(const char *proxy_command, const char *user, const char *host, const char *host_arg, int port) { char *tmp, *ret, strport[NI_MAXSERV]; + const char *keyalias = options.host_key_alias ? + options.host_key_alias : host_arg; snprintf(strport, sizeof strport, "%d", port); xasprintf(&tmp, "exec %s", proxy_command); ret = percent_expand(tmp, "h", host, + "k", keyalias, "n", host_arg, "p", strport, "r", options.user, @@ -102,24 +106,6 @@ expand_proxy_command(const char *proxy_command, const char *user, 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. @@ -141,7 +127,7 @@ ssh_proxy_fdpass_connect(struct ssh *ssh, const char *host, "proxy dialer: %.100s", strerror(errno)); command_string = expand_proxy_command(proxy_command, options.user, - host_arg, host, port); + host, host_arg, port); debug("Executing proxy dialer command: %.500s", command_string); /* Fork and execute the proxy command. */ @@ -166,8 +152,8 @@ ssh_proxy_fdpass_connect(struct ssh *ssh, const char *host, * error messages may be printed on the user's terminal. */ if (!debug_flag && options.control_path != NULL && - options.control_persist) - stderr_null(); + options.control_persist && stdfd_devnull(0, 0, 1) == -1) + error_f("stdfd_devnull failed"); argv[0] = shell; argv[1] = "-c"; @@ -224,7 +210,7 @@ ssh_proxy_connect(struct ssh *ssh, const char *host, const char *host_arg, strerror(errno)); command_string = expand_proxy_command(proxy_command, options.user, - host_arg, host, port); + host, host_arg, port); debug("Executing proxy command: %.500s", command_string); @@ -275,8 +261,8 @@ ssh_proxy_connect(struct ssh *ssh, const char *host, const char *host_arg, * error messages may be printed on the user's terminal. */ if (!debug_flag && options.control_path != NULL && - options.control_persist) - stderr_null(); + options.control_persist && stdfd_devnull(0, 0, 1) == -1) + error_f("stdfd_devnull failed"); argv[0] = shell; argv[1] = "-c"; @@ -285,7 +271,7 @@ ssh_proxy_connect(struct ssh *ssh, const char *host, const char *host_arg, /* Execute the proxy command. Note that we gave up any extra privileges above. */ - signal(SIGPIPE, SIG_DFL); + ssh_signal(SIGPIPE, SIG_DFL); execv(argv[0], argv); perror(argv[0]); exit(1); @@ -356,8 +342,7 @@ check_ifaddrs(const char *ifname, int af, const struct ifaddrs *ifaddrs, htonl(INADDR_LOOPBACK)) continue; if (*rlenp < sizeof(struct sockaddr_in)) { - error("%s: v4 addr doesn't fit", - __func__); + error_f("v4 addr doesn't fit"); return -1; } *rlenp = sizeof(struct sockaddr_in); @@ -371,8 +356,7 @@ check_ifaddrs(const char *ifname, int af, const struct ifaddrs *ifaddrs, IN6_IS_ADDR_LOOPBACK(v6addr))) continue; if (*rlenp < sizeof(struct sockaddr_in6)) { - error("%s: v6 addr doesn't fit", - __func__); + error_f("v6 addr doesn't fit"); return -1; } *rlenp = sizeof(struct sockaddr_in6); @@ -407,6 +391,10 @@ ssh_create_socket(struct addrinfo *ai) } fcntl(sock, F_SETFD, FD_CLOEXEC); + /* Use interactive QOS (if specified) until authentication completed */ + if (options.ip_qos_interactive != INT_MAX) + set_sock_tos(sock, options.ip_qos_interactive); + /* Bind the socket to an alternative local IP address */ if (options.bind_address == NULL && options.bind_interface == NULL) return sock; @@ -449,15 +437,14 @@ ssh_create_socket(struct addrinfo *ai) } 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)); + error_f("getnameinfo failed: %s", 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); + debug_f("bound to %s", ntop); /* success */ goto out; fail: @@ -484,15 +471,15 @@ fail: */ 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) + struct sockaddr_storage *hostaddr, u_short port, int connection_attempts, + int *timeout_ms, int want_keepalive) { 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__); + debug3_f("entering"); memset(ntop, 0, sizeof(ntop)); memset(strport, 0, sizeof(strport)); @@ -516,7 +503,7 @@ ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { oerrno = errno; - error("%s: getnameinfo failed", __func__); + error_f("getnameinfo failed"); errno = oerrno; continue; } @@ -575,19 +562,19 @@ ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop, int ssh_connect(struct ssh *ssh, const char *host, const char *host_arg, struct addrinfo *addrs, struct sockaddr_storage *hostaddr, u_short port, - int family, int connection_attempts, int *timeout_ms, int want_keepalive) + 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); + connection_attempts, timeout_ms, want_keepalive); } else if (strcmp(options.proxy_command, "-") == 0) { if ((in = dup(STDIN_FILENO)) == -1 || (out = dup(STDOUT_FILENO)) == -1) { if (in >= 0) close(in); - error("%s: dup() in/out failed", __func__); + error_f("dup() in/out failed"); return -1; /* ssh_packet_set_connection logs error */ } if ((ssh_packet_set_connection(ssh, in, out)) == NULL) @@ -607,53 +594,28 @@ 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; + char *p, *cp; int ret = -1; if (options.batch_mode) return 0; for (msg = prompt;;msg = fingerprint ? again_fp : again) { - p = read_passphrase(msg, RP_ECHO); + cp = p = read_passphrase(msg, RP_ECHO); if (p == NULL) return 0; - p[strcspn(p, "\n")] = '\0'; + p += strspn(p, " \t"); /* skip leading whitespace */ + p[strcspn(p, " \t\n")] = '\0'; /* remove trailing whitespace */ if (p[0] == '\0' || strcasecmp(p, "no") == 0) ret = 0; else if (strcasecmp(p, "yes") == 0 || (fingerprint != NULL && - strcasecmp(p, fingerprint) == 0)) + strcmp(p, fingerprint) == 0)) ret = 1; - free(p); + free(cp); 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) { @@ -703,7 +665,7 @@ get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr, if (options.proxy_command == NULL) { if (getnameinfo(hostaddr, addrlen, ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0) - fatal("%s: getnameinfo failed", __func__); + fatal_f("getnameinfo failed"); *hostfile_ipaddr = put_host_port(ntop, port); } else { *hostfile_ipaddr = xstrdup("match & HKF_MATCH_HOST) != 0) + return 0; + /* not interested in marker lines */ + if (l->marker != MRK_NONE) + return 0; + /* we are only interested in exact key matches */ + if (l->key == NULL || !sshkey_equal(ctx->key, l->key)) + return 0; + path = try_tilde_unexpand(l->path); + debug_f("found matching key in %s:%lu", path, l->linenum); + ctx->names = xrecallocarray(ctx->names, + ctx->nnames, ctx->nnames + 1, sizeof(*ctx->names)); + xasprintf(&ctx->names[ctx->nnames], "%s:%lu: %s", path, l->linenum, + strncmp(l->hosts, HASH_MAGIC, strlen(HASH_MAGIC)) == 0 ? + "[hashed name]" : l->hosts); + ctx->nnames++; + free(path); + return 0; +} + +static int +hostkeys_find_by_key_hostfile(const char *file, const char *which, + struct find_by_key_ctx *ctx) +{ + int r; + + debug3_f("trying %s hostfile \"%s\"", which, file); + if ((r = hostkeys_foreach(file, hostkeys_find_by_key_cb, ctx, + ctx->host, ctx->ip, HKF_WANT_PARSE_KEY, 0)) != 0) { + if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) { + debug_f("hostkeys file %s does not exist", file); + return 0; + } + error_fr(r, "hostkeys_foreach failed for %s", file); + return r; + } + return 0; +} + +/* + * Find 'key' in known hosts file(s) that do not match host/ip. + * Used to display also-known-as information for previously-unseen hostkeys. + */ +static void +hostkeys_find_by_key(const char *host, const char *ip, const struct sshkey *key, + char **user_hostfiles, u_int num_user_hostfiles, + char **system_hostfiles, u_int num_system_hostfiles, + char ***names, u_int *nnames) +{ + struct find_by_key_ctx ctx = {0, 0, 0, 0, 0}; + u_int i; + + *names = NULL; + *nnames = 0; + + if (key == NULL || sshkey_is_cert(key)) + return; + + ctx.host = host; + ctx.ip = ip; + ctx.key = key; + + for (i = 0; i < num_user_hostfiles; i++) { + if (hostkeys_find_by_key_hostfile(user_hostfiles[i], + "user", &ctx) != 0) + goto fail; + } + for (i = 0; i < num_system_hostfiles; i++) { + if (hostkeys_find_by_key_hostfile(system_hostfiles[i], + "system", &ctx) != 0) + goto fail; + } + /* success */ + *names = ctx.names; + *nnames = ctx.nnames; + ctx.names = NULL; + ctx.nnames = 0; + return; + fail: + for (i = 0; i < ctx.nnames; i++) + free(ctx.names[i]); + free(ctx.names); +} + +#define MAX_OTHER_NAMES 8 /* Maximum number of names to list */ +static char * +other_hostkeys_message(const char *host, const char *ip, + const struct sshkey *key, + char **user_hostfiles, u_int num_user_hostfiles, + char **system_hostfiles, u_int num_system_hostfiles) +{ + char *ret = NULL, **othernames = NULL; + u_int i, n, num_othernames = 0; + + hostkeys_find_by_key(host, ip, key, + user_hostfiles, num_user_hostfiles, + system_hostfiles, num_system_hostfiles, + &othernames, &num_othernames); + if (num_othernames == 0) + return xstrdup("This key is not known by any other names"); + + xasprintf(&ret, "This host key is known by the following other " + "names/addresses:"); + + n = num_othernames; + if (n > MAX_OTHER_NAMES) + n = MAX_OTHER_NAMES; + for (i = 0; i < n; i++) { + xextendf(&ret, "\n", " %s", othernames[i]); + } + if (n < num_othernames) { + xextendf(&ret, "\n", " (%d additional names ommitted)", + num_othernames - n); + } + for (i = 0; i < num_othernames; i++) + free(othernames[i]); + free(othernames); + return ret; +} + +void +load_hostkeys_command(struct hostkeys *hostkeys, const char *command_template, + const char *invocation, const struct ssh_conn_info *cinfo, + const struct sshkey *host_key, const char *hostfile_hostname) +{ + int r, i, ac = 0; + char *key_fp = NULL, *keytext = NULL, *tmp; + char *command = NULL, *tag = NULL, **av = NULL; + FILE *f = NULL; + pid_t pid; + void (*osigchld)(int); + + xasprintf(&tag, "KnownHostsCommand-%s", invocation); + + if (host_key != NULL) { + if ((key_fp = sshkey_fingerprint(host_key, + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + fatal_f("sshkey_fingerprint failed"); + if ((r = sshkey_to_base64(host_key, &keytext)) != 0) + fatal_fr(r, "sshkey_to_base64 failed"); + } + /* + * NB. all returns later this function should go via "out" to + * ensure the original SIGCHLD handler is restored properly. + */ + osigchld = ssh_signal(SIGCHLD, SIG_DFL); + + /* Turn the command into an argument vector */ + if (argv_split(command_template, &ac, &av) != 0) { + error("%s \"%s\" contains invalid quotes", tag, + command_template); + goto out; + } + if (ac == 0) { + error("%s \"%s\" yielded no arguments", tag, + command_template); + goto out; + } + for (i = 1; i < ac; i++) { + tmp = percent_dollar_expand(av[i], + DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo), + "H", hostfile_hostname, + "I", invocation, + "t", host_key == NULL ? "NONE" : sshkey_ssh_name(host_key), + "f", key_fp == NULL ? "NONE" : key_fp, + "K", keytext == NULL ? "NONE" : keytext, + (char *)NULL); + if (tmp == NULL) + fatal_f("percent_expand failed"); + free(av[i]); + av[i] = tmp; + } + /* Prepare a printable command for logs, etc. */ + command = argv_assemble(ac, av); + + if ((pid = subprocess(tag, command, ac, av, &f, + SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_UNSAFE_PATH| + SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL)) == 0) + goto out; + + load_hostkeys_file(hostkeys, hostfile_hostname, tag, f, 1); + + if (exited_cleanly(pid, tag, command, 0) != 0) + fatal("KnownHostsCommand failed"); + + out: + if (f != NULL) + fclose(f); + ssh_signal(SIGCHLD, osigchld); + for (i = 0; i < ac; i++) + free(av[i]); + free(av); + free(tag); + free(command); + free(key_fp); + free(keytext); +} + /* * 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. @@ -735,19 +948,20 @@ get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr, #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, +check_host_key(char *hostname, const struct ssh_conn_info *cinfo, + struct sockaddr *hostaddr, u_short port, + struct sshkey *host_key, int readonly, int clobber_port, char **user_hostfiles, u_int num_user_hostfiles, - char **system_hostfiles, u_int num_system_hostfiles) + char **system_hostfiles, u_int num_system_hostfiles, + const char *hostfile_command) { - HostStatus host_status; - HostStatus ip_status; + HostStatus host_status = -1, ip_status = -1; 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; + const char *type, *fail_reason; + const struct hostkey_entry *host_found = NULL, *ip_found = NULL; 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; @@ -767,6 +981,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, options.host_key_alias == NULL) { debug("Forcing accepting of host key for " "loopback/localhost."); + options.update_hostkeys = 0; return 0; } @@ -774,7 +989,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, * 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); + get_hostfile_hostname_ipaddr(hostname, hostaddr, + clobber_port ? 0 : port, &host, &ip); /* * Turn off check_host_ip if the connection is to localhost, via proxy @@ -786,17 +1002,25 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, host_hostkeys = init_hostkeys(); for (i = 0; i < num_user_hostfiles; i++) - load_hostkeys(host_hostkeys, host, user_hostfiles[i]); + load_hostkeys(host_hostkeys, host, user_hostfiles[i], 0); for (i = 0; i < num_system_hostfiles; i++) - load_hostkeys(host_hostkeys, host, system_hostfiles[i]); + load_hostkeys(host_hostkeys, host, system_hostfiles[i], 0); + if (hostfile_command != NULL && !clobber_port) { + load_hostkeys_command(host_hostkeys, hostfile_command, + "HOSTNAME", cinfo, host_key, host); + } 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]); + load_hostkeys(ip_hostkeys, ip, user_hostfiles[i], 0); for (i = 0; i < num_system_hostfiles; i++) - load_hostkeys(ip_hostkeys, ip, system_hostfiles[i]); + load_hostkeys(ip_hostkeys, ip, system_hostfiles[i], 0); + if (hostfile_command != NULL && !clobber_port) { + load_hostkeys_command(ip_hostkeys, hostfile_command, + "ADDRESS", cinfo, host_key, ip); + } } retry: @@ -811,6 +1035,14 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, host_status = check_key_in_hostkeys(host_hostkeys, host_key, &host_found); + /* + * If there are no hostfiles, or if the hostkey was found via + * KnownHostsCommand, then don't try to touch the disk. + */ + if (!readonly && (num_user_hostfiles == 0 || + (host_found != NULL && host_found->note != 0))) + readonly = RDONLY; + /* * Also perform check for the ip address, skip the check if we are * localhost, looking for a certificate, or the hostname was an ip @@ -834,10 +1066,40 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, 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 (want_cert) { + if (sshkey_cert_check_host(host_key, + options.host_key_alias == NULL ? + hostname : options.host_key_alias, 0, + options.ca_sign_algorithms, &fail_reason) != 0) { + error("%s", fail_reason); + goto fail; + } + /* + * Do not attempt hostkey update if a certificate was + * successfully matched. + */ + if (options.update_hostkeys != 0) { + options.update_hostkeys = 0; + debug3_f("certificate host key in use; " + "disabling UpdateHostkeys"); + } + } + /* Turn off UpdateHostkeys if key was in system known_hosts */ + if (options.update_hostkeys != 0 && + (path_in_hostfiles(host_found->file, + system_hostfiles, num_system_hostfiles) || + (ip_status == HOST_OK && ip_found != NULL && + path_in_hostfiles(ip_found->file, + system_hostfiles, num_system_hostfiles)))) { + options.update_hostkeys = 0; + debug3_f("host key found in GlobalKnownHostsFile; " + "disabling UpdateHostkeys"); + } + if (options.update_hostkeys != 0 && host_found->note) { + options.update_hostkeys = 0; + debug3_f("host key found via KnownHostsCommand; " + "disabling UpdateHostkeys"); + } if (options.check_host_ip && ip_status == HOST_NEW) { if (readonly || want_cert) logit("%s host key for IP address " @@ -859,7 +1121,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, ra = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_RANDOMART); if (fp == NULL || ra == NULL) - fatal("%s: sshkey_fingerprint fail", __func__); + fatal_f("sshkey_fingerprint failed"); logit("Host key fingerprint is %s\n%s", fp, ra); free(ra); free(fp); @@ -868,11 +1130,13 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, break; case HOST_NEW: if (options.host_key_alias == NULL && port != 0 && - port != SSH_DEFAULT_PORT) { + port != SSH_DEFAULT_PORT && !clobber_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) { + if (check_host_key(hostname, cinfo, hostaddr, 0, + host_key, ROQUIET, 1, + user_hostfiles, num_user_hostfiles, + system_hostfiles, num_system_hostfiles, + hostfile_command) == 0) { debug("found matching key w/out port"); break; } @@ -892,45 +1156,48 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, goto fail; } else if (options.strict_host_key_checking == SSH_STRICT_HOSTKEY_ASK) { - char msg1[1024], msg2[1024]; + char *msg1 = NULL, *msg2 = NULL; + + xasprintf(&msg1, "The authenticity of host " + "'%.200s (%s)' can't be established", host, ip); + + if (show_other_keys(host_hostkeys, host_key)) { + xextendf(&msg1, "\n", "but keys of different " + "type are already known for this host."); + } else + xextendf(&msg1, "", "."); - 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'; + fatal_f("sshkey_fingerprint failed"); + xextendf(&msg1, "\n", "%s key fingerprint is %s.", + type, fp); + if (options.visual_host_key) + xextendf(&msg1, "\n", "%s", ra); 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"); + xextendf(&msg1, "\n", + "%s host key fingerprint found in DNS.", + matching_host_key_dns ? + "Matching" : "No matching"); } - 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" + /* msg2 informs for other names matching this key */ + if ((msg2 = other_hostkeys_message(host, ip, host_key, + user_hostfiles, num_user_hostfiles, + system_hostfiles, num_system_hostfiles)) != NULL) + xextendf(&msg1, "\n", "%s", msg2); + + xextendf(&msg1, "\n", "Are you sure you want to continue connecting " - "(yes/no/[fingerprint])? ", - host, ip, msg1, type, fp, - options.visual_host_key ? "\n" : "", - options.visual_host_key ? ra : "", - msg2); + "(yes/no/[fingerprint])? "); + + confirmed = confirm(msg1, fp); free(ra); - confirmed = confirm(msg, fp); free(fp); + free(msg1); + free(msg2); if (!confirmed) goto fail; hostkey_trusted = 1; /* user explicitly confirmed */ @@ -1035,8 +1302,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, */ 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); + error("Host key for %.200s has changed and you have " + "requested strict checking.", host); goto fail; } @@ -1091,6 +1358,11 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, options.tun_open = SSH_TUNMODE_NO; cancelled_forwarding = 1; } + if (options.update_hostkeys != 0) { + error("UpdateHostkeys is disabled because the host " + "key is not trusted."); + options.update_hostkeys = 0; + } if (options.exit_on_forward_failure && cancelled_forwarding) fatal("Error: forwarding disabled due to host key " "check failure"); @@ -1138,8 +1410,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, } if (!hostkey_trusted && options.update_hostkeys) { - debug("%s: hostkey not known or explicitly trusted: " - "disabling UpdateHostkeys", __func__); + debug_f("hostkey not known or explicitly trusted: " + "disabling UpdateHostkeys"); options.update_hostkeys = 0; } @@ -1159,10 +1431,9 @@ fail: */ 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)); + fatal_fr(r, "decode key"); if ((r = sshkey_drop_cert(raw_key)) != 0) - fatal("Couldn't drop certificate: %s", ssh_err(r)); + fatal_r(r, "Couldn't drop certificate"); host_key = raw_key; goto retry; } @@ -1178,7 +1449,8 @@ fail: /* 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) +verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key, + const struct ssh_conn_info *cinfo) { u_int i; int r = -1, flags = 0; @@ -1187,7 +1459,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key) if ((fp = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { - error("%s: fingerprint host key: %s", __func__, ssh_err(r)); + error_fr(r, "fingerprint host key"); r = -1; goto out; } @@ -1195,8 +1467,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key) 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)); + error_fr(r, "fingerprint CA key"); r = -1; goto out; } @@ -1218,8 +1489,8 @@ verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key) } if (sshkey_equal(previous_host_key, host_key)) { - debug2("%s: server host key %s %s matches cached key", - __func__, sshkey_type(host_key), fp); + debug2_f("server host key %s %s matches cached key", + sshkey_type(host_key), fp); r = 0; goto out; } @@ -1237,9 +1508,9 @@ verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key) 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)); + error_r(r, "Error checking host key %s %s in " + "revoked keys file %s", sshkey_type(host_key), + fp, options.revoked_host_keys); r = -1; goto out; } @@ -1273,9 +1544,10 @@ verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key) } } } - 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); + r = check_host_key(host, cinfo, hostaddr, options.port, host_key, + RDRW, 0, options.user_hostfiles, options.num_user_hostfiles, + options.system_hostfiles, options.num_system_hostfiles, + options.known_hosts_command); out: sshkey_free(plain); @@ -1298,10 +1570,12 @@ out: */ void ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost, - struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms) + struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms, + const struct ssh_conn_info *cinfo) { char *host; char *server_user, *local_user; + int r; local_user = xstrdup(pw->pw_name); server_user = options.user ? options.user : local_user; @@ -1311,8 +1585,8 @@ ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost, lowercase(host); /* Exchange protocol version identification strings with the server. */ - if (kex_exchange_identification(ssh, timeout_ms, NULL) != 0) - cleanup_exit(255); /* error already logged */ + if ((r = kex_exchange_identification(ssh, timeout_ms, NULL)) != 0) + sshpkt_fatal(ssh, r, "banner exchange"); /* Put the connection into non-blocking mode. */ ssh_packet_set_nonblocking(ssh); @@ -1320,7 +1594,7 @@ ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost, /* key exchange */ /* authenticate user */ debug("Authenticating to %s:%d as '%s'", host, port, server_user); - ssh_kex2(ssh, host, hostaddr, port); + ssh_kex2(ssh, host, hostaddr, port, cinfo); ssh_userauth2(ssh, local_user, server_user, host, sensitive); free(local_user); free(host); @@ -1345,14 +1619,15 @@ show_other_keys(struct hostkeys *hostkeys, struct sshkey *key) for (i = 0; type[i] != -1; i++) { if (type[i] == key->type) continue; - if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found)) + if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], + -1, &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__); + fatal_f("sshkey_fingerprint fail"); logit("WARNING: %s key found for host %s\n" "in %s:%lu\n" "%s key fingerprint %s.", @@ -1376,7 +1651,7 @@ warn_changed_key(struct sshkey *host_key) fp = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_DEFAULT); if (fp == NULL) - fatal("%s: sshkey_fingerprint fail", __func__); + fatal_f("sshkey_fingerprint fail"); error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); @@ -1413,10 +1688,10 @@ ssh_local_cmd(const char *args) if ((shell = getenv("SHELL")) == NULL || *shell == '\0') shell = _PATH_BSHELL; - osighand = signal(SIGCHLD, SIG_DFL); + osighand = ssh_signal(SIGCHLD, SIG_DFL); pid = fork(); if (pid == 0) { - signal(SIGPIPE, SIG_DFL); + ssh_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", @@ -1427,7 +1702,7 @@ ssh_local_cmd(const char *args) while (waitpid(pid, &status, 0) == -1) if (errno != EINTR) fatal("Couldn't wait for child: %s", strerror(errno)); - signal(SIGCHLD, osighand); + ssh_signal(SIGCHLD, osighand); if (!WIFEXITED(status)) return (1); @@ -1436,10 +1711,11 @@ ssh_local_cmd(const char *args) } void -maybe_add_key_to_agent(char *authfile, struct sshkey *private, - char *comment, char *passphrase) +maybe_add_key_to_agent(const char *authfile, struct sshkey *private, + const char *comment, const char *passphrase) { int auth_sock = -1, r; + const char *skprovider = NULL; if (options.add_keys_to_agent == 0) return; @@ -1455,9 +1731,12 @@ maybe_add_key_to_agent(char *authfile, struct sshkey *private, close(auth_sock); return; } - - if ((r = ssh_add_identity_constrained(auth_sock, private, comment, 0, - (options.add_keys_to_agent == 3), 0)) == 0) + if (sshkey_is_sk(private)) + skprovider = options.sk_provider; + if ((r = ssh_add_identity_constrained(auth_sock, private, + comment == NULL ? authfile : comment, + options.add_keys_to_agent_lifespan, + (options.add_keys_to_agent == 3), 0, skprovider)) == 0) debug("identity added to agent: %s", authfile); else debug("could not add identity to agent: %s (%d)", authfile, r); diff --git a/sshconnect.h b/sshconnect.h index 2e84b8bc5..f518a9a13 100644 --- a/sshconnect.h +++ b/sshconnect.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.h,v 1.39 2019/09/13 04:27:35 djm Exp $ */ +/* $OpenBSD: sshconnect.h,v 1.46 2020/12/22 00:15:23 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -30,27 +30,65 @@ struct Sensitive { int nkeys; }; +struct ssh_conn_info { + char *conn_hash_hex; + char *shorthost; + char *uidstr; + char *keyalias; + char *thishost; + char *host_arg; + char *portstr; + char *remhost; + char *remuser; + char *homedir; + char *locuser; +}; + struct addrinfo; struct ssh; +struct hostkeys; +struct ssh_conn_info; + +/* default argument for client percent expansions */ +#define DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(conn_info) \ + "C", conn_info->conn_hash_hex, \ + "L", conn_info->shorthost, \ + "i", conn_info->uidstr, \ + "k", conn_info->keyalias, \ + "l", conn_info->thishost, \ + "n", conn_info->host_arg, \ + "p", conn_info->portstr, \ + "d", conn_info->homedir, \ + "h", conn_info->remhost, \ + "r", conn_info->remuser, \ + "u", conn_info->locuser int ssh_connect(struct ssh *, const char *, const char *, struct addrinfo *, struct sockaddr_storage *, u_short, - int, int, int *, int); + int, int *, int); void ssh_kill_proxy_command(void); void ssh_login(struct ssh *, Sensitive *, const char *, - struct sockaddr *, u_short, struct passwd *, int); + struct sockaddr *, u_short, struct passwd *, int, + const struct ssh_conn_info *); -int verify_host_key(char *, struct sockaddr *, struct sshkey *); +int verify_host_key(char *, struct sockaddr *, struct sshkey *, + const struct ssh_conn_info *); void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short, char **, char **); -void ssh_kex2(struct ssh *ssh, char *, struct sockaddr *, u_short); +void ssh_kex2(struct ssh *ssh, char *, struct sockaddr *, u_short, + const struct ssh_conn_info *); void ssh_userauth2(struct ssh *ssh, const char *, const char *, char *, Sensitive *); int ssh_local_cmd(const char *); -void maybe_add_key_to_agent(char *, struct sshkey *, char *, char *); +void maybe_add_key_to_agent(const char *, struct sshkey *, + const char *, const char *); + +void load_hostkeys_command(struct hostkeys *, const char *, + const char *, const struct ssh_conn_info *, + const struct sshkey *, const char *); diff --git a/sshconnect2.c b/sshconnect2.c index 87fa70a40..059c9480d 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.308 2019/08/05 11:50:33 dtucker Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.346 2021/01/27 10:05:28 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -33,12 +33,13 @@ #include #include +#include #include #include #include -#include #include #include +#include #include #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) #include @@ -72,6 +73,8 @@ #include "hostfile.h" #include "ssherr.h" #include "utf8.h" +#include "ssh-sk.h" +#include "sk-api.h" #ifdef GSSAPI #include "ssh-gss.h" @@ -86,26 +89,39 @@ 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 char *xxx_host; +static struct sockaddr *xxx_hostaddr; +static const struct ssh_conn_info *xxx_conn_info; static int verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh) { - if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1) + if (verify_host_key(xxx_host, xxx_hostaddr, hostkey, + xxx_conn_info) == -1) fatal("Host key verification failed."); return 0; } +/* Returns the first item from a comma-separated algorithm list */ static char * -order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port) +first_alg(const char *algs) { - char *oavail, *avail, *first, *last, *alg, *hostname, *ret; + char *ret, *cp; + + ret = xstrdup(algs); + if ((cp = strchr(ret, ',')) != NULL) + *cp = '\0'; + return ret; +} + +static char * +order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port, + const struct ssh_conn_info *cinfo) +{ + char *oavail = NULL, *avail = NULL, *first = NULL, *last = NULL; + char *alg = NULL, *hostname = NULL, *ret = NULL, *best = NULL; size_t maxlen; - struct hostkeys *hostkeys; + struct hostkeys *hostkeys = NULL; int ktype; u_int i; @@ -113,11 +129,37 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port) 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]); + load_hostkeys(hostkeys, hostname, options.user_hostfiles[i], 0); + for (i = 0; i < options.num_system_hostfiles; i++) { + load_hostkeys(hostkeys, hostname, + options.system_hostfiles[i], 0); + } + if (options.known_hosts_command != NULL) { + load_hostkeys_command(hostkeys, options.known_hosts_command, + "ORDER", cinfo, NULL, host); + } + /* + * If a plain public key exists that matches the type of the best + * preference HostkeyAlgorithms, then use the whole list as is. + * Note that we ignore whether the best preference algorithm is a + * certificate type, as sshconnect.c will downgrade certs to + * plain keys if necessary. + */ + best = first_alg(options.hostkeyalgorithms); + if (lookup_key_in_hostkeys_by_type(hostkeys, + sshkey_type_plain(sshkey_type_from_name(best)), + sshkey_ecdsa_nid_from_name(best), NULL)) { + debug3_f("have matching best-preference key type %s, " + "using HostkeyAlgorithms verbatim", best); + ret = xstrdup(options.hostkeyalgorithms); + goto out; + } - oavail = avail = xstrdup(KEX_DEFAULT_PK_ALG); + /* + * Otherwise, prefer the host key algorithms that match known keys + * while keeping the ordering of HostkeyAlgorithms as much as possible. + */ + oavail = avail = xstrdup(options.hostkeyalgorithms); maxlen = strlen(avail) + 1; first = xmalloc(maxlen); last = xmalloc(maxlen); @@ -132,19 +174,35 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port) 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)) + fatal_f("unknown alg %s", alg); + /* + * If we have a @cert-authority marker in known_hosts then + * prefer all certificate algorithms. + */ + if (sshkey_type_is_cert(ktype) && + lookup_marker_in_hostkeys(hostkeys, MRK_CA)) { ALG_APPEND(first, alg); - else - ALG_APPEND(last, alg); + continue; + } + /* If the key appears in known_hosts then prefer it */ + if (lookup_key_in_hostkeys_by_type(hostkeys, + sshkey_type_plain(ktype), + sshkey_ecdsa_nid_from_name(alg), NULL)) { + ALG_APPEND(first, alg); + continue; + } + /* Otherwise, put it last */ + 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); - + debug3_f("prefer hostkeyalgs: %s", first); + else + debug3_f("no algorithms matched; accept original"); + out: + free(best); free(first); free(last); free(hostname); @@ -155,42 +213,55 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port) } void -ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) +ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, + const struct ssh_conn_info *cinfo) { char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; char *s, *all_key; - int r; + int r, use_known_hosts_order = 0; xxx_host = host; xxx_hostaddr = hostaddr; + xxx_conn_info = cinfo; + + /* + * If the user has not specified HostkeyAlgorithms, or has only + * appended or removed algorithms from that list then prefer algorithms + * that are in the list that are supported by known_hosts keys. + */ + if (options.hostkeyalgorithms == NULL || + options.hostkeyalgorithms[0] == '-' || + options.hostkeyalgorithms[0] == '+') + use_known_hosts_order = 1; + + /* Expand or fill in HostkeyAlgorithms */ + all_key = sshkey_alg_list(0, 0, 1, ','); + if ((r = kex_assemble_names(&options.hostkeyalgorithms, + kex_default_pk_alg(), all_key)) != 0) + fatal_fr(r, "kex_assemble_namelist"); + free(all_key); 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); + fatal_f("kex_names_cat"); + myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(ssh, s); myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(options.ciphers); + compat_cipher_proposal(ssh, options.ciphers); myproposal[PROPOSAL_ENC_ALGS_STOC] = - compat_cipher_proposal(options.ciphers); + compat_cipher_proposal(ssh, 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_COMP_ALGS_STOC] = + (char *)compression_alg_list(options.compression); 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); + if (use_known_hosts_order) { + /* Query known_hosts and prefer algorithms that appear there */ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = - compat_pkalg_proposal(options.hostkeyalgorithms); + compat_pkalg_proposal(ssh, + order_hostkeyalgs(host, hostaddr, port, cinfo)); } else { - /* Enforce default */ - options.hostkeyalgorithms = xstrdup(KEX_DEFAULT_PK_ALG); - /* Prefer algorithms that we already have keys for */ + /* Use specified HostkeyAlgorithms exactly */ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = - compat_pkalg_proposal( - order_hostkeyalgs(host, hostaddr, port)); + compat_pkalg_proposal(ssh, options.hostkeyalgorithms); } if (options.rekey_limit || options.rekey_interval) @@ -199,7 +270,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) - fatal("kex_setup: %s", ssh_err(r)); + fatal_r(r, "kex_setup"); #ifdef WITH_OPENSSL ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client; ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client; @@ -213,19 +284,16 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) # endif #endif ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; - ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client; + ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; ssh->kex->verify_host_key=&verify_host_key_callback; 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); + compat_kex_proposal(ssh, options.kex_algorithms); if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) - fatal("kex_prop2buf: %s", ssh_err(r)); - - session_id2 = ssh->kex->session_id; - session_id2_len = ssh->kex->session_id_len; + fatal_r(r, "kex_prop2buf"); #ifdef DEBUG_KEXDH /* send 1st encrypted/maced/compressed message */ @@ -233,7 +301,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) (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)); + fatal_fr(r, "send packet"); #endif } @@ -401,14 +469,13 @@ ssh_userauth2(struct ssh *ssh, const char *local_user, authctxt.agent_fd = -1; pubkey_prepare(&authctxt); if (authctxt.method == NULL) { - fatal("%s: internal error: cannot send userauth none request", - __func__); + fatal_f("internal error: cannot send userauth none request"); } 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)); + fatal_fr(r, "send packet"); ssh->authctxt = &authctxt; ssh_dispatch_init(ssh, &input_userauth_error); @@ -506,7 +573,7 @@ userauth(struct ssh *ssh, char *authlist) static int input_userauth_error(int type, u_int32_t seq, struct ssh *ssh) { - fatal("%s: bad message during authentication: type %d", __func__, type); + fatal_f("bad message during authentication: type %d", type); return 0; } @@ -518,7 +585,7 @@ input_userauth_banner(int type, u_int32_t seq, struct ssh *ssh) size_t len; int r; - debug3("%s", __func__); + debug3_f("entering"); if ((r = sshpkt_get_cstring(ssh, &msg, &len)) != 0 || (r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0) goto out; @@ -537,7 +604,7 @@ input_userauth_success(int type, u_int32_t seq, struct ssh *ssh) Authctxt *authctxt = ssh->authctxt; if (authctxt == NULL) - fatal("%s: no authentication context", __func__); + fatal_f("no authentication context"); free(authctxt->authlist); authctxt->authlist = NULL; if (authctxt->method != NULL && authctxt->method->cleanup != NULL) @@ -555,7 +622,7 @@ 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_f("no authentication context"); fatal("Unexpected authentication success during %s.", authctxt->method->name); @@ -601,17 +668,23 @@ static char * format_identity(Identity *id) { char *fp = NULL, *ret = NULL; + const char *note = ""; if (id->key != NULL) { fp = sshkey_fingerprint(id->key, options.fingerprint_hash, SSH_FP_DEFAULT); } + if (id->key) { + if ((id->key->flags & SSHKEY_FLAG_EXT) != 0) + note = " token"; + else if (sshkey_is_sk(id->key)) + note = " authenticator"; + } 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->userprovided ? " explicit" : "", note, id->agent_fd != -1 ? " agent" : ""); free(fp); return ret; @@ -639,11 +712,11 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) goto done; if ((pktype = sshkey_type_from_name(pkalg)) == KEY_UNSPEC) { - debug("%s: server sent unknown pkalg %s", __func__, pkalg); + debug_f("server sent unknown pkalg %s", pkalg); goto done; } if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { - debug("no key from blob. pkalg %s: %s", pkalg, ssh_err(r)); + debug_r(r, "no key from blob. pkalg %s", pkalg); goto done; } if (key->type != pktype) { @@ -667,7 +740,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) if (!found || id == NULL) { fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); - error("%s: server replied with unknown key: %s %s", __func__, + error_f("server replied with unknown key: %s %s", sshkey_type(key), fp == NULL ? "" : fp); goto done; } @@ -733,7 +806,7 @@ userauth_gssapi(struct ssh *ssh) (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)); + fatal_fr(r, "send packet"); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); @@ -781,7 +854,7 @@ process_gssapi_token(struct ssh *ssh, gss_buffer_t recv_tok) (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "send %u packet", type); gss_release_buffer(&ms, &send_tok); } @@ -792,17 +865,18 @@ process_gssapi_token(struct ssh *ssh, gss_buffer_t recv_tok) if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "send completion"); } else { struct sshbuf *b; if ((b = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); ssh_gssapi_buildmic(b, authctxt->server_user, - authctxt->service, "gssapi-with-mic"); + authctxt->service, "gssapi-with-mic", + ssh->kex->session_id); if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) - fatal("%s: sshbuf_mutable_ptr failed", __func__); + fatal_f("sshbuf_mutable_ptr failed"); gssbuf.length = sshbuf_len(b); status = ssh_gssapi_sign(gssctxt, &gssbuf, &mic); @@ -813,7 +887,7 @@ process_gssapi_token(struct ssh *ssh, gss_buffer_t recv_tok) (r = sshpkt_put_string(ssh, mic.value, mic.length)) != 0 || (r = sshpkt_send(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); + fatal_fr(r, "send MIC"); } sshbuf_free(b); @@ -971,7 +1045,7 @@ userauth_none(struct ssh *ssh) (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)); + fatal_fr(r, "send packet"); return 1; } @@ -1000,7 +1074,7 @@ userauth_passwd(struct ssh *ssh) (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)); + fatal_fr(r, "send packet"); free(prompt); if (password != NULL) @@ -1109,23 +1183,24 @@ key_sig_algorithm(struct ssh *ssh, const struct sshkey *key) */ 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))) { + (key->type == KEY_RSA_CERT && (ssh->compat & SSH_BUG_SIGTYPE))) { /* Filter base key signature alg against our configuration */ return match_list(sshkey_ssh_name(key), - options.pubkey_key_types, NULL); + options.pubkey_accepted_algos, NULL); } /* * For RSA keys/certs, since these might have a different sig type: - * find the first entry in PubkeyAcceptedKeyTypes of the right type + * find the first entry in PubkeyAcceptedAlgorithms of the right type * that also appears in the supported signature algorithms list from * the server. */ - oallowed = allowed = xstrdup(options.pubkey_key_types); + oallowed = allowed = xstrdup(options.pubkey_accepted_algos); 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); + tmp = match_list(sshkey_sigalg_by_name(cp), + ssh->kex->server_sig_algs, NULL); if (tmp != NULL) alg = xstrdup(cp); free(tmp); @@ -1140,8 +1215,13 @@ 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; + struct sshkey *sign_key = NULL, *prv = NULL; + int retried = 0, r = SSH_ERR_INTERNAL_ERROR; + struct notifier_ctx *notifier = NULL; + char *fp = NULL, *pin = NULL, *prompt = NULL; + + *sigp = NULL; + *lenp = 0; /* The agent supports this key. */ if (id->key != NULL && id->agent_fd != -1) { @@ -1155,27 +1235,67 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp, */ 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; + sign_key = id->key; + } else { + /* 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_f("private key %s contents do not match public", + id->filename); + r = SSH_ERR_KEY_NOT_FOUND; + goto out; + } + sign_key = prv; + if (sshkey_is_sk(sign_key)) { + if ((sign_key->sk_flags & + SSH_SK_USER_VERIFICATION_REQD)) { + retry_pin: + xasprintf(&prompt, "Enter PIN for %s key %s: ", + sshkey_type(sign_key), id->filename); + pin = read_passphrase(prompt, 0); + } + if ((sign_key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) { + /* XXX should batch mode just skip these? */ + if ((fp = sshkey_fingerprint(sign_key, + options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) + fatal_f("fingerprint failed"); + notifier = notify_start(options.batch_mode, + "Confirm user presence for key %s %s", + sshkey_type(sign_key), fp); + free(fp); + } + } + } + if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen, + alg, options.sk_provider, pin, compat)) != 0) { + debug_fr(r, "sshkey_sign"); + if (pin == NULL && !retried && sshkey_is_sk(sign_key) && + r == SSH_ERR_KEY_WRONG_PASSPHRASE) { + notify_complete(notifier, NULL); + notifier = NULL; + retried = 1; + goto retry_pin; + } + goto out; } - /* 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; + /* + * PKCS#11 tokens may not support all signature algorithms, + * so check what we get back. + */ + if ((r = sshkey_check_sigtype(*sigp, *lenp, alg)) != 0) { + debug_fr(r, "sshkey_check_sigtype"); + goto out; } - r = sshkey_sign(prv, sigp, lenp, data, datalen, alg, compat); + /* success */ + r = 0; + out: + free(prompt); + if (pin != NULL) + freezero(pin, strlen(pin)); + notify_complete(notifier, r == 0 ? "User presence confirmed" : NULL); sshkey_free(prv); return r; } @@ -1215,7 +1335,7 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id) SSH_FP_DEFAULT)) == NULL) return 0; - debug3("%s: %s %s", __func__, sshkey_type(id->key), fp); + debug3_f("%s %s", sshkey_type(id->key), fp); /* * If the key is an certificate, try to find a matching private key @@ -1252,12 +1372,12 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id) } } if (sign_id != NULL) { - debug2("%s: using private key \"%s\"%s for " - "certificate", __func__, id->filename, + debug2_f("using private key \"%s\"%s for " + "certificate", id->filename, id->agent_fd != -1 ? " from agent" : ""); } else { - debug("%s: no separate private key for certificate " - "\"%s\"", __func__, id->filename); + debug_f("no separate private key for certificate " + "\"%s\"", id->filename); } } @@ -1275,26 +1395,21 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id) signature = NULL; if ((alg = key_sig_algorithm(fallback_sigtype ? NULL : ssh, id->key)) == NULL) { - error("%s: no mutual signature supported", __func__); + error_f("no mutual signature supported"); goto out; } - debug3("%s: signing using %s", __func__, alg); + debug3_f("signing using %s %s", alg, fp); 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)); - } + fatal_f("sshbuf_new failed"); + if (ssh->compat & SSH_OLD_SESSIONID) { + if ((r = sshbuf_putb(b, ssh->kex->session_id)) != 0) + fatal_fr(r, "sshbuf_putb"); } else { - if ((r = sshbuf_put_string(b, session_id2, - session_id2_len)) != 0) { - fatal("%s: sshbuf_put_string: %s", - __func__, ssh_err(r)); - } + if ((r = sshbuf_put_stringb(b, + ssh->kex->session_id)) != 0) + fatal_fr(r, "sshbuf_put_stringb"); } skip = sshbuf_len(b); if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || @@ -1304,13 +1419,12 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id) (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)); + fatal_fr(r, "assemble signed data"); } /* generate signature */ r = identity_sign(sign_id, &signature, &slen, - sshbuf_ptr(b), sshbuf_len(b), datafellows, alg); + sshbuf_ptr(b), sshbuf_len(b), ssh->compat, alg); if (r == 0) break; else if (r == SSH_ERR_KEY_NOT_FOUND) @@ -1325,28 +1439,30 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id) loc, sshkey_type(id->key), fp); continue; } - error("%s: signing failed: %s", __func__, ssh_err(r)); + error_fr(r, "signing failed for %s \"%s\"%s", + sshkey_type(sign_id->key), sign_id->filename, + id->agent_fd != -1 ? " from agent" : ""); goto out; } if (slen == 0 || signature == NULL) /* shouldn't happen */ - fatal("%s: no signature", __func__); + fatal_f("no signature"); /* append signature */ if ((r = sshbuf_put_string(b, signature, slen)) != 0) - fatal("%s: append signature: %s", __func__, ssh_err(r)); + fatal_fr(r, "append signature"); #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)); + fatal_fr(r, "consume"); /* 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)); + fatal_fr(r, "enqueue request"); /* success */ sent = 1; @@ -1370,13 +1486,13 @@ send_pubkey_test(struct ssh *ssh, Identity *id) int sent = 0, r; if ((alg = key_sig_algorithm(ssh, id->key)) == NULL) { - debug("%s: no mutual signature algorithm", __func__); + debug_f("no mutual signature algorithm"); goto out; } if ((r = sshkey_to_blob(id->key, &blob, &bloblen)) != 0) { /* we cannot handle this key */ - debug3("%s: cannot handle key", __func__); + debug3_f("cannot handle key"); goto out; } /* register callback for USERAUTH_PK_OK message */ @@ -1390,7 +1506,7 @@ send_pubkey_test(struct ssh *ssh, Identity *id) (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)); + fatal_fr(r, "send packet"); sent = 1; out: @@ -1408,8 +1524,9 @@ load_identity_file(Identity *id) struct stat st; if (stat(id->filename, &st) == -1) { - (id->userprovided ? logit : debug3)("no such identity: %s: %s", - id->filename, strerror(errno)); + do_log2(id->userprovided ? + SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_DEBUG3, + "no such identity: %s: %s", id->filename, strerror(errno)); return NULL; } snprintf(prompt, sizeof prompt, @@ -1439,17 +1556,24 @@ load_identity_file(Identity *id) break; case SSH_ERR_SYSTEM_ERROR: if (errno == ENOENT) { - debug2("Load key \"%s\": %s", - id->filename, ssh_err(r)); + debug2_r(r, "Load key \"%s\"", id->filename); quit = 1; break; } /* FALLTHROUGH */ default: - error("Load key \"%s\": %s", id->filename, ssh_err(r)); + error_r(r, "Load key \"%s\"", id->filename); quit = 1; break; } + if (private != NULL && sshkey_is_sk(private) && + options.sk_provider == NULL) { + debug("key \"%s\" is an authenticator-hosted key, " + "but no provider specified", id->filename); + sshkey_free(private); + private = NULL; + quit = 1; + } if (!quit && private != NULL && id->agent_fd == -1 && !(id->key && id->isprivate)) maybe_add_key_to_agent(id->filename, private, comment, @@ -1467,25 +1591,25 @@ static int key_type_allowed_by_config(struct sshkey *key) { if (match_pattern_list(sshkey_ssh_name(key), - options.pubkey_key_types, 0) == 1) + options.pubkey_accepted_algos, 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) + options.pubkey_accepted_algos, 0) == 1) return 1; if (match_pattern_list("rsa-sha2-256", - options.pubkey_key_types, 0) == 1) + options.pubkey_accepted_algos, 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) + options.pubkey_accepted_algos, 0) == 1) return 1; if (match_pattern_list("rsa-sha2-256-cert-v01@openssh.com", - options.pubkey_key_types, 0) == 1) + options.pubkey_accepted_algos, 0) == 1) return 1; break; } @@ -1495,8 +1619,8 @@ key_type_allowed_by_config(struct sshkey *key) /* * try keys in the following order: - * 1. certificates listed in the config file - * 2. other input certificates + * 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 @@ -1520,8 +1644,18 @@ pubkey_prepare(Authctxt *authctxt) /* 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) + if (key && key->cert && + key->cert->type != SSH2_CERT_TYPE_USER) { + debug_f("ignoring certificate %s: not a user " + "certificate", options.identity_files[i]); continue; + } + if (key && sshkey_is_sk(key) && options.sk_provider == NULL) { + debug_f("ignoring authenticator-hosted key %s as no " + "SecurityKeyProvider has been specified", + options.identity_files[i]); + continue; + } options.identity_keys[i] = NULL; id = xcalloc(1, sizeof(*id)); id->agent_fd = -1; @@ -1534,8 +1668,18 @@ pubkey_prepare(Authctxt *authctxt) 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) + key->cert->type != SSH2_CERT_TYPE_USER) { + debug_f("ignoring certificate %s: not a user " + "certificate", options.identity_files[i]); continue; + } + if (key && sshkey_is_sk(key) && options.sk_provider == NULL) { + debug_f("ignoring authenticator-hosted key " + "certificate %s as no " + "SecurityKeyProvider has been specified", + options.identity_files[i]); + continue; + } id = xcalloc(1, sizeof(*id)); id->agent_fd = -1; id->key = key; @@ -1546,12 +1690,10 @@ pubkey_prepare(Authctxt *authctxt) /* 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)); + debug_fr(r, "ssh_get_authentication_socket"); } 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)); + debug_fr(r, "ssh_fetch_identitylist"); close(agent_fd); } else { for (j = 0; j < idlist->nkeys; j++) { @@ -1582,10 +1724,7 @@ pubkey_prepare(Authctxt *authctxt) } 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); - } + TAILQ_CONCAT(preferred, &agent, next); authctxt->agent_fd = agent_fd; } /* Prefer PKCS11 keys that are explicitly listed */ @@ -1595,7 +1734,7 @@ pubkey_prepare(Authctxt *authctxt) found = 0; TAILQ_FOREACH(id2, &files, next) { if (id2->key == NULL || - (id2->key->flags & SSHKEY_FLAG_EXT) == 0) + (id2->key->flags & SSHKEY_FLAG_EXT) != 0) continue; if (sshkey_equal(id->key, id2->key)) { TAILQ_REMOVE(&files, id, next); @@ -1611,15 +1750,12 @@ pubkey_prepare(Authctxt *authctxt) } } /* 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_CONCAT(preferred, &files, next); + /* finally, filter by PubkeyAcceptedAlgorithms */ 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", + "corresponding algo not in PubkeyAcceptedAlgorithms", sshkey_ssh_name(id->key), id->filename); TAILQ_REMOVE(preferred, id, next); sshkey_free(id->key); @@ -1634,7 +1770,7 @@ pubkey_prepare(Authctxt *authctxt) debug("Will attempt key: %s", ident); free(ident); } - debug2("%s: done", __func__); + debug2_f("done"); } static void @@ -1666,12 +1802,12 @@ pubkey_reset(Authctxt *authctxt) } static int -try_identity(Identity *id) +try_identity(struct ssh *ssh, Identity *id) { if (!id->key) return (0); if (sshkey_type_plain(id->key->type) == KEY_RSA && - (datafellows & SSH_BUG_RSASIGMD5) != 0) { + (ssh->compat & SSH_BUG_RSASIGMD5) != 0) { debug("Skipped %s key %s for RSA/MD5 server", sshkey_type(id->key), id->filename); return (0); @@ -1699,7 +1835,7 @@ userauth_pubkey(struct ssh *ssh) * private key instead */ if (id->key != NULL) { - if (try_identity(id)) { + if (try_identity(ssh, id)) { ident = format_identity(id); debug("Offering public key: %s", ident); free(ident); @@ -1709,7 +1845,7 @@ userauth_pubkey(struct ssh *ssh) debug("Trying private key: %s", id->filename); id->key = load_identity_file(id); if (id->key != NULL) { - if (try_identity(id)) { + if (try_identity(ssh, id)) { id->isprivate = 1; sent = sign_and_send_pubkey(ssh, id); } @@ -1751,7 +1887,7 @@ userauth_kbdint(struct ssh *ssh) (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)); + fatal_fr(r, "send packet"); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req); return 1; @@ -1765,15 +1901,15 @@ 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; + char *display_prompt = NULL, *response = NULL; u_char echo = 0; u_int num_prompts, i; int r; - debug2("input_userauth_info_req"); + debug2_f("entering"); if (authctxt == NULL) - fatal("input_userauth_info_req: no authentication context"); + fatal_f("no authentication context"); authctxt->info_req_seen = 1; @@ -1798,17 +1934,22 @@ input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh) (r = sshpkt_put_u32(ssh, num_prompts)) != 0) goto out; - debug2("input_userauth_info_req: num_prompts %d", num_prompts); + debug2_f("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 (asmprintf(&display_prompt, INT_MAX, NULL, "(%s@%s) %s", + authctxt->server_user, options.host_key_alias ? + options.host_key_alias : authctxt->host, prompt) == -1) + fatal_f("asmprintf failed"); + response = read_passphrase(display_prompt, echo ? RP_ECHO : 0); if ((r = sshpkt_put_cstring(ssh, response)) != 0) goto out; freezero(response, strlen(response)); free(prompt); - response = prompt = NULL; + free(display_prompt); + display_prompt = response = prompt = NULL; } /* done with parsing incoming message. */ if ((r = sshpkt_get_end(ssh)) != 0 || @@ -1819,6 +1960,7 @@ input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh) if (response) freezero(response, strlen(response)); free(prompt); + free(display_prompt); free(name); free(inst); free(lang); @@ -1841,46 +1983,46 @@ ssh_keysign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp, *lenp = 0; if (stat(_PATH_SSH_KEY_SIGN, &st) == -1) { - error("%s: not installed: %s", __func__, strerror(errno)); + error_f("not installed: %s", strerror(errno)); return -1; } if (fflush(stdout) != 0) { - error("%s: fflush: %s", __func__, strerror(errno)); + error_f("fflush: %s", strerror(errno)); return -1; } if (pipe(to) == -1) { - error("%s: pipe: %s", __func__, strerror(errno)); + error_f("pipe: %s", strerror(errno)); return -1; } if (pipe(from) == -1) { - error("%s: pipe: %s", __func__, strerror(errno)); + error_f("pipe: %s", strerror(errno)); return -1; } if ((pid = fork()) == -1) { - error("%s: fork: %s", __func__, strerror(errno)); + error_f("fork: %s", strerror(errno)); return -1; } - osigchld = signal(SIGCHLD, SIG_DFL); + osigchld = ssh_signal(SIGCHLD, SIG_DFL); if (pid == 0) { close(from[0]); if (dup2(from[1], STDOUT_FILENO) == -1) - fatal("%s: dup2: %s", __func__, strerror(errno)); + fatal_f("dup2: %s", strerror(errno)); close(to[1]); if (dup2(to[0], STDIN_FILENO) == -1) - fatal("%s: dup2: %s", __func__, strerror(errno)); + fatal_f("dup2: %s", strerror(errno)); close(from[1]); close(to[0]); if (dup2(sock, STDERR_FILENO + 1) == -1) - fatal("%s: dup2: %s", __func__, strerror(errno)); + fatal_f("dup2: %s", strerror(errno)); sock = STDERR_FILENO + 1; fcntl(sock, F_SETFD, 0); /* keep the socket on exec */ closefrom(sock + 1); - debug3("%s: [child] pid=%ld, exec %s", - __func__, (long)getpid(), _PATH_SSH_KEY_SIGN); + debug3_f("[child] pid=%ld, exec %s", + (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, + fatal_f("exec(%s): %s", _PATH_SSH_KEY_SIGN, strerror(errno)); } close(from[1]); @@ -1888,55 +2030,53 @@ ssh_keysign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp, sock = STDERR_FILENO + 1; if ((b = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); /* 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)); + fatal_fr(r, "buffer error"); if (ssh_msg_send(to[1], version, b) == -1) - fatal("%s: couldn't send request", __func__); + fatal_f("couldn't send request"); sshbuf_reset(b); r = ssh_msg_recv(from[0], b); close(from[0]); close(to[1]); if (r < 0) { - error("%s: no reply", __func__); + error_f("no reply"); goto fail; } errno = 0; while (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) { - error("%s: waitpid %ld: %s", - __func__, (long)pid, strerror(errno)); + error_f("waitpid %ld: %s", (long)pid, strerror(errno)); goto fail; } } if (!WIFEXITED(status)) { - error("%s: exited abnormally", __func__); + error_f("exited abnormally"); goto fail; } if (WEXITSTATUS(status) != 0) { - error("%s: exited with status %d", - __func__, WEXITSTATUS(status)); + error_f("exited with status %d", WEXITSTATUS(status)); goto fail; } if ((r = sshbuf_get_u8(b, &rversion)) != 0) { - error("%s: buffer error: %s", __func__, ssh_err(r)); + error_fr(r, "buffer error"); goto fail; } if (rversion != version) { - error("%s: bad version", __func__); + error_f("bad version"); goto fail; } if ((r = sshbuf_get_string(b, sigp, lenp)) != 0) { - error("%s: buffer error: %s", __func__, ssh_err(r)); + error_fr(r, "buffer error"); fail: - signal(SIGCHLD, osigchld); + ssh_signal(SIGCHLD, osigchld); sshbuf_free(b); return -1; } - signal(SIGCHLD, osigchld); + ssh_signal(SIGCHLD, osigchld); sshbuf_free(b); return 0; @@ -1954,12 +2094,12 @@ userauth_hostbased(struct ssh *ssh) int i, r, success = 0; if (authctxt->ktypes == NULL) { - authctxt->oktypes = xstrdup(options.hostbased_key_types); + authctxt->oktypes = xstrdup(options.hostbased_accepted_algos); authctxt->ktypes = authctxt->oktypes; } /* - * Work through each listed type pattern in HostbasedKeyTypes, + * Work through each listed type pattern in HostbasedAcceptedAlgorithms, * trying each hostkey that matches the type in turn. */ for (;;) { @@ -1968,8 +2108,7 @@ userauth_hostbased(struct ssh *ssh) if (authctxt->active_ktype == NULL || *authctxt->active_ktype == '\0') break; - debug3("%s: trying key type %s", __func__, - authctxt->active_ktype); + debug3_f("trying key type %s", authctxt->active_ktype); /* check for a useful key */ private = NULL; @@ -2002,42 +2141,41 @@ userauth_hostbased(struct ssh *ssh) if ((fp = sshkey_fingerprint(private, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { - error("%s: sshkey_fingerprint failed", __func__); + error_f("sshkey_fingerprint failed"); goto out; } - debug("%s: trying hostkey %s %s", - __func__, sshkey_ssh_name(private), fp); + debug_f("trying hostkey %s %s", sshkey_ssh_name(private), fp); /* figure out a name for the client host */ lname = get_local_name(ssh_packet_get_connection_in(ssh)); if (lname == NULL) { - error("%s: cannot get local ipaddr/name", __func__); + error_f("cannot get local ipaddr/name"); goto out; } /* XXX sshbuf_put_stringf? */ xasprintf(&chost, "%s.", lname); - debug2("%s: chost %s", __func__, chost); + debug2_f("chost %s", chost); /* construct data */ if ((b = sshbuf_new()) == NULL) { - error("%s: sshbuf_new failed", __func__); + error_f("sshbuf_new failed"); goto out; } if ((r = sshkey_to_blob(private, &keyblob, &keylen)) != 0) { - error("%s: sshkey_to_blob: %s", __func__, ssh_err(r)); + error_fr(r, "sshkey_to_blob"); goto out; } - if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 || + if ((r = sshbuf_put_stringb(b, ssh->kex->session_id)) != 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_cstring(b, authctxt->active_ktype)) != 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)); + error_fr(r, "buffer error"); goto out; } @@ -2054,13 +2192,13 @@ userauth_hostbased(struct ssh *ssh) (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_cstring(ssh, authctxt->active_ktype)) != 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)); + error_fr(r, "packet error"); goto out; } success = 1; @@ -2169,17 +2307,16 @@ authmethods_get(void) int r; if ((b = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); 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)); + fatal_fr(r, "buffer error"); } } if ((list = sshbuf_dup_string(b)) == NULL) - fatal("%s: sshbuf_dup_string failed", __func__); + fatal_f("sshbuf_dup_string failed"); sshbuf_free(b); return list; } diff --git a/sshd.8 b/sshd.8 index fb133c14b..b2fad56d3 100644 --- a/sshd.8 +++ b/sshd.8 @@ -33,13 +33,13 @@ .\" (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.8,v 1.304 2018/07/22 12:16:59 dtucker Exp $ -.Dd $Mdocdate: July 22 2018 $ +.\" $OpenBSD: sshd.8,v 1.313 2020/08/27 01:07:10 djm Exp $ +.Dd $Mdocdate: August 27 2020 $ .Dt SSHD 8 .Os .Sh NAME .Nm sshd -.Nd OpenSSH SSH daemon +.Nd OpenSSH daemon .Sh SYNOPSIS .Nm sshd .Bk -words @@ -253,16 +253,13 @@ 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. +Forward secrecy 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 rest of the session is encrypted using a symmetric cipher. 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). +through a cryptographic message authentication code (MAC). .Pp Finally, the server and the client enter an authentication dialog. The client tries to authenticate itself using @@ -429,25 +426,39 @@ comments). Public keys consist of the following space-separated fields: options, keytype, base64-encoded key, comment. The options field is optional. -The keytype is -.Dq ecdsa-sha2-nistp256 , -.Dq ecdsa-sha2-nistp384 , -.Dq ecdsa-sha2-nistp521 , -.Dq ssh-ed25519 , -.Dq ssh-dss -or -.Dq ssh-rsa ; -the comment field is not used for anything (but may be convenient for the +The supported key types are: +.Pp +.Bl -item -compact -offset indent +.It +sk-ecdsa-sha2-nistp256@openssh.com +.It +ecdsa-sha2-nistp256 +.It +ecdsa-sha2-nistp384 +.It +ecdsa-sha2-nistp521 +.It +sk-ssh-ed25519@openssh.com +.It +ssh-ed25519 +.It +ssh-dss +.It +ssh-rsa +.El +.Pp +The comment field is not used for anything (but may be convenient for the user to identify the key). .Pp 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. +8 kilobytes, which permits RSA keys up to 16 kilobits. You don't want to type them in; instead, copy the .Pa id_dsa.pub , .Pa id_ecdsa.pub , +.Pa id_ecdsa_sk.pub , .Pa id_ed25519.pub , +.Pa id_ed25519_sk.pub , or the .Pa id_rsa.pub file and edit it. @@ -589,8 +600,8 @@ IPv6 addresses can be specified by enclosing the address in square brackets. Multiple .Cm permitopen options may be applied separated by commas. -No pattern matching is performed on the specified hostnames, -they must be literal domains or addresses. +No pattern matching or name lookup is performed on the +specified hostnames, they must be literal host names and/or addresses. A port specification of .Cm * matches any port. @@ -613,6 +624,20 @@ option. Permits tty allocation previously disabled by the .Cm restrict option. +.It Cm no-touch-required +Do not require demonstration of user presence +for signatures made using this key. +This option only makes sense for the FIDO authenticator algorithms +.Cm ecdsa-sk +and +.Cm ed25519-sk . +.It Cm verify-required +Require that signatures made using this key attest that they verified +the user, e.g. via a PIN. +This option only makes sense for the FIDO authenticator algorithms +.Cm ecdsa-sk +and +.Cm ed25519-sk . .It Cm restrict Enable all restrictions, i.e. disable port, agent and X11 forwarding, as well as disabling PTY allocation @@ -656,6 +681,8 @@ restrict,command="uptime" ssh-rsa AAAA1C8...32Tv== user@example.net restrict,pty,command="nethack" ssh-rsa AAAA1f8...IrrC5== user@example.net +no-touch-required sk-ecdsa-sha2-nistp256@openssh.com AAAAInN...Ko== +user@example.net .Ed .Sh SSH_KNOWN_HOSTS FILE FORMAT The diff --git a/sshd.c b/sshd.c index 1ab4016e5..930a088f2 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.537 2019/06/28 13:35:04 deraadt Exp $ */ +/* $OpenBSD: sshd.c,v 1.570 2021/02/05 02:20:23 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -122,6 +122,8 @@ #include "auth-options.h" #include "version.h" #include "ssherr.h" +#include "sk-api.h" +#include "srclimit.h" /* Re-exec fds */ #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) @@ -214,13 +216,6 @@ struct { 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; @@ -261,6 +256,9 @@ struct sshauthopt *auth_opts = NULL; /* sshd_config buffer */ struct sshbuf *cfg; +/* Included files from the configuration file */ +struct include_list includes = TAILQ_HEAD_INITIALIZER(includes); + /* message to be displayed after login */ struct sshbuf *loginmsg; @@ -272,6 +270,8 @@ void destroy_sensitive_data(void); void demote_sensitive_data(void); static void do_ssh2_kex(struct ssh *); +static char *listener_proctitle; + /* * Close all listening sockets */ @@ -306,10 +306,7 @@ close_startup_pipes(void) static void sighup_handler(int sig) { - int save_errno = errno; - received_sighup = 1; - errno = save_errno; } /* @@ -325,8 +322,7 @@ sighup_restart(void) 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 */ + ssh_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)); @@ -376,7 +372,7 @@ grace_alarm_handler(int sig) * keys command helpers. */ if (getpgid(0) == getpid()) { - signal(SIGTERM, SIG_IGN); + ssh_signal(SIGTERM, SIG_IGN); kill(0, SIGTERM); } @@ -417,9 +413,8 @@ demote_sensitive_data(void) 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)); + fatal_r(r, "could not demote host %s key", + sshkey_type(sensitive_data.host_keys[i])); sshkey_free(sensitive_data.host_keys[i]); sensitive_data.host_keys[i] = tmp; } @@ -823,8 +818,7 @@ privsep_preauth(struct ssh *ssh) if (have_agent) { r = ssh_get_authentication_socket(&auth_sock); if (r != 0) { - error("Could not get agent socket: %s", - ssh_err(r)); + error_r(r, "Could not get agent socket"); have_agent = 0; } } @@ -837,17 +831,17 @@ privsep_preauth(struct ssh *ssh) if (errno == EINTR) continue; pmonitor->m_pid = -1; - fatal("%s: waitpid: %s", __func__, strerror(errno)); + fatal_f("waitpid: %s", 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)); + fatal_f("preauth child exited with status %d", + WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) - fatal("%s: preauth child terminated by signal %d", - __func__, WTERMSIG(status)); + fatal_f("preauth child terminated by signal %d", + WTERMSIG(status)); if (box != NULL) ssh_sandbox_parent_finish(box); return 1; @@ -974,12 +968,11 @@ 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); + debug3_f("%s key not permitted by HostkeyAlgorithms", s); return; } if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) > 0 ? "," : "", s)) != 0) - fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_putf"); } static char * @@ -991,7 +984,7 @@ list_hostkey_types(void) u_int i; if ((b = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); for (i = 0; i < options.num_host_key_files; i++) { key = sensitive_data.host_keys[i]; if (key == NULL) @@ -1007,6 +1000,8 @@ list_hostkey_types(void) case KEY_DSA: case KEY_ECDSA: case KEY_ED25519: + case KEY_ECDSA_SK: + case KEY_ED25519_SK: case KEY_XMSS: append_hostkey_type(b, sshkey_ssh_name(key)); break; @@ -1026,15 +1021,17 @@ list_hostkey_types(void) case KEY_DSA_CERT: case KEY_ECDSA_CERT: case KEY_ED25519_CERT: + case KEY_ECDSA_SK_CERT: + case KEY_ED25519_SK_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__); + fatal_f("sshbuf_dup_string failed"); sshbuf_free(b); - debug("%s: %s", __func__, ret); + debug_f("%s", ret); return ret; } @@ -1050,6 +1047,8 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) case KEY_DSA_CERT: case KEY_ECDSA_CERT: case KEY_ED25519_CERT: + case KEY_ECDSA_SK_CERT: + case KEY_ED25519_SK_CERT: case KEY_XMSS_CERT: key = sensitive_data.host_certificates[i]; break; @@ -1059,10 +1058,20 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) key = sensitive_data.host_pubkeys[i]; break; } - if (key != NULL && key->type == type && - (key->type != KEY_ECDSA || key->ecdsa_nid == nid)) + if (key == NULL || key->type != type) + continue; + switch (type) { + case KEY_ECDSA: + case KEY_ECDSA_SK: + case KEY_ECDSA_CERT: + case KEY_ECDSA_SK_CERT: + if (key->ecdsa_nid != nid) + continue; + /* FALLTHROUGH */ + default: return need_private ? sensitive_data.host_keys[i] : key; + } } return NULL; } @@ -1136,7 +1145,7 @@ notify_hostkeys(struct ssh *ssh) return; if ((buf = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new", __func__); + fatal_f("sshbuf_new"); 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 || @@ -1144,8 +1153,7 @@ notify_hostkeys(struct ssh *ssh) continue; fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); - debug3("%s: key %d: %s %s", __func__, i, - sshkey_ssh_name(key), fp); + debug3_f("key %d: %s %s", i, sshkey_ssh_name(key), fp); free(fp); if (nkeys == 0) { /* @@ -1160,15 +1168,14 @@ notify_hostkeys(struct ssh *ssh) /* 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)); + fatal_fr(r, "couldn't put hostkey %d", i); if ((r = sshpkt_put_stringb(ssh, buf)) != 0) sshpkt_fatal(ssh, r, "%s: append key", __func__); nkeys++; } - debug3("%s: sent %u hostkeys", __func__, nkeys); + debug3_f("sent %u hostkeys", nkeys); if (nkeys == 0) - fatal("%s: no hostkeys", __func__); + fatal_f("no hostkeys"); if ((r = sshpkt_send(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: send", __func__); sshbuf_free(buf); @@ -1181,7 +1188,7 @@ notify_hostkeys(struct ssh *ssh) * all connections are dropped for startups > max_startups */ static int -drop_connection(int startups) +should_drop_connection(int startups) { int p, r; @@ -1198,21 +1205,73 @@ drop_connection(int startups) p += options.max_startups_rate; r = arc4random_uniform(100); - debug("drop_connection: p %d, r %d", p, r); + debug_f("p %d, r %d", p, r); return (r < p) ? 1 : 0; } +/* + * Check whether connection should be accepted by MaxStartups. + * Returns 0 if the connection is accepted. If the connection is refused, + * returns 1 and attempts to send notification to client. + * Logs when the MaxStartups condition is entered or exited, and periodically + * while in that state. + */ +static int +drop_connection(int sock, int startups, int notify_pipe) +{ + char *laddr, *raddr; + const char msg[] = "Exceeded MaxStartups\r\n"; + static time_t last_drop, first_drop; + static u_int ndropped; + LogLevel drop_level = SYSLOG_LEVEL_VERBOSE; + time_t now; + + now = monotime(); + if (!should_drop_connection(startups) && + srclimit_check_allow(sock, notify_pipe) == 1) { + if (last_drop != 0 && + startups < options.max_startups_begin - 1) { + /* XXX maybe need better hysteresis here */ + logit("exited MaxStartups throttling after %s, " + "%u connections dropped", + fmt_timeframe(now - first_drop), ndropped); + last_drop = 0; + } + return 0; + } + +#define SSHD_MAXSTARTUPS_LOG_INTERVAL (5 * 60) + if (last_drop == 0) { + error("beginning MaxStartups throttling"); + drop_level = SYSLOG_LEVEL_INFO; + first_drop = now; + ndropped = 0; + } else if (last_drop + SSHD_MAXSTARTUPS_LOG_INTERVAL < now) { + /* Periodic logs */ + error("in MaxStartups throttling for %s, " + "%u connections dropped", + fmt_timeframe(now - first_drop), ndropped + 1); + drop_level = SYSLOG_LEVEL_INFO; + } + last_drop = now; + ndropped++; + + laddr = get_local_ipaddr(sock); + raddr = get_peer_ipaddr(sock); + do_log2(drop_level, "drop connection #%d from [%s]:%d on [%s]:%d " + "past MaxStartups", startups, raddr, get_peer_port(sock), + laddr, get_local_port(sock)); + free(laddr); + free(raddr); + /* best-effort notification to client */ + (void)write(sock, msg, sizeof(msg) - 1); + return 1; +} + static void usage(void) { - fprintf(stderr, "%s, %s\n", - SSH_RELEASE, -#ifdef WITH_OPENSSL - OpenSSL_version(OPENSSL_VERSION) -#else - "without OpenSSL" -#endif - ); + fprintf(stderr, "%s, %s\n", SSH_RELEASE, SSH_OPENSSL_VERSION); fprintf(stderr, "usage: sshd [-46DdeiqTt] [-C connection_spec] [-c host_cert_file]\n" " [-E log_file] [-f config_file] [-g login_grace_time]\n" @@ -1224,72 +1283,100 @@ usage(void) static void send_rexec_state(int fd, struct sshbuf *conf) { - struct sshbuf *m; + struct sshbuf *m = NULL, *inc = NULL; + struct include_item *item = NULL; int r; - debug3("%s: entering fd = %d config len %zu", __func__, fd, + debug3_f("entering fd = %d config len %zu", fd, sshbuf_len(conf)); + if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + + /* pack includes into a string */ + TAILQ_FOREACH(item, &includes, entry) { + if ((r = sshbuf_put_cstring(inc, item->selector)) != 0 || + (r = sshbuf_put_cstring(inc, item->filename)) != 0 || + (r = sshbuf_put_stringb(inc, item->contents)) != 0) + fatal_fr(r, "compose includes"); + } + /* * Protocol from reexec master to child: * string configuration - * string rngseed (only if OpenSSL is not self-seeded) + * string included_files[] { + * string selector + * string filename + * string contents + * } + * string rng_seed (if required) */ - 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 ((r = sshbuf_put_stringb(m, conf)) != 0 || + (r = sshbuf_put_stringb(m, inc)) != 0) + fatal_fr(r, "compose config"); #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__); + error_f("ssh_msg_send failed"); sshbuf_free(m); + sshbuf_free(inc); - debug3("%s: done", __func__); + debug3_f("done"); } static void recv_rexec_state(int fd, struct sshbuf *conf) { - struct sshbuf *m; + struct sshbuf *m, *inc; u_char *cp, ver; size_t len; int r; + struct include_item *item; - debug3("%s: entering fd = %d", __func__, fd); + debug3_f("entering fd = %d", fd); - if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); if (ssh_msg_recv(fd, m) == -1) - fatal("%s: ssh_msg_recv failed", __func__); + fatal_f("ssh_msg_recv failed"); if ((r = sshbuf_get_u8(m, &ver)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse version"); 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)); + fatal_f("rexec version mismatch"); + if ((r = sshbuf_get_string(m, &cp, &len)) != 0 || + (r = sshbuf_get_stringb(m, inc)) != 0) + fatal_fr(r, "parse config"); + #if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY) rexec_recv_rng_seed(m); #endif + if (conf != NULL && (r = sshbuf_put(conf, cp, len))) + fatal_fr(r, "sshbuf_put"); + + while (sshbuf_len(inc) != 0) { + item = xcalloc(1, sizeof(*item)); + if ((item->contents = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + if ((r = sshbuf_get_cstring(inc, &item->selector, NULL)) != 0 || + (r = sshbuf_get_cstring(inc, &item->filename, NULL)) != 0 || + (r = sshbuf_get_stringb(inc, item->contents)) != 0) + fatal_fr(r, "parse includes"); + TAILQ_INSERT_TAIL(&includes, item, entry); + } + free(cp); sshbuf_free(m); - debug3("%s: done", __func__); + debug3_f("done"); } /* Accept a connection from inetd */ static void server_accept_inetd(int *sock_in, int *sock_out) { - int fd; - if (rexeced_flag) { close(REEXEC_CONFIG_PASS_FD); *sock_in = *sock_out = dup(STDIN_FILENO); @@ -1302,14 +1389,8 @@ server_accept_inetd(int *sock_in, int *sock_out) * 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); - } + if (stdfd_devnull(1, 1, !log_stderr) == -1) + error_f("stdfd_devnull failed"); debug("inetd sockets after dupping: %d, %d", *sock_in, *sock_out); } @@ -1393,6 +1474,10 @@ server_listen(void) { u_int i; + /* Initialise per-source limit tracking. */ + srclimit_init(options.max_startups, options.per_source_max_startups, + options.per_source_masklen_ipv4, options.per_source_masklen_ipv6); + for (i = 0; i < options.num_listen_addrs; i++) { listen_on_addrs(&options.listen_addrs[i]); freeaddrinfo(options.listen_addrs[i].addrs); @@ -1417,7 +1502,7 @@ 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, listening = 0, lameduck = 0; + int ostartups = -1, startups = 0, listening = 0, lameduck = 0; int startup_p[2] = { -1 , -1 }; char c = 0; struct sockaddr_storage from; @@ -1431,7 +1516,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) for (i = 0; i < num_listen_socks; i++) if (listen_socks[i] > maxfd) maxfd = listen_socks[i]; - /* pipes connected to unauthenticated childs */ + /* pipes connected to unauthenticated child sshd processes */ startup_pipes = xcalloc(options.max_startups, sizeof(int)); startup_flags = xcalloc(options.max_startups, sizeof(int)); for (i = 0; i < options.max_startups; i++) @@ -1442,6 +1527,12 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) * the daemon is killed with a signal. */ for (;;) { + if (ostartups != startups) { + setproctitle("%s [listener] %d of %d-%d startups", + listener_proctitle, startups, + options.max_startups_begin, options.max_startups); + ostartups = startups; + } if (received_sighup) { if (!lameduck) { debug("Received SIGHUP; waiting for children"); @@ -1485,14 +1576,15 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) 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)); + error_f("startup pipe %d (fd=%d): " + "read %s", i, startup_pipes[i], + strerror(errno)); } /* FALLTHROUGH */ case 0: /* child exited or completed auth */ close(startup_pipes[i]); + srclimit_done(startup_pipes[i]); startup_pipes[i] = -1; startups--; if (startup_flags[i]) @@ -1522,25 +1614,13 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) usleep(100 * 1000); continue; } - if (unset_nonblock(*newsock) == -1) { - close(*newsock); + if (unset_nonblock(*newsock) == -1 || + pipe(startup_p) == -1) 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) { + if (drop_connection(*newsock, startups, startup_p[0])) { close(*newsock); + close(startup_p[0]); + close(startup_p[1]); continue; } @@ -1669,9 +1749,9 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) close(startup_p[1]); if (rexec_flag) { + close(config_s[1]); send_rexec_state(config_s[0], cfg); close(config_s[0]); - close(config_s[1]); } close(*newsock); @@ -1767,7 +1847,7 @@ set_process_rdomain(struct ssh *ssh, const char *name) 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); + debug_f("set routing domain %d (was %d)", rtable, ortable); #else /* defined(__OpenBSD__) */ fatal("Unable to set routing domain: not supported in this platform"); #endif @@ -1784,16 +1864,16 @@ accumulate_host_timing_secret(struct sshbuf *server_cfg, int r; if (ctx == NULL && (ctx = ssh_digest_start(SSH_DIGEST_SHA512)) == NULL) - fatal("%s: ssh_digest_start", __func__); + fatal_f("ssh_digest_start"); 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__); + fatal_f("ssh_digest_update"); len = ssh_digest_bytes(SSH_DIGEST_SHA512); hash = xmalloc(len); if (ssh_digest_final(ctx, hash, len) != 0) - fatal("%s: ssh_digest_final", __func__); + fatal_f("ssh_digest_final"); options.timing_secret = PEEK_U64(hash); freezero(hash, len); ssh_digest_free(ctx); @@ -1801,15 +1881,26 @@ accumulate_host_timing_secret(struct sshbuf *server_cfg, return; } if ((buf = sshbuf_new()) == NULL) - fatal("%s could not allocate buffer", __func__); + fatal_f("could not allocate buffer"); if ((r = sshkey_private_serialize(key, buf)) != 0) - fatal("sshkey_private_serialize: %s", ssh_err(r)); + fatal_fr(r, "decode key"); if (ssh_digest_update(ctx, sshbuf_ptr(buf), sshbuf_len(buf)) != 0) - fatal("%s: ssh_digest_update", __func__); + fatal_f("ssh_digest_update"); sshbuf_reset(buf); sshbuf_free(buf); } +static char * +prepare_proctitle(int ac, char **av) +{ + char *ret = NULL; + int i; + + for (i = 0; i < ac; i++) + xextendf(&ret, " ", "%s", av[i]); + return ret; +} + /* * Main program for the daemon. */ @@ -1962,7 +2053,7 @@ main(int ac, char **av) case 'o': line = xstrdup(optarg); if (process_server_config_line(&options, line, - "command-line", 0, NULL, NULL) != 0) + "command-line", 0, NULL, NULL, &includes) != 0) exit(1); free(line); break; @@ -2009,7 +2100,7 @@ main(int ac, char **av) SYSLOG_LEVEL_INFO : options.log_level, options.log_facility == SYSLOG_FACILITY_NOT_SET ? SYSLOG_FACILITY_AUTH : options.log_facility, - log_stderr || !inetd_flag); + log_stderr || !inetd_flag || debug_flag); /* * Unset KRB5CCNAME, otherwise the user's session may inherit it from @@ -2030,8 +2121,9 @@ main(int ac, char **av) /* Fetch our configuration */ if ((cfg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if (rexeced_flag) { + setproctitle("%s", "[rexeced]"); recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg); if (!debug_flag) { startup_pipe = dup(REEXEC_STARTUP_PIPE_FD); @@ -2049,7 +2141,7 @@ main(int ac, char **av) load_server_config(config_file_name, cfg); parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, - cfg, NULL); + cfg, &includes, NULL); /* Fill in default values for those options not explicitly set. */ fill_default_server_options(&options); @@ -2093,13 +2185,7 @@ main(int ac, char **av) exit(1); } - debug("sshd version %s, %s", SSH_VERSION, -#ifdef WITH_OPENSSL - OpenSSL_version(OPENSSL_VERSION) -#else - "without OpenSSL" -#endif - ); + debug("sshd version %s, %s", SSH_VERSION, SSH_OPENSSL_VERSION); /* Store privilege separation user for later use if required. */ privsep_chroot = use_privsep && (getuid() == 0 || geteuid() == 0); @@ -2132,8 +2218,8 @@ main(int ac, char **av) 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)); + error_r(r, "Could not connect to agent \"%s\"", + options.host_key_agent); } for (i = 0; i < options.num_host_key_files; i++) { @@ -2145,22 +2231,38 @@ main(int ac, char **av) if (privsep_unauth_child || privsep_auth_child) key = NULL; else /*TODO - remove this*/ if ((r = sshkey_load_private(options.host_key_files[i], "", &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) - do_log2(ll, "Unable to load host key \"%s\": %s", - options.host_key_files[i], ssh_err(r)); - if (r == 0 && (r = sshkey_shield_private(key)) != 0) { - do_log2(ll, "Unable to shield host key \"%s\": %s", - options.host_key_files[i], ssh_err(r)); + do_log2_r(r, ll, "Unable to load host key \"%s\"", + options.host_key_files[i]); + if (sshkey_is_sk(key) && + key->sk_flags & SSH_SK_USER_PRESENCE_REQD) { + debug("host key %s requires user presence, ignoring", + options.host_key_files[i]); + key->sk_flags &= ~SSH_SK_USER_PRESENCE_REQD; + } + if (r == 0 && key != NULL && + (r = sshkey_shield_private(key)) != 0) { + do_log2_r(r, ll, "Unable to shield host key \"%s\"", + options.host_key_files[i]); sshkey_free(key); key = NULL; } if ((r = sshkey_load_public(options.host_key_files[i], &pubkey, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) - do_log2(ll, "Unable to load host key \"%s\": %s", - options.host_key_files[i], ssh_err(r)); - if (pubkey == NULL && key != NULL) + do_log2_r(r, ll, "Unable to load host key \"%s\"", + options.host_key_files[i]); + if (pubkey != NULL && key != NULL) { + if (!sshkey_equal(pubkey, key)) { + error("Public key for %s does not match " + "private key", options.host_key_files[i]); + sshkey_free(pubkey); + pubkey = NULL; + } + } + 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)); + fatal_r(r, "Could not demote key: \"%s\"", + options.host_key_files[i]); + } sensitive_data.host_keys[i] = key; sensitive_data.host_pubkeys[i] = pubkey; @@ -2184,6 +2286,8 @@ main(int ac, char **av) case KEY_DSA: case KEY_ECDSA: case KEY_ED25519: + case KEY_ECDSA_SK: + case KEY_ED25519_SK: case KEY_XMSS: if (have_agent || key != NULL) sensitive_data.have_ssh2_key = 1; @@ -2216,8 +2320,8 @@ main(int ac, char **av) 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)); + error_r(r, "Could not load host certificate \"%s\"", + options.host_cert_files[i]); continue; } if (!sshkey_is_cert(key)) { @@ -2272,7 +2376,7 @@ done_loading_hostkeys: if (connection_info == NULL) connection_info = get_connection_info(ssh, 0, 0); connection_info->test = 1; - parse_server_match_config(&options, connection_info); + parse_server_match_config(&options, &includes, connection_info); dump_config(&options); } @@ -2301,6 +2405,7 @@ done_loading_hostkeys: rexec_argv[rexec_argc] = "-R"; rexec_argv[rexec_argc + 1] = NULL; } + listener_proctitle = prepare_proctitle(ac, av); /* Ensure that umask disallows at least group and world write */ new_umask = umask(0077) | 0022; @@ -2309,7 +2414,10 @@ done_loading_hostkeys: /* 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); + log_init(__progname, options.log_level, + options.log_facility, log_stderr); + for (i = 0; i < options.num_log_verbose; i++) + log_verbose_add(options.log_verbose[i]); /* * If not in debugging mode, not started from inetd and not already @@ -2333,7 +2441,7 @@ done_loading_hostkeys: error("chdir(\"/\"): %s", strerror(errno)); /* ignore SIGPIPE */ - signal(SIGPIPE, SIG_IGN); + ssh_signal(SIGPIPE, SIG_IGN); /* Get a connection, either from inetd or a listening TCP socket */ if (inetd_flag) { @@ -2347,10 +2455,10 @@ done_loading_hostkeys: platform_pre_listen(); server_listen(); - signal(SIGHUP, sighup_handler); - signal(SIGCHLD, main_sigchld_handler); - signal(SIGTERM, sigterm_handler); - signal(SIGQUIT, sigterm_handler); + ssh_signal(SIGHUP, sighup_handler); + ssh_signal(SIGCHLD, main_sigchld_handler); + ssh_signal(SIGTERM, sigterm_handler); + ssh_signal(SIGQUIT, sigterm_handler); /* * Write out the pid file after the sigterm handler @@ -2393,8 +2501,6 @@ done_loading_hostkeys: #ifndef FORK_NOT_SUPPORTED 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); @@ -2410,6 +2516,7 @@ done_loading_hostkeys: dup2(config_s[1], REEXEC_CONFIG_PASS_FD); close(config_s[1]); + ssh_signal(SIGHUP, SIG_IGN); /* avoid reset to SIG_DFL */ execv(rexec_argv[0], rexec_argv); /* Reexec has failed, fall back and continue */ @@ -2421,12 +2528,8 @@ done_loading_hostkeys: /* 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); - } + if (stdfd_devnull(1, 1, 0) == -1) + error_f("stdfd_devnull failed"); debug("rexec cleanup in %d out %d newsock %d pipe %d sock %d", sock_in, sock_out, newsock, startup_pipe, config_s[0]); } @@ -2435,18 +2538,13 @@ done_loading_hostkeys: 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); + /* We will not restart on SIGHUP since it no longer makes sense. */ + ssh_signal(SIGALRM, SIG_DFL); + ssh_signal(SIGHUP, SIG_DFL); + ssh_signal(SIGTERM, SIG_DFL); + ssh_signal(SIGQUIT, SIG_DFL); + ssh_signal(SIGCHLD, SIG_DFL); + ssh_signal(SIGINT, SIG_DFL); /* * Register our connection. This turns encryption off because we do @@ -2513,13 +2611,14 @@ done_loading_hostkeys: * mode; it is just annoying to have the server exit just when you * are about to discover the bug. */ - signal(SIGALRM, grace_alarm_handler); + ssh_signal(SIGALRM, grace_alarm_handler); if (!debug_flag) alarm(options.login_grace_time); - if (kex_exchange_identification(ssh, -1, options.version_addendum) != 0) - cleanup_exit(255); /* error already logged */ -idexch_done: + if ((r = kex_exchange_identification(ssh, -1, + options.version_addendum)) != 0) + sshpkt_fatal(ssh, r, "banner exchange"); + ssh_packet_set_nonblocking(ssh); /* allocate authentication context */ @@ -2537,7 +2636,7 @@ idexch_done: /* prepare buffer to collect messages to display to user after login */ if ((loginmsg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); auth_debug_reset(); if (use_privsep) { @@ -2545,7 +2644,7 @@ idexch_done: 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)); + error_r(r, "Unable to get agent socket"); have_agent = 0; } } @@ -2571,7 +2670,7 @@ idexch_done: * authentication. */ alarm(0); - signal(SIGALRM, SIG_DFL); + ssh_signal(SIGALRM, SIG_DFL); authctxt->authenticated = 1; if (startup_pipe != -1) { close(startup_pipe); @@ -2648,24 +2747,25 @@ sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey, 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__); + data, dlen, alg, options.sk_provider, NULL, + ssh->compat) < 0) + fatal_f("privkey sign failed"); } else { if (mm_sshkey_sign(ssh, pubkey, signature, slenp, - data, dlen, alg, ssh->compat) < 0) - fatal("%s: pubkey sign failed", __func__); + data, dlen, alg, options.sk_provider, NULL, + ssh->compat) < 0) + fatal_f("pubkey sign failed"); } } else { if (privkey) { if (sshkey_sign(privkey, signature, slenp, data, dlen, - alg, ssh->compat) < 0) - fatal("%s: privkey sign failed", __func__); + alg, options.sk_provider, NULL, ssh->compat) < 0) + fatal_f("privkey sign failed"); } 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)); + fatal_fr(r, "agent sign failed"); } } } @@ -2680,11 +2780,11 @@ do_ssh2_kex(struct ssh *ssh) struct kex *kex; int r; - myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( + myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(ssh, options.kex_algorithms); - myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal( + myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal(ssh, options.ciphers); - myproposal[PROPOSAL_ENC_ALGS_STOC] = compat_cipher_proposal( + myproposal[PROPOSAL_ENC_ALGS_STOC] = compat_cipher_proposal(ssh, options.ciphers); myproposal[PROPOSAL_MAC_ALGS_CTOS] = myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; @@ -2699,11 +2799,11 @@ do_ssh2_kex(struct ssh *ssh) options.rekey_interval); myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( - list_hostkey_types()); + ssh, list_hostkey_types()); /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) - fatal("kex_setup: %s", ssh_err(r)); + fatal_r(r, "kex_setup"); kex = ssh->kex; #ifdef WITH_OPENSSL kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server; @@ -2718,7 +2818,7 @@ do_ssh2_kex(struct ssh *ssh) # endif #endif kex->kex[KEX_C25519_SHA256] = kex_gen_server; - kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP761X25519_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; @@ -2726,15 +2826,13 @@ do_ssh2_kex(struct ssh *ssh) 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(); + 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_fr(r, "send test"); #endif debug("KEX done"); } @@ -2749,9 +2847,10 @@ cleanup_exit(int i) 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)); + errno != ESRCH) { + error_f("kill(%d): %s", pmonitor->m_pid, + strerror(errno)); + } } } #ifdef SSH_AUDIT_EVENTS diff --git a/sshd_config.5 b/sshd_config.5 index 9486f2a1c..3db9353c9 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -33,13 +33,13 @@ .\" (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.290 2019/09/06 14:45:34 naddy Exp $ -.Dd $Mdocdate: September 6 2019 $ +.\" $OpenBSD: sshd_config.5,v 1.328 2021/02/27 23:42:37 djm Exp $ +.Dd $Mdocdate: February 27 2021 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME .Nm sshd_config -.Nd OpenSSH SSH daemon configuration file +.Nd OpenSSH daemon configuration file .Sh DESCRIPTION .Xr sshd 8 reads configuration data from @@ -113,11 +113,8 @@ 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 , +The allow/deny groups directives are processed in the following order: .Cm DenyGroups , -and finally .Cm AllowGroups . .Pp See PATTERNS in @@ -173,12 +170,9 @@ 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: +The allow/deny users directives are processed in the following order: .Cm DenyUsers , -.Cm AllowUsers , -.Cm DenyGroups , -and finally -.Cm AllowGroups . +.Cm AllowUsers . .Pp See PATTERNS in .Xr ssh_config 5 @@ -253,12 +247,10 @@ 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 +is tried after the usual .Cm AuthorizedKeysFile -files. +files and will not be executed if a matching key is found there. By default, no .Cm AuthorizedKeysCommand is run. @@ -385,8 +377,8 @@ 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 +ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384, +ecdsa-sha2-nistp521,rsa-sha2-512,rsa-sha2-256,ssh-rsa .Ed .Pp Certificates signed using other algorithms will not be accepted for @@ -525,6 +517,9 @@ is set to 15, and .Cm ClientAliveCountMax is left at the default, unresponsive SSH clients will be disconnected after approximately 45 seconds. +Setting a zero +.Cm ClientAliveCountMax +disables connection termination. .It Cm ClientAliveInterval Sets a timeout interval in seconds after which if no data has been received from the client, @@ -552,11 +547,8 @@ 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 , +The allow/deny groups directives are processed in the following order: .Cm DenyGroups , -and finally .Cm AllowGroups . .Pp See PATTERNS in @@ -573,12 +565,9 @@ 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: +The allow/deny users directives are processed in the following order: .Cm DenyUsers , -.Cm AllowUsers , -.Cm DenyGroups , -and finally -.Cm AllowGroups . +.Cm AllowUsers . .Pp See PATTERNS in .Xr ssh_config 5 @@ -669,35 +658,42 @@ 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. +.It Cm HostbasedAcceptedAlgorithms +Specifies the signature algorithms that will be accepted for hostbased +authentication as a list of comma-separated patterns. Alternately if the specified list begins with a .Sq + -character, then the specified key types will be appended to the default set -instead of replacing them. +character, then the specified signature algorithms will be appended to +the default set instead of replacing them. If the specified list begins with a .Sq - -character, then the specified key types (including wildcards) will be removed -from the default set instead of replacing them. +character, then the specified signature algorithms (including wildcards) +will be removed from the default set instead of replacing them. If the specified list begins with a .Sq ^ -character, then the specified key types will be placed at the head of the -default set. +character, then the specified signature algorithms will be placed at +the head of the default set. The default for this option is: .Bd -literal -offset 3n +ssh-ed25519-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, -rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com, +sk-ssh-ed25519-cert-v01@openssh.com, +sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +rsa-sha2-512-cert-v01@openssh.com, +rsa-sha2-256-cert-v01@openssh.com, ssh-rsa-cert-v01@openssh.com, +ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa +sk-ssh-ed25519@openssh.com, +sk-ecdsa-sha2-nistp256@openssh.com, +rsa-sha2-512,rsa-sha2-256,ssh-rsa .Ed .Pp -The list of available key types may also be obtained using -.Qq ssh -Q key . +The list of available signature algorithms may also be obtained using +.Qq ssh -Q HostbasedAcceptedAlgorithms . +This was formerly named HostbasedAcceptedKeyTypes. .It Cm HostbasedAuthentication Specifies whether rhosts or /etc/hosts.equiv authentication together with successful public key client host authentication is allowed @@ -760,36 +756,55 @@ 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 +Specifies the host key signature algorithms that the server offers. The default for this option is: .Bd -literal -offset 3n +ssh-ed25519-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, -rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com, +sk-ssh-ed25519-cert-v01@openssh.com, +sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +rsa-sha2-512-cert-v01@openssh.com, +rsa-sha2-256-cert-v01@openssh.com, ssh-rsa-cert-v01@openssh.com, +ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa +sk-ssh-ed25519@openssh.com, +sk-ecdsa-sha2-nistp256@openssh.com, +rsa-sha2-512,rsa-sha2-256,ssh-rsa .Ed .Pp -The list of available key types may also be obtained using -.Qq ssh -Q key . +The list of available signature algorithms may also be obtained using +.Qq ssh -Q HostKeyAlgorithms . .It Cm IgnoreRhosts -Specifies that +Specifies whether to ignore per-user .Pa .rhosts and .Pa .shosts -files will not be used in +files during .Cm HostbasedAuthentication . -.Pp +The system-wide .Pa /etc/hosts.equiv and .Pa /etc/shosts.equiv -are still used. -The default is -.Cm yes . +are still used regardless of this setting. +.Pp +Accepted values are +.Cm yes +(the default) to ignore all per-user files, +.Cm shosts-only +to allow the use of +.Pa .shosts +but to ignore +.Pa .rhosts +or +.Cm no +to allow both +.Pa .shosts +and +.Pa rhosts . .It Cm IgnoreUserKnownHosts Specifies whether .Xr sshd 8 @@ -800,7 +815,20 @@ during and use only the system-wide known hosts file .Pa /etc/ssh/known_hosts . The default is -.Cm no . +.Dq no . +.It Cm Include +Include the specified configuration file(s). +Multiple pathnames may be specified and each pathname may contain +.Xr glob 7 +wildcards that will be expanded and processed in lexical order. +Files without absolute paths are assumed to be in +.Pa /etc/ssh . +An +.Cm Include +directive may appear inside a +.Cm Match +block +to perform conditional inclusion. .It Cm IPQoS Specifies the IPv4 type-of-service or DSCP class for the connection. Accepted values are @@ -825,6 +853,7 @@ Accepted values are .Cm cs6 , .Cm cs7 , .Cm ef , +.Cm le , .Cm lowdelay , .Cm throughput , .Cm reliability , @@ -920,6 +949,8 @@ ecdh-sha2-nistp256 ecdh-sha2-nistp384 .It ecdh-sha2-nistp521 +.It +sntrup761x25519-sha512@openssh.com .El .Pp The default is: @@ -928,11 +959,11 @@ 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 +diffie-hellman-group14-sha256 .Ed .Pp The list of available key exchange algorithms may also be obtained using -.Qq ssh -Q kex . +.Qq ssh -Q KexAlgorithms . .It Cm ListenAddress Specifies the local addresses .Xr sshd 8 @@ -998,6 +1029,23 @@ 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 LogVerbose +Specify one or more overrides to LogLevel. +An override consists of a pattern lists that matches the source file, function +and line number to force detailed logging for. +For example, an override pattern of: +.Bd -literal -offset indent +kex.c:*:1000,*:kex_exchange_identification():*,packet.c:* +.Ed +.Pp +would enable detailed logging for line 1000 of +.Pa kex.c , +everything in the +.Fn kex_exchange_identification +function, and all code in the +.Pa packet.c +file. +This option is intended for debugging and no overrides are enabled by default. .It Cm MACs Specifies the available MAC (message authentication code) algorithms. The MAC algorithm is used for data integrity protection. @@ -1139,12 +1187,15 @@ Available keywords are .Cm ClientAliveInterval , .Cm DenyGroups , .Cm DenyUsers , +.Cm DisableForwarding , .Cm ForceCommand , .Cm GatewayPorts , .Cm GSSAPIAuthentication , -.Cm HostbasedAcceptedKeyTypes , +.Cm HostbasedAcceptedAlgorithms , .Cm HostbasedAuthentication , .Cm HostbasedUsesNameFromPacketOnly , +.Cm IgnoreRhosts , +.Cm Include , .Cm IPQoS , .Cm KbdInteractiveAuthentication , .Cm KerberosAuthentication , @@ -1159,7 +1210,7 @@ Available keywords are .Cm PermitTTY , .Cm PermitTunnel , .Cm PermitUserRC , -.Cm PubkeyAcceptedKeyTypes , +.Cm PubkeyAcceptedAlgorithms , .Cm PubkeyAuthentication , .Cm RekeyLimit , .Cm RevokedKeys , @@ -1287,7 +1338,9 @@ An argument of 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. +can be used for host or port to allow all hosts or ports respectively. +Otherwise, no pattern matching or address lookups are performed on supplied +names. By default all port forwarding requests are permitted. .It Cm PermitRootLogin Specifies whether root can log in using @@ -1375,6 +1428,23 @@ Specifies whether any file is executed. The default is .Cm yes . +.It Cm PerSourceMaxStartups +Specifies the number of unauthenticated connections allowed from a +given source address, or +.Dq none +if there is no limit. +This limit is applied in addition to +.Cm MaxStartups , +whichever is lower. +The default is +.Cm none . +.It Cm PerSourceNetBlockSize +Specifies the number of bits of source address that are grouped together +for the purposes of applying PerSourceMaxStartups limits. +Values for IPv4 and optionally IPv6 may be specified, separated by a colon. +The default is +.Cm 32:128 , +which means each address is considered individually. .It Cm PidFile Specifies the file that contains the process ID of the SSH daemon, or @@ -1408,42 +1478,83 @@ when a user logs in interactively. 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. +.It Cm PubkeyAcceptedAlgorithms +Specifies the signature algorithms that will be accepted for public key +authentication as a list of comma-separated patterns. Alternately if the specified list begins with a .Sq + -character, then the specified key types will be appended to the default set +character, then the specified algorithms will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - -character, then the specified key types (including wildcards) will be removed +character, then the specified algorithms (including wildcards) will be removed from the default set instead of replacing them. If the specified list begins with a .Sq ^ -character, then the specified key types will be placed at the head of the +character, then the specified algorithms will be placed at the head of the default set. The default for this option is: .Bd -literal -offset 3n +ssh-ed25519-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, -rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com, +sk-ssh-ed25519-cert-v01@openssh.com, +sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +rsa-sha2-512-cert-v01@openssh.com, +rsa-sha2-256-cert-v01@openssh.com, ssh-rsa-cert-v01@openssh.com, +ssh-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa +sk-ssh-ed25519@openssh.com, +sk-ecdsa-sha2-nistp256@openssh.com, +rsa-sha2-512,rsa-sha2-256,ssh-rsa .Ed .Pp -The list of available key types may also be obtained using -.Qq ssh -Q key . +The list of available signature algorithms may also be obtained using +.Qq ssh -Q PubkeyAcceptedAlgorithms . +.It Cm PubkeyAuthOptions +Sets one or more public key authentication options. +The supported keywords are: +.Cm none +(the default; indicating no additional options are enabled), +.Cm touch-required +and +.Cm verify-required . +.Pp +The +.Cm touch-required +option causes public key authentication using a FIDO authenticator algorithm +(i.e.\& +.Cm ecdsa-sk +or +.Cm ed25519-sk ) +to always require the signature to attest that a physically present user +explicitly confirmed the authentication (usually by touching the authenticator). +By default, +.Xr sshd 8 +requires user presence unless overridden with an authorized_keys option. +The +.Cm touch-required +flag disables this override. +.Pp +The +.Cm verify-required +option requires a FIDO key signature attest that the user was verified, +e.g. via a PIN. +.Pp +Neither the +.Cm touch-required +or +.Cm verify-required +options have any effect for other, non-FIDO, public key types. .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 +session key is renegotiated, optionally followed by 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 , @@ -1487,6 +1598,10 @@ will be bound to this If the routing domain is set to .Cm \&%D , then the domain in which the incoming connection was received will be applied. +.It Cm SecurityKeyProvider +Specifies a path to a library that will be used when loading +FIDO authenticator-hosted keys, overriding the default of using +the built-in USB HID support. .It Cm SetEnv Specifies one or more environment variables to set in child sessions started by diff --git a/ssherr.c b/ssherr.c index 8ad3d5750..bd954aadd 100644 --- a/ssherr.c +++ b/ssherr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssherr.c,v 1.8 2018/07/03 11:39:54 djm Exp $ */ +/* $OpenBSD: ssherr.c,v 1.10 2020/01/25 23:13:09 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -141,6 +141,10 @@ ssh_err(int n) return "number is too large"; case SSH_ERR_SIGN_ALG_UNSUPPORTED: return "signature algorithm not supported"; + case SSH_ERR_FEATURE_UNSUPPORTED: + return "requested feature not supported"; + case SSH_ERR_DEVICE_NOT_FOUND: + return "device not found"; default: return "unknown error"; } diff --git a/ssherr.h b/ssherr.h index 348da5a20..085e75274 100644 --- a/ssherr.h +++ b/ssherr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssherr.h,v 1.6 2018/07/03 11:39:54 djm Exp $ */ +/* $OpenBSD: ssherr.h,v 1.8 2020/01/25 23:13:09 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -80,6 +80,8 @@ #define SSH_ERR_KEY_LENGTH -56 #define SSH_ERR_NUMBER_TOO_LARGE -57 #define SSH_ERR_SIGN_ALG_UNSUPPORTED -58 +#define SSH_ERR_FEATURE_UNSUPPORTED -59 +#define SSH_ERR_DEVICE_NOT_FOUND -60 /* Translate a numeric error code to a human-readable error string */ const char *ssh_err(int n); diff --git a/sshkey-xmss.c b/sshkey-xmss.c index 9e5f5e475..c81c68963 100644 --- a/sshkey-xmss.c +++ b/sshkey-xmss.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey-xmss.c,v 1.6 2019/10/09 00:02:57 djm Exp $ */ +/* $OpenBSD: sshkey-xmss.c,v 1.9 2020/10/19 22:49:23 dtucker Exp $ */ /* * Copyright (c) 2017 Markus Friedl. All rights reserved. * @@ -45,6 +45,7 @@ #include "sshkey.h" #include "sshkey-xmss.h" #include "atomicio.h" +#include "log.h" #include "xmss_fast.h" @@ -69,7 +70,7 @@ struct ssh_xmss_state { u_int32_t maxidx; /* restricted # of signatures */ int have_state; /* .state file exists */ int lockfd; /* locked in sshkey_xmss_get_state() */ - int allow_update; /* allow sshkey_xmss_update_state() */ + u_char allow_update; /* allow sshkey_xmss_update_state() */ char *enc_ciphername;/* encrypt state with cipher */ u_char *enc_keyiv; /* encrypt state with key */ u_int32_t enc_keyiv_len; /* length of enc_keyiv */ @@ -79,7 +80,7 @@ int sshkey_xmss_init_bds_state(struct sshkey *); int sshkey_xmss_init_enc_key(struct sshkey *, const char *); void sshkey_xmss_free_bds(struct sshkey *); int sshkey_xmss_get_state_from_file(struct sshkey *, const char *, - int *, sshkey_printfn *); + int *, int); int sshkey_xmss_encrypt_state(const struct sshkey *, struct sshbuf *, struct sshbuf **); int sshkey_xmss_decrypt_state(const struct sshkey *, struct sshbuf *, @@ -87,7 +88,8 @@ int sshkey_xmss_decrypt_state(const struct sshkey *, struct sshbuf *, int sshkey_xmss_serialize_enc_key(const struct sshkey *, struct sshbuf *); int sshkey_xmss_deserialize_enc_key(struct sshkey *, struct sshbuf *); -#define PRINT(s...) do { if (pr) pr(s); } while (0) +#define PRINT(...) do { if (printerror) sshlog(__FILE__, __func__, __LINE__, \ + 0, SYSLOG_LEVEL_ERROR, __VA_ARGS__); } while (0) int sshkey_xmss_init(struct sshkey *key, const char *name) @@ -392,7 +394,7 @@ sshkey_xmss_generate_private_key(struct sshkey *k, u_int bits) int sshkey_xmss_get_state_from_file(struct sshkey *k, const char *filename, - int *have_file, sshkey_printfn *pr) + int *have_file, int printerror) { struct sshbuf *b = NULL, *enc = NULL; int ret = SSH_ERR_SYSTEM_ERROR, r, fd = -1; @@ -440,7 +442,7 @@ done: } int -sshkey_xmss_get_state(const struct sshkey *k, sshkey_printfn *pr) +sshkey_xmss_get_state(const struct sshkey *k, int printerror) { struct ssh_xmss_state *state = k->xmss_state; u_int32_t idx = 0; @@ -493,9 +495,9 @@ sshkey_xmss_get_state(const struct sshkey *k, sshkey_printfn *pr) } /* XXX no longer const */ if ((r = sshkey_xmss_get_state_from_file((struct sshkey *)k, - statefile, &have_state, pr)) != 0) { + statefile, &have_state, printerror)) != 0) { if ((r = sshkey_xmss_get_state_from_file((struct sshkey *)k, - ostatefile, &have_ostate, pr)) == 0) { + ostatefile, &have_ostate, printerror)) == 0) { state->allow_update = 1; r = sshkey_xmss_forward_state(k, 1); state->idx = PEEK_U32(k->xmss_sk); @@ -563,7 +565,7 @@ sshkey_xmss_forward_state(const struct sshkey *k, u_int32_t reserve) } int -sshkey_xmss_update_state(const struct sshkey *k, sshkey_printfn *pr) +sshkey_xmss_update_state(const struct sshkey *k, int printerror) { struct ssh_xmss_state *state = k->xmss_state; struct sshbuf *b = NULL, *enc = NULL; @@ -716,6 +718,7 @@ sshkey_xmss_serialize_state_opt(const struct sshkey *k, struct sshbuf *b, { struct ssh_xmss_state *state = k->xmss_state; int r = SSH_ERR_INVALID_ARGUMENT; + u_char have_stack, have_filename, have_enc; if (state == NULL) return SSH_ERR_INVALID_ARGUMENT; @@ -727,9 +730,35 @@ sshkey_xmss_serialize_state_opt(const struct sshkey *k, struct sshbuf *b, break; case SSHKEY_SERIALIZE_FULL: if ((r = sshkey_xmss_serialize_enc_key(k, b)) != 0) - break; + return r; r = sshkey_xmss_serialize_state(k, b); break; + case SSHKEY_SERIALIZE_SHIELD: + /* all of stack/filename/enc are optional */ + have_stack = state->stack != NULL; + if ((r = sshbuf_put_u8(b, have_stack)) != 0) + return r; + if (have_stack) { + state->idx = PEEK_U32(k->xmss_sk); /* update */ + if ((r = sshkey_xmss_serialize_state(k, b)) != 0) + return r; + } + have_filename = k->xmss_filename != NULL; + if ((r = sshbuf_put_u8(b, have_filename)) != 0) + return r; + if (have_filename && + (r = sshbuf_put_cstring(b, k->xmss_filename)) != 0) + return r; + have_enc = state->enc_keyiv != NULL; + if ((r = sshbuf_put_u8(b, have_enc)) != 0) + return r; + if (have_enc && + (r = sshkey_xmss_serialize_enc_key(k, b)) != 0) + return r; + if ((r = sshbuf_put_u32(b, state->maxidx)) != 0 || + (r = sshbuf_put_u8(b, state->allow_update)) != 0) + return r; + break; case SSHKEY_SERIALIZE_DEFAULT: r = 0; break; @@ -748,7 +777,7 @@ sshkey_xmss_deserialize_state(struct sshkey *k, struct sshbuf *b) u_int32_t i, lh, node; size_t ls, lsl, la, lk, ln, lr; char *magic; - int r; + int r = SSH_ERR_INTERNAL_ERROR; if (state == NULL) return SSH_ERR_INVALID_ARGUMENT; @@ -767,9 +796,11 @@ sshkey_xmss_deserialize_state(struct sshkey *k, struct sshbuf *b) (r = sshbuf_get_string(b, &state->th_nodes, &ln)) != 0 || (r = sshbuf_get_string(b, &state->retain, &lr)) != 0 || (r = sshbuf_get_u32(b, &lh)) != 0) - return r; - if (strcmp(magic, SSH_XMSS_K2_MAGIC) != 0) - return SSH_ERR_INVALID_ARGUMENT; + goto out; + if (strcmp(magic, SSH_XMSS_K2_MAGIC) != 0) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } /* XXX check stackoffset */ if (ls != num_stack(state) || lsl != num_stacklevels(state) || @@ -777,8 +808,10 @@ sshkey_xmss_deserialize_state(struct sshkey *k, struct sshbuf *b) lk != num_keep(state) || ln != num_th_nodes(state) || lr != num_retain(state) || - lh != num_treehash(state)) - return SSH_ERR_INVALID_ARGUMENT; + lh != num_treehash(state)) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } for (i = 0; i < num_treehash(state); i++) { th = &state->treehash[i]; if ((r = sshbuf_get_u32(b, &th->h)) != 0 || @@ -786,7 +819,7 @@ sshkey_xmss_deserialize_state(struct sshkey *k, struct sshbuf *b) (r = sshbuf_get_u32(b, &th->stackusage)) != 0 || (r = sshbuf_get_u8(b, &th->completed)) != 0 || (r = sshbuf_get_u32(b, &node)) != 0) - return r; + goto out; if (node < num_th_nodes(state)) th->node = &state->th_nodes[node]; } @@ -794,14 +827,19 @@ sshkey_xmss_deserialize_state(struct sshkey *k, struct sshbuf *b) xmss_set_bds_state(&state->bds, state->stack, state->stackoffset, state->stacklevels, state->auth, state->keep, state->treehash, state->retain, 0); - return 0; + /* success */ + r = 0; + out: + free(magic); + return r; } int sshkey_xmss_deserialize_state_opt(struct sshkey *k, struct sshbuf *b) { + struct ssh_xmss_state *state = k->xmss_state; enum sshkey_serialize_rep opts; - u_char have_state; + u_char have_state, have_stack, have_filename, have_enc; int r; if ((r = sshbuf_get_u8(b, &have_state)) != 0) @@ -812,6 +850,26 @@ sshkey_xmss_deserialize_state_opt(struct sshkey *k, struct sshbuf *b) case SSHKEY_SERIALIZE_DEFAULT: r = 0; break; + case SSHKEY_SERIALIZE_SHIELD: + if ((r = sshbuf_get_u8(b, &have_stack)) != 0) + return r; + if (have_stack && + (r = sshkey_xmss_deserialize_state(k, b)) != 0) + return r; + if ((r = sshbuf_get_u8(b, &have_filename)) != 0) + return r; + if (have_filename && + (r = sshbuf_get_cstring(b, &k->xmss_filename, NULL)) != 0) + return r; + if ((r = sshbuf_get_u8(b, &have_enc)) != 0) + return r; + if (have_enc && + (r = sshkey_xmss_deserialize_enc_key(k, b)) != 0) + return r; + if ((r = sshbuf_get_u32(b, &state->maxidx)) != 0 || + (r = sshbuf_get_u8(b, &state->allow_update)) != 0) + return r; + break; case SSHKEY_SERIALIZE_STATE: if ((r = sshkey_xmss_deserialize_state(k, b)) != 0) return r; diff --git a/sshkey-xmss.h b/sshkey-xmss.h index b9f8ead10..bf52d293c 100644 --- a/sshkey-xmss.h +++ b/sshkey-xmss.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey-xmss.h,v 1.1 2018/02/23 15:58:38 markus Exp $ */ +/* $OpenBSD: sshkey-xmss.h,v 1.2 2020/10/19 22:49:23 dtucker Exp $ */ /* * Copyright (c) 2017 Markus Friedl. All rights reserved. * @@ -47,10 +47,10 @@ int sshkey_xmss_deserialize_pk_info(struct sshkey *, struct sshbuf *); int sshkey_xmss_siglen(const struct sshkey *, size_t *); void *sshkey_xmss_params(const struct sshkey *); void *sshkey_xmss_bds_state(const struct sshkey *); -int sshkey_xmss_get_state(const struct sshkey *, sshkey_printfn *); +int sshkey_xmss_get_state(const struct sshkey *, int); int sshkey_xmss_enable_maxsign(struct sshkey *, u_int32_t); int sshkey_xmss_forward_state(const struct sshkey *, u_int32_t); -int sshkey_xmss_update_state(const struct sshkey *, sshkey_printfn *); +int sshkey_xmss_update_state(const struct sshkey *, int); u_int32_t sshkey_xmss_signatures_left(const struct sshkey *); #endif /* SSHKEY_XMSS_H */ diff --git a/sshkey.c b/sshkey.c index 4b29bfcf9..71463edbb 100644 --- a/sshkey.c +++ b/sshkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.c,v 1.84 2019/10/09 00:04:42 djm Exp $ */ +/* $OpenBSD: sshkey.c,v 1.115 2021/02/02 22:36:46 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. @@ -57,6 +57,7 @@ #define SSHKEY_INTERNAL #include "sshkey.h" #include "match.h" +#include "ssh-sk.h" #ifdef WITH_XMSS #include "sshkey-xmss.h" @@ -115,6 +116,10 @@ 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 }, + { "sk-ssh-ed25519@openssh.com", "ED25519-SK", NULL, + KEY_ED25519_SK, 0, 0, 0 }, + { "sk-ssh-ed25519-cert-v01@openssh.com", "ED25519-SK-CERT", NULL, + KEY_ED25519_SK_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, @@ -134,6 +139,10 @@ static const struct keytype keytypes[] = { { "ecdsa-sha2-nistp521", "ECDSA", NULL, KEY_ECDSA, NID_secp521r1, 0, 0 }, # endif /* OPENSSL_HAS_NISTP521 */ + { "sk-ecdsa-sha2-nistp256@openssh.com", "ECDSA-SK", NULL, + KEY_ECDSA_SK, NID_X9_62_prime256v1, 0, 0 }, + { "webauthn-sk-ecdsa-sha2-nistp256@openssh.com", "ECDSA-SK", NULL, + KEY_ECDSA_SK, NID_X9_62_prime256v1, 0, 1 }, # endif /* OPENSSL_HAS_ECC */ { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL, KEY_RSA_CERT, 0, 1, 0 }, @@ -152,6 +161,8 @@ static const struct keytype keytypes[] = { { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL, KEY_ECDSA_CERT, NID_secp521r1, 1, 0 }, # endif /* OPENSSL_HAS_NISTP521 */ + { "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-SK-CERT", NULL, + KEY_ECDSA_SK_CERT, NID_X9_62_prime256v1, 1, 0 }, # endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ { NULL, NULL, NULL, -1, -1, 0, 0 } @@ -220,13 +231,26 @@ sshkey_type_from_name(const char *name) return KEY_UNSPEC; } +static int +key_type_is_ecdsa_variant(int type) +{ + switch (type) { + case KEY_ECDSA: + case KEY_ECDSA_CERT: + case KEY_ECDSA_SK: + case KEY_ECDSA_SK_CERT: + return 1; + } + return 0; +} + 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) + if (!key_type_is_ecdsa_variant(kt->type)) continue; if (kt->name != NULL && strcmp(name, kt->name) == 0) return kt->nid; @@ -322,10 +346,14 @@ sshkey_size(const struct sshkey *k) return BN_num_bits(dsa_p); case KEY_ECDSA: case KEY_ECDSA_CERT: + case KEY_ECDSA_SK: + case KEY_ECDSA_SK_CERT: return sshkey_curve_nid_to_bits(k->ecdsa_nid); #endif /* WITH_OPENSSL */ case KEY_ED25519: case KEY_ED25519_CERT: + case KEY_ED25519_SK: + case KEY_ED25519_SK_CERT: case KEY_XMSS: case KEY_XMSS_CERT: return 256; /* XXX */ @@ -340,7 +368,9 @@ sshkey_type_is_valid_ca(int type) case KEY_RSA: case KEY_DSA: case KEY_ECDSA: + case KEY_ECDSA_SK: case KEY_ED25519: + case KEY_ED25519_SK: case KEY_XMSS: return 1; default: @@ -356,6 +386,20 @@ sshkey_is_cert(const struct sshkey *k) return sshkey_type_is_cert(k->type); } +int +sshkey_is_sk(const struct sshkey *k) +{ + if (k == NULL) + return 0; + switch (sshkey_type_plain(k->type)) { + case KEY_ECDSA_SK: + case KEY_ED25519_SK: + return 1; + default: + return 0; + } +} + /* Return the cert-less equivalent to a certified key type */ int sshkey_type_plain(int type) @@ -367,8 +411,12 @@ sshkey_type_plain(int type) return KEY_DSA; case KEY_ECDSA_CERT: return KEY_ECDSA; + case KEY_ECDSA_SK_CERT: + return KEY_ECDSA_SK; case KEY_ED25519_CERT: return KEY_ED25519; + case KEY_ED25519_SK_CERT: + return KEY_ED25519_SK; case KEY_XMSS_CERT: return KEY_XMSS; default: @@ -542,11 +590,15 @@ sshkey_new(int type) break; case KEY_ECDSA: case KEY_ECDSA_CERT: + case KEY_ECDSA_SK: + case KEY_ECDSA_SK_CERT: /* Cannot do anything until we know the group */ break; #endif /* WITH_OPENSSL */ case KEY_ED25519: case KEY_ED25519_CERT: + case KEY_ED25519_SK: + case KEY_ED25519_SK_CERT: case KEY_XMSS: case KEY_XMSS_CERT: /* no need to prealloc */ @@ -586,6 +638,12 @@ sshkey_free(struct sshkey *k) k->dsa = NULL; break; # ifdef OPENSSL_HAS_ECC + case KEY_ECDSA_SK: + case KEY_ECDSA_SK_CERT: + free(k->sk_application); + sshbuf_free(k->sk_key_handle); + sshbuf_free(k->sk_reserved); + /* FALLTHROUGH */ case KEY_ECDSA: case KEY_ECDSA_CERT: EC_KEY_free(k->ecdsa); @@ -593,6 +651,12 @@ sshkey_free(struct sshkey *k) break; # endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ + case KEY_ED25519_SK: + case KEY_ED25519_SK_CERT: + free(k->sk_application); + sshbuf_free(k->sk_key_handle); + sshbuf_free(k->sk_reserved); + /* FALLTHROUGH */ case KEY_ED25519: case KEY_ED25519_CERT: freezero(k->ed25519_pk, ED25519_PK_SZ); @@ -653,9 +717,6 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) 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 || @@ -685,26 +746,35 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) 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_SK: + case KEY_ECDSA_SK_CERT: + if (a->sk_application == NULL || b->sk_application == NULL) + return 0; + if (strcmp(a->sk_application, b->sk_application) != 0) + return 0; + /* FALLTHROUGH */ 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_KEY_get0_group(b->ecdsa), NULL) != 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); + EC_KEY_get0_public_key(b->ecdsa), NULL) != 0) return 0; - } - BN_CTX_free(bnctx); return 1; # endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ + case KEY_ED25519_SK: + case KEY_ED25519_SK_CERT: + if (a->sk_application == NULL || b->sk_application == NULL) + return 0; + if (strcmp(a->sk_application, b->sk_application) != 0) + return 0; + /* FALLTHROUGH */ case KEY_ED25519: case KEY_ED25519_CERT: return a->ed25519_pk != NULL && b->ed25519_pk != NULL && @@ -760,9 +830,11 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, #ifdef WITH_OPENSSL case KEY_DSA_CERT: case KEY_ECDSA_CERT: + case KEY_ECDSA_SK_CERT: case KEY_RSA_CERT: #endif /* WITH_OPENSSL */ case KEY_ED25519_CERT: + case KEY_ED25519_SK_CERT: #ifdef WITH_XMSS case KEY_XMSS_CERT: #endif /* WITH_XMSS */ @@ -786,6 +858,7 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, break; # ifdef OPENSSL_HAS_ECC case KEY_ECDSA: + case KEY_ECDSA_SK: if (key->ecdsa == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((ret = sshbuf_put_cstring(b, typename)) != 0 || @@ -793,6 +866,11 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 || (ret = sshbuf_put_eckey(b, key->ecdsa)) != 0) return ret; + if (type == KEY_ECDSA_SK) { + if ((ret = sshbuf_put_cstring(b, + key->sk_application)) != 0) + return ret; + } break; # endif case KEY_RSA: @@ -806,12 +884,18 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, break; #endif /* WITH_OPENSSL */ case KEY_ED25519: + case KEY_ED25519_SK: 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; + if (type == KEY_ED25519_SK) { + if ((ret = sshbuf_put_cstring(b, + key->sk_application)) != 0) + return ret; + } break; #ifdef WITH_XMSS case KEY_XMSS: @@ -946,10 +1030,8 @@ sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg, r = 0; out: free(ret); - if (blob != NULL) { - explicit_bzero(blob, blob_len); - free(blob); - } + if (blob != NULL) + freezero(blob, blob_len); return r; } @@ -1207,12 +1289,10 @@ sshkey_fingerprint(const struct sshkey *k, int dgst_alg, dgst_raw, dgst_raw_len, k); break; default: - explicit_bzero(dgst_raw, dgst_raw_len); - free(dgst_raw); + freezero(dgst_raw, dgst_raw_len); return NULL; } - explicit_bzero(dgst_raw, dgst_raw_len); - free(dgst_raw); + freezero(dgst_raw, dgst_raw_len); return retval; } @@ -1226,7 +1306,7 @@ peek_type_nid(const char *s, size_t l, int *nid) continue; if (memcmp(s, kt->name, l) == 0) { *nid = -1; - if (kt->type == KEY_ECDSA || kt->type == KEY_ECDSA_CERT) + if (key_type_is_ecdsa_variant(kt->type)) *nid = kt->nid; return kt->type; } @@ -1252,11 +1332,15 @@ sshkey_read(struct sshkey *ret, char **cpp) case KEY_RSA: case KEY_DSA: case KEY_ECDSA: + case KEY_ECDSA_SK: case KEY_ED25519: + case KEY_ED25519_SK: case KEY_DSA_CERT: case KEY_ECDSA_CERT: + case KEY_ECDSA_SK_CERT: case KEY_RSA_CERT: case KEY_ED25519_CERT: + case KEY_ED25519_SK_CERT: #ifdef WITH_XMSS case KEY_XMSS: case KEY_XMSS_CERT: @@ -1311,7 +1395,7 @@ sshkey_read(struct sshkey *ret, char **cpp) sshkey_free(k); return SSH_ERR_KEY_TYPE_MISMATCH; } - if (sshkey_type_plain(type) == KEY_ECDSA && curve_nid != k->ecdsa_nid) { + if (key_type_is_ecdsa_variant(type) && curve_nid != k->ecdsa_nid) { sshkey_free(k); return SSH_ERR_EC_CURVE_MISMATCH; } @@ -1355,6 +1439,19 @@ sshkey_read(struct sshkey *ret, char **cpp) k->ecdsa_nid = -1; #ifdef DEBUG_PK sshkey_dump_ec_key(ret->ecdsa); +#endif + break; + case KEY_ECDSA_SK: + EC_KEY_free(ret->ecdsa); + ret->ecdsa = k->ecdsa; + ret->ecdsa_nid = k->ecdsa_nid; + ret->sk_application = k->sk_application; + k->ecdsa = NULL; + k->ecdsa_nid = -1; + k->sk_application = NULL; +#ifdef DEBUG_PK + sshkey_dump_ec_key(ret->ecdsa); + fprintf(stderr, "App: %s\n", ret->sk_application); #endif break; # endif /* OPENSSL_HAS_ECC */ @@ -1367,6 +1464,13 @@ sshkey_read(struct sshkey *ret, char **cpp) /* XXX */ #endif break; + case KEY_ED25519_SK: + freezero(ret->ed25519_pk, ED25519_PK_SZ); + ret->ed25519_pk = k->ed25519_pk; + ret->sk_application = k->sk_application; + k->ed25519_pk = NULL; + k->sk_application = NULL; + break; #ifdef WITH_XMSS case KEY_XMSS: free(ret->xmss_pk); @@ -1555,7 +1659,6 @@ sshkey_ecdsa_key_to_nid(EC_KEY *k) }; int nid; u_int i; - BN_CTX *bnctx; const EC_GROUP *g = EC_KEY_get0_group(k); /* @@ -1568,18 +1671,13 @@ sshkey_ecdsa_key_to_nid(EC_KEY *k) */ 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); + if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) return -1; - } - if (EC_GROUP_cmp(g, eg, bnctx) == 0) + if (EC_GROUP_cmp(g, eg, NULL) == 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); @@ -1756,15 +1854,14 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) #endif /* WITH_OPENSSL */ *pkp = NULL; + if ((n = sshkey_new(k->type)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } 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 || @@ -1789,10 +1886,8 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) # 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; - } + case KEY_ECDSA_SK: + case KEY_ECDSA_SK_CERT: n->ecdsa_nid = k->ecdsa_nid; n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); if (n->ecdsa == NULL) { @@ -1804,14 +1899,15 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } + if (k->type != KEY_ECDSA_SK && k->type != KEY_ECDSA_SK_CERT) + break; + /* Append security-key application string */ + if ((n->sk_application = strdup(k->sk_application)) == NULL) + 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) { @@ -1827,10 +1923,8 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) #endif /* WITH_OPENSSL */ case KEY_ED25519: case KEY_ED25519_CERT: - if ((n = sshkey_new(k->type)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } + case KEY_ED25519_SK: + case KEY_ED25519_SK_CERT: if (k->ed25519_pk != NULL) { if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) { r = SSH_ERR_ALLOC_FAIL; @@ -1838,17 +1932,20 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) } memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ); } + if (k->type != KEY_ED25519_SK && + k->type != KEY_ED25519_SK_CERT) + break; + /* Append security-key application string */ + if ((n->sk_application = strdup(k->sk_application)) == NULL) + goto out; 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) { + u_int32_t left; size_t pklen = sshkey_xmss_pklen(k); if (pklen == 0 || sshkey_xmss_pklen(n) != pklen) { r = SSH_ERR_INTERNAL_ERROR; @@ -1859,6 +1956,10 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) goto out; } memcpy(n->xmss_pk, k->xmss_pk, pklen); + /* simulate number of signatures left on pubkey */ + left = sshkey_xmss_signatures_left(k); + if (left) + sshkey_xmss_enable_maxsign(n, left); } break; #endif /* WITH_XMSS */ @@ -1943,7 +2044,7 @@ sshkey_shield_private(struct sshkey *k) if (sshkey_is_shielded(k) && (r = sshkey_unshield_private(k)) != 0) goto out; if ((r = sshkey_private_serialize_opt(k, prvbuf, - SSHKEY_SERIALIZE_FULL)) != 0) + SSHKEY_SERIALIZE_SHIELD)) != 0) goto out; /* pad to cipher blocksize */ i = 0; @@ -1986,6 +2087,9 @@ sshkey_shield_private(struct sshkey *k) enc = prekey = NULL; /* transferred */ enclen = 0; + /* preserve key fields that are required for correct operation */ + k->sk_flags = kswap->sk_flags; + /* success */ r = 0; @@ -2207,7 +2311,7 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) goto out; } if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, - sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0)) != 0) + sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0, NULL)) != 0) goto out; if ((ret = sshkey_get_sigtype(sig, slen, &key->cert->signature_type)) != 0) @@ -2337,15 +2441,17 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, DSA_print_fp(stderr, key->dsa, 8); #endif break; +# ifdef OPENSSL_HAS_ECC case KEY_ECDSA_CERT: + case KEY_ECDSA_SK_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: + case KEY_ECDSA_SK: if ((key = sshkey_new(type)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; @@ -2386,10 +2492,22 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, #ifdef DEBUG_PK sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q); #endif + if (type == KEY_ECDSA_SK || type == KEY_ECDSA_SK_CERT) { + /* Parse additional security-key application string */ + if (sshbuf_get_cstring(b, &key->sk_application, + NULL) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } +#ifdef DEBUG_PK + fprintf(stderr, "App: %s\n", key->sk_application); +#endif + } break; # endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ case KEY_ED25519_CERT: + case KEY_ED25519_SK_CERT: /* Skip nonce */ if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { ret = SSH_ERR_INVALID_FORMAT; @@ -2397,6 +2515,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, } /* FALLTHROUGH */ case KEY_ED25519: + case KEY_ED25519_SK: if ((ret = sshbuf_get_string(b, &pk, &len)) != 0) goto out; if (len != ED25519_PK_SZ) { @@ -2407,6 +2526,17 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, ret = SSH_ERR_ALLOC_FAIL; goto out; } + if (type == KEY_ED25519_SK || type == KEY_ED25519_SK_CERT) { + /* Parse additional security-key application string */ + if (sshbuf_get_cstring(b, &key->sk_application, + NULL) != 0) { + ret = SSH_ERR_INVALID_FORMAT; + goto out; + } +#ifdef DEBUG_PK + fprintf(stderr, "App: %s\n", key->sk_application); +#endif + } key->ed25519_pk = pk; pk = NULL; break; @@ -2605,7 +2735,8 @@ sshkey_check_sigtype(const u_char *sig, size_t siglen, int sshkey_sign(struct sshkey *key, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, const char *alg, u_int compat) + const u_char *data, size_t datalen, + const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) { int was_shielded = sshkey_is_shielded(key); int r2, r = SSH_ERR_INTERNAL_ERROR; @@ -2639,6 +2770,13 @@ sshkey_sign(struct sshkey *key, case KEY_ED25519_CERT: r = ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat); break; + case KEY_ED25519_SK: + case KEY_ED25519_SK_CERT: + case KEY_ECDSA_SK_CERT: + case KEY_ECDSA_SK: + r = sshsk_sign(sk_provider, key, sigp, lenp, data, + datalen, compat, sk_pin); + break; #ifdef WITH_XMSS case KEY_XMSS: case KEY_XMSS_CERT: @@ -2661,8 +2799,11 @@ sshkey_sign(struct sshkey *key, 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) + const u_char *data, size_t dlen, const char *alg, u_int compat, + struct sshkey_sig_details **detailsp) { + if (detailsp != NULL) + *detailsp = NULL; if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; switch (key->type) { @@ -2674,6 +2815,10 @@ sshkey_verify(const struct sshkey *key, case KEY_ECDSA_CERT: case KEY_ECDSA: return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat); + case KEY_ECDSA_SK_CERT: + case KEY_ECDSA_SK: + return ssh_ecdsa_sk_verify(key, sig, siglen, data, dlen, + compat, detailsp); # endif /* OPENSSL_HAS_ECC */ case KEY_RSA_CERT: case KEY_RSA: @@ -2682,6 +2827,10 @@ sshkey_verify(const struct sshkey *key, case KEY_ED25519: case KEY_ED25519_CERT: return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat); + case KEY_ED25519_SK: + case KEY_ED25519_SK_CERT: + return ssh_ed25519_sk_verify(key, sig, siglen, data, dlen, + compat, detailsp); #ifdef WITH_XMSS case KEY_XMSS: case KEY_XMSS_CERT: @@ -2709,7 +2858,13 @@ sshkey_to_certified(struct sshkey *k) case KEY_ECDSA: newtype = KEY_ECDSA_CERT; break; + case KEY_ECDSA_SK: + newtype = KEY_ECDSA_SK_CERT; + break; #endif /* WITH_OPENSSL */ + case KEY_ED25519_SK: + newtype = KEY_ED25519_SK_CERT; + break; case KEY_ED25519: newtype = KEY_ED25519_CERT; break; @@ -2742,6 +2897,7 @@ sshkey_drop_cert(struct sshkey *k) /* Sign a certified key, (re-)generating the signed certblob. */ int sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, + const char *sk_provider, const char *sk_pin, sshkey_certify_signer *signer, void *signer_ctx) { struct sshbuf *principals = NULL; @@ -2806,12 +2962,18 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, break; # ifdef OPENSSL_HAS_ECC case KEY_ECDSA_CERT: + case KEY_ECDSA_SK_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; + if (k->type == KEY_ECDSA_SK_CERT) { + if ((ret = sshbuf_put_cstring(cert, + k->sk_application)) != 0) + goto out; + } break; # endif /* OPENSSL_HAS_ECC */ case KEY_RSA_CERT: @@ -2822,9 +2984,15 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, break; #endif /* WITH_OPENSSL */ case KEY_ED25519_CERT: + case KEY_ED25519_SK_CERT: if ((ret = sshbuf_put_string(cert, k->ed25519_pk, ED25519_PK_SZ)) != 0) goto out; + if (k->type == KEY_ED25519_SK_CERT) { + if ((ret = sshbuf_put_cstring(cert, + k->sk_application)) != 0) + goto out; + } break; #ifdef WITH_XMSS case KEY_XMSS_CERT: @@ -2868,7 +3036,7 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, /* Sign the whole mess */ if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), - sshbuf_len(cert), alg, 0, signer_ctx)) != 0) + sshbuf_len(cert), alg, sk_provider, sk_pin, 0, signer_ctx)) != 0) goto out; /* Check and update signature_type against what was actually used */ if ((ret = sshkey_get_sigtype(sig_blob, sig_len, &sigtype)) != 0) @@ -2898,30 +3066,37 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, static int default_key_sign(struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, - const char *alg, u_int compat, void *ctx) + const char *alg, const char *sk_provider, const char *sk_pin, + u_int compat, void *ctx) { if (ctx != NULL) return SSH_ERR_INVALID_ARGUMENT; - return sshkey_sign(key, sigp, lenp, data, datalen, alg, compat); + return sshkey_sign(key, sigp, lenp, data, datalen, alg, + sk_provider, sk_pin, compat); } int -sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg) +sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg, + const char *sk_provider, const char *sk_pin) { - return sshkey_certify_custom(k, ca, alg, default_key_sign, NULL); + return sshkey_certify_custom(k, ca, alg, sk_provider, sk_pin, + default_key_sign, NULL); } int sshkey_cert_check_authority(const struct sshkey *k, - int want_host, int require_principal, + int want_host, int require_principal, int wildcard_pattern, const char *name, const char **reason) { u_int i, principal_matches; time_t now = time(NULL); - if (reason != NULL) - *reason = NULL; - + if (reason == NULL) + return SSH_ERR_INVALID_ARGUMENT; + if (!sshkey_is_cert(k)) { + *reason = "Key is not a certificate"; + return SSH_ERR_KEY_CERT_INVALID; + } if (want_host) { if (k->cert->type != SSH2_CERT_TYPE_HOST) { *reason = "Certificate invalid: not a host certificate"; @@ -2954,6 +3129,7 @@ sshkey_cert_check_authority(const struct sshkey *k, } else if (name != NULL) { principal_matches = 0; for (i = 0; i < k->cert->nprincipals; i++) { + #ifdef WINDOWS char cert_principal_name_copy[UNLEN + DNLEN + 1 + 1] = { 0, }; strcpy_s(cert_principal_name_copy, _countof(cert_principal_name_copy), k->cert->principals[i]); @@ -2961,7 +3137,6 @@ sshkey_cert_check_authority(const struct sshkey *k, /* * For domain user we need special handling. * We support both "domain\user" and "domain/user" formats. - * compare user, domain separately. */ if (strstr(name, "/") || strstr(name, "\\")) { char *tmp = NULL; @@ -2970,14 +3145,29 @@ sshkey_cert_check_authority(const struct sshkey *k, } /* In windows, usernames are case insensitive */ - if (_strcmpi(name, cert_principal_name_copy) == 0) { -#else - if (strcmp(name, k->cert->principals[i]) == 0) { -#endif - + if (wildcard_pattern) { + /* Use match_pattern_list for case insensitive compairision */ + if (match_pattern_list(cert_principal_name_copy, + name, 1)) { + principal_matches = 1; + break; + } + } else if (_strcmpi(name, cert_principal_name_copy) == 0) { principal_matches = 1; break; } +#else + if (wildcard_pattern) { + if (match_pattern(k->cert->principals[i], + name)) { + principal_matches = 1; + break; + } + } else if (strcmp(name, k->cert->principals[i]) == 0) { + principal_matches = 1; + break; + } +#endif } if (!principal_matches) { *reason = "Certificate invalid: name is not a listed " @@ -2988,10 +3178,32 @@ sshkey_cert_check_authority(const struct sshkey *k, return 0; } +int +sshkey_cert_check_host(const struct sshkey *key, const char *host, + int wildcard_principals, const char *ca_sign_algorithms, + const char **reason) +{ + int r; + + if ((r = sshkey_cert_check_authority(key, 1, 0, wildcard_principals, + host, reason)) != 0) + return r; + if (sshbuf_len(key->cert->critical) != 0) { + *reason = "Certificate contains unsupported critical options"; + return SSH_ERR_KEY_CERT_INVALID; + } + if (ca_sign_algorithms != NULL && + (r = sshkey_check_cert_sigtype(key, ca_sign_algorithms)) != 0) { + *reason = "Certificate signed with disallowed algorithm"; + 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]; + char from[32], to[32], ret[128]; time_t tt; struct tm *tm; @@ -3111,6 +3323,28 @@ sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, EC_KEY_get0_private_key(key->ecdsa))) != 0) goto out; break; + case KEY_ECDSA_SK: + 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_cstring(b, key->sk_application)) != 0 || + (r = sshbuf_put_u8(b, key->sk_flags)) != 0 || + (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 || + (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0) + goto out; + break; + case KEY_ECDSA_SK_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_cstring(b, key->sk_application)) != 0 || + (r = sshbuf_put_u8(b, key->sk_flags)) != 0 || + (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 || + (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0) + goto out; + break; # endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ case KEY_ED25519: @@ -3132,6 +3366,29 @@ sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, ED25519_SK_SZ)) != 0) goto out; break; + case KEY_ED25519_SK: + if ((r = sshbuf_put_string(b, key->ed25519_pk, + ED25519_PK_SZ)) != 0 || + (r = sshbuf_put_cstring(b, key->sk_application)) != 0 || + (r = sshbuf_put_u8(b, key->sk_flags)) != 0 || + (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 || + (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0) + goto out; + break; + case KEY_ED25519_SK_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_cstring(b, key->sk_application)) != 0 || + (r = sshbuf_put_u8(b, key->sk_flags)) != 0 || + (r = sshbuf_put_stringb(b, key->sk_key_handle)) != 0 || + (r = sshbuf_put_stringb(b, key->sk_reserved)) != 0) + goto out; + break; #ifdef WITH_XMSS case KEY_XMSS: if (key->xmss_name == NULL) { @@ -3192,10 +3449,12 @@ int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) { char *tname = NULL, *curve = NULL, *xmss_name = NULL; + char *expect_sk_application = 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 *expect_ed25519_pk = NULL; u_char *xmss_pk = NULL, *xmss_sk = NULL; #ifdef WITH_OPENSSL BIGNUM *exponent = NULL; @@ -3210,38 +3469,60 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) 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 (sshkey_type_is_cert(type)) { + /* + * Certificate key private keys begin with the certificate + * itself. Make sure this matches the type of the enclosing + * private key. + */ + if ((r = sshkey_froms(buf, &k)) != 0) + goto out; + if (k->type != type) { + r = SSH_ERR_KEY_CERT_MISMATCH; + goto out; + } + /* For ECDSA keys, the group must match too */ + if (k->type == KEY_ECDSA && + k->ecdsa_nid != sshkey_ecdsa_nid_from_name(tname)) { + r = SSH_ERR_KEY_CERT_MISMATCH; + goto out; + } + /* + * Several fields are redundant between certificate and + * private key body, we require these to match. + */ + expect_sk_application = k->sk_application; + expect_ed25519_pk = k->ed25519_pk; + k->sk_application = NULL; + k->ed25519_pk = NULL; + } else { if ((k = sshkey_new(type)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } + } + switch (type) { +#ifdef WITH_OPENSSL + case KEY_DSA: 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) + (r = sshbuf_get_bignum2(buf, &dsa_pub_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)) { + if (!DSA_set0_key(k->dsa, dsa_pub_key, NULL)) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } - dsa_pub_key = dsa_priv_key = NULL; /* transferred */ - break; + dsa_pub_key = NULL; /* transferred */ + /* FALLTHROUGH */ case KEY_DSA_CERT: - if ((r = sshkey_froms(buf, &k)) != 0 || - (r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0) + if ((r = sshbuf_get_bignum2(buf, &dsa_priv_key)) != 0) goto out; - if (k->type != type) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } if (!DSA_set0_key(k->dsa, NULL, dsa_priv_key)) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; @@ -3250,10 +3531,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) 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; @@ -3269,8 +3546,11 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } - if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 || - (r = sshbuf_get_bignum2(buf, &exponent))) + if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0) + goto out; + /* FALLTHROUGH */ + case KEY_ECDSA_CERT: + if ((r = sshbuf_get_bignum2(buf, &exponent)) != 0) goto out; if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; @@ -3281,63 +3561,71 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) (r = sshkey_ec_validate_private(k->ecdsa)) != 0) goto out; break; - case KEY_ECDSA_CERT: - if ((r = sshkey_froms(buf, &k)) != 0 || - (r = sshbuf_get_bignum2(buf, &exponent)) != 0) - goto out; - if (k->type != type || - k->ecdsa_nid != sshkey_ecdsa_nid_from_name(tname)) { - r = SSH_ERR_INVALID_FORMAT; + case KEY_ECDSA_SK: + if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) { + r = SSH_ERR_INVALID_ARGUMENT; goto out; } - if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { + 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; + } + if ((k->sk_key_handle = sshbuf_new()) == NULL || + (k->sk_reserved = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); + if (k->ecdsa == NULL) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } + if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 || + (r = sshbuf_get_cstring(buf, &k->sk_application, + NULL)) != 0 || + (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 || + (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 || + (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0) + 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) + EC_KEY_get0_public_key(k->ecdsa))) != 0) + goto out; + break; + case KEY_ECDSA_SK_CERT: + if ((k->sk_key_handle = sshbuf_new()) == NULL || + (k->sk_reserved = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if ((r = sshbuf_get_cstring(buf, &k->sk_application, + NULL)) != 0 || + (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 || + (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 || + (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0) + goto out; + if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa), + EC_KEY_get0_public_key(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 ((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) + (r = sshbuf_get_bignum2(buf, &rsa_e)) != 0) goto out; - if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, rsa_d)) { + if (!RSA_set0_key(k->rsa, rsa_n, rsa_e, NULL)) { 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; + rsa_n = rsa_e = NULL; /* transferred */ + /* FALLTHROUGH */ case KEY_RSA_CERT: - if ((r = sshkey_froms(buf, &k)) != 0 || - (r = sshbuf_get_bignum2(buf, &rsa_d)) != 0 || + if ((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 (k->type != type) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } if (!RSA_set0_key(k->rsa, NULL, NULL, rsa_d)) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; @@ -3355,10 +3643,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) break; #endif /* WITH_OPENSSL */ case KEY_ED25519: - if ((k = sshkey_new(type)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } + case KEY_ED25519_CERT: if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 || (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0) goto out; @@ -3368,58 +3653,40 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) } 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 (k->type != type) { - r = SSH_ERR_INVALID_FORMAT; - 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; /* transferred */ break; -#ifdef WITH_XMSS - case KEY_XMSS: - if ((k = sshkey_new(type)) == NULL) { + case KEY_ED25519_SK: + case KEY_ED25519_SK_CERT: + if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0) + goto out; + if (pklen != ED25519_PK_SZ) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((k->sk_key_handle = sshbuf_new()) == NULL || + (k->sk_reserved = sshbuf_new()) == 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) + if ((r = sshbuf_get_cstring(buf, &k->sk_application, + NULL)) != 0 || + (r = sshbuf_get_u8(buf, &k->sk_flags)) != 0 || + (r = sshbuf_get_stringb(buf, k->sk_key_handle)) != 0 || + (r = sshbuf_get_stringb(buf, k->sk_reserved)) != 0) goto out; + k->ed25519_pk = ed25519_pk; + ed25519_pk = NULL; /* transferred */ break; +#ifdef WITH_XMSS + case KEY_XMSS: case KEY_XMSS_CERT: - if ((r = sshkey_froms(buf, &k)) != 0 || - (r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 || + if ((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 (k->type != type || strcmp(xmss_name, k->xmss_name) != 0) { - r = SSH_ERR_INVALID_FORMAT; + if (type == KEY_XMSS && + (r = sshkey_xmss_init(k, xmss_name)) != 0) goto out; - } if (pklen != sshkey_xmss_pklen(k) || sklen != sshkey_xmss_sklen(k)) { r = SSH_ERR_INVALID_FORMAT; @@ -3449,6 +3716,13 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) break; } #endif /* WITH_OPENSSL */ + if ((expect_sk_application != NULL && (k->sk_application == NULL || + strcmp(expect_sk_application, k->sk_application) != 0)) || + (expect_ed25519_pk != NULL && (k->ed25519_pk == NULL || + memcmp(expect_ed25519_pk, k->ed25519_pk, ED25519_PK_SZ) != 0))) { + r = SSH_ERR_KEY_CERT_MISMATCH; + goto out; + } /* success */ r = 0; if (kp != NULL) { @@ -3478,6 +3752,8 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) free(xmss_name); freezero(xmss_pk, pklen); freezero(xmss_sk, sklen); + free(expect_sk_application); + free(expect_ed25519_pk); return r; } @@ -3485,9 +3761,8 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) 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; + BIGNUM *order = NULL, *x = NULL, *y = NULL, *tmp = NULL; int ret = SSH_ERR_KEY_INVALID_EC_VALUE; /* @@ -3498,10 +3773,6 @@ sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) * 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. @@ -3514,18 +3785,18 @@ sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) 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) { + if ((x = BN_new()) == NULL || + (y = BN_new()) == NULL || + (order = BN_new()) == NULL || + (tmp = BN_new()) == 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 || + if (EC_GROUP_get_order(group, order, NULL) != 1 || EC_POINT_get_affine_coordinates_GFp(group, public, - x, y, bnctx) != 1) { + x, y, NULL) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } @@ -3538,7 +3809,7 @@ sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) ret = SSH_ERR_ALLOC_FAIL; goto out; } - if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1) { + if (EC_POINT_mul(group, nq, NULL, public, order, NULL) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } @@ -3554,7 +3825,10 @@ sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) goto out; ret = 0; out: - BN_CTX_free(bnctx); + BN_clear_free(x); + BN_clear_free(y); + BN_clear_free(order); + BN_clear_free(tmp); EC_POINT_free(nq); return ret; } @@ -3562,22 +3836,16 @@ sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) int sshkey_ec_validate_private(const EC_KEY *key) { - BN_CTX *bnctx; - BIGNUM *order, *tmp; + BIGNUM *order = NULL, *tmp = NULL; 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) { + if ((order = BN_new()) == NULL || (tmp = BN_new()) == 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) { + if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, NULL) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } @@ -3594,47 +3862,43 @@ sshkey_ec_validate_private(const EC_KEY *key) goto out; ret = 0; out: - BN_CTX_free(bnctx); + BN_clear_free(order); + BN_clear_free(tmp); return ret; } void sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point) { - BIGNUM *x, *y; - BN_CTX *bnctx; + BIGNUM *x = NULL, *y = NULL; 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 ((x = BN_new()) == NULL || (y = BN_new()) == NULL) { + fprintf(stderr, "%s: BN_new failed\n", __func__); + goto out; } 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; + goto out; } - if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, - bnctx) != 1) { + if (EC_POINT_get_affine_coordinates_GFp(group, point, + x, y, NULL) != 1) { fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n", __func__); - return; + goto out; } fputs("x=", stderr); BN_print_fp(stderr, x); fputs("\ny=", stderr); BN_print_fp(stderr, y); fputs("\n", stderr); - BN_CTX_free(bnctx); + out: + BN_clear_free(x); + BN_clear_free(y); } void @@ -3773,46 +4037,31 @@ sshkey_private_to_blob2(struct sshkey *prv, struct sshbuf *blob, 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); - } + if (key != NULL) + freezero(key, keylen + ivlen); + if (pubkeyblob != NULL) + freezero(pubkeyblob, pubkeylen); + if (b64 != NULL) + freezero(b64, strlen(b64)); return r; } static int -sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, - struct sshkey **keyp, char **commentp) +private2_uudecode(struct sshbuf *blob, struct sshbuf **decodedp) { - 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; + int r; + u_char last; 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 (blob == NULL || decodedp == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + *decodedp = NULL; if ((encoded = sshbuf_new()) == NULL || - (decoded = sshbuf_new()) == NULL || - (decrypted = sshbuf_new()) == NULL) { + (decoded = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } @@ -3877,13 +4126,56 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, r = SSH_ERR_INVALID_FORMAT; goto out; } + /* success */ + *decodedp = decoded; + decoded = NULL; + r = 0; + out: + sshbuf_free(encoded); + sshbuf_free(decoded); + return r; +} + +static int +private2_decrypt(struct sshbuf *decoded, const char *passphrase, + struct sshbuf **decryptedp, struct sshkey **pubkeyp) +{ + char *ciphername = NULL, *kdfname = NULL; + const struct sshcipher *cipher = NULL; + int r = SSH_ERR_INTERNAL_ERROR; + size_t keylen = 0, ivlen = 0, authlen = 0, slen = 0; + struct sshbuf *kdf = NULL, *decrypted = NULL; + struct sshcipher_ctx *ciphercontext = NULL; + struct sshkey *pubkey = NULL; + u_char *key = NULL, *salt = NULL, *dp; + u_int blocksize, rounds, nkeys, encrypted_len, check1, check2; + + if (decoded == NULL || decryptedp == NULL || pubkeyp == NULL) + return SSH_ERR_INVALID_ARGUMENT; + + *decryptedp = NULL; + *pubkeyp = NULL; + + if ((decrypted = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + 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, &nkeys)) != 0) + goto out; + + if (nkeys != 1) { + /* XXX only one key supported at present */ + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + + if ((r = sshkey_froms(decoded, &pubkey)) != 0 || (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0) goto out; @@ -3891,23 +4183,18 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, 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) { + if (strcmp(kdfname, "none") == 0 && strcmp(ciphername, "none") != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } - if (nkeys != 1) { - /* XXX only one key supported */ - r = SSH_ERR_INVALID_FORMAT; + if ((passphrase == NULL || strlen(passphrase) == 0) && + strcmp(kdfname, "none") != 0) { + /* passphrase required */ + r = SSH_ERR_KEY_WRONG_PASSPHRASE; goto out; } @@ -3972,13 +4259,38 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, r = SSH_ERR_KEY_WRONG_PASSPHRASE; goto out; } + /* success */ + *decryptedp = decrypted; + decrypted = NULL; + *pubkeyp = pubkey; + pubkey = NULL; + r = 0; + out: + cipher_free(ciphercontext); + free(ciphername); + free(kdfname); + sshkey_free(pubkey); + if (salt != NULL) { + explicit_bzero(salt, slen); + free(salt); + } + if (key != NULL) { + explicit_bzero(key, keylen + ivlen); + free(key); + } + sshbuf_free(kdf); + sshbuf_free(decrypted); + return r; +} - /* 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 after private key */ +static int +private2_check_padding(struct sshbuf *decrypted) +{ + u_char pad; + size_t i; + int r = SSH_ERR_INTERNAL_ERROR; - /* Check deterministic padding */ i = 0; while (sshbuf_len(decrypted)) { if ((r = sshbuf_get_u8(decrypted, &pad)) != 0) @@ -3988,8 +4300,54 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, goto out; } } + /* success */ + r = 0; + out: + explicit_bzero(&pad, sizeof(pad)); + explicit_bzero(&i, sizeof(i)); + return r; +} - /* XXX decode pubkey and check against private */ +static int +sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, + struct sshkey **keyp, char **commentp) +{ + char *comment = NULL; + int r = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *decoded = NULL, *decrypted = NULL; + struct sshkey *k = NULL, *pubkey = NULL; + + if (keyp != NULL) + *keyp = NULL; + if (commentp != NULL) + *commentp = NULL; + + /* Undo base64 encoding and decrypt the private section */ + if ((r = private2_uudecode(blob, &decoded)) != 0 || + (r = private2_decrypt(decoded, passphrase, + &decrypted, &pubkey)) != 0) + goto out; + + if (type != KEY_UNSPEC && + sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) { + r = SSH_ERR_KEY_TYPE_MISMATCH; + 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 after private section */ + if ((r = private2_check_padding(decrypted)) != 0) + goto out; + + /* Check that the public key in the envelope matches the private key */ + if (!sshkey_equal(pubkey, k)) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } /* success */ r = 0; @@ -4002,27 +4360,63 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, 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); + sshkey_free(pubkey); return r; } +static int +sshkey_parse_private2_pubkey(struct sshbuf *blob, int type, + struct sshkey **keyp) +{ + int r = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *decoded = NULL; + struct sshkey *pubkey = NULL; + u_int nkeys = 0; + + if (keyp != NULL) + *keyp = NULL; + + if ((r = private2_uudecode(blob, &decoded)) != 0) + goto out; + /* parse public key from unencrypted envelope */ + if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 || + (r = sshbuf_skip_string(decoded)) != 0 || /* cipher */ + (r = sshbuf_skip_string(decoded)) != 0 || /* KDF alg */ + (r = sshbuf_skip_string(decoded)) != 0 || /* KDF hint */ + (r = sshbuf_get_u32(decoded, &nkeys)) != 0) + goto out; + + if (nkeys != 1) { + /* XXX only one key supported at present */ + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + + /* Parse the public key */ + if ((r = sshkey_froms(decoded, &pubkey)) != 0) + goto out; + + if (type != KEY_UNSPEC && + sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) { + r = SSH_ERR_KEY_TYPE_MISMATCH; + goto out; + } + + /* success */ + r = 0; + if (keyp != NULL) { + *keyp = pubkey; + pubkey = NULL; + } + out: + sshbuf_free(decoded); + sshkey_free(pubkey); + return r; +} #ifdef WITH_OPENSSL /* convert SSH v2 key to PEM or PKCS#8 format */ @@ -4131,9 +4525,13 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, break; /* see below */ #endif /* WITH_OPENSSL */ case KEY_ED25519: + case KEY_ED25519_SK: #ifdef WITH_XMSS case KEY_XMSS: #endif /* WITH_XMSS */ +#ifdef WITH_OPENSSL + case KEY_ECDSA_SK: +#endif /* WITH_OPENSSL */ return sshkey_private_to_blob2(key, blob, passphrase, comment, openssh_format_cipher, openssh_format_rounds); default: @@ -4155,7 +4553,6 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, #endif /* WITH_OPENSSL */ } - #ifdef WITH_OPENSSL static int translate_libcrypto_error(unsigned long pem_err) @@ -4346,24 +4743,16 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, *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 */ + /* No fallback for new-format-only keys */ return sshkey_parse_private2(blob, type, passphrase, keyp, commentp); - case KEY_UNSPEC: + default: 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) + /* Only fallback to PEM parser if a format error occurred. */ + if (r != SSH_ERR_INVALID_FORMAT) return r; #ifdef WITH_OPENSSL return sshkey_parse_private_pem_fileblob(blob, type, @@ -4371,8 +4760,6 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, #else return SSH_ERR_INVALID_FORMAT; #endif /* WITH_OPENSSL */ - default: - return SSH_ERR_KEY_TYPE_UNKNOWN; } } @@ -4389,6 +4776,26 @@ sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase, passphrase, keyp, commentp); } +void +sshkey_sig_details_free(struct sshkey_sig_details *details) +{ + freezero(details, sizeof(*details)); +} + +int +sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, int type, + struct sshkey **pubkeyp) +{ + int r = SSH_ERR_INTERNAL_ERROR; + + if (pubkeyp != NULL) + *pubkeyp = NULL; + /* only new-format private keys bundle a public key inside */ + if ((r = sshkey_parse_private2_pubkey(blob, type, pubkeyp)) != 0) + return r; + return 0; +} + #ifdef WITH_XMSS /* * serialize the key with the current state and forward the state @@ -4396,7 +4803,7 @@ sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase, */ int sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b, - u_int32_t maxsign, sshkey_printfn *pr) + u_int32_t maxsign, int printerror) { int r, rupdate; @@ -4404,14 +4811,14 @@ sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b, 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 || + if ((r = sshkey_xmss_get_state(k, printerror)) != 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 ((rupdate = sshkey_xmss_update_state(k, printerror)) != 0) { if (r == 0) r = rupdate; } @@ -4450,7 +4857,7 @@ sshkey_set_filename(struct sshkey *k, const char *filename) #else int sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b, - u_int32_t maxsign, sshkey_printfn *pr) + u_int32_t maxsign, int printerror) { return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT); } diff --git a/sshkey.h b/sshkey.h index 1119a7b07..146c7ca8c 100644 --- a/sshkey.h +++ b/sshkey.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.h,v 1.34 2019/09/03 08:31:20 djm Exp $ */ +/* $OpenBSD: sshkey.h,v 1.49 2021/01/26 00:49:30 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -39,6 +39,7 @@ # define EC_GROUP void # define EC_POINT void # endif /* OPENSSL_HAS_ECC */ +#define SSH_OPENSSL_VERSION OpenSSL_version(OPENSSL_VERSION) #else /* WITH_OPENSSL */ # define BIGNUM void # define RSA void @@ -46,6 +47,7 @@ # define EC_KEY void # define EC_GROUP void # define EC_POINT void +#define SSH_OPENSSL_VERSION "without OpenSSL" #endif /* WITH_OPENSSL */ #define SSH_RSA_MINIMUM_MODULUS_SIZE 1024 @@ -65,6 +67,10 @@ enum sshkey_types { KEY_ED25519_CERT, KEY_XMSS, KEY_XMSS_CERT, + KEY_ECDSA_SK, + KEY_ECDSA_SK_CERT, + KEY_ED25519_SK, + KEY_ED25519_SK_CERT, KEY_UNSPEC }; @@ -83,9 +89,10 @@ enum sshkey_fp_rep { /* 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, + SSHKEY_SERIALIZE_STATE = 1, /* only state is serialized */ + SSHKEY_SERIALIZE_FULL = 2, /* include keys for saving to disk */ + SSHKEY_SERIALIZE_SHIELD = 3, /* everything, for encrypting in ram */ + SSHKEY_SERIALIZE_INFO = 254, /* minimal information */ }; /* Private key disk formats */ @@ -118,18 +125,30 @@ struct sshkey_cert { struct sshkey { int type; int flags; + /* KEY_RSA */ RSA *rsa; + /* KEY_DSA */ DSA *dsa; + /* KEY_ECDSA and KEY_ECDSA_SK */ int ecdsa_nid; /* NID of curve */ EC_KEY *ecdsa; + /* KEY_ED25519 and KEY_ED25519_SK */ u_char *ed25519_sk; u_char *ed25519_pk; + /* KEY_XMSS */ 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; + /* KEY_ECDSA_SK and KEY_ED25519_SK */ + char *sk_application; + uint8_t sk_flags; + struct sshbuf *sk_key_handle; + struct sshbuf *sk_reserved; + /* Certificates */ struct sshkey_cert *cert; + /* Private key shielding */ u_char *shielded_private; size_t shielded_len; u_char *shield_prekey; @@ -139,6 +158,12 @@ struct sshkey { #define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES #define ED25519_PK_SZ crypto_sign_ed25519_PUBLICKEYBYTES +/* Additional fields contained in signature */ +struct sshkey_sig_details { + uint32_t sk_counter; /* U2F signature counter */ + uint8_t sk_flags; /* U2F signature flags; see ssh-sk.h */ +}; + struct sshkey *sshkey_new(int); void sshkey_free(struct sshkey *); int sshkey_equal_public(const struct sshkey *, @@ -164,23 +189,28 @@ int sshkey_unshield_private(struct sshkey *); int sshkey_type_from_name(const char *); int sshkey_is_cert(const struct sshkey *); +int sshkey_is_sk(const struct sshkey *); int sshkey_type_is_cert(int); int sshkey_type_plain(int); 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, +int sshkey_cert_check_authority(const struct sshkey *, int, int, int, const char *, const char **); +int sshkey_cert_check_host(const struct sshkey *, const char *, + 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 *); +int sshkey_certify(struct sshkey *, struct sshkey *, + const char *, const char *, const char *); /* Variant allowing use of a custom signature function (e.g. for ssh-agent) */ typedef int sshkey_certify_signer(struct sshkey *, u_char **, size_t *, - const u_char *, size_t, const char *, u_int, void *); + const u_char *, size_t, const char *, const char *, const char *, + u_int, void *); int sshkey_certify_custom(struct sshkey *, struct sshkey *, const char *, - sshkey_certify_signer *, void *); + const char *, const char *, sshkey_certify_signer *, void *); int sshkey_ecdsa_nid_from_name(const char *); int sshkey_curve_name_to_nid(const char *); @@ -209,9 +239,9 @@ int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *); int sshkey_putb_plain(const struct sshkey *, struct sshbuf *); int sshkey_sign(struct sshkey *, u_char **, size_t *, - const u_char *, size_t, const char *, u_int); + const u_char *, size_t, const char *, const char *, const char *, u_int); int sshkey_verify(const struct sshkey *, const u_char *, size_t, - const u_char *, size_t, const char *, u_int); + const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); int sshkey_check_sigtype(const u_char *, size_t, const char *); const char *sshkey_sigalg_by_name(const char *); int sshkey_get_sigtype(const u_char *, size_t, char **); @@ -234,22 +264,21 @@ 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); +int sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, + int type, struct sshkey **pubkeyp); /* 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(struct sshkey *key, struct sshbuf *buf, - u_int32_t maxsign, sshkey_printfn *pr); +int sshkey_forward_state(const struct sshkey *, u_int32_t, int); +int sshkey_private_serialize_maxsign(struct sshkey *key, + struct sshbuf *buf, u_int32_t maxsign, int); + +void sshkey_sig_details_free(struct sshkey_sig_details *); #ifdef SSHKEY_INTERNAL int ssh_rsa_sign(const struct sshkey *key, @@ -268,11 +297,19 @@ int ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, 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_ecdsa_sk_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat, + struct sshkey_sig_details **detailsp); 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_ed25519_sk_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat, + struct sshkey_sig_details **detailsp); 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, diff --git a/sshlogin.c b/sshlogin.c index 4ed419494..82dd84819 100644 --- a/sshlogin.c +++ b/sshlogin.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshlogin.c,v 1.34 2019/06/28 13:35:04 deraadt Exp $ */ +/* $OpenBSD: sshlogin.c,v 1.35 2020/10/18 11:32:02 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -90,8 +90,11 @@ static void store_lastlog_message(const char *user, uid_t uid) { #ifndef NO_SSH_LASTLOG - char *time_string, hostname[HOST_NAME_MAX+1] = ""; +# ifndef CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG + char hostname[HOST_NAME_MAX+1] = ""; time_t last_login_time; +# endif + char *time_string; int r; if (!options.print_lastlog) @@ -119,7 +122,7 @@ store_lastlog_message(const char *user, uid_t uid) r = sshbuf_putf(loginmsg, "Last login: %s from %s\r\n", time_string, hostname); if (r != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "sshbuf_putf"); } # endif /* CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG */ #endif /* NO_SSH_LASTLOG */ diff --git a/sshpty.c b/sshpty.c index bce09e255..cae0b977a 100644 --- a/sshpty.c +++ b/sshpty.c @@ -27,6 +27,7 @@ #endif #include #include +#include #include #include #ifdef HAVE_UTIL_H diff --git a/sshsig.c b/sshsig.c index b19cd077d..4ce4674cd 100644 --- a/sshsig.c +++ b/sshsig.c @@ -1,3 +1,4 @@ +/* $OpenBSD: sshsig.c,v 1.20 2021/01/31 10:50:10 dtucker Exp $ */ /* * Copyright (c) 2019 Google LLC * @@ -53,27 +54,26 @@ sshsig_armor(const struct sshbuf *blob, struct sshbuf **out) *out = NULL; if ((buf = sshbuf_new()) == NULL) { - error("%s: sshbuf_new failed", __func__); + error_f("sshbuf_new failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put(buf, BEGIN_SIGNATURE, sizeof(BEGIN_SIGNATURE)-1)) != 0) { - error("%s: sshbuf_putf failed: %s", __func__, ssh_err(r)); + error_fr(r, "sshbuf_putf"); goto out; } if ((r = sshbuf_dtob64(blob, buf, 1)) != 0) { - error("%s: Couldn't base64 encode signature blob: %s", - __func__, ssh_err(r)); + error_fr(r, "base64 encode signature"); goto out; } if ((r = sshbuf_put(buf, END_SIGNATURE, sizeof(END_SIGNATURE)-1)) != 0 || (r = sshbuf_put_u8(buf, '\n')) != 0) { - error("%s: sshbuf_put failed: %s", __func__, ssh_err(r)); + error_fr(r, "sshbuf_put"); goto out; } /* success */ @@ -95,7 +95,7 @@ sshsig_dearmor(struct sshbuf *sig, struct sshbuf **out) char *b64 = NULL; if ((sbuf = sshbuf_fromb(sig)) == NULL) { - error("%s: sshbuf_fromb failed", __func__); + error_f("sshbuf_fromb failed"); return SSH_ERR_ALLOC_FAIL; } @@ -106,7 +106,7 @@ sshsig_dearmor(struct sshbuf *sig, struct sshbuf **out) } if ((r = sshbuf_consume(sbuf, sizeof(BEGIN_SIGNATURE)-1)) != 0) { - error("%s: sshbuf_consume failed: %s", __func__, ssh_err(r)); + error_fr(r, "consume"); goto done; } @@ -117,24 +117,24 @@ sshsig_dearmor(struct sshbuf *sig, struct sshbuf **out) } if ((r = sshbuf_consume_end(sbuf, sshbuf_len(sbuf)-eoffset)) != 0) { - error("%s: sshbuf_consume failed: %s", __func__, ssh_err(r)); + error_fr(r, "consume"); goto done; } if ((b64 = sshbuf_dup_string(sbuf)) == NULL) { - error("%s: sshbuf_dup_string failed", __func__); + error_f("sshbuf_dup_string failed"); r = SSH_ERR_ALLOC_FAIL; goto done; } if ((buf = sshbuf_new()) == NULL) { - error("%s: sshbuf_new() failed", __func__); + error_f("sshbuf_new() failed"); r = SSH_ERR_ALLOC_FAIL; goto done; } if ((r = sshbuf_b64tod(buf, b64)) != 0) { - error("Couldn't decode signature: %s", ssh_err(r)); + error_fr(r, "decode base64"); goto done; } @@ -151,8 +151,9 @@ done: static int sshsig_wrap_sign(struct sshkey *key, const char *hashalg, - const struct sshbuf *h_message, const char *sig_namespace, - struct sshbuf **out, sshsig_signer *signer, void *signer_ctx) + const char *sk_provider, const char *sk_pin, const struct sshbuf *h_message, + const char *sig_namespace, struct sshbuf **out, + sshsig_signer *signer, void *signer_ctx) { int r; size_t slen = 0; @@ -163,7 +164,7 @@ sshsig_wrap_sign(struct sshkey *key, const char *hashalg, if ((tosign = sshbuf_new()) == NULL || (blob = sshbuf_new()) == NULL) { - error("%s: sshbuf_new failed", __func__); + error_f("sshbuf_new failed"); r = SSH_ERR_ALLOC_FAIL; goto done; } @@ -173,7 +174,7 @@ sshsig_wrap_sign(struct sshkey *key, const char *hashalg, (r = sshbuf_put_string(tosign, NULL, 0)) != 0 || /* reserved */ (r = sshbuf_put_cstring(tosign, hashalg)) != 0 || (r = sshbuf_put_stringb(tosign, h_message)) != 0) { - error("Couldn't construct message to sign: %s", ssh_err(r)); + error_fr(r, "assemble message to sign"); goto done; } @@ -184,15 +185,15 @@ sshsig_wrap_sign(struct sshkey *key, const char *hashalg, if (signer != NULL) { if ((r = signer(key, &sig, &slen, sshbuf_ptr(tosign), sshbuf_len(tosign), - sign_alg, 0, signer_ctx)) != 0) { - error("Couldn't sign message: %s", ssh_err(r)); + sign_alg, sk_provider, sk_pin, 0, signer_ctx)) != 0) { + error_r(r, "Couldn't sign message (signer)"); goto done; } } else { if ((r = sshkey_sign(key, &sig, &slen, sshbuf_ptr(tosign), sshbuf_len(tosign), - sign_alg, 0)) != 0) { - error("Couldn't sign message: %s", ssh_err(r)); + sign_alg, sk_provider, sk_pin, 0)) != 0) { + error_r(r, "Couldn't sign message"); goto done; } } @@ -204,12 +205,14 @@ sshsig_wrap_sign(struct sshkey *key, const char *hashalg, (r = sshbuf_put_string(blob, NULL, 0)) != 0 || /* reserved */ (r = sshbuf_put_cstring(blob, hashalg)) != 0 || (r = sshbuf_put_string(blob, sig, slen)) != 0) { - error("Couldn't populate blob: %s", ssh_err(r)); + error_fr(r, "assemble signature object"); goto done; } - *out = blob; - blob = NULL; + if (out != NULL) { + *out = blob; + blob = NULL; + } r = 0; done: free(sig); @@ -246,7 +249,7 @@ sshsig_check_hashalg(const char *hashalg) if (hashalg == NULL || match_pattern_list(hashalg, HASHALG_ALLOWED, 0) == 1) return 0; - error("%s: unsupported hash algorithm \"%.100s\"", __func__, hashalg); + error_f("unsupported hash algorithm \"%.100s\"", hashalg); return SSH_ERR_SIGN_ALG_UNSUPPORTED; } @@ -268,7 +271,7 @@ sshsig_peek_hashalg(struct sshbuf *signature, char **hashalgp) (r = sshbuf_get_string(buf, NULL, NULL)) != 0 || (r = sshbuf_get_cstring(buf, &hashalg, NULL)) != 0 || (r = sshbuf_get_string_direct(buf, NULL, NULL)) != 0) { - error("Couldn't parse signature blob: %s", ssh_err(r)); + error_fr(r, "parse signature object"); goto done; } @@ -285,7 +288,7 @@ sshsig_peek_hashalg(struct sshbuf *signature, char **hashalgp) static int sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg, const struct sshbuf *h_message, const char *expect_namespace, - struct sshkey **sign_keyp) + struct sshkey **sign_keyp, struct sshkey_sig_details **sig_details) { int r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *buf = NULL, *toverify = NULL; @@ -294,12 +297,14 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg, char *got_namespace = NULL, *sigtype = NULL, *sig_hashalg = NULL; size_t siglen; - debug("%s: verify message length %zu", __func__, sshbuf_len(h_message)); + debug_f("verify message length %zu", sshbuf_len(h_message)); + if (sig_details != NULL) + *sig_details = NULL; if (sign_keyp != NULL) *sign_keyp = NULL; if ((toverify = sshbuf_new()) == NULL) { - error("%s: sshbuf_new failed", __func__); + error_f("sshbuf_new failed"); r = SSH_ERR_ALLOC_FAIL; goto done; } @@ -309,7 +314,7 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg, (r = sshbuf_put_string(toverify, NULL, 0)) != 0 || /* reserved */ (r = sshbuf_put_cstring(toverify, hashalg)) != 0 || (r = sshbuf_put_stringb(toverify, h_message)) != 0) { - error("Couldn't construct message to verify: %s", ssh_err(r)); + error_fr(r, "assemble message to verify"); goto done; } @@ -321,7 +326,7 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg, (r = sshbuf_get_string(signature, NULL, NULL)) != 0 || (r = sshbuf_get_cstring(signature, &sig_hashalg, NULL)) != 0 || (r = sshbuf_get_string_direct(signature, &sig, &siglen)) != 0) { - error("Couldn't parse signature blob: %s", ssh_err(r)); + error_fr(r, "parse signature object"); goto done; } @@ -333,23 +338,23 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg, if (strcmp(expect_namespace, got_namespace) != 0) { error("Couldn't verify signature: namespace does not match"); - debug("%s: expected namespace \"%s\" received \"%s\"", - __func__, expect_namespace, got_namespace); + debug_f("expected namespace \"%s\" received \"%s\"", + expect_namespace, got_namespace); r = SSH_ERR_SIGNATURE_INVALID; goto done; } if (strcmp(hashalg, sig_hashalg) != 0) { error("Couldn't verify signature: hash algorithm mismatch"); - debug("%s: expected algorithm \"%s\" received \"%s\"", - __func__, hashalg, sig_hashalg); + debug_f("expected algorithm \"%s\" received \"%s\"", + hashalg, sig_hashalg); r = SSH_ERR_SIGNATURE_INVALID; goto done; } /* Ensure that RSA keys use an acceptable signature algorithm */ if (sshkey_type_plain(key->type) == KEY_RSA) { if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0) { - error("Couldn't verify signature: unable to get " - "signature type: %s", ssh_err(r)); + error_r(r, "Couldn't verify signature: unable to get " + "signature type"); goto done; } if (match_pattern_list(sigtype, RSA_SIGN_ALLOWED, 0) != 1) { @@ -360,8 +365,8 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg, } } if ((r = sshkey_verify(key, sig, siglen, sshbuf_ptr(toverify), - sshbuf_len(toverify), NULL, 0)) != 0) { - error("Signature verification failed: %s", ssh_err(r)); + sshbuf_len(toverify), NULL, 0, sig_details)) != 0) { + error_r(r, "Signature verification failed"); goto done; } @@ -394,16 +399,15 @@ hash_buffer(const struct sshbuf *m, const char *hashalg, struct sshbuf **bp) if ((r = sshsig_check_hashalg(hashalg)) != 0) return r; if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) { - error("%s: can't look up hash algorithm %s", - __func__, hashalg); + error_f("can't look up hash algorithm %s", hashalg); return SSH_ERR_INTERNAL_ERROR; } if ((r = ssh_digest_buffer(alg, m, hash, sizeof(hash))) != 0) { - error("%s: ssh_digest_buffer failed: %s", __func__, ssh_err(r)); + error_fr(r, "ssh_digest_buffer"); return r; } if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) { - debug3("%s: final hash: %s", __func__, hex); + debug3_f("final hash: %s", hex); freezero(hex, strlen(hex)); } if ((b = sshbuf_new()) == NULL) { @@ -411,7 +415,7 @@ hash_buffer(const struct sshbuf *m, const char *hashalg, struct sshbuf **bp) goto out; } if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) { - error("%s: sshbuf_put: %s", __func__, ssh_err(r)); + error_fr(r, "sshbuf_put"); goto out; } *bp = b; @@ -421,11 +425,12 @@ hash_buffer(const struct sshbuf *m, const char *hashalg, struct sshbuf **bp) out: sshbuf_free(b); explicit_bzero(hash, sizeof(hash)); - return 0; + return r; } int sshsig_signb(struct sshkey *key, const char *hashalg, + const char *sk_provider, const char *sk_pin, const struct sshbuf *message, const char *sig_namespace, struct sshbuf **out, sshsig_signer *signer, void *signer_ctx) { @@ -437,11 +442,11 @@ sshsig_signb(struct sshkey *key, const char *hashalg, if (out != NULL) *out = NULL; if ((r = hash_buffer(message, hashalg, &b)) != 0) { - error("%s: hash_buffer failed: %s", __func__, ssh_err(r)); + error_fr(r, "hash buffer"); goto out; } - if ((r = sshsig_wrap_sign(key, hashalg, b, sig_namespace, out, - signer, signer_ctx)) != 0) + if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, sk_pin, b, + sig_namespace, out, signer, signer_ctx)) != 0) goto out; /* success */ r = 0; @@ -452,24 +457,26 @@ sshsig_signb(struct sshkey *key, const char *hashalg, int sshsig_verifyb(struct sshbuf *signature, const struct sshbuf *message, - const char *expect_namespace, struct sshkey **sign_keyp) + const char *expect_namespace, struct sshkey **sign_keyp, + struct sshkey_sig_details **sig_details) { struct sshbuf *b = NULL; int r = SSH_ERR_INTERNAL_ERROR; char *hashalg = NULL; + if (sig_details != NULL) + *sig_details = NULL; if (sign_keyp != NULL) *sign_keyp = NULL; - if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0) return r; - debug("%s: signature made with hash \"%s\"", __func__, hashalg); + debug_f("signature made with hash \"%s\"", hashalg); if ((r = hash_buffer(message, hashalg, &b)) != 0) { - error("%s: hash_buffer failed: %s", __func__, ssh_err(r)); + error_fr(r, "hash buffer"); goto out; } if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace, - sign_keyp)) != 0) + sign_keyp, sig_details)) != 0) goto out; /* success */ r = 0; @@ -494,12 +501,11 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp) if ((r = sshsig_check_hashalg(hashalg)) != 0) return r; if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) { - error("%s: can't look up hash algorithm %s", - __func__, hashalg); + error_f("can't look up hash algorithm %s", hashalg); return SSH_ERR_INTERNAL_ERROR; } if ((ctx = ssh_digest_start(alg)) == NULL) { - error("%s: ssh_digest_start failed", __func__); + error_f("ssh_digest_start failed"); return SSH_ERR_INTERNAL_ERROR; } for (;;) { @@ -507,28 +513,27 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp) if (errno == EINTR || errno == EAGAIN) continue; oerrno = errno; - error("%s: read: %s", __func__, strerror(errno)); + error_f("read: %s", strerror(errno)); ssh_digest_free(ctx); errno = oerrno; r = SSH_ERR_SYSTEM_ERROR; goto out; } else if (n == 0) { - debug2("%s: hashed %zu bytes", __func__, total); + debug2_f("hashed %zu bytes", total); break; /* EOF */ } total += (size_t)n; if ((r = ssh_digest_update(ctx, rbuf, (size_t)n)) != 0) { - error("%s: ssh_digest_update: %s", - __func__, ssh_err(r)); + error_fr(r, "ssh_digest_update"); goto out; } } if ((r = ssh_digest_final(ctx, hash, sizeof(hash))) != 0) { - error("%s: ssh_digest_final: %s", __func__, ssh_err(r)); + error_fr(r, "ssh_digest_final"); goto out; } if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) { - debug3("%s: final hash: %s", __func__, hex); + debug3_f("final hash: %s", hex); freezero(hex, strlen(hex)); } if ((b = sshbuf_new()) == NULL) { @@ -536,7 +541,7 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp) goto out; } if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) { - error("%s: sshbuf_put: %s", __func__, ssh_err(r)); + error_fr(r, "sshbuf_put"); goto out; } *bp = b; @@ -547,11 +552,12 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp) sshbuf_free(b); ssh_digest_free(ctx); explicit_bzero(hash, sizeof(hash)); - return 0; + return r; } int sshsig_sign_fd(struct sshkey *key, const char *hashalg, + const char *sk_provider, const char *sk_pin, int fd, const char *sig_namespace, struct sshbuf **out, sshsig_signer *signer, void *signer_ctx) { @@ -563,11 +569,11 @@ sshsig_sign_fd(struct sshkey *key, const char *hashalg, if (out != NULL) *out = NULL; if ((r = hash_file(fd, hashalg, &b)) != 0) { - error("%s: hash_file failed: %s", __func__, ssh_err(r)); + error_fr(r, "hash_file"); return r; } - if ((r = sshsig_wrap_sign(key, hashalg, b, sig_namespace, out, - signer, signer_ctx)) != 0) + if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, sk_pin, b, + sig_namespace, out, signer, signer_ctx)) != 0) goto out; /* success */ r = 0; @@ -578,24 +584,26 @@ sshsig_sign_fd(struct sshkey *key, const char *hashalg, int sshsig_verify_fd(struct sshbuf *signature, int fd, - const char *expect_namespace, struct sshkey **sign_keyp) + const char *expect_namespace, struct sshkey **sign_keyp, + struct sshkey_sig_details **sig_details) { struct sshbuf *b = NULL; int r = SSH_ERR_INTERNAL_ERROR; char *hashalg = NULL; + if (sig_details != NULL) + *sig_details = NULL; if (sign_keyp != NULL) *sign_keyp = NULL; - if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0) return r; - debug("%s: signature made with hash \"%s\"", __func__, hashalg); + debug_f("signature made with hash \"%s\"", hashalg); if ((r = hash_file(fd, hashalg, &b)) != 0) { - error("%s: hash_file failed: %s", __func__, ssh_err(r)); + error_fr(r, "hash_file"); goto out; } if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace, - sign_keyp)) != 0) + sign_keyp, sig_details)) != 0) goto out; /* success */ r = 0; @@ -672,56 +680,116 @@ sshsigopt_free(struct sshsigopt *opts) } static int -check_allowed_keys_line(const char *path, u_long linenum, char *line, - const struct sshkey *sign_key, const char *principal, - const char *sig_namespace) +parse_principals_key_and_options(const char *path, u_long linenum, char *line, + const char *required_principal, char **principalsp, struct sshkey **keyp, + struct sshsigopt **sigoptsp) { - struct sshkey *found_key = NULL; - char *cp, *opts = NULL, *identities = NULL; - int r, found = 0; + char *opts = NULL, *tmp, *cp, *principals = NULL; const char *reason = NULL; struct sshsigopt *sigopts = NULL; + struct sshkey *key = NULL; + int r = SSH_ERR_INTERNAL_ERROR; - if ((found_key = sshkey_new(KEY_UNSPEC)) == NULL) { - error("%s: sshkey_new failed", __func__); - return SSH_ERR_ALLOC_FAIL; - } + if (principalsp != NULL) + *principalsp = NULL; + if (sigoptsp != NULL) + *sigoptsp = NULL; + if (keyp != NULL) + *keyp = NULL; - /* format: identity[,identity...] [option[,option...]] key */ cp = line; cp = cp + strspn(cp, " \t"); /* skip leading whitespace */ if (*cp == '#' || *cp == '\0') - goto done; - if ((identities = strdelimw(&cp)) == NULL) { - error("%s:%lu: invalid line", path, linenum); - goto done; - } - if (match_pattern_list(principal, identities, 0) != 1) { - /* principal didn't match */ - goto done; - } - debug("%s: %s:%lu: matched principal \"%s\"", - __func__, path, linenum, principal); + return SSH_ERR_KEY_NOT_FOUND; /* blank or all-comment line */ - if (sshkey_read(found_key, &cp) != 0) { + /* format: identity[,identity...] [option[,option...]] key */ + if ((tmp = strdelimw(&cp)) == NULL) { + error("%s:%lu: invalid line", path, linenum); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((principals = strdup(tmp)) == NULL) { + error_f("strdup failed"); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + /* + * Bail out early if we're looking for a particular principal and this + * line does not list it. + */ + if (required_principal != NULL) { + if (match_pattern_list(required_principal, + principals, 0) != 1) { + /* principal didn't match */ + r = SSH_ERR_KEY_NOT_FOUND; + goto out; + } + debug_f("%s:%lu: matched principal \"%s\"", + path, linenum, required_principal); + } + + if ((key = sshkey_new(KEY_UNSPEC)) == NULL) { + error_f("sshkey_new failed"); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + if (sshkey_read(key, &cp) != 0) { /* no key? Check for options */ opts = cp; if (sshkey_advance_past_options(&cp) != 0) { - error("%s:%lu: invalid options", - path, linenum); - goto done; + error("%s:%lu: invalid options", path, linenum); + r = SSH_ERR_INVALID_FORMAT; + goto out; } *cp++ = '\0'; skip_space(&cp); - if (sshkey_read(found_key, &cp) != 0) { - error("%s:%lu: invalid key", path, - linenum); - goto done; + if (sshkey_read(key, &cp) != 0) { + error("%s:%lu: invalid key", path, linenum); + r = SSH_ERR_INVALID_FORMAT; + goto out; } } debug3("%s:%lu: options %s", path, linenum, opts == NULL ? "" : opts); if ((sigopts = sshsigopt_parse(opts, path, linenum, &reason)) == NULL) { error("%s:%lu: bad options: %s", path, linenum, reason); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + /* success */ + if (principalsp != NULL) { + *principalsp = principals; + principals = NULL; /* transferred */ + } + if (sigoptsp != NULL) { + *sigoptsp = sigopts; + sigopts = NULL; /* transferred */ + } + if (keyp != NULL) { + *keyp = key; + key = NULL; /* transferred */ + } + r = 0; + out: + free(principals); + sshsigopt_free(sigopts); + sshkey_free(key); + return r; +} + +static int +check_allowed_keys_line(const char *path, u_long linenum, char *line, + const struct sshkey *sign_key, const char *principal, + const char *sig_namespace) +{ + struct sshkey *found_key = NULL; + int r, found = 0; + const char *reason = NULL; + struct sshsigopt *sigopts = NULL; + + /* Parse the line */ + if ((r = parse_principals_key_and_options(path, linenum, line, + principal, NULL, &found_key, &sigopts)) != 0) { + /* error already logged */ goto done; } @@ -741,7 +809,7 @@ check_allowed_keys_line(const char *path, u_long linenum, char *line, } else if (sigopts->ca && sshkey_is_cert(sign_key) && sshkey_equal_public(sign_key->cert->signature_key, found_key)) { /* Match of certificate's CA key */ - if ((r = sshkey_cert_check_authority(sign_key, 0, 1, + if ((r = sshkey_cert_check_authority(sign_key, 0, 1, 0, principal, &reason)) != 0) { error("%s:%lu: certificate not authorized: %s", path, linenum, reason); @@ -768,7 +836,7 @@ sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key, char *line = NULL; size_t linesize = 0; u_long linenum = 0; - int r, oerrno; + int r = SSH_ERR_INTERNAL_ERROR, oerrno; /* Check key and principal against file */ if ((f = fopen(path, "r")) == NULL) { @@ -785,6 +853,7 @@ sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key, principal, sig_namespace); free(line); line = NULL; + linesize = 0; if (r == SSH_ERR_KEY_NOT_FOUND) continue; else if (r == 0) { @@ -799,3 +868,175 @@ sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key, free(line); return r == 0 ? SSH_ERR_KEY_NOT_FOUND : r; } + +static int +cert_filter_principals(const char *path, u_long linenum, + char **principalsp, const struct sshkey *cert) +{ + char *cp, *oprincipals, *principals; + const char *reason; + struct sshbuf *nprincipals; + int r = SSH_ERR_INTERNAL_ERROR, success = 0; + + oprincipals = principals = *principalsp; + *principalsp = NULL; + + if ((nprincipals = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + + while ((cp = strsep(&principals, ",")) != NULL && *cp != '\0') { + if (strcspn(cp, "!?*") != strlen(cp)) { + debug("%s:%lu: principal \"%s\" not authorized: " + "contains wildcards", path, linenum, cp); + continue; + } + /* Check against principals list in certificate */ + if ((r = sshkey_cert_check_authority(cert, 0, 1, 0, + cp, &reason)) != 0) { + debug("%s:%lu: principal \"%s\" not authorized: %s", + path, linenum, cp, reason); + continue; + } + if ((r = sshbuf_putf(nprincipals, "%s%s", + sshbuf_len(nprincipals) != 0 ? "," : "", cp)) != 0) { + error_f("buffer error"); + goto out; + } + } + if (sshbuf_len(nprincipals) == 0) { + error("%s:%lu: no valid principals found", path, linenum); + r = SSH_ERR_KEY_CERT_INVALID; + goto out; + } + if ((principals = sshbuf_dup_string(nprincipals)) == NULL) { + error_f("buffer error"); + goto out; + } + /* success */ + success = 1; + *principalsp = principals; + out: + sshbuf_free(nprincipals); + free(oprincipals); + return success ? 0 : r; +} + +static int +get_matching_principals_from_line(const char *path, u_long linenum, char *line, + const struct sshkey *sign_key, char **principalsp) +{ + struct sshkey *found_key = NULL; + char *principals = NULL; + int r, found = 0; + struct sshsigopt *sigopts = NULL; + + if (principalsp != NULL) + *principalsp = NULL; + + /* Parse the line */ + if ((r = parse_principals_key_and_options(path, linenum, line, + NULL, &principals, &found_key, &sigopts)) != 0) { + /* error already logged */ + goto done; + } + + if (!sigopts->ca && sshkey_equal(found_key, sign_key)) { + /* Exact match of key */ + debug("%s:%lu: matched key", path, linenum); + /* success */ + found = 1; + } else if (sigopts->ca && sshkey_is_cert(sign_key) && + sshkey_equal_public(sign_key->cert->signature_key, found_key)) { + /* Remove principals listed in file but not allowed by cert */ + if ((r = cert_filter_principals(path, linenum, + &principals, sign_key)) != 0) { + /* error already displayed */ + debug_r(r, "%s:%lu: cert_filter_principals", + path, linenum); + goto done; + } + debug("%s:%lu: matched certificate CA key", path, linenum); + /* success */ + found = 1; + } else { + /* Key didn't match */ + goto done; + } + done: + if (found && principalsp != NULL) { + *principalsp = principals; + principals = NULL; /* transferred */ + } + free(principals); + sshkey_free(found_key); + sshsigopt_free(sigopts); + return found ? 0 : SSH_ERR_KEY_NOT_FOUND; +} + +int +sshsig_find_principals(const char *path, const struct sshkey *sign_key, + char **principals) +{ + FILE *f = NULL; + char *line = NULL; + size_t linesize = 0; + u_long linenum = 0; + int r = SSH_ERR_INTERNAL_ERROR, oerrno; + + if ((f = fopen(path, "r")) == NULL) { + oerrno = errno; + error("Unable to open allowed keys file \"%s\": %s", + path, strerror(errno)); + errno = oerrno; + return SSH_ERR_SYSTEM_ERROR; + } + + while (getline(&line, &linesize, f) != -1) { + linenum++; + r = get_matching_principals_from_line(path, linenum, line, + sign_key, principals); + free(line); + line = NULL; + linesize = 0; + if (r == SSH_ERR_KEY_NOT_FOUND) + continue; + else if (r == 0) { + /* success */ + fclose(f); + return 0; + } else + break; + } + free(line); + /* Either we hit an error parsing or we simply didn't find the key */ + if (ferror(f) != 0) { + oerrno = errno; + fclose(f); + error("Unable to read allowed keys file \"%s\": %s", + path, strerror(errno)); + errno = oerrno; + return SSH_ERR_SYSTEM_ERROR; + } + fclose(f); + return r == 0 ? SSH_ERR_KEY_NOT_FOUND : r; +} + +int +sshsig_get_pubkey(struct sshbuf *signature, struct sshkey **pubkey) +{ + struct sshkey *pk = NULL; + int r = SSH_ERR_SIGNATURE_INVALID; + + if (pubkey == NULL) + return SSH_ERR_INTERNAL_ERROR; + if ((r = sshsig_parse_preamble(signature)) != 0) + return r; + if ((r = sshkey_froms(signature, &pk)) != 0) + return r; + + *pubkey = pk; + pk = NULL; + return 0; +} diff --git a/sshsig.h b/sshsig.h index e3eeb601b..67794a971 100644 --- a/sshsig.h +++ b/sshsig.h @@ -1,3 +1,4 @@ +/* $OpenBSD: sshsig.h,v 1.9 2020/08/31 00:17:41 djm Exp $ */ /* * Copyright (c) 2019 Google LLC * @@ -20,9 +21,11 @@ struct sshbuf; struct sshkey; struct sshsigopt; +struct sshkey_sig_details; typedef int sshsig_signer(struct sshkey *, u_char **, size_t *, - const u_char *, size_t, const char *, u_int, void *); + const u_char *, size_t, const char *, const char *, const char *, + u_int, void *); /* Buffer-oriented API */ @@ -32,8 +35,9 @@ typedef int sshsig_signer(struct sshkey *, u_char **, size_t *, * out is populated with the detached signature, or NULL on failure. */ int sshsig_signb(struct sshkey *key, const char *hashalg, - const struct sshbuf *message, const char *sig_namespace, - struct sshbuf **out, sshsig_signer *signer, void *signer_ctx); + const char *sk_provider, const char *sk_pin, const struct sshbuf *message, + const char *sig_namespace, struct sshbuf **out, + sshsig_signer *signer, void *signer_ctx); /* * Verifies that a detached signature is valid and optionally returns key @@ -42,7 +46,7 @@ int sshsig_signb(struct sshkey *key, const char *hashalg, */ int sshsig_verifyb(struct sshbuf *signature, const struct sshbuf *message, const char *sig_namespace, - struct sshkey **sign_keyp); + struct sshkey **sign_keyp, struct sshkey_sig_details **sig_details); /* File/FD-oriented API */ @@ -52,8 +56,9 @@ int sshsig_verifyb(struct sshbuf *signature, * out is populated with the detached signature, or NULL on failure. */ int sshsig_sign_fd(struct sshkey *key, const char *hashalg, - int fd, const char *sig_namespace, struct sshbuf **out, - sshsig_signer *signer, void *signer_ctx); + const char *sk_provider, const char *sk_pin, + int fd, const char *sig_namespace, + struct sshbuf **out, sshsig_signer *signer, void *signer_ctx); /* * Verifies that a detached signature over a file is valid and optionally @@ -61,7 +66,8 @@ int sshsig_sign_fd(struct sshkey *key, const char *hashalg, * Returns 0 on success or a negative SSH_ERR_* error code on failure. */ int sshsig_verify_fd(struct sshbuf *signature, int fd, - const char *sig_namespace, struct sshkey **sign_keyp); + const char *sig_namespace, struct sshkey **sign_keyp, + struct sshkey_sig_details **sig_details); /* Utility functions */ @@ -89,4 +95,13 @@ struct sshsigopt *sshsigopt_parse(const char *opts, /* Free signature options */ void sshsigopt_free(struct sshsigopt *opts); +/* Get public key from signature */ +int sshsig_get_pubkey(struct sshbuf *signature, struct sshkey **pubkey); + +/* Find principal in allowed_keys file, given a sshkey. Returns + * 0 on success. + */ +int sshsig_find_principals(const char *path, const struct sshkey *sign_key, + char **principal); + #endif /* SSHSIG_H */ diff --git a/ttymodes.c b/ttymodes.c index f0c2a5d37..1d20ce800 100644 --- a/ttymodes.c +++ b/ttymodes.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ttymodes.c,v 1.34 2018/07/09 21:20:26 markus Exp $ */ +/* $OpenBSD: ttymodes.c,v 1.36 2021/01/27 09:26:54 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -283,11 +283,11 @@ ssh_tty_make_modes(struct ssh *ssh, int fd, struct termios *tiop) int r, ibaud, obaud; if ((buf = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if (tiop == NULL) { if (fd == -1) { - debug("%s: no fd or tio", __func__); + debug_f("no fd or tio"); goto end; } if (tcgetattr(fd, &tio) == -1) { @@ -304,23 +304,23 @@ ssh_tty_make_modes(struct ssh *ssh, int fd, struct termios *tiop) (r = sshbuf_put_u32(buf, obaud)) != 0 || (r = sshbuf_put_u8(buf, TTY_OP_ISPEED)) != 0 || (r = sshbuf_put_u32(buf, ibaud)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "compose"); /* Store values of mode flags. */ #define TTYCHAR(NAME, OP) \ if ((r = sshbuf_put_u8(buf, OP)) != 0 || \ (r = sshbuf_put_u32(buf, \ special_char_encode(tio.c_cc[NAME]))) != 0) \ - fatal("%s: buffer error: %s", __func__, ssh_err(r)); \ + fatal_fr(r, "compose %s", #NAME); #define SSH_TTYMODE_IUTF8 42 /* for SSH_BUG_UTF8TTYMODE */ #define TTYMODE(NAME, FIELD, OP) \ - if (OP == SSH_TTYMODE_IUTF8 && (datafellows & SSH_BUG_UTF8TTYMODE)) { \ - debug3("%s: SSH_BUG_UTF8TTYMODE", __func__); \ + if (OP == SSH_TTYMODE_IUTF8 && (ssh->compat & SSH_BUG_UTF8TTYMODE)) { \ + debug3_f("SSH_BUG_UTF8TTYMODE"); \ } else if ((r = sshbuf_put_u8(buf, OP)) != 0 || \ (r = sshbuf_put_u32(buf, ((tio.FIELD & NAME) != 0))) != 0) \ - fatal("%s: buffer error: %s", __func__, ssh_err(r)); \ + fatal_fr(r, "compose %s", #NAME); #include "ttymodes.h" @@ -331,7 +331,7 @@ end: /* Mark end of mode data. */ if ((r = sshbuf_put_u8(buf, TTY_OP_END)) != 0 || (r = sshpkt_put_stringb(ssh, buf)) != 0) - fatal("%s: packet error: %s", __func__, ssh_err(r)); + fatal_fr(r, "compose end"); sshbuf_free(buf); } @@ -351,11 +351,11 @@ ssh_tty_parse_modes(struct ssh *ssh, int fd) size_t len; if ((r = sshpkt_get_string_direct(ssh, &data, &len)) != 0) - fatal("%s: packet error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse"); if (len == 0) return; if ((buf = sshbuf_from(data, len)) == NULL) { - error("%s: sshbuf_from failed", __func__); + error_f("sshbuf_from failed"); return; } @@ -371,15 +371,14 @@ ssh_tty_parse_modes(struct ssh *ssh, int fd) while (sshbuf_len(buf) > 0) { if ((r = sshbuf_get_u8(buf, &opcode)) != 0) - fatal("%s: packet error: %s", __func__, ssh_err(r)); + fatal_fr(r, "parse opcode"); switch (opcode) { case TTY_OP_END: goto set; case TTY_OP_ISPEED: if ((r = sshbuf_get_u32(buf, &baud)) != 0) - fatal("%s: packet error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "parse ispeed"); if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) == -1) error("cfsetispeed failed for %d", baud); @@ -387,8 +386,7 @@ ssh_tty_parse_modes(struct ssh *ssh, int fd) case TTY_OP_OSPEED: if ((r = sshbuf_get_u32(buf, &baud)) != 0) - fatal("%s: packet error: %s", - __func__, ssh_err(r)); + fatal_fr(r, "parse ospeed"); if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) == -1) error("cfsetospeed failed for %d", baud); @@ -397,15 +395,13 @@ ssh_tty_parse_modes(struct ssh *ssh, int fd) #define TTYCHAR(NAME, OP) \ case OP: \ if ((r = sshbuf_get_u32(buf, &u)) != 0) \ - fatal("%s: packet error: %s", __func__, \ - ssh_err(r)); \ + fatal_fr(r, "parse %s", #NAME); \ tio.c_cc[NAME] = special_char_decode(u); \ break; #define TTYMODE(NAME, FIELD, OP) \ case OP: \ if ((r = sshbuf_get_u32(buf, &u)) != 0) \ - fatal("%s: packet error: %s", __func__, \ - ssh_err(r)); \ + fatal_fr(r, "parse %s", #NAME); \ if (u) \ tio.FIELD |= NAME; \ else \ @@ -429,12 +425,10 @@ ssh_tty_parse_modes(struct ssh *ssh, int fd) */ if (opcode > 0 && opcode < 160) { if ((r = sshbuf_get_u32(buf, NULL)) != 0) - fatal("%s: packet error: %s", __func__, - ssh_err(r)); + fatal_fr(r, "parse arg"); break; } else { - logit("%s: unknown opcode %d", __func__, - opcode); + logit_f("unknown opcode %d", opcode); goto set; } } @@ -444,7 +438,7 @@ set: len = sshbuf_len(buf); sshbuf_free(buf); if (len > 0) { - logit("%s: %zu bytes left", __func__, len); + logit_f("%zu bytes left", len); return; /* Don't process bytes passed */ } if (failure == -1) diff --git a/umac.c b/umac.c index ccae39f30..3d4e285bb 100644 --- a/umac.c +++ b/umac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: umac.c,v 1.17 2018/04/10 00:10:49 djm Exp $ */ +/* $OpenBSD: umac.c,v 1.20 2020/03/13 03:17:07 djm Exp $ */ /* ----------------------------------------------------------------------- * * umac.c -- C Implementation UMAC Message Authentication @@ -39,7 +39,7 @@ * at http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ (search for * "Barreto"). The only two files needed are rijndael-alg-fst.c and * rijndael-alg-fst.h. Brian Gladman's version is distributed with the GNU - * Public lisence at http://fp.gladman.plus.com/AES/index.htm. It + * Public license at http://fp.gladman.plus.com/AES/index.htm. It * includes a fast IA-32 assembly version. The OpenSSL crypo library is * the third. * @@ -74,6 +74,7 @@ #include "includes.h" #include #include +#include #include #include #include @@ -1204,8 +1205,7 @@ int umac_delete(struct umac_ctx *ctx) if (ctx) { if (ALLOC_BOUNDARY) ctx = (struct umac_ctx *)ctx->free_ptr; - explicit_bzero(ctx, sizeof(*ctx) + ALLOC_BOUNDARY); - free(ctx); + freezero(ctx, sizeof(*ctx) + ALLOC_BOUNDARY); } return (1); } diff --git a/utf8.c b/utf8.c index db7cb8f35..7f63b25ae 100644 --- a/utf8.c +++ b/utf8.c @@ -1,4 +1,4 @@ -/* $OpenBSD: utf8.c,v 1.8 2018/08/21 13:56:27 schwarze Exp $ */ +/* $OpenBSD: utf8.c,v 1.11 2020/05/01 06:28:52 djm Exp $ */ /* * Copyright (c) 2016 Ingo Schwarze * @@ -43,7 +43,6 @@ static int dangerous_locale(void); static int grow_dst(char **, size_t *, size_t, char **, size_t); -static int vasnmprintf(char **, size_t, int *, const char *, va_list); /* @@ -101,7 +100,7 @@ grow_dst(char **dst, size_t *sz, size_t maxsz, char **dp, size_t need) * written is returned in *wp. */ -static int +int vasnmprintf(char **str, size_t maxsz, int *wp, const char *fmt, va_list ap) { char *src; /* Source string returned from vasprintf. */ @@ -241,7 +240,7 @@ int snmprintf(char *str, size_t sz, int *wp, const char *fmt, ...) { va_list ap; - char *cp; + char *cp = NULL; int ret; va_start(ap, fmt); @@ -255,6 +254,20 @@ snmprintf(char *str, size_t sz, int *wp, const char *fmt, ...) return ret; } +int +asmprintf(char **outp, size_t sz, int *wp, const char *fmt, ...) +{ + va_list ap; + int ret; + + *outp = NULL; + va_start(ap, fmt); + ret = vasnmprintf(outp, sz, wp, fmt, ap); + va_end(ap); + + return ret; +} + /* * To stay close to the standard interfaces, the following functions * return the number of non-NUL bytes written. @@ -263,11 +276,13 @@ snmprintf(char *str, size_t sz, int *wp, const char *fmt, ...) int vfmprintf(FILE *stream, const char *fmt, va_list ap) { - char *str; + char *str = NULL; int ret; - if ((ret = vasnmprintf(&str, INT_MAX, NULL, fmt, ap)) < 0) + if ((ret = vasnmprintf(&str, INT_MAX, NULL, fmt, ap)) < 0) { + free(str); return -1; + } if (fputs(str, stream) == EOF) ret = -1; free(str); diff --git a/utf8.h b/utf8.h index 88c5a34a3..9d6d9a32c 100644 --- a/utf8.h +++ b/utf8.h @@ -1,4 +1,4 @@ -/* $OpenBSD: utf8.h,v 1.1 2016/05/25 23:48:45 schwarze Exp $ */ +/* $OpenBSD: utf8.h,v 1.3 2020/05/01 06:28:52 djm Exp $ */ /* * Copyright (c) 2016 Ingo Schwarze * @@ -15,6 +15,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +int vasnmprintf(char **, size_t, int *, const char *, va_list); int mprintf(const char *, ...) __attribute__((format(printf, 1, 2))); int fmprintf(FILE *, const char *, ...) @@ -22,4 +23,6 @@ int fmprintf(FILE *, const char *, ...) int vfmprintf(FILE *, const char *, va_list); int snmprintf(char *, size_t, int *, const char *, ...) __attribute__((format(printf, 4, 5))); +int asmprintf(char **, size_t, int *, const char *, ...) + __attribute__((format(printf, 4, 5))); void msetlocale(void); diff --git a/version.h b/version.h index bdc8adb0d..067b356e0 100644 --- a/version.h +++ b/version.h @@ -1,4 +1,4 @@ -/* $OpenBSD: version.h,v 1.85 2019/10/09 00:04:57 djm Exp $ */ +/* $OpenBSD: version.h,v 1.89 2021/03/02 01:48:18 djm Exp $ */ #define SSH_VERSION "OpenSSH_for_Windows_8.1" diff --git a/xmalloc.c b/xmalloc.c index 9cd0127dd..b48d33bbf 100644 --- a/xmalloc.c +++ b/xmalloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xmalloc.c,v 1.35 2019/06/06 05:13:13 otto Exp $ */ +/* $OpenBSD: xmalloc.c,v 1.36 2019/11/12 22:32:48 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -95,6 +95,17 @@ xstrdup(const char *str) return cp; } +int +xvasprintf(char **ret, const char *fmt, va_list ap) +{ + int i; + + i = vasprintf(ret, fmt, ap); + if (i < 0 || *ret == NULL) + fatal("xvasprintf: could not allocate memory"); + return i; +} + int xasprintf(char **ret, const char *fmt, ...) { @@ -102,11 +113,7 @@ xasprintf(char **ret, const char *fmt, ...) int i; va_start(ap, fmt); - i = vasprintf(ret, fmt, ap); + i = xvasprintf(ret, fmt, ap); va_end(ap); - - if (i < 0 || *ret == NULL) - fatal("xasprintf: could not allocate memory"); - - return (i); + return i; } diff --git a/xmalloc.h b/xmalloc.h index 1d5f62df7..abaf7ada2 100644 --- a/xmalloc.h +++ b/xmalloc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: xmalloc.h,v 1.18 2019/06/06 05:13:13 otto Exp $ */ +/* $OpenBSD: xmalloc.h,v 1.19 2019/11/12 22:32:48 djm Exp $ */ /* * Author: Tatu Ylonen @@ -24,3 +24,5 @@ char *xstrdup(const char *); int xasprintf(char **, const char *, ...) __attribute__((__format__ (printf, 2, 3))) __attribute__((__nonnull__ (2))); +int xvasprintf(char **, const char *, va_list) + __attribute__((__nonnull__ (2)));