diff --git a/crypto/openssh/.depend b/crypto/openssh/.depend index 259bf3b2f136..4897698ab74a 100644 --- a/crypto/openssh/.depend +++ b/crypto/openssh/.depend @@ -1,178 +1,179 @@ # Automatically generated by makedepend. # Run "make depend" to rebuild. # 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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 xmalloc.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h canohost.h auth2-hostbased.o: monitor_wrap.h pathnames.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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-pubkeyfile.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 log.h ssherr.h misc.h sshkey.h digest.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h authfile.h match.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h pathnames.h monitor_wrap.h digest.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h pathnames.h monitor_wrap.h digest.h kex.h +auth2.o: mac.h crypto_api.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 myproposal.h sshbuf.h digest.h xmalloc.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 misc.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 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 uidswap.h readconf.o: 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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 atomicio.h pathnames.h log.h ssherr.h misc.h progressmeter.h utf8.h sftp.h sftp-common.h sftp-client.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 pathnames.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h servconf.o: 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: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 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 session.o: 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 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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 channels.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 sshbuf.h ssherr.h log.h misc.h match.h uidswap.h sftp.h sftp-common.h sftp-usergroup.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 log.h ssherr.h xmalloc.h sftp-common.h sftp-client.h openbsd-compat/glob.h sftp-usergroup.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 sftp-usergroup.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 hostfile.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 log.h ssherr.h misc.h digest.h match.h msg.h pathnames.h ssh-pkcs11.h sk-api.h myproposal.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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: dispatch.h log.h ssherr.h atomicio.h misc.h hostfile.h ssh_api.h ssh2.h dns.h addr.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 digest.h kex.h mac.h crypto_api.h compat.h myproposal.h packet.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 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 authfd.h sshconnect.o: 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/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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: 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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 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 dh.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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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 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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-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/crypto/openssh/.github/configs b/crypto/openssh/.github/configs index c7d6a55ab962..df82faf5046b 100755 --- a/crypto/openssh/.github/configs +++ b/crypto/openssh/.github/configs @@ -1,351 +1,361 @@ #!/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 if [ "$config" = "" ]; then config="default" fi unset CC CFLAGS CPPFLAGS LDFLAGS LTESTS SUDO TEST_TARGET="tests compat-tests" LTESTS="" SKIP_LTESTS="" SUDO=sudo # run with sudo by default TEST_SSH_UNSAFE_PERMISSIONS=1 # Stop on first test failure to minimize logs TEST_SSH_FAIL_FATAL=yes CONFIGFLAGS="" LIBCRYPTOFLAGS="" case "$config" in default|sol64) ;; c89) # If we don't have LLONG_MAX, configure will figure out that it can # get it by setting -std=gnu99, at which point we won't be testing # C89 any more. To avoid this, feed it in via CFLAGS. llong_max=`gcc -E -dM - /dev/null)" ]; then REGRESS_INTEROP_PUTTY=yes export REGRESS_INTEROP_PUTTY fi export CC CFLAGS CPPFLAGS LDFLAGS LTESTS SUDO export TEST_TARGET TEST_SSH_UNSAFE_PERMISSIONS TEST_SSH_FAIL_FATAL diff --git a/crypto/openssh/.github/setup_ci.sh b/crypto/openssh/.github/setup_ci.sh index 010a333a6642..d0ba7b4724e9 100755 --- a/crypto/openssh/.github/setup_ci.sh +++ b/crypto/openssh/.github/setup_ci.sh @@ -1,224 +1,243 @@ #!/bin/sh PACKAGES="" . .github/configs $@ host=`./config.guess` echo "config.guess: $host" case "$host" in *cygwin) PACKAGER=setup echo Setting CYGWIN system environment variable. setx CYGWIN "binmode" echo Removing extended ACLs so umask works as expected. setfacl -b . regress PACKAGES="$PACKAGES,autoconf,automake,cygwin-devel,gcc-core" PACKAGES="$PACKAGES,make,openssl-devel,zlib-devel" ;; *-darwin*) PACKAGER=brew - brew install automake - exit 0 + PACKAGES="automake" ;; *) PACKAGER=apt esac TARGETS=$@ INSTALL_FIDO_PPA="no" export DEBIAN_FRONTEND=noninteractive -#echo "Setting up for '$TARGETS'" - -set -ex +set -e if [ -x "`which lsb_release 2>&1`" ]; then lsb_release -a fi -# Ubuntu 22.04 defaults to private home dirs which prevent the -# agent-getpeerid test from running ssh-add as nobody. See -# https://github.com/actions/runner-images/issues/6106 -if [ ! -z "$SUDO" ] && ! "$SUDO" -u nobody test -x ~; then - echo ~ is not executable by nobody, adding perms. - chmod go+x ~ +if [ ! -z "$SUDO" ]; then + # Ubuntu 22.04 defaults to private home dirs which prevent the + # agent-getpeerid test from running ssh-add as nobody. See + # https://github.com/actions/runner-images/issues/6106 + if ! "$SUDO" -u nobody test -x ~; then + echo ~ is not executable by nobody, adding perms. + chmod go+x ~ + fi + # Some of the Mac OS X runners don't have a nopasswd sudo rule. Regular + # sudo still works, but sudo -u doesn't. Restore the sudo rule. + if ! "$SUDO" grep -E 'runner.*NOPASSWD' /etc/passwd >/dev/null; then + echo "Restoring runner nopasswd rule to sudoers." + echo 'runner ALL=(ALL) NOPASSWD: ALL' |$SUDO tee -a /etc/sudoers + fi + if ! "$SUDO" -u nobody -S test -x ~ -Date: Wed Oct 4 15:34:10 2023 +1100 +Date: Tue Dec 19 01:59:50 2023 +1100 - crank version numbers + crank versions -commit f65f187b105d9b5c12fd750a211397d08c17c6d4 -Author: djm@openbsd.org -Date: Wed Oct 4 04:04:09 2023 +0000 +commit 2f2c65cb5f1518a9c556d3e8efa27ea0ca305c6b +Author: Damien Miller +Date: Tue Dec 19 01:59:06 2023 +1100 - upstream: openssh-9.5 - - OpenBSD-Commit-ID: 5e0af680480bd3b6f5560cf840ad032d48fd6b16 + depend -commit ffe27e54a4bb18d5d3bbd3f4cc93a41b8d94dfd2 +commit e48cdee8e19059203b1aeeabec2350b8375fa61f Author: djm@openbsd.org -Date: Wed Oct 4 04:03:50 2023 +0000 +Date: Mon Dec 18 14:50:08 2023 +0000 - upstream: add some cautionary text about % token expansion and - - shell metacharacters; based on report from vinci AT protonmail.ch + upstream: regress test for agent PKCS#11-backed certificates - OpenBSD-Commit-ID: aa1450a54fcee2f153ef70368d90edb1e7019113 + OpenBSD-Regress-ID: 38f681777cb944a8cc3bf9d0ad62959a16764df9 -commit 60ec3d54fd1ebfe2dda75893fa1e870b8dffbb0d +commit 2f512f862df1d5f456f82a0334c9e8cc7208a2a1 Author: djm@openbsd.org -Date: Tue Oct 3 23:56:10 2023 +0000 +Date: Mon Dec 18 14:49:39 2023 +0000 - upstream: fix link to agent draft; spotted by Jann Horn + upstream: regress test for constrained PKCS#11 keys - OpenBSD-Commit-ID: ff5bda21a83ec013db683e282256a85201d2dc4b + OpenBSD-Regress-ID: b2f26ae95d609d12257b43aef7cd7714c82618ff -commit 12e2d4b13f6f63ce2de13cbfcc9e4d0d4b4ab231 -Author: Damien Miller -Date: Wed Oct 4 10:54:04 2023 +1100 +commit cdddd66412ca5920ed4d3ebbfa6ace12dbd9b82f +Author: djm@openbsd.org +Date: Mon Dec 18 14:48:44 2023 +0000 - use portable provider allowlist path in manpage + upstream: openssh-9.6 - spotted by Jann Horn + OpenBSD-Commit-ID: 21759837cf0e0092d9a2079f8fb562071c11016b -commit 6c2c6ffde75df95fd838039850d3dd3d84956d87 -Author: deraadt@openbsd.org -Date: Tue Sep 19 20:37:07 2023 +0000 +commit 6d51feab157cedf1e7ef5b3f8781ca8ff9c4ab1b +Author: djm@openbsd.org +Date: Mon Dec 18 14:48:08 2023 +0000 - upstream: typo; from Jim Spath + upstream: ssh-agent: record failed session-bind attempts - OpenBSD-Commit-ID: 2f5fba917b5d4fcf93d9e0b0756c7f63189e228e + Record failed attempts to session-bind a connection and refuse signing + operations on that connection henceforth. + + Prevents a future situation where we add a new hostkey type that is not + recognised by an older ssh-agent, that consequently causes session-bind + to fail (this situation is only likely to arise when people mix ssh(1) + and ssh-agent(1) of different versions on the same host). Previously, + after such a failure the agent socket would be considered unbound and + not subject to restriction. + + Spotted by Jann Horn + + OpenBSD-Commit-ID: b0fdd023e920aa4831413f640de4c5307b53552e -commit b6b49130a0089b297245ee39e769231d7c763014 +commit 7ef3787c84b6b524501211b11a26c742f829af1a Author: djm@openbsd.org -Date: Sun Sep 10 23:12:32 2023 +0000 +Date: Mon Dec 18 14:47:44 2023 +0000 - upstream: rename remote_glob() -> sftp_glob() to match other API + upstream: ban user/hostnames with most shell metacharacters - OpenBSD-Commit-ID: d9dfb3708d824ec02970a84d96cf5937e0887229 + This makes ssh(1) refuse user or host names provided on the + commandline that contain most shell metacharacters. + + Some programs that invoke ssh(1) using untrusted data do not filter + metacharacters in arguments they supply. This could create + interactions with user-specified ProxyCommand and other directives + that allow shell injection attacks to occur. + + It's a mistake to invoke ssh(1) with arbitrary untrusted arguments, + but getting this stuff right can be tricky, so this should prevent + most obvious ways of creating risky situations. It however is not + and cannot be perfect: ssh(1) has no practical way of interpreting + what shell quoting rules are in use and how they interact with the + user's specified ProxyCommand. + + To allow configurations that use strange user or hostnames to + continue to work, this strictness is applied only to names coming + from the commandline. Names specified using User or Hostname + directives in ssh_config(5) are not affected. + + feedback/ok millert@ markus@ dtucker@ deraadt@ + + OpenBSD-Commit-ID: 3b487348b5964f3e77b6b4d3da4c3b439e94b2d9 -commit 21b79af6c8d2357c822c84cef3fbdb8001ed263b +commit 0cb50eefdd29f0fec31d0e71cc4b004a5f704e67 Author: djm@openbsd.org -Date: Sun Sep 10 03:51:55 2023 +0000 +Date: Mon Dec 18 14:47:20 2023 +0000 - upstream: typo in comment + upstream: stricter handling of channel window limits - OpenBSD-Commit-ID: 69285e0ce962a7c6b0ab5f17a293c60a0a360a18 - -commit 41232d25532b4d2ef6c5db62efc0cf50a79d26ca -Author: Darren Tucker -Date: Sun Sep 10 15:45:38 2023 +1000 - - Use zero-call-used-regs=used with Apple compilers. + This makes ssh/sshd more strict in handling non-compliant peers that + send more data than the advertised channel window allows. Previously + the additional data would be silently discarded. This change will + cause ssh/sshd to terminate the connection if the channel window is + exceeded by more than a small grace allowance. - Apple's versions of clang have version numbers that do not match the - corresponding upstream clang versions. Unfortunately, they do still - have the clang-15 zero-call-used-regs=all bug, so for now use the value - that doesn't result in segfaults. We could allowlist future versions - that are known to work. bz#3584 (and probably also our github CI - failures). + ok markus@ + + OpenBSD-Commit-ID: 811e21b41831eba3dd7f67b3d409a438f20d3037 -commit 90ccc5918ea505bf156c31148b6b59a1bf5d6dc6 +commit 4448a2938abc76e6bd33ba09b2ec17a216dfb491 Author: djm@openbsd.org -Date: Sun Sep 10 03:25:53 2023 +0000 +Date: Mon Dec 18 14:46:56 2023 +0000 - upstream: randomise keystroke obfuscation intervals and average + upstream: Make it possible to load certs from PKCS#11 tokens - interval rate. ok dtucker@ + Adds a protocol extension to allow grafting certificates supplied by + ssh-add to keys loaded from PKCS#11 tokens in the agent. - OpenBSD-Commit-ID: 05f61d051ab418fcfc4857ff306e420037502382 + feedback/ok markus@ + + OpenBSD-Commit-ID: bb5433cd28ede2bc910996eb3c0b53e20f86037f -commit bd1b9e52f5fa94d87223c90905c5fdc1a7c32aa6 +commit 881d9c6af9da4257c69c327c4e2f1508b2fa754b Author: djm@openbsd.org -Date: Fri Sep 8 06:34:24 2023 +0000 +Date: Mon Dec 18 14:46:12 2023 +0000 - upstream: fix sizeof(*ptr) instead sizeof(ptr) in realloc (pointer here + upstream: apply destination constraints to all p11 keys - is char**, so harmless); spotted in CID 416964 + Previously applied only to the first key returned from each token. - OpenBSD-Commit-ID: c61caa4a5a667ee20bb1042098861e6c72c69002 + ok markus@ + + OpenBSD-Commit-ID: 36df3afb8eb94eec6b2541f063d0d164ef8b488d -commit c4f966482983e18601eec70a1563115de836616f +commit a7ed931caeb68947d30af8a795f4108b6efad761 Author: djm@openbsd.org -Date: Fri Sep 8 06:10:57 2023 +0000 +Date: Mon Dec 18 14:45:49 2023 +0000 - upstream: regress test recursive remote-remote directories copies where + upstream: add "ext-info-in-auth@openssh.com" extension - the directory contains a symlink to another directory. + This adds another transport protocol extension to allow a sshd to send + SSH2_MSG_EXT_INFO during user authentication, after the server has + learned the username that is being logged in to. - also remove errant `set -x` that snuck in at some point + This lets sshd to update the acceptable signature algoritms for public + key authentication, and allows these to be varied via sshd_config(5) + "Match" directives, which are evaluated after the server learns the + username being authenticated. - OpenBSD-Regress-ID: 1c94a48bdbd633ef2285954ee257725cd7bc456f + Full details in the PROTOCOL file + + OpenBSD-Commit-ID: 1de7da7f2b6c32a46043d75fcd49b0cbb7db7779 -commit 5e1dfe5014ebc194641678303e22ab3bba15f4e5 +commit 1edb00c58f8a6875fad6a497aa2bacf37f9e6cd5 Author: djm@openbsd.org -Date: Fri Sep 8 06:10:02 2023 +0000 +Date: Mon Dec 18 14:45:17 2023 +0000 - upstream: fix recursive remote-remote copies of directories that + upstream: implement "strict key exchange" in ssh and sshd - contain symlinks to other directories (similar to bz3611) + This adds a protocol extension to improve the integrity of the SSH + transport protocol, particular in and around the initial key exchange + (KEX) phase. - OpenBSD-Commit-ID: 7e19d2ae09b4f941bf8eecc3955c9120171da37f + Full details of the extension are in the PROTOCOL file. + + with markus@ + + OpenBSD-Commit-ID: 2a66ac962f0a630d7945fee54004ed9e9c439f14 -commit 7c0ce2bf98b303b6ad91493ee3247d96c18ba1f6 -Author: djm@openbsd.org -Date: Fri Sep 8 05:50:57 2023 +0000 +commit 59d691b886c79e70b1d1c4ab744e81fd176222fd +Author: Damien Miller +Date: Mon Dec 18 14:49:11 2023 +1100 - upstream: regress test for recursive copies of directories containing + better detection of broken -fzero-call-used-regs - symlinks to other directories. bz3611, ok dtucker@ + Use OSSH_CHECK_CFLAG_LINK() for detection of these flags and extend + test program to exercise varargs, which seems to catch more stuff. - OpenBSD-Regress-ID: eaa4c29cc5cddff4e72a16bcce14aeb1ecfc94b9 + ok dtucker@ -commit 2de990142a83bf60ef694378b8598706bc654b08 +commit aa7b21708511a6d4aed3839fc9f6e82e849dd4a1 Author: djm@openbsd.org -Date: Fri Sep 8 05:56:13 2023 +0000 +Date: Wed Dec 13 03:28:19 2023 +0000 - upstream: the sftp code was one of my first contributions to + upstream: when invoking KnownHostsCommand to determine the order of - OpenSSH and it shows - the function names are terrible. + host key algorithms to request, ensure that the hostname passed to the + command is decorated with the port number for ports other than 22. - Rename do_blah() to sftp_blah() to make them less so. + This matches the behaviour of KnownHostsCommand when invoked to look + up the actual host key. - Completely mechanical except for sftp_stat() and sftp_lstat() which - change from returning a pointer to a static variable (error-prone) to - taking a pointer to a caller-provided receiver. + bz3643, ok dtucker@ - OpenBSD-Commit-ID: eb54d6a72d0bbba4d623e2175cf5cc4c75dc2ba4 + OpenBSD-Commit-ID: 5cfabc0b7c6c7ab473666df314f377b1f15420b1 -commit 249d8bd0472b53e3a2a0e138b4c030a31e83346a -Author: djm@openbsd.org -Date: Fri Sep 8 05:50:12 2023 +0000 +commit 4086bd6652c0badccc020218a62190a7798fb72c +Author: markus@openbsd.org +Date: Fri Dec 8 09:18:39 2023 +0000 - upstream: fix scp in SFTP mode recursive upload and download of - - directories that contain symlinks to other directories. In scp mode, the - links would be followed, but in SFTP mode they were not. bz3611, ok dtucker@ + upstream: prevent leak in sshsig_match_principals; ok djm@ - OpenBSD-Commit-ID: 9760fda668eaa94a992250d7670dfbc62a45197c + OpenBSD-Commit-ID: 594f61ad4819ff5c72dfe99ba666a17f0e1030ae -commit 0e1f4401c466fa4fdaea81b6dadc8dd1fc4cf0af +commit 19d3ee2f3adf7d9a606ff015c1e153744702c4c9 Author: djm@openbsd.org -Date: Wed Sep 6 23:36:09 2023 +0000 +Date: Wed Dec 6 21:06:48 2023 +0000 - upstream: regression test for override of subsystem in match blocks + upstream: short circuit debug log processing early if we're not going - OpenBSD-Regress-ID: 5f8135da3bfda71067084c048d717b0e8793e87c + to log anything. From Kobe Housen + + OpenBSD-Commit-ID: 2bcddd695872a1bef137cfff7823044dcded90ea -commit 8a1450c62035e834d8a79a5d0d1c904236f9dcfe -Author: djm@openbsd.org -Date: Wed Sep 6 23:35:35 2023 +0000 +commit 947affad4831df015c498c00c6351ea6f13895d5 +Author: Darren Tucker +Date: Mon Nov 27 09:37:28 2023 +1100 - upstream: allow override of Sybsystem directives in sshd Match - - blocks + Add tests for OpenSSL 3.2.0 and 3.2 stable branch. + +commit 747dce36206675ca6b885010a835733df469351b +Author: Darren Tucker +Date: Sat Nov 25 09:03:38 2023 +1100 + + Use non-zero arg in compiler test program. - OpenBSD-Commit-ID: 3911d18a826a2d2fe7e4519075cf3e57af439722 + Now that we're running the test program, passing zero to the test function + can cause divide-by-zero exceptions which might show up in logs. -commit 6e52826e2a74d077147a82ead8d4fbd5b54f4e3b -Author: djm@openbsd.org -Date: Wed Sep 6 23:26:37 2023 +0000 +commit 3d44a5c56585d1c351dbc006240a591b6da502b1 +Author: dtucker@openbsd.org +Date: Fri Nov 24 00:31:30 2023 +0000 - upstream: allocate the subsystems array as necessary and remove the + upstream: Plug mem leak of msg when processing a quit message. - fixed limit of subsystems. Saves a few kb of memory in the server and makes - it more like the other options. + Coverity CID#427852, ok djm@ - OpenBSD-Commit-ID: e683dfca6bdcbc3cc339bb6c6517c0c4736a547f + OpenBSD-Commit-ID: bf85362addbe2134c3d8c4b80f16601fbff823b7 -commit e19069c9fac4c111d6496b19c7f7db43b4f07b4f -Author: djm@openbsd.org -Date: Wed Sep 6 23:23:53 2023 +0000 +commit 1d7f9b6e297877bd00973e6dc5c0642dbefc3b5f +Author: dtucker@openbsd.org +Date: Thu Nov 23 03:37:05 2023 +0000 - upstream: preserve quoting of Subsystem commands and arguments. + upstream: Include existing mux path in debug message. - This may change behaviour of exotic configurations, but the most common - subsystem configuration (sftp-server) is unlikely to be affected. + OpenBSD-Commit-ID: 1c3641be10c2f4fbad2a1b088a441d072e18bf16 + +commit f29934066bd0e561a2e516b7e584fb92d2eedee0 +Author: Darren Tucker +Date: Thu Nov 23 19:41:27 2023 +1100 + + Add an Ubuntu 22.04 test VM. - OpenBSD-Commit-ID: 8ffa296aeca981de5b0945242ce75aa6dee479bf + This is the same version as Github's runners so most of the testing on + it is over there, but having a local VM makes debugging much easier. -commit 52dfe3c72d98503d8b7c6f64fc7e19d685636c0b -Author: djm@openbsd.org -Date: Wed Sep 6 23:21:36 2023 +0000 +commit a93284a780cd3972afe5f89086b75d564ba157f3 +Author: Darren Tucker +Date: Thu Nov 23 19:36:22 2023 +1100 - upstream: downgrade duplicate Subsystem directives from being a + Add gcc-12 -Werror test on Ubuntu 22.04. - fatal error to being a debug message to match behaviour with just about all - other directives. + Explictly specify gcc-11 on Ubuntu 22.04 (it's the system compiler). + +commit 670f5a647e98b6fd95ad64f789f87ee3274b481b +Author: Darren Tucker +Date: Thu Nov 23 19:34:57 2023 +1100 + + Check return value from write to prevent warning. - OpenBSD-Commit-ID: fc90ed2cc0c18d4eb8e33d2c5e98d25f282588ce + ... and since we're testing for flags with -Werror, this caused + configure to mis-detect compiler flags. -commit 1ee0a16e07b6f0847ff463d7b5221c4bf1876e25 -Author: djm@openbsd.org -Date: Wed Sep 6 23:18:15 2023 +0000 +commit cea007d691cfedfa07a5b8599f97ce0511f53fc9 +Author: Darren Tucker +Date: Wed Nov 22 21:18:55 2023 +1100 - upstream: handle cr+lf (instead of just cr) in sshsig signature + Run compiler test program when compiling natively. - files + ok djm@ + +commit ee0d305828f13536c0a416bbf9c3e81039d9ea55 +Author: Darren Tucker +Date: Wed Nov 22 21:18:07 2023 +1100 + + Factor out compiler test program into a macro. - OpenBSD-Commit-ID: 647460a212b916540016d066568816507375fd7f + ok djm@ -commit e1c284d60a928bcdd60bc575c6f9604663502770 -Author: job@openbsd.org -Date: Mon Sep 4 10:29:58 2023 +0000 +commit de304c76316b029df460673725a9104224b9959b +Author: Darren Tucker +Date: Wed Nov 22 08:55:36 2023 +1100 - upstream: Generate Ed25519 keys when invoked without arguments + Add fbsd14 VM to test pool. + +commit 99a2df5e1994cdcb44ba2187b5f34d0e9190be91 +Author: Darren Tucker +Date: Tue Nov 21 16:19:29 2023 +1100 + + Expand -fzero-call-used-regs test to cover gcc 11. - Ed25519 public keys are very convenient due to their small size. - OpenSSH has supported Ed25519 since version 6.5 (January 2014). + It turns out that gcc also has some problems with -fzero-call-used-regs, + at least v11 on mips. Previously the test in OSSH_CHECK_CFLAG_COMPILE + was sufficient to catch it with "=all", but not sufficient for "=used". + Expand the testcase and include it in the other tests for good measure. + See bz#3629. ok djm@. + +commit ff220d4010717f7bfbbc02a2400666fb9d24f250 +Author: Darren Tucker +Date: Tue Nov 21 14:04:34 2023 +1100 + + Stop using -fzero-call-used-regs=all - OK djm@ markus@ sthen@ deraadt@ + ... since it seems to be problematic with several different versions of + clang. Only use -fzero-call-used-regs=used which is less + problematic, except with Apple's clang where we don't use it at all. + bz#3629, ok djm@ + +commit 2a19e02f36b16f0f6cc915f7d1e60ead5e36303b +Author: Darren Tucker +Date: Tue Nov 21 14:02:18 2023 +1100 + + Allow for vendor prefix on clang version numbers. - OpenBSD-Commit-ID: f498beaad19c8cdcc357381a60df4a9c69858b3f + Correctly detects the version of OpenBSD's native clang, as well as + Apple's. Spotted tb@, ok djm@. -commit 694150ad92765574ff82a18f4e86322bd3231e68 +commit c52db0114826d73eff6cdbf205e9c1fa4f7ca6c6 Author: djm@openbsd.org -Date: Mon Sep 4 00:08:14 2023 +0000 +Date: Mon Nov 20 02:50:00 2023 +0000 - upstream: trigger keystroke timing obfucation only if the channels - - layer enqueud some data in the last poll() cycle; this avoids triggering the - obfuscatior for non-channels data like ClientAlive probes and also fixes a - related problem were the obfucations would be triggered on fully quiescent - connections. + upstream: set errno=EAFNOSUPPORT when filtering addresses that don't - Based on / tested by naddy@ + match AddressFamily; yields slightly better error message if no address + matches. bz#3526 - OpenBSD-Commit-ID: d98f32dc62d7663ff4660e4556e184032a0db123 + OpenBSD-Commit-ID: 29cea900ddd8b04a4d1968da5c4a893be2ebd9e6 -commit b5fd97896b59a3a46245cf438cc8b16c795d9f74 +commit 26f3f3bbc69196d908cad6558c8c7dc5beb8d74a Author: djm@openbsd.org -Date: Mon Sep 4 00:04:02 2023 +0000 +Date: Wed Nov 15 23:03:38 2023 +0000 - upstream: avoid bogus "obfuscate_keystroke_timing: stopping ..." + upstream: when connecting via socket (the default case), filter - debug messages when keystroke timing obfuscation was never started; spotted - by naddy@ + addresses by AddressFamily if one was specified. Fixes the case where, if + CanonicalizeHostname is enabled, ssh may ignore AddressFamily. bz5326; ok + dtucker - OpenBSD-Commit-ID: 5c270d35f7d2974db5c1646e9c64188f9393be31 + OpenBSD-Commit-ID: 6c7d7751f6cd055126b2b268a7b64dcafa447439 -commit ccf7d913db34e49b7a6db1b8331bd402004c840d +commit 050c335c8da43741ed0df2570ebfbd5d1dfd0a31 Author: djm@openbsd.org -Date: Mon Sep 4 00:01:46 2023 +0000 +Date: Wed Nov 15 22:51:49 2023 +0000 - upstream: make channel_output_poll() return a flag indicating + upstream: when deciding whether to enable keystroke timing - whether channel data was enqueued. Will be used to improve keystroke timing - obfuscation. Problem spotted by / tested by naddy@ + obfuscation, only consider enabling it when a channel with a tty is open. - OpenBSD-Commit-ID: f9776c7b0065ba7c3bbe50431fd3b629f44314d0 + Avoids turning on the obfucation when X11 forwarding only is in use, + which slows it right down. Reported by Roger Marsh + + OpenBSD-Commit-ID: c292f738db410f729190f92de100c39ec931a4f1 -commit 43254b326ac6e2131dbd750f9464dc62c14bd5a7 -Author: djm@openbsd.org -Date: Sun Sep 3 23:59:32 2023 +0000 +commit 676377ce67807a24e08a54cd60ec832946cc6cae +Author: tobhe@openbsd.org +Date: Mon Nov 13 09:18:19 2023 +0000 - upstream: set interactive mode for ControlPersist sessions if they + upstream: Make sure sftp_get_limits() only returns 0 if 'limits' - originally requested a tty; enables keystroke timing obfuscation for most - ControlPersist sessions. Spotted by naddy@ + was initialized. This fixes a potential uninitialized use of 'limits' in + sftp_init() if sftp_get_limits() returned early because of an unexpected + message type. - OpenBSD-Commit-ID: 72783a26254202e2f3f41a2818a19956fe49a772 + ok djm@ + + OpenBSD-Commit-ID: 1c177d7c3becc1d71bc8763eecf61873a1d3884c -commit ff3eda68ceb2e2bb8f48e3faceb96076c3e85c20 +commit 64e0600f23c6dec36c3875392ac95b8a9100c2d6 Author: Darren Tucker -Date: Thu Aug 31 23:02:35 2023 +1000 +Date: Mon Nov 13 20:03:31 2023 +1100 - Set LLONG_MAX for C89 test. + Test current releases of LibreSSL and OpenSSL. - If we don't have LLONG_MAX, configure will figure out that it can get it - by setting -std=gnu99, at which point we won't be testing C89 any more. - To avoid this, feed it in via CFLAGS. + Retire some of the older releases. -commit f98031773db361424d59e3301aa92aacf423d920 -Author: djm@openbsd.org -Date: Tue Aug 29 02:50:10 2023 +0000 +commit c8ed7cc545879ac15f6ce428be4b29c35598bb2a +Author: dtucker@openbsd.org +Date: Wed Nov 1 02:08:38 2023 +0000 - upstream: make PerSourceMaxStartups first-match-wins; ok dtucker@ + upstream: Specify ssh binary to use - OpenBSD-Commit-ID: dac0c24cb709e3c595b8b4f422a0355dc5a3b4e7 + ... instead of relying on installed one. Fixes test failures in -portable + when running tests prior to installation. + + OpenBSD-Regress-ID: b6d6ba71c23209c616efc805a60d9a445d53a685 -commit cfa66857db90cd908de131e0041a50ffc17c7df8 -Author: djm@openbsd.org -Date: Mon Aug 28 09:52:09 2023 +0000 +commit e9fc2c48121cada1b4dcc5dadea5d447fe0093c3 +Author: Darren Tucker +Date: Wed Nov 1 13:11:31 2023 +1100 - upstream: descriptive text shouldn't be under .Cm + Put long-running test targets on hipri runners. - OpenBSD-Commit-ID: b1afaeb456a52bc8a58f4f9f8b2f9fa8f6bf651b + Some of the selfhosted test targets take a long time to run for various + reasons, so label them for "libvirt-hipri" runners so that they can + start immediately. This should reduce the time to complete all tests. -commit 01dbf3d46651b7d6ddf5e45d233839bbfffaeaec +commit 7ddf27668f0e21233f08c0ab2fe9ee3fdd6ab1e2 Author: djm@openbsd.org -Date: Mon Aug 28 09:48:11 2023 +0000 +Date: Wed Nov 1 00:29:46 2023 +0000 - upstream: limit artificial login delay to a reasonable maximum (5s) + upstream: add some tests of forced commands overriding Subsystem - and don't delay at all for the "none" authentication mechanism. Patch by - Dmitry Belyavskiy in bz3602 with polish/ok dtucker@ + directives - OpenBSD-Commit-ID: 85b364676dd84cf1de0e98fc2fbdcb1a844ce515 + OpenBSD-Regress-ID: eb48610282f6371672bdf2a8b5d2aa33cfbd322b -commit 528da5b9d7c5da01ed7a73ff21c722e1b5326006 -Author: jmc@openbsd.org -Date: Mon Aug 28 05:32:28 2023 +0000 +commit fb06f9b5a065dfbbef5916fc4accc03c0bf026dd +Author: dtucker@openbsd.org +Date: Tue Oct 31 04:15:40 2023 +0000 - upstream: add spacing for punctuation when macro args; + upstream: Don't try to use sudo inside sshd log wrapper. - OpenBSD-Commit-ID: e80343c16ce0420b2aec98701527cf90371bd0db + We still need to check if we're using sudo since we don't want to chown + unecessarily, as on some platforms this causes an error which pollutes + stderr. We also don't want to unnecessarily invoke sudo, since it's + running in the context of the proxycommand, on *other* platforms it + may not be able to authenticate, and if we're using SUDO then it should + already be privileged. + + OpenBSD-Regress-ID: 70d58df7503db699de579a9479300e5f3735f4ee -commit 3867361ca691d0956ef7d5fb8181cf554a91d84a -Author: djm@openbsd.org -Date: Mon Aug 28 04:06:52 2023 +0000 +commit fc3cc33e88c242c704781c6c48087838f1dcfa2a +Author: dtucker@openbsd.org +Date: Tue Oct 31 02:58:45 2023 +0000 - upstream: explicit long long type in timing calculations (doesn't + upstream: Only try to chmod logfile if we have sudo. If we don't have - matter, since the range is pre-clamped) + sudo then we won't need to chmod. - OpenBSD-Commit-ID: f786ed902d04a5b8ecc581d068fea1a79aa772de + OpenBSD-Regress-ID: dbad2f5ece839658ef8af3376cb1fb1cabe2e324 -commit 7603ba71264e7fa938325c37eca993e2fa61272f +commit 3a506598fddd3f18f9095af3fe917f24cbdd32e0 Author: djm@openbsd.org -Date: Mon Aug 28 03:31:16 2023 +0000 +Date: Mon Oct 30 23:00:25 2023 +0000 - upstream: Add keystroke timing obfuscation to the client. - - This attempts to hide inter-keystroke timings by sending interactive - traffic at fixed intervals (default: every 20ms) when there is only a - small amount of data being sent. It also sends fake "chaff" keystrokes - for a random interval after the last real keystroke. These are - controlled by a new ssh_config ObscureKeystrokeTiming keyword/ + upstream: move PKCS#11 setup code to test-exec.sh so it can be reused - feedback/ok markus@ + elsewhere - OpenBSD-Commit-ID: 02231ddd4f442212820976068c34a36e3c1b15be + OpenBSD-Regress-ID: 1d29e6be40f994419795d9e660a8d07f538f0acb -commit dce6d80d2ed3cad2c516082682d5f6ca877ef714 +commit f82fa227a52661c37404a6d33bbabf14fed05db0 Author: djm@openbsd.org -Date: Mon Aug 28 03:28:43 2023 +0000 +Date: Mon Oct 30 17:32:00 2023 +0000 - upstream: Introduce a transport-level ping facility - - This adds a pair of SSH transport protocol messages SSH2_MSG_PING/PONG - to implement a ping capability. These messages use numbers in the "local - extensions" number space and are advertised using a "ping@openssh.com" - ext-info message with a string version number of "0". + upstream: tidy and refactor PKCS#11 setup code - ok markus@ - - OpenBSD-Commit-ID: b6b3c4cb2084c62f85a8dc67cf74954015eb547f - -commit d2d247938b38b928f8a6e1a47a330c5584d3a358 -Author: tobhe@openbsd.org -Date: Mon Aug 21 21:16:18 2023 +0000 - - upstream: Log errors in kex_exchange_identification() with level + Replace the use of a perl script to delete the controlling TTY with a + SSH_ASKPASS script to directly load the PIN. - verbose instead of error to reduce preauth log spam. All of those get logged - with a more generic error message by sshpkt_fatal(). + Move PKCS#11 setup code to functions in anticipation of it being used + elsewhere in additional tests. - feedback from sthen@ - ok djm@ + Reduce stdout spam - OpenBSD-Commit-ID: bd47dab4695b134a44c379f0e9a39eed33047809 + OpenBSD-Regress-ID: 07705c31de30bab9601a95daf1ee6bef821dd262 -commit 9d7193a8359639801193ad661a59d1ae4dc3d302 -Author: djm@openbsd.org -Date: Mon Aug 21 04:59:54 2023 +0000 +commit 3cf698c6d4ffa9be1da55672a3519e2135a6366a +Author: Darren Tucker +Date: Mon Oct 30 21:35:03 2023 +1100 - upstream: correct math for ClientAliveInterval that caused the - - probes to be sent less frequently than configured; from Dawid Majchrzak - - OpenBSD-Commit-ID: 641153e7c05117436ddfc58267aa267ca8b80038 + Add obsd74 test VM and retire obsd69 and obsd70. -commit 3c6ab63b383b0b7630da175941e01de9db32a256 +commit 3e21d58a09894acb38dc69ed615d101131f473d0 Author: Darren Tucker -Date: Fri Aug 25 14:48:02 2023 +1000 +Date: Mon Oct 30 18:34:12 2023 +1100 - Include Portable version in sshd version string. - - bz#3608, ok djm@ + Add OpenSSL 3.3.0 as a known dev version. -commit 17fa6cd10a26e193bb6f65d21264d2fe553bcd87 +commit 917ba181c2cbdb250a443589ec732aa36fd51ffa Author: Darren Tucker -Date: Mon Aug 21 19:47:58 2023 +1000 +Date: Mon Oct 30 13:32:03 2023 +1100 - obsd-arm64 host is real hardware... + Restore nopasswd sudo rule on Mac OS X. - so put in the correct config location. + This seems to be missing from some (but not all) github runners, so + restore it if it seems to be missing. -commit 598ca75c85acaaacee5ef954251e489cc20d7be9 +commit c5698abad6d4ec98ca20bcaaabaeacd5e1ec3f4f Author: Darren Tucker -Date: Mon Aug 21 18:38:36 2023 +1000 +Date: Mon Oct 30 13:26:52 2023 +1100 - Add OpenBSD ARM64 test host. + Don't exit early when setting up on Mac OS X. + + We probably need some of the other bits in there (specifically, setting + the perms on the home directory) so make it less of a special snowflake. -commit 1acac79bfbe207e8db639e8043524962037c8feb -Author: Darren Tucker -Date: Mon Aug 21 18:05:26 2023 +1000 +commit 1d6a878ceba60b9dc14037dddc8f036070c0065f +Author: dtucker@openbsd.org +Date: Sun Oct 29 06:22:07 2023 +0000 - Add test for zlib development branch. + upstream: Only try to chown logfiles that exist to prevent spurious + + errors. + + OpenBSD-Regress-ID: f1b20a476734e885078c481f1324c9ea03af991e -commit 84efebf352fc700e9040c8065707c63caedd36a3 -Author: djm@openbsd.org -Date: Mon Aug 21 04:36:46 2023 +0000 +commit e612376427a66f835e284f6b426d16d7c85301bc +Author: anton@openbsd.org +Date: Thu Oct 26 18:52:45 2023 +0000 - upstream: want stdlib.h for free(3) + upstream: make use of bsd.regress.mk in extra and interop targets; ok - OpenBSD-Commit-ID: 743af3c6e3ce5e6cecd051668f0327a01f44af29 + dtucker@ + + OpenBSD-Regress-ID: 7ea21b5f6fc4506165093b2123d88d20ff13a4f0 -commit cb4ed12ffc332d1f72d054ed92655b5f1c38f621 -Author: Darren Tucker -Date: Sat Aug 19 07:39:08 2023 +1000 +commit ea0039173957d0edcd6469b9614dcedb44dcb4f9 +Author: dtucker@openbsd.org +Date: Thu Oct 26 12:44:07 2023 +0000 - Fix zlib version check for 1.3 and future version. + upstream: Skip conch interop tests when not enabled instead of fatal. - bz#3604. + OpenBSD-Regress-ID: b0abf81c24ac6c21f367233663228ba16fa96a46 -commit 25b75e21f16bccdaa472ea1889b293c9bd51a87b -Author: Darren Tucker -Date: Mon Aug 14 11:10:08 2023 +1000 +commit d220b9ed5494252b26b95f05be118472bc3ab5c0 +Author: dtucker@openbsd.org +Date: Wed Oct 25 05:38:08 2023 +0000 - Add 9.4 branch to CI status page. + upstream: Import regenerated moduli. + + OpenBSD-Commit-ID: 95f5dd6107e8902b87dc5b005ef2b53f1ff378b8 -commit 803e22eabd3ba75485eedd8b7b44d6ace79f2052 -Author: djm@openbsd.org -Date: Fri Aug 18 01:37:41 2023 +0000 +commit a611e4db4009447a0151f31a44e235ca32ed4429 +Author: anton@openbsd.org +Date: Wed Oct 25 08:01:59 2023 +0000 - upstream: fix regression in OpenSSH 9.4 (mux.c r1.99) that caused + upstream: ssh conch interop tests requires a controlling terminal; - multiplexed sessions to ignore SIGINT under some circumstances. Reported by / - feedback naddy@, ok dtucker@ + ok dtucker@ - OpenBSD-Commit-ID: 4d5c6c894664f50149153fd4764f21f43e7d7e5a + OpenBSD-Regress-ID: cbf2701bc347c2f19d907f113779c666f1ecae4a -commit e706bca324a70f68dadfd0ec69edfdd486eed23a -Author: djm@openbsd.org -Date: Wed Aug 16 16:14:11 2023 +0000 +commit da951b5e08c167acb5d6e2eec6f146502f5d6ed8 +Author: anton@openbsd.org +Date: Mon Oct 23 11:30:49 2023 +0000 - upstream: defence-in-depth MaxAuthTries check in monitor; ok markus + upstream: Use private key that is allowed by sshd defaults in conch - OpenBSD-Commit-ID: 65a4225dc708e2dae71315adf93677edace46c21 - -commit d1ab7eb90474df656d5e9935bae6df0bd000d343 -Author: djm@openbsd.org -Date: Mon Aug 14 03:37:00 2023 +0000 - - upstream: add message number of SSH2_MSG_NEWCOMPRESS defined in RFC8308 + interop tests. - OpenBSD-Commit-ID: 6c984171c96ed67effd7b5092f3d3975d55d6028 + ok dtucker@ + + OpenBSD-Regress-ID: 3b7f65c8f409c328bcd4b704f60cb3d31746f045 -commit fa8da52934cb7dff6f660a143276bdb28bb9bbe1 +commit 1ca166dbb3c0ce632b98869cd955f69320aa6fe8 Author: Darren Tucker -Date: Sun Aug 13 15:01:27 2023 +1000 +Date: Fri Oct 20 20:43:00 2023 +1100 - Add obsd72 and obsd73 test targets. + Install Dropbear for interop testing. -commit f9f18006678d2eac8b0c5a5dddf17ab7c50d1e9f -Author: djm@openbsd.org -Date: Thu Aug 10 23:05:48 2023 +0000 +commit f993bb58351c5cb71e61aede63805a34a6d4daea +Author: Darren Tucker +Date: Fri Oct 20 20:39:03 2023 +1100 - upstream: better debug logging of sessions' exit status + Resync PuTTY and Conch path handling with upstream. - OpenBSD-Commit-ID: 82237567fcd4098797cbdd17efa6ade08e1a36b0 + Now that configure finds these for us we can remove these -portable + specific changes. -commit a8c57bcb077f0cfdffcf9f23866bf73bb93e185c -Author: naddy@openbsd.org -Date: Thu Aug 10 14:37:32 2023 +0000 +commit ff85becd5f5f06a76efa45d30fb204a3c5e5215c +Author: Darren Tucker +Date: Fri Oct 20 20:35:46 2023 +1100 - upstream: drop a wayward comma, ok jmc@ + Have configure find PuTTY and Conch binaries. - OpenBSD-Commit-ID: 5c11fbb9592a29b37bbf36f66df50db9d38182c6 + This will let us remove some -portable specific changes from + test-exec.sh. -commit e962f9b318a238db1becc53c2bf79dd3a49095b4 -Author: Damien Miller -Date: Thu Aug 10 11:10:22 2023 +1000 +commit c54a50359b9cecddbf3ffcdc26efcb3cd6071ec1 +Author: dtucker@openbsd.org +Date: Fri Oct 20 07:37:07 2023 +0000 - depend + upstream: Allow overriding the locations of the Dropbear binaries + + similar to what we do for the PuTTY ones. + + OpenBSD-Regress-ID: 7de0e00518fb0c8fdc5f243b7f82f523c936049c -commit 0fcb60bf83130dfa428bc4422b3a3ac20fb528af -Author: Damien Miller -Date: Thu Aug 10 11:05:42 2023 +1000 +commit fbaa707d455a61d0aef8ae65e02a25bac5351e5c +Author: dtucker@openbsd.org +Date: Fri Oct 20 06:56:45 2023 +0000 - update versions in RPM specs + upstream: Add interop test with Dropbear. + + Right now this is only dbclient not the Dropbear server since it won't + currently run as a ProxyCommand. + + OpenBSD-Regress-ID: 8cb898c414fcdb252ca6328896b0687acdaee496 -commit d0cee4298491314f09afa1c4383a66d913150b26 -Author: Damien Miller -Date: Thu Aug 10 11:05:14 2023 +1000 +commit c2003d0dbdcdb61ca336c3f90c5c2b4a09c8e73f +Author: Fabio Pedretti +Date: Mon Oct 16 11:59:53 2023 +0200 - update version in README + Update openssl-devel dependency in RPM spec. + + Since openssh 9.4p1, openssl >= 1.1.1 is required, so + build with --without-openssl elsewhere. + According to https://repology.org/project/openssl/versions + openssl 1.1.1 is available on fedora >= 29 and rhel >= 8. + Successfully build tested, installed and run on rhel 6 -commit 78b4dc6684f4d35943b46b24ee645edfdb9974f5 -Author: djm@openbsd.org -Date: Thu Aug 10 01:01:07 2023 +0000 +commit 064e09cd632721c7e6889904e07767443ee23821 +Author: Fabio Pedretti +Date: Mon Oct 16 10:13:06 2023 +0200 - upstream: openssh-9.4 + Remove reference of dropped sshd.pam.old file - OpenBSD-Commit-ID: 71fc1e01a4c4ea061b252bd399cda7be757e6e35 + The file was removed in openssh 8.8 -commit 58ca4f0aa8c4306ac0a629c9a85fb1efaf4ff092 -Author: Darren Tucker -Date: Thu Aug 10 11:30:24 2023 +1000 +commit 62db354b696b378a164b6e478cb6b0171dcb0c3d +Author: dtucker@openbsd.org +Date: Mon Oct 16 08:40:00 2023 +0000 - Only include unistd.h once. + upstream: Move declaration of "len" into the block where it's used. + + This lets us compile Portable with -Werror with when OpenSSL doesn't have + Ed25519 support. + + OpenBSD-Commit-ID: e02e4b4af351946562a7caee905da60eff16ba29 -commit 3961ed02dc578517a9d2535128cff5c3a5460d28 +commit 6eee8c972d5901d10e80634a006b4e346b2c8c19 Author: Damien Miller -Date: Thu Aug 10 09:08:49 2023 +1000 +Date: Fri Oct 13 15:15:05 2023 +1100 - wrap poll.h include in HAVE_POLL_H + run t-extra regress tests + + This exposes the t-extra regress tests (including agent-pkcs11.sh) as + a new extra-tests target in the top level Makefile and runs them by + default. ok dtucker@ -commit e535fbe2af893046c28adfcd787c1fdbae36a24a -Author: dtucker@openbsd.org -Date: Fri Aug 4 06:32:40 2023 +0000 +commit 637624dbbac13f2bc3c8ec5b15c9d627d07f2935 +Author: Darren Tucker +Date: Thu Oct 12 22:01:23 2023 +1100 - upstream: Apply ConnectTimeout to multiplexing local socket - - connections. If the multiplex socket exists but the connection times out, - ssh will fall back to a direct connection the same way it would if the socket - did not exist at all. ok djm@ + Don't use make -j2. - OpenBSD-Commit-ID: 2fbe1a36d4a24b98531b2d298a6557c8285dc1b4 + While we have 2 cores available on github runners, not using it means + that the most recent log message is the actual failure, rather than + having to search back through the log for it. -commit 9d92e7b24848fcc605945f7c2e3460c7c31832ce +commit 971e0cfcfd52ef1d73cf5244074c306a60006e89 Author: Darren Tucker -Date: Thu Aug 3 19:35:33 2023 +1000 +Date: Thu Oct 12 16:23:05 2023 +1100 - Fix RNG seeding for OpenSSL w/out self seeding. + Correct arg order for ED255519 AC_LINK_IFELSE test. + +commit c616e64688b2a0c1b4daad69b056099be998d121 +Author: djm@openbsd.org +Date: Thu Oct 12 03:51:08 2023 +0000 + + upstream: typos and extra debug trace calls - When sshd is built with an OpenSSL that does not self-seed, it would - fail in the preauth privsep process while handling a new connection. - Sanity checked by djm@ + OpenBSD-Regress-ID: 98a2a6b9333743274359e3c0f0e65cf919a591d1 -commit f70010d9b0b3e7e95de8aa0b961e1d74362cfb5d +commit c49a3fbf10162128c67c59562348de2041188974 Author: djm@openbsd.org -Date: Wed Aug 2 23:04:38 2023 +0000 +Date: Thu Oct 12 03:48:53 2023 +0000 - upstream: CheckHostIP has defaulted to 'no' for a while; make the + upstream: ensure logs are owned by correct user; feedback/ok - commented- out config option match. From Ed Maste + dtucker@ - OpenBSD-Commit-ID: e66e934c45a9077cb1d51fc4f8d3df4505db58d9 + OpenBSD-Regress-ID: c3297af8f07717f1d400a5d34529962f1a76b5a3 -commit c88a8788f9865d02b986d00405b9f0be65ad0b5a -Author: dtucker@openbsd.org -Date: Tue Aug 1 08:15:04 2023 +0000 +commit 5ec0ed79ac074c3437b25f6cba8b8cf21c8d4587 +Author: djm@openbsd.org +Date: Thu Oct 12 03:36:32 2023 +0000 - upstream: remove unnecessary if statement. + upstream: 64 %-expansion keys ought to be enough for anybody; ok - github PR#422 from eyalasulin999, ok djm@ + dtucker (we just hit the previous limit in some cases) - OpenBSD-Commit-ID: 2b6b0dde4407e039f58f86c8d2ff584a8205ea55 + OpenBSD-Commit-ID: 84070f8001ec22ff5d669f836b62f206e08c5787 -commit 77b8b865cd5a8c79a47605c0c5b2bacf4692c4d5 -Author: jmc@openbsd.org -Date: Fri Jul 28 05:42:36 2023 +0000 +commit f59a94e22e46db2c23eddeb871aa9e8d93ab0016 +Author: djm@openbsd.org +Date: Thu Oct 12 02:48:43 2023 +0000 - upstream: %C is a callable macro in mdoc(7) + upstream: don't dereference NULL pointer when hashing jumphost - so, as we do for %D, escape it; + OpenBSD-Commit-ID: 251c0263e1759a921341c7efe7f1d4c73e1c70f4 + +commit 281c79168edcc303abfd5bca983616eaa24c5f32 +Author: Damien Miller +Date: Thu Oct 12 13:20:01 2023 +1100 + + Solaris: prefer PRIV_XPOLICY to PRIV_LIMIT - OpenBSD-Commit-ID: 538cfcddbbb59dc3a8739604319491dcb8e0c0c9 + If the system support PRIV_XPOLICY and one is set, then don't + modify PRIV_LIMIT. bz2833, patch from Ron Jordan, ok dtucker@ -commit e0f91aa9c2fbfc951e9ced7e1305455fc614d3f2 +commit 98fc34df837f3a3b79d2a111b96fe8a39adcab55 Author: djm@openbsd.org -Date: Fri Jul 28 05:33:15 2023 +0000 +Date: Thu Oct 12 02:18:18 2023 +0000 - upstream: don't need to start a command here; use ssh -N instead. + upstream: add %j token that expands to the configured ProxyJump - Fixes failure on cygwin spotted by Darren + hostname (or the empty string if this option is not being used). bz3610, ok + dtucker - OpenBSD-Regress-ID: ff678a8cc69160a3b862733d935ec4a383f93cfb + OpenBSD-Commit-ID: ce9983f7efe6a178db90dc5c1698df025df5e339 -commit f446a44f30bc680e0d026a4204844b02646c1c2d +commit 7f3180be8a85320b5d3221714b40c16e66881249 Author: djm@openbsd.org -Date: Wed May 17 05:52:01 2023 +0000 +Date: Thu Oct 12 02:15:53 2023 +0000 - upstream: add LTESTS_FROM variable to allow skipping of tests up to + upstream: release GSS OIDs only at end of authentication; bz2982, - a specific point. e.g. "make LTESTS_FROM=t-sftp" will only run the sftp.sh - test and subsequent ones. ok dtucker@ + ok dtucker@ - OpenBSD-Regress-ID: 07f653de731def074b29293db946042706fcead3 + OpenBSD-Commit-ID: 0daa41e0525ae63cae4483519ecaa37ac485d94c -commit 8eb8899d612440a9b608bee7f916081d3d0b7812 +commit a612b93de5d86e955bfb6e24278f621118eea500 Author: djm@openbsd.org -Date: Fri May 12 06:37:42 2023 +0000 +Date: Thu Oct 12 02:12:53 2023 +0000 - upstream: test ChrootDirectory in Match block + upstream: mask SIGINT/TERM/QUIT/HUP before checking quit_pending - OpenBSD-Regress-ID: a6150262f39065939f025e546af2a346ffe674c1 + and use ppoll() to unmask them in the mainloop. Avoids race condition between + signaling ssh to exit and polling. bz3531; ok dtucker + + OpenBSD-Commit-ID: 5c14e1aabcddedb95cdf972283d9c0d5083229e7 -commit e43f43d3f19516222e9a143468ea0dc1b3ab67b6 +commit 531b27a006116fe7aff325510aaa576f24844452 Author: djm@openbsd.org -Date: Fri May 12 06:36:27 2023 +0000 +Date: Wed Oct 11 23:23:58 2023 +0000 - upstream: better error messages + upstream: sync usage() with ssh.1; spotted by kn@ - OpenBSD-Regress-ID: 55e4186604e80259496d841e690ea2090981bc7a + OpenBSD-Commit-ID: 191a85639477dcb5fa1616d270d93b7c8d5c1dfd -commit 6958f00acf3b9e0b3730f7287e69996bcf3ceda4 +commit 64f7ca881b19be754425dca60d1590d306c9d1d0 Author: djm@openbsd.org -Date: Thu Jul 27 22:26:49 2023 +0000 +Date: Wed Oct 11 23:14:33 2023 +0000 - upstream: don't incorrectly truncate logged strings retrieved from + upstream: ssh -Q does not make sense with other command-line options, - PKCS#11 modules; based on GHPR406 by Jakub Jelen; ok markus + so give it its own line in the manpage - OpenBSD-Commit-ID: 7ed1082f23a13b38c373008f856fd301d50012f9 + OpenBSD-Commit-ID: 00a747f0655c12122bbb77c2796be0013c105361 -commit d1ffde6b55170cd4b9a72bfd9a3f17508e6cf714 +commit a752a6c0e1001f93696d7025f0c867f0376e2ecf Author: djm@openbsd.org -Date: Thu Jul 27 22:25:17 2023 +0000 +Date: Wed Oct 11 22:42:26 2023 +0000 - upstream: make sshd_config AuthorizedPrincipalsCommand and + upstream: add ChannelTimeout support to the client, mirroring the - AuthorizedKeysCommand accept the %D (routing domain) and a new %C (connection - address/port 4-tuple) as expansion sequences; ok markus + same option in the server. ok markus@ - OpenBSD-Commit-ID: ee9a48bf1a74c4ace71b69de69cfdaa2a7388565 + OpenBSD-Commit-ID: 55630b26f390ac063980cfe7ad8c54b03284ef02 -commit 999a2886ca1844a7a74b905e5f2c8c701f9838cd +commit 76e91e7238cdc5662bc818e2a48d466283840d23 Author: djm@openbsd.org -Date: Thu Jul 27 22:23:05 2023 +0000 +Date: Wed Oct 11 22:41:05 2023 +0000 - upstream: increase default KDF work-factor for OpenSSH format + upstream: add support for reading ED25519 private keys in PEM PKCS8 - private keys from 16 to 24; { feedback ok } x { deraadt markus } + format; ok markus@ tb@ - OpenBSD-Commit-ID: a3afb1383f8ff0a49613d449f02395d9e8d4a9ec + OpenBSD-Commit-ID: 01b85c91757e6b057e9b23b8a23f96415c3c7174 -commit 0fa803a1dd1c7b546c166000e23a869cf6c4ec10 -Author: Darren Tucker -Date: Thu Jul 27 02:25:09 2023 +1000 +commit fc77c8e352c0f44125425c05265e3a00c183d78a +Author: djm@openbsd.org +Date: Wed Oct 11 06:40:54 2023 +0000 - Prefer OpenSSL's SHA256 in sk-dummy.so + upstream: mention "none" is a valid argument to IdentityFile; bz3080 - Previously sk-dummy.so used libc's (or compat's) SHA256 since it may be - built without OpenSSL. In many cases, however, including both libc's - and OpenSSL's headers together caused conflicting definitions. + OpenBSD-Commit-ID: 1b4fb590ef731099349a7d468b77f02b240ac926 + +commit c97520d23d1fe53d30725a2af25d2dddd6f2faff +Author: djm@openbsd.org +Date: Wed Oct 11 05:42:08 2023 +0000 + + upstream: in olde rcp/scp protocol mode, when rejecting a path from the - We tried working around this (on OpenSSL <1.1 you could define - OPENSSL_NO_SHA, NetBSD had USE_LIBC_SHA2, various #define hacks) with - varying levels of success. Since OpenSSL >=1.1 removed OPENSSL_NO_SHA - and including most OpenSSL headers would bring sha.h in, even if it - wasn't used directly this was a constant hassle. + server as not matching the glob that the client sent, log (at debug level) + the received pathname as well as the list of possible expected paths expanded + from the glob. bz2966 - Admit defeat and use OpenSSL's SHA256 unless we aren't using OpenSSL at - all. ok djm@ - -commit 36cdb5dbf55c99c0faad06066f56a7c341258c1f -Author: Darren Tucker -Date: Thu Jul 27 10:29:44 2023 +1000 - - Retire dfly58 test VM. Add dfly64. + OpenBSD-Commit-ID: 0bd8db8a595334ca86bca8f36e23fc0395315765 -commit 2d34205dab08ede9b0676efa57647fc49e6decbe +commit 208c2b719879805983398160791d6a1ef9c2c3fc Author: djm@openbsd.org -Date: Wed Jul 26 23:06:00 2023 +0000 +Date: Wed Oct 11 04:46:29 2023 +0000 - upstream: make ssh -f (fork after authentication) work properly in + upstream: s/%.100s/%s/ in SSH- banner construction as there's no - multiplexed cases (inc. ControlPersist). bz3589 bz3589 Based on patches by - Peter Chubb; ok dtucker@ + reason to limit its size: the version string bring included is a compile time + constant going into an allocated banner string. - OpenBSD-Commit-ID: a7a2976a54b93e6767dc846b85647e6ec26969ac + OpenBSD-Commit-ID: 0ef73304b9bf3e534c60900cd84ab699f859ebcd -commit 076aeda86a7ee9be8fd2f0181ec7b9729a6ceb37 -Author: naddy@openbsd.org -Date: Sun Jul 23 20:04:45 2023 +0000 +commit 0354790826b97c41bbd171a965574e159b58d83e +Author: tb@openbsd.org +Date: Tue Oct 10 06:49:54 2023 +0000 - upstream: man page typos; ok jmc@ + upstream: Garbage collect cipher_get_keyiv_len() - OpenBSD-Commit-ID: e6ddfef94b0eb867ad88abe07cedc8ed581c07f0 - -commit 135e7d5fe31f700e6dfc61ce914970c5ee7175ba -Author: jmc@openbsd.org -Date: Thu Jul 20 05:43:39 2023 +0000 - - upstream: tweak the allow-remote-pkcs11 text; + This is a compat20 leftover, unused since 2017. - OpenBSD-Commit-ID: bc965460a89edf76865b7279b45cf9cbdebd558a - -commit 5f83342b61d1f76c141de608ed2bd293990416bd -Author: Darren Tucker -Date: Tue Jul 25 13:00:22 2023 +1000 - - Handle a couple more OpenSSL no-ecc cases. + ok djm - ok djm@ - -commit edc2ef4e418e514c99701451fae4428ec04ce538 -Author: Damien Miller -Date: Thu Jul 20 12:53:44 2023 +1000 - - depend - -commit 51fda734e0d3c2df256fc03e8b060c4305be6e59 -Author: Damien Miller -Date: Thu Jul 20 12:53:21 2023 +1000 - - Bring back OPENSSL_HAS_ECC to ssh-pkcs11-client + OpenBSD-Commit-ID: 91fa5497c9dc6883064624ac27813a567883fdce -commit 099cdf59ce1e72f55d421c8445bf6321b3004755 +commit 8d29ee4115001a02641386ae394992c65ed279e0 Author: djm@openbsd.org -Date: Wed Jul 19 14:03:45 2023 +0000 +Date: Tue Oct 10 03:57:45 2023 +0000 - upstream: Separate ssh-pkcs11-helpers for each p11 module - - Make ssh-pkcs11-client start an independent helper for each provider, - providing better isolation between modules and reliability if a single - module misbehaves. - - This also implements reference counting of PKCS#11-hosted keys, - allowing ssh-pkcs11-helper subprocesses to be automatically reaped - when no remaining keys reference them. This fixes some bugs we have - that make PKCS11 keys unusable after they have been deleted, e.g. - https://bugzilla.mindrot.org/show_bug.cgi?id=3125 + upstream: Reserve a range of "local extension" message numbers that - ok markus@ + OpenSSH promises not to use (comment change only) - OpenBSD-Commit-ID: 0ce188b14fe271ab0568f4500070d96c5657244e + OpenBSD-Commit-ID: e61795b453d4892d2c99ce1039112c4a00250e03 -commit 29ef8a04866ca14688d5b7fed7b8b9deab851f77 +commit 90b0d73d63a706e85f6431f05a62d2ce1b476472 Author: djm@openbsd.org -Date: Wed Jul 19 14:02:27 2023 +0000 +Date: Fri Oct 6 03:32:15 2023 +0000 - upstream: Ensure FIDO/PKCS11 libraries contain expected symbols - - This checks via nlist(3) that candidate provider libraries contain one - of the symbols that we will require prior to dlopen(), which can cause - a number of side effects, including execution of constructors. - - Feedback deraadt; ok markus + upstream: typo in error message - OpenBSD-Commit-ID: 1508a5fbd74e329e69a55b56c453c292029aefbe + OpenBSD-Regress-ID: 6a8edf0dc39941298e3780b147b10c0a600b4fee -commit 1f2731f5d7a8f8a8385c6031667ed29072c0d92a +commit e84517f51532ec913d8fb01a8aab7307134774bb Author: djm@openbsd.org -Date: Wed Jul 19 13:56:33 2023 +0000 +Date: Fri Oct 6 03:25:14 2023 +0000 - upstream: Disallow remote addition of FIDO/PKCS11 provider + upstream: Perform the softhsm2 setup as discrete steps rather than - libraries to ssh-agent by default. - - The old behaviour of allowing remote clients from loading providers - can be restored using `ssh-agent -O allow-remote-pkcs11`. + as a long shell pipeline. Makes it easier to figure out what has happened + when it breaks. - Detection of local/remote clients requires a ssh(1) that supports - the `session-bind@openssh.com` extension. Forwarding access to a - ssh-agent socket using non-OpenSSH tools may circumvent this control. + OpenBSD-Regress-ID: b3f1292115fed65765d0a95414df16e27772d81c + +commit cb54becff4d776238e0e9072943ba0872260535d +Author: claudio@openbsd.org +Date: Sun Sep 24 08:14:13 2023 +0000 + + upstream: REGRESS_FAIL_EARLY defaults to yes now. So no need to - ok markus@ + overload the value here anymore. OK tb@ bluhm@ - OpenBSD-Commit-ID: 4c2bdf79b214ae7e60cc8c39a45501344fa7bd7c + OpenBSD-Regress-ID: f063330f1bebbcd373100afccebc91a965b14496 -commit 892506b13654301f69f9545f48213fc210e5c5cc -Author: djm@openbsd.org -Date: Wed Jul 19 13:55:53 2023 +0000 +commit f01f5137ceba65baf34ceac5a298c12ac01b1fef +Author: jmc@openbsd.org +Date: Wed Oct 4 05:42:10 2023 +0000 - upstream: terminate process if requested to load a PKCS#11 provider + upstream: spelling fix; - that isn't a PKCS#11 provider; from / ok markus@ - - OpenBSD-Commit-ID: 39532cf18b115881bb4cfaee32084497aadfa05c + OpenBSD-Commit-ID: 493f95121567e5ab0d9dd1150f873b5535ca0195 -commit f3f56df8ec476b2de6cbdbdfdb77a2a61087829d +commit 80a2f64b8c1d27383cc83d182b73920d1e6a91f1 Author: Damien Miller -Date: Wed Jul 19 12:07:18 2023 +1000 +Date: Wed Oct 4 15:34:10 2023 +1100 - agent_fuzz doesn't want stdint.h conditionalised + crank version numbers -commit 750911fd31d307a767cc86e3bfa90bbbb77b1a25 -Author: Damien Miller -Date: Tue Jul 18 15:41:12 2023 +1000 +commit f65f187b105d9b5c12fd750a211397d08c17c6d4 +Author: djm@openbsd.org +Date: Wed Oct 4 04:04:09 2023 +0000 - conditionalise stdint.h inclusion on HAVE_STDINT_H + upstream: openssh-9.5 - fixes build on AIX5 at least + OpenBSD-Commit-ID: 5e0af680480bd3b6f5560cf840ad032d48fd6b16 -commit ff047504fa6e008c4092f8929881816b8993bea0 -Author: Damien Miller -Date: Tue Jul 18 15:30:45 2023 +1000 +commit ffe27e54a4bb18d5d3bbd3f4cc93a41b8d94dfd2 +Author: djm@openbsd.org +Date: Wed Oct 4 04:03:50 2023 +0000 - conditionalise match localnetwork on ifaddrs.h + upstream: add some cautionary text about % token expansion and - Fixes build breakage on platforms that lack getifaddrs() + shell metacharacters; based on report from vinci AT protonmail.ch + + OpenBSD-Commit-ID: aa1450a54fcee2f153ef70368d90edb1e7019113 -commit b87b03282e466ca2927954ce93f5dbf0bfdc68f6 +commit 60ec3d54fd1ebfe2dda75893fa1e870b8dffbb0d Author: djm@openbsd.org -Date: Mon Jul 17 06:16:33 2023 +0000 +Date: Tue Oct 3 23:56:10 2023 +0000 - upstream: missing match localnetwork negation check + upstream: fix link to agent draft; spotted by Jann Horn - OpenBSD-Commit-ID: 9a08ed8dae27d3f38cf280f1b28d4e0ff41a737a + OpenBSD-Commit-ID: ff5bda21a83ec013db683e282256a85201d2dc4b -commit 6d6e185ba29ef4274164b77eab4dc763907f8821 -Author: jmc@openbsd.org -Date: Mon Jul 17 05:41:53 2023 +0000 +commit 12e2d4b13f6f63ce2de13cbfcc9e4d0d4b4ab231 +Author: Damien Miller +Date: Wed Oct 4 10:54:04 2023 +1100 - upstream: - add -P to usage() - sync the arg name to -J in usage() - - with that in ssh.1 - reformat usage() to match what "man ssh" does on 80width + use portable provider allowlist path in manpage - OpenBSD-Commit-ID: 5235dd7aa42e5bf90ae54579d519f92fc107036e + spotted by Jann Horn -commit f1a9898283a0638667b587ee4a950afd61ab51b0 -Author: jmc@openbsd.org -Date: Mon Jul 17 05:38:10 2023 +0000 +commit 6c2c6ffde75df95fd838039850d3dd3d84956d87 +Author: deraadt@openbsd.org +Date: Tue Sep 19 20:37:07 2023 +0000 - upstream: -P before -p in SYNOPSIS; + upstream: typo; from Jim Spath - OpenBSD-Commit-ID: 535f5257c779e26c6a662a038d241b017f8cab7c + OpenBSD-Commit-ID: 2f5fba917b5d4fcf93d9e0b0756c7f63189e228e -commit eef4d7e873568e1c84c36bb4034e2c3378250a61 -Author: jsg@openbsd.org -Date: Mon Jul 17 05:36:14 2023 +0000 +commit b6b49130a0089b297245ee39e769231d7c763014 +Author: djm@openbsd.org +Date: Sun Sep 10 23:12:32 2023 +0000 - upstream: configuation -> configuration + upstream: rename remote_glob() -> sftp_glob() to match other API - OpenBSD-Commit-ID: 4776ced33b780f1db0b2902faec99312f26a726b + OpenBSD-Commit-ID: d9dfb3708d824ec02970a84d96cf5937e0887229 -commit dc1dbe94cf6532bd546a3373ad436404f8850e5f +commit 21b79af6c8d2357c822c84cef3fbdb8001ed263b Author: djm@openbsd.org -Date: Mon Jul 17 05:26:38 2023 +0000 +Date: Sun Sep 10 03:51:55 2023 +0000 - upstream: move other RCSIDs to before their respective license blocks + upstream: typo in comment - too no code change + OpenBSD-Commit-ID: 69285e0ce962a7c6b0ab5f17a293c60a0a360a18 + +commit 41232d25532b4d2ef6c5db62efc0cf50a79d26ca +Author: Darren Tucker +Date: Sun Sep 10 15:45:38 2023 +1000 + + Use zero-call-used-regs=used with Apple compilers. - OpenBSD-Commit-ID: ef5bf46b57726e4260a63b032b0b5ac3b4fe9cd4 + Apple's versions of clang have version numbers that do not match the + corresponding upstream clang versions. Unfortunately, they do still + have the clang-15 zero-call-used-regs=all bug, so for now use the value + that doesn't result in segfaults. We could allowlist future versions + that are known to work. bz#3584 (and probably also our github CI + failures). -commit ebe11044681caff78834ca6b78311ad19c1860b8 +commit 90ccc5918ea505bf156c31148b6b59a1bf5d6dc6 Author: djm@openbsd.org -Date: Mon Jul 17 05:22:30 2023 +0000 +Date: Sun Sep 10 03:25:53 2023 +0000 - upstream: Move RCSID to before license block and away from #includes, + upstream: randomise keystroke obfuscation intervals and average - where it caused merge conflict in -portable for each commit :( + interval rate. ok dtucker@ - OpenBSD-Commit-ID: 756ebac963df3245258b962e88150ebab9d5fc20 + OpenBSD-Commit-ID: 05f61d051ab418fcfc4857ff306e420037502382 -commit 05c08e5f628de3ecf6f7ea20947735bcfa3201e0 +commit bd1b9e52f5fa94d87223c90905c5fdc1a7c32aa6 Author: djm@openbsd.org -Date: Mon Jul 17 05:20:15 2023 +0000 +Date: Fri Sep 8 06:34:24 2023 +0000 - upstream: return SSH_ERR_KRL_BAD_MAGIC when a KRL doesn't contain a + upstream: fix sizeof(*ptr) instead sizeof(ptr) in realloc (pointer here - valid magic number and not SSH_ERR_MESSAGE_INCOMPLETE; the former is needed - to fall back to text revocation lists in some cases; fixes t-cert-hostkey. + is char**, so harmless); spotted in CID 416964 - OpenBSD-Commit-ID: 5c670a6c0f027e99b7774ef29f18ba088549c7e1 - -commit c6fad2c3d19b74f0bd0af1ef040fc74f3a1d9ebb -Author: Damien Miller -Date: Mon Jul 17 14:56:14 2023 +1000 - - avoid AF_LINK on platforms that don't define it + OpenBSD-Commit-ID: c61caa4a5a667ee20bb1042098861e6c72c69002 -commit 919bc3d3b712c920de1ae6be5ac6561c98886d7e +commit c4f966482983e18601eec70a1563115de836616f Author: djm@openbsd.org -Date: Mon Jul 17 04:08:31 2023 +0000 +Date: Fri Sep 8 06:10:57 2023 +0000 - upstream: Add support for configuration tags to ssh(1). + upstream: regress test recursive remote-remote directories copies where - This adds a ssh_config(5) "Tag" directive and corresponding - "Match tag" predicate that may be used to select blocks of - configuration similar to the pf.conf(5) keywords of the same - name. + the directory contains a symlink to another directory. - ok markus + also remove errant `set -x` that snuck in at some point - OpenBSD-Commit-ID: dc08358e70e702b59ac3e591827e5a96141b06a3 + OpenBSD-Regress-ID: 1c94a48bdbd633ef2285954ee257725cd7bc456f -commit 3071d85a47061c1bdaf11a0ac233b501ecba862c +commit 5e1dfe5014ebc194641678303e22ab3bba15f4e5 Author: djm@openbsd.org -Date: Mon Jul 17 04:04:36 2023 +0000 +Date: Fri Sep 8 06:10:02 2023 +0000 - upstream: add a "match localnetwork" predicate. - - This allows matching on the addresses of available network interfaces - and may be used to vary the effective client configuration based on - network location (e.g. to use a ProxyJump when not on a particular - network). + upstream: fix recursive remote-remote copies of directories that - ok markus@ + contain symlinks to other directories (similar to bz3611) - OpenBSD-Commit-ID: cffb6ff9a3803abfc52b5cad0aa190c5e424c139 + OpenBSD-Commit-ID: 7e19d2ae09b4f941bf8eecc3955c9120171da37f -commit beec17bb311365b75a0a5941418d4b96df7d7888 +commit 7c0ce2bf98b303b6ad91493ee3247d96c18ba1f6 Author: djm@openbsd.org -Date: Mon Jul 17 04:01:10 2023 +0000 +Date: Fri Sep 8 05:50:57 2023 +0000 - upstream: remove vestigal support for KRL signatures + upstream: regress test for recursive copies of directories containing - When the KRL format was originally defined, it included support for - signing of KRL objects. However, the code to sign KRLs and verify KRL - signatues was never completed in OpenSSH. + symlinks to other directories. bz3611, ok dtucker@ - Now, some years later, we have SSHSIG support in ssh-keygen that is - more general, well tested and actually works. So this removes the - semi-finished KRL signing/verification support from OpenSSH and - refactors the remaining code to realise the benefit - primarily, we - no longer need to perform multiple parsing passes over KRL objects. - - ok markus@ - - OpenBSD-Commit-ID: 517437bab3d8180f695c775410c052340e038804 + OpenBSD-Regress-ID: eaa4c29cc5cddff4e72a16bcce14aeb1ecfc94b9 -commit 449566f64c21b4578d5c0c431badd0328adc53ed +commit 2de990142a83bf60ef694378b8598706bc654b08 Author: djm@openbsd.org -Date: Mon Jul 17 03:57:21 2023 +0000 +Date: Fri Sep 8 05:56:13 2023 +0000 - upstream: Support for KRL extensions. - - This defines wire formats for optional KRL extensions and implements - parsing of the new submessages. No actual extensions are supported at - this point. + upstream: the sftp code was one of my first contributions to - ok markus + OpenSSH and it shows - the function names are terrible. - OpenBSD-Commit-ID: ae2fcde9a22a9ba7f765bd4f36b3f5901d8c3fa7 - -commit 18ea857770e84825a3a6238bb37f54864487b59f -Author: dtucker@openbsd.org -Date: Fri Jul 14 07:44:21 2023 +0000 - - upstream: Include stdint.h for SIZE_MAX. Fixes OPENSSL=no build. + Rename do_blah() to sftp_blah() to make them less so. - OpenBSD-Commit-ID: e7c31034a5434f2ead3579b13a7892960651e6b0 - -commit 20b768fcd13effe0f2d3619661b6c8592c773553 -Author: Darren Tucker -Date: Fri Jul 14 17:07:32 2023 +1000 - - Fix typo in declaration of nmesg. - -commit 4b94d09542e36ebde2eb9ad89bc68431609932de -Author: Damien Miller -Date: Fri Jul 14 15:34:47 2023 +1000 - - portable-specific int overflow defence-in-depth + Completely mechanical except for sftp_stat() and sftp_lstat() which + change from returning a pointer to a static variable (error-prone) to + taking a pointer to a caller-provided receiver. - These too are unreachable, but we want the code to be safe regardless of - context. Reported by Yair Mizrahi @ JFrog + OpenBSD-Commit-ID: eb54d6a72d0bbba4d623e2175cf5cc4c75dc2ba4 -commit 2ee48adb9fc8692e8d6ac679dcc9f35e89ad68f0 +commit 249d8bd0472b53e3a2a0e138b4c030a31e83346a Author: djm@openbsd.org -Date: Fri Jul 14 05:31:44 2023 +0000 +Date: Fri Sep 8 05:50:12 2023 +0000 - upstream: add defence-in-depth checks for some unreachable integer + upstream: fix scp in SFTP mode recursive upload and download of - overflows reported by Yair Mizrahi @ JFrog; feedback/ok millert@ + directories that contain symlinks to other directories. In scp mode, the + links would be followed, but in SFTP mode they were not. bz3611, ok dtucker@ - OpenBSD-Commit-ID: 52af085f4e7ef9f9d8423d8c1840a6a88bda90bd + OpenBSD-Commit-ID: 9760fda668eaa94a992250d7670dfbc62a45197c -commit 4b43bc358ae6f6b19a973679246dc5172f6ac41b +commit 0e1f4401c466fa4fdaea81b6dadc8dd1fc4cf0af Author: djm@openbsd.org -Date: Mon Jul 10 04:51:26 2023 +0000 +Date: Wed Sep 6 23:36:09 2023 +0000 - upstream: misplaced debug message + upstream: regression test for override of subsystem in match blocks - OpenBSD-Commit-ID: d0f12af0a5067a756aa707bc39a83fa6f58bf7e5 + OpenBSD-Regress-ID: 5f8135da3bfda71067084c048d717b0e8793e87c -commit 8c7203bcee4c4f98a22487b4631fe068b992099b -Author: Damien Miller -Date: Wed Jul 12 11:41:19 2023 +1000 +commit 8a1450c62035e834d8a79a5d0d1c904236f9dcfe +Author: djm@openbsd.org +Date: Wed Sep 6 23:35:35 2023 +0000 - replace deprecate selinux matchpathcon function + upstream: allow override of Sybsystem directives in sshd Match - This function is apparently deprecated. Documentation on what is the - supposed replacement is is non-existent, so this follows the approach - glibc used https://sourceware.org/git/?p=glibc.git;a=patch;h=f278835f59 + blocks - ok dtucker@ + OpenBSD-Commit-ID: 3911d18a826a2d2fe7e4519075cf3e57af439722 -commit 7e8800f5d701efffa39ccb63ca1e095ea777c31a -Author: dtucker@openbsd.org -Date: Thu Jul 6 22:17:59 2023 +0000 +commit 6e52826e2a74d077147a82ead8d4fbd5b54f4e3b +Author: djm@openbsd.org +Date: Wed Sep 6 23:26:37 2023 +0000 - upstream: minleft and maxsign are u_int so cast appropriately. Prompted + upstream: allocate the subsystems array as necessary and remove the - by github PR#410, ok deraadt. + fixed limit of subsystems. Saves a few kb of memory in the server and makes + it more like the other options. - OpenBSD-Commit-ID: 0514cd51db3ec60239966622a0d3495b15406ddd + OpenBSD-Commit-ID: e683dfca6bdcbc3cc339bb6c6517c0c4736a547f -commit 94842bfe9b09fc93189c6ed0dc9bbebc1d44a426 -Author: dlg@openbsd.org -Date: Tue Jul 4 03:59:21 2023 +0000 +commit e19069c9fac4c111d6496b19c7f7db43b4f07b4f +Author: djm@openbsd.org +Date: Wed Sep 6 23:23:53 2023 +0000 - upstream: add support for unix domain sockets to ssh -W + upstream: preserve quoting of Subsystem commands and arguments. - ok djm@ dtucker@ + This may change behaviour of exotic configurations, but the most common + subsystem configuration (sftp-server) is unlikely to be affected. - OpenBSD-Commit-ID: 3e6d47567b895c7c28855c7bd614e106c987a6d8 + OpenBSD-Commit-ID: 8ffa296aeca981de5b0945242ce75aa6dee479bf -commit a95fc5eed09a0238fb127b6c50e8498432b79dae -Author: David Seifert -Date: Fri May 12 14:06:01 2023 +0200 +commit 52dfe3c72d98503d8b7c6f64fc7e19d685636c0b +Author: djm@openbsd.org +Date: Wed Sep 6 23:21:36 2023 +0000 - gss-serv.c: `MAXHOSTNAMELEN` -> `HOST_NAME_MAX` + upstream: downgrade duplicate Subsystem directives from being a - `MAXHOSTNAMELEN` is not defined in POSIX, which breaks on musl: - https://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html + fatal error to being a debug message to match behaviour with just about all + other directives. - Bug: https://bugs.gentoo.org/834044 + OpenBSD-Commit-ID: fc90ed2cc0c18d4eb8e33d2c5e98d25f282588ce -commit 8a6cd08850f576e7527c52a1b086cae82fab290e -Author: Darren Tucker -Date: Fri Jun 23 09:49:02 2023 +1000 +commit 1ee0a16e07b6f0847ff463d7b5221c4bf1876e25 +Author: djm@openbsd.org +Date: Wed Sep 6 23:18:15 2023 +0000 - Update runner OS version for hardenedmalloc test. + upstream: handle cr+lf (instead of just cr) in sshsig signature - Hardenedmalloc dropped support for "legacy glibc" versions in their - 64dad0a69 so use a newer Ubuntu version for the runner for that test. - -commit cfca6f17e64baed6822bb927ed9f372ce64d9c5b -Author: Damien Miller -Date: Thu Jun 22 15:04:03 2023 +1000 - - handle sysconf(SC_OPEN_MAX) returning > INT_MAX; + files - bz3581; ok dtucker + OpenBSD-Commit-ID: 647460a212b916540016d066568816507375fd7f -commit c1c2ca1365b3f7b626683690bd2c68265f6d8ffd -Author: djm@openbsd.org -Date: Wed Jun 21 05:10:26 2023 +0000 +commit e1c284d60a928bcdd60bc575c6f9604663502770 +Author: job@openbsd.org +Date: Mon Sep 4 10:29:58 2023 +0000 - upstream: better validate CASignatureAlgorithms in ssh_config and - - sshd_config. + upstream: Generate Ed25519 keys when invoked without arguments - Previously this directive would accept certificate algorithm names, but - these were unusable in practice as OpenSSH does not support CA chains. + Ed25519 public keys are very convenient due to their small size. + OpenSSH has supported Ed25519 since version 6.5 (January 2014). - part of bz3577; ok dtucker@ + OK djm@ markus@ sthen@ deraadt@ - OpenBSD-Commit-ID: a992d410c8a78ec982701bc3f91043dbdb359912 + OpenBSD-Commit-ID: f498beaad19c8cdcc357381a60df4a9c69858b3f -commit 4e73cd0f4ab3e5b576c56cac9732da62c8fc0565 +commit 694150ad92765574ff82a18f4e86322bd3231e68 Author: djm@openbsd.org -Date: Wed Jun 21 05:08:32 2023 +0000 +Date: Mon Sep 4 00:08:14 2023 +0000 - upstream: make `ssh -Q CASignatureAlgorithms` only list signature + upstream: trigger keystroke timing obfucation only if the channels - algorithms that are valid for CA signing. Previous behaviour was to list all - signing algorithms, including certificate algorithms (OpenSSH certificates do - not support CA chains). part of bz3577; ok dtucker@ + layer enqueud some data in the last poll() cycle; this avoids triggering the + obfuscatior for non-channels data like ClientAlive probes and also fixes a + related problem were the obfucations would be triggered on fully quiescent + connections. - OpenBSD-Commit-ID: 99c2b072dbac0f44fd1f2269e3ff6c1b5d7d3e59 + Based on / tested by naddy@ + + OpenBSD-Commit-ID: d98f32dc62d7663ff4660e4556e184032a0db123 -commit a69062f1695ac9c3c3dea29d3044c72aaa6af0ea +commit b5fd97896b59a3a46245cf438cc8b16c795d9f74 Author: djm@openbsd.org -Date: Wed Jun 21 05:06:04 2023 +0000 +Date: Mon Sep 4 00:04:02 2023 +0000 - upstream: handle rlimits > INT_MAX (rlim_t is u64); ok dtucker + upstream: avoid bogus "obfuscate_keystroke_timing: stopping ..." - bz3581 + debug messages when keystroke timing obfuscation was never started; spotted + by naddy@ - OpenBSD-Commit-ID: 31cf59c041becc0e5ccb0a77106f812c4cd1cd74 + OpenBSD-Commit-ID: 5c270d35f7d2974db5c1646e9c64188f9393be31 -commit 8d33f2aa6bb895a7f85a47189913639086347b75 +commit ccf7d913db34e49b7a6db1b8331bd402004c840d Author: djm@openbsd.org -Date: Tue Jun 20 23:59:33 2023 +0000 +Date: Mon Sep 4 00:01:46 2023 +0000 - upstream: prepare for support for connecting to unix domain sockets + upstream: make channel_output_poll() return a flag indicating - using ssh -W by explicitly decoding PORT_STREAMLOCAL (a negative number) from - the u32 that's passed over the multiplexing socket; previously code would - just cast, which is UB. + whether channel data was enqueued. Will be used to improve keystroke timing + obfuscation. Problem spotted by / tested by naddy@ - OpenBSD-Commit-ID: e5ac5f40d354096c51e8c118a5c1b2d2b7a31384 + OpenBSD-Commit-ID: f9776c7b0065ba7c3bbe50431fd3b629f44314d0 -commit b4ac435b4e67f8eb5932d8f59eb5b3cf7dc38df0 +commit 43254b326ac6e2131dbd750f9464dc62c14bd5a7 Author: djm@openbsd.org -Date: Tue Jun 20 00:05:09 2023 +0000 +Date: Sun Sep 3 23:59:32 2023 +0000 - upstream: reset comment=NULL for each key in do_fingerprint(); + upstream: set interactive mode for ControlPersist sessions if they - fixes "no comment" not showing on when running `ssh-keygen -l` on multiple - keys where one has a comment and other following keys do not. Patch from - Markus Kuhn via GHPR407, bz3580 + originally requested a tty; enables keystroke timing obfuscation for most + ControlPersist sessions. Spotted by naddy@ - OpenBSD-Commit-ID: 3cce84456fdcd67dc6b84e369f92c6686d111d9b + OpenBSD-Commit-ID: 72783a26254202e2f3f41a2818a19956fe49a772 -commit b53a809a549dcd4fbde554c6aa283e597b15ea33 -Author: millert@openbsd.org -Date: Mon Jun 5 13:24:36 2023 +0000 +commit ff3eda68ceb2e2bb8f48e3faceb96076c3e85c20 +Author: Darren Tucker +Date: Thu Aug 31 23:02:35 2023 +1000 - upstream: Store timeouts as int, not u_int as they are limited to - - INT_MAX. Fixes sign compare warnings systems with 32-bit time_t due to type - promotion. OK djm@ + Set LLONG_MAX for C89 test. - OpenBSD-Commit-ID: 48081e9ad35705c5f1705711704a4c2ff94e87b7 + If we don't have LLONG_MAX, configure will figure out that it can get it + by setting -std=gnu99, at which point we won't be testing C89 any more. + To avoid this, feed it in via CFLAGS. -commit 2709809fd616a0991dc18e3a58dea10fb383c3f0 -Author: Philip Hands -Date: Wed May 24 19:41:14 2023 +0200 +commit f98031773db361424d59e3301aa92aacf423d920 +Author: djm@openbsd.org +Date: Tue Aug 29 02:50:10 2023 +0000 - fixup! if -s & -p specified, mention 'sftp -P' on + upstream: make PerSourceMaxStartups first-match-wins; ok dtucker@ - success + OpenBSD-Commit-ID: dac0c24cb709e3c595b8b4f422a0355dc5a3b4e7 + +commit cfa66857db90cd908de131e0041a50ffc17c7df8 +Author: djm@openbsd.org +Date: Mon Aug 28 09:52:09 2023 +0000 + + upstream: descriptive text shouldn't be under .Cm - SSH-Copy-ID-Upstream: 32686e7c65b4fa2846e474d3315102dfa0f043b0 + OpenBSD-Commit-ID: b1afaeb456a52bc8a58f4f9f8b2f9fa8f6bf651b -commit 204e0bf05161b7641500d7ab266c21217412379f -Author: Darren Tucker -Date: Tue Aug 3 21:25:48 2021 +1000 +commit 01dbf3d46651b7d6ddf5e45d233839bbfffaeaec +Author: djm@openbsd.org +Date: Mon Aug 28 09:48:11 2023 +0000 - Make ssh-copy-id(1) consistent with OpenSSH. + upstream: limit artificial login delay to a reasonable maximum (5s) - This makes the ssh-copy-id man page more consistent with the rest of the - OpenSSH man pages: - - new sentence, new line - - no sentences >80 - - N.B. -> NB - - zap unused .Pp - - zap trailing whitespace - - Report from Debian via mindrot bz#3331, diff from jmc at openbsd.org. + and don't delay at all for the "none" authentication mechanism. Patch by + Dmitry Belyavskiy in bz3602 with polish/ok dtucker@ - SSH-Copy-ID-Upstream: d8974cfb6242316460ed22a1ccc662800a50c5d3 + OpenBSD-Commit-ID: 85b364676dd84cf1de0e98fc2fbdcb1a844ce515 -commit 9de79df66d1430d290fab670bb4b18612875e518 -Author: Philip Hands -Date: Wed May 24 11:45:43 2023 +0200 +commit 528da5b9d7c5da01ed7a73ff21c722e1b5326006 +Author: jmc@openbsd.org +Date: Mon Aug 28 05:32:28 2023 +0000 - if -s & -p specified, mention 'sftp -P' on success - - This was inspired by this: - https://github.com/openssh/openssh-portable/pull/321 - but I thought that it was better to not do the sed patching. - - BTW the reason one can get away with using $SSH_OPTS throughout, despite - the lowercase -p in there, even if sftp is in use, is that the sftp call - is using the already-established ssh master connection, so the port was - passed to the earlier ssh. + upstream: add spacing for punctuation when macro args; - SSH-Copy-ID-Upstream: 1c124d9bfafdbe28a00b683367ebf5750ce12eb2 + OpenBSD-Commit-ID: e80343c16ce0420b2aec98701527cf90371bd0db -commit 801cda54c00e0f4e7d89345a90874c8d05dc233a -Author: Philip Hands -Date: Tue May 23 23:07:11 2023 +0200 +commit 3867361ca691d0956ef7d5fb8181cf554a91d84a +Author: djm@openbsd.org +Date: Mon Aug 28 04:06:52 2023 +0000 - drop whitespace + upstream: explicit long long type in timing calculations (doesn't - SSH-Copy-ID-Upstream: e604fae1cdee35c18055d35dcec530cf12ef00ad - -commit 288482f53613f3e74544eb92deeb24f7c7f1f371 -Author: Philip Hands -Date: Tue May 23 20:52:13 2023 +0200 - - make -x also apply to the target script + matter, since the range is pre-clamped) - SSH-Copy-ID-Upstream: 3c4214704f427bd0654adf9b0fc079253db21cf4 + OpenBSD-Commit-ID: f786ed902d04a5b8ecc581d068fea1a79aa772de -commit b79e7b88ed44f0e4339f0ff35c96c78a92175a8d -Author: Philip Hands -Date: Tue May 23 16:46:42 2023 +0200 +commit 7603ba71264e7fa938325c37eca993e2fa61272f +Author: djm@openbsd.org +Date: Mon Aug 28 03:31:16 2023 +0000 - add -t option to specify the target path - - Allow the default target path (.ssh/authorized_files) to be over-riden - - This was inspired by this MR from Panagiotis Cheilaris - - https://gitlab.com/phil_hands/ssh-copy-id/-/merge_requests/8 + upstream: Add keystroke timing obfuscation to the client. - SSH-Copy-ID-Upstream: a942a0e076874adb6d8b2f0fb76d6c7918190fcd - -commit 914f4ad138714c471ba72fb6d5496b6235320edd -Author: Carlos Rodríguez Gili -Date: Tue Apr 20 19:23:57 2021 +0200 - - Fix test error for /bin/sh on Solaris 10 and older + This attempts to hide inter-keystroke timings by sending interactive + traffic at fixed intervals (default: every 20ms) when there is only a + small amount of data being sent. It also sends fake "chaff" keystrokes + for a random interval after the last real keystroke. These are + controlled by a new ssh_config ObscureKeystrokeTiming keyword/ - On Solaris 10 and older targets /bin/sh is not POSIX-compliant. - Test -z `...` fails with error 'sh: test: argument expected'. - Using quotes around backticks fixes this and doesn't break - POSIX compatibility. + feedback/ok markus@ - SSH-Copy-ID-Upstream: 98394072a3f985b2650c1e8eab2fef84e38cc065 + OpenBSD-Commit-ID: 02231ddd4f442212820976068c34a36e3c1b15be -commit bd382dca316c721aed1e45edcf4c4e0f6374afb0 -Author: Jakub Jelen -Date: Tue Mar 2 21:34:05 2021 +0000 +commit dce6d80d2ed3cad2c516082682d5f6ca877ef714 +Author: djm@openbsd.org +Date: Mon Aug 28 03:28:43 2023 +0000 - Remove outdated comment - - The commit b068122 removed the code dropping the trailing colon, but the comment stayed leaving the code confusing for future readers + upstream: Introduce a transport-level ping facility - SSH-Copy-ID-Upstream: 930d39f238117cd53810240ec989d0356aa1c1f6 - -commit bdcaf7939029433635d63aade8f9ac762aca2bbe -Author: Darren Tucker -Date: Wed May 10 18:50:46 2023 +1000 - - Special case OpenWrt instead of Dropbear. + This adds a pair of SSH transport protocol messages SSH2_MSG_PING/PONG + to implement a ping capability. These messages use numbers in the "local + extensions" number space and are advertised using a "ping@openssh.com" + ext-info message with a string version number of "0". - OpenWrt overrides the location of authorized_keys for root. Currently we - assume that all Dropbear installations behave this way, which is not the - case. Check for OpenWrt and root user before using that location instead - of assuming that for all Dropbear servers. Prompted by Github PR#250. + ok markus@ - SSH-Copy-ID-Upstream: 0e1f5d443a9967483c33945793107ae3f3e4af2d + OpenBSD-Commit-ID: b6b3c4cb2084c62f85a8dc67cf74954015eb547f -commit cf84498f67abe93f813a296167b406a0db7b288e -Author: Philip Hands -Date: Thu May 18 18:20:55 2023 +0200 +commit d2d247938b38b928f8a6e1a47a330c5584d3a358 +Author: tobhe@openbsd.org +Date: Mon Aug 21 21:16:18 2023 +0000 - ssh-copy-id: add -x option (for debugging) + upstream: Log errors in kex_exchange_identification() with level - This option causes the ssh-copy-id to run with set -x + verbose instead of error to reduce preauth log spam. All of those get logged + with a more generic error message by sshpkt_fatal(). - SSH-Copy-ID-Upstream: a0ee367ea8c0a29c8b4515245e408d2d349e7844 - -commit b4a1efdcb88f03394c08e7f68ed4e11676830002 -Author: Philip Hands -Date: Thu May 18 17:14:41 2023 +0200 - - update copyright notices + feedback from sthen@ + ok djm@ - SSH-Copy-ID-Upstream: c284ed33b361814ea48ff68cbd01ca525b2bf117 + OpenBSD-Commit-ID: bd47dab4695b134a44c379f0e9a39eed33047809 -commit fcd78e31cdd45a7e69ccfe6d8a3b1037dc1de290 +commit 9d7193a8359639801193ad661a59d1ae4dc3d302 Author: djm@openbsd.org -Date: Wed May 24 23:01:06 2023 +0000 +Date: Mon Aug 21 04:59:54 2023 +0000 - upstream: fix AuthorizedPrincipalsCommand when AuthorizedKeysCommand + upstream: correct math for ClientAliveInterval that caused the - appears previously in configuration. Reported by John Meyers in bz3574 ok - dtucker@ + probes to be sent less frequently than configured; from Dawid Majchrzak - OpenBSD-Commit-ID: 1c92e4517284386703936e1d3abaa36cfacf1951 + OpenBSD-Commit-ID: 641153e7c05117436ddfc58267aa267ca8b80038 -commit 5ec5504f1d328d5bfa64280cd617c3efec4f78f3 -Author: dtucker@openbsd.org -Date: Wed May 10 10:04:20 2023 +0000 +commit 3c6ab63b383b0b7630da175941e01de9db32a256 +Author: Darren Tucker +Date: Fri Aug 25 14:48:02 2023 +1000 - upstream: Remove unused prototypes for ssh1 RSA functions. - - From lengyijun via github PR#396. + Include Portable version in sshd version string. - OpenBSD-Commit-ID: 379a5afa8b7a0f3cba0c8a9bcceb4e5e33a5c1ef + bz#3608, ok djm@ -commit fbf362b3891ae4b36052d1b39f37fc618b41c476 +commit 17fa6cd10a26e193bb6f65d21264d2fe553bcd87 Author: Darren Tucker -Date: Tue May 9 19:26:56 2023 +1000 +Date: Mon Aug 21 19:47:58 2023 +1000 - main(void) to prevent unused variable warning. + obsd-arm64 host is real hardware... + + so put in the correct config location. -commit baf854c8bb0a6d0af5c696c801e631a48dabbaba +commit 598ca75c85acaaacee5ef954251e489cc20d7be9 Author: Darren Tucker -Date: Tue May 9 19:25:45 2023 +1000 +Date: Mon Aug 21 18:38:36 2023 +1000 - Remove warning pragma since clang doesn't like it. + Add OpenBSD ARM64 test host. -commit 5fbb7a1349fbbb48ccb1b8cafff2c1854370d87d +commit 1acac79bfbe207e8db639e8043524962037c8feb Author: Darren Tucker -Date: Tue May 9 17:13:33 2023 +1000 +Date: Mon Aug 21 18:05:26 2023 +1000 - Suppress warning for snprintf truncation test. + Add test for zlib development branch. -commit 47742c513e4e045ecc985c6483fc5c8b050acda2 -Author: Darren Tucker -Date: Tue May 9 17:12:50 2023 +1000 +commit 84efebf352fc700e9040c8065707c63caedd36a3 +Author: djm@openbsd.org +Date: Mon Aug 21 04:36:46 2023 +0000 - Update OpenSSL compat test for 3.x. + upstream: want stdlib.h for free(3) + + OpenBSD-Commit-ID: 743af3c6e3ce5e6cecd051668f0327a01f44af29 -commit 86ad25d455a2313126125540e61e0f9314283f88 +commit cb4ed12ffc332d1f72d054ed92655b5f1c38f621 Author: Darren Tucker -Date: Mon May 8 20:23:08 2023 +1000 +Date: Sat Aug 19 07:39:08 2023 +1000 - Add macos13 PAM test target. + Fix zlib version check for 1.3 and future version. + + bz#3604. -commit 77cca2c4b13bc6e5f389565583b6202b0d1bccc2 +commit 25b75e21f16bccdaa472ea1889b293c9bd51a87b Author: Darren Tucker -Date: Mon May 8 20:14:46 2023 +1000 +Date: Mon Aug 14 11:10:08 2023 +1000 - Skip agent-peereid test on macos13. - - sudo -S nobody doesn't work on the github runners (probably a - permission issue) so skip that test. + Add 9.4 branch to CI status page. -commit b356b8e91678ea295bcf44df5248c3fbf499fdcf -Author: Darren Tucker -Date: Mon May 8 20:14:28 2023 +1000 +commit 803e22eabd3ba75485eedd8b7b44d6ace79f2052 +Author: djm@openbsd.org +Date: Fri Aug 18 01:37:41 2023 +0000 - Include config.guess in debug output. + upstream: fix regression in OpenSSH 9.4 (mux.c r1.99) that caused + + multiplexed sessions to ignore SIGINT under some circumstances. Reported by / + feedback naddy@, ok dtucker@ + + OpenBSD-Commit-ID: 4d5c6c894664f50149153fd4764f21f43e7d7e5a -commit b7afd8a4ecaca8afd3179b55e9db79c0ff210237 -Author: Darren Tucker -Date: Mon May 8 20:12:59 2023 +1000 +commit e706bca324a70f68dadfd0ec69edfdd486eed23a +Author: djm@openbsd.org +Date: Wed Aug 16 16:14:11 2023 +0000 - Handle OpenSSL >=3 ABI compatibility. + upstream: defence-in-depth MaxAuthTries check in monitor; ok markus - Beyond OpenSSL 3.0, the ABI compatibility guarantees are wider (only - major must match instead of major and minor in earlier versions). - bz#3548, ok djm@ + OpenBSD-Commit-ID: 65a4225dc708e2dae71315adf93677edace46c21 -commit 0e9e2663eb2c6e9c3e10d15d70418312ae67e542 -Author: dtucker@openbsd.org -Date: Mon May 1 08:57:29 2023 +0000 +commit d1ab7eb90474df656d5e9935bae6df0bd000d343 +Author: djm@openbsd.org +Date: Mon Aug 14 03:37:00 2023 +0000 - upstream: Import regenerated moduli. + upstream: add message number of SSH2_MSG_NEWCOMPRESS defined in RFC8308 - OpenBSD-Commit-ID: 3d5f811cfcaed8cc4a97e1db49ac61bdf118113c + OpenBSD-Commit-ID: 6c984171c96ed67effd7b5092f3d3975d55d6028 -commit d9687f49682e1e93383fc15ab2018850b2ef38c3 +commit fa8da52934cb7dff6f660a143276bdb28bb9bbe1 Author: Darren Tucker -Date: Mon May 1 11:45:14 2023 +1000 +Date: Sun Aug 13 15:01:27 2023 +1000 - Add macos-13 test target. - - Also flatten OS list for clarity. + Add obsd72 and obsd73 test targets. -commit aacfd6767497b8fa6d41ecdd3f8e265d1e9ef1f6 +commit f9f18006678d2eac8b0c5a5dddf17ab7c50d1e9f Author: djm@openbsd.org -Date: Sun Apr 30 22:54:22 2023 +0000 +Date: Thu Aug 10 23:05:48 2023 +0000 - upstream: adjust ftruncate() logic to handle servers that reorder - - requests. + upstream: better debug logging of sessions' exit status - sftp/scp will ftruncate the destination file after a transfer completes, - to deal with the case where a longer destination file already existed. - We tracked the highest contiguous block transferred to deal with this - case, but our naive tracking doesn't deal with servers that reorder - requests - a misfeature strictly permitted by the protocol but seldom - implemented. - - Adjust the logic to ftruncate() at the highest absolute block received - when the transfer is successful. feedback deraadt@ ok markus@ - - prompted by https://github.com/openssh/openssh-portable/commit/9b733#commitcomment-110679778 - - OpenBSD-Commit-ID: 4af7fac75958ad8507b4fea58706f3ff0cfddb1b - -commit c8eb3941758615c8284a48fff47872db926da63c -Author: djm@openbsd.org -Date: Wed Apr 26 01:36:03 2023 +0000 - - upstream: Check for ProxyJump=none in CanonicalizeHostname logic. - - Previously ssh would incorrectly refuse to canonicalise the hostname - if ProxyJump was explicitly set to "none" when CanonicalizeHostname=yes - - bz3567; ok dtucker - - OpenBSD-Commit-ID: 80a58e43c3a32f97361282f756ec8d3f37989efd - -commit ac383f3a5c6f529a2e8a5bc44af79a08c7da294e -Author: jsg@openbsd.org -Date: Wed Apr 12 14:22:04 2023 +0000 - - upstream: remove duplicate signal.h include - - OpenBSD-Commit-ID: 30c0a34d74d91ddd0e6992525da70d3293392f70 + OpenBSD-Commit-ID: 82237567fcd4098797cbdd17efa6ade08e1a36b0 -commit 740dafa20f3f3d325f6f5d44e990b8c8a6d3d816 -Author: jsg@openbsd.org -Date: Wed Apr 12 08:53:54 2023 +0000 +commit a8c57bcb077f0cfdffcf9f23866bf73bb93e185c +Author: naddy@openbsd.org +Date: Thu Aug 10 14:37:32 2023 +0000 - upstream: fix double words ok dtucker@ + upstream: drop a wayward comma, ok jmc@ - OpenBSD-Commit-ID: 44d3223902fbce5276422bdc8063ab72a4078489 + OpenBSD-Commit-ID: 5c11fbb9592a29b37bbf36f66df50db9d38182c6 -commit 6452f89577ec4f22440c31b8e19b061d1a7c4b2a -Author: Darren Tucker -Date: Tue Apr 11 16:49:19 2023 +1000 +commit e962f9b318a238db1becc53c2bf79dd3a49095b4 +Author: Damien Miller +Date: Thu Aug 10 11:10:22 2023 +1000 - Test against LibreSSL 3.7.2. + depend -commit 2138f6be595ca106fe4805a1e3ab9c4d8acc697b +commit 0fcb60bf83130dfa428bc4422b3a3ac20fb528af Author: Damien Miller -Date: Thu Apr 6 14:33:10 2023 +1000 +Date: Thu Aug 10 11:05:42 2023 +1000 - remove unused upper-case const strings in fmtfp - - no float format that uses upper-case is supported nor are hex floats. - ok dtucker + update versions in RPM specs -commit 484c5e6168fdb22cbcd73c4ff987cf9ca47989ca -Author: djm@openbsd.org -Date: Thu Apr 6 03:56:02 2023 +0000 +commit d0cee4298491314f09afa1c4383a66d913150b26 +Author: Damien Miller +Date: Thu Aug 10 11:05:14 2023 +1000 - upstream: simplify sshsig_find_principals() similar to what happened to - - sshsig_check_allowed_keys() in r1.31, removing some dead code - - OpenBSD-Commit-ID: a493e628d4d6c08f878c276d998f4313ba61702d + update version in README -commit 3a7b110fbc7e096423f8f7b459deffe4c65d70f4 +commit 78b4dc6684f4d35943b46b24ee645edfdb9974f5 Author: djm@openbsd.org -Date: Thu Apr 6 03:21:31 2023 +0000 +Date: Thu Aug 10 01:01:07 2023 +0000 - upstream: remove redundant ssh!=NULL check; we'd already - - dereferenced it + upstream: openssh-9.4 - OpenBSD-Commit-ID: 852bf12591ec5a9fb12dcbde9b1fd3945ad0df3c + OpenBSD-Commit-ID: 71fc1e01a4c4ea061b252bd399cda7be757e6e35 -commit 2519110659a1efac6c976895a86659d1b341c91b -Author: djm@openbsd.org -Date: Thu Apr 6 03:19:32 2023 +0000 +commit 58ca4f0aa8c4306ac0a629c9a85fb1efaf4ff092 +Author: Darren Tucker +Date: Thu Aug 10 11:30:24 2023 +1000 - upstream: match_user() shouldn't be called with user==NULL unless - - host and ipaddr are also NULL - - OpenBSD-Commit-ID: fa3518346c21483e9e01a2e4b9436ae501daf8ea + Only include unistd.h once. -commit 3b9ceaad7ad63c1c03c2a89e148340ad3a62a482 -Author: djm@openbsd.org -Date: Thu Apr 6 03:12:32 2023 +0000 +commit 3961ed02dc578517a9d2535128cff5c3a5460d28 +Author: Damien Miller +Date: Thu Aug 10 09:08:49 2023 +1000 - upstream: don't care about glob() return value here. - - OpenBSD-Commit-ID: 85bb82fea90478a482e9f65a1bec0aa24227fd66 + wrap poll.h include in HAVE_POLL_H -commit 09d8da0849e2791b2500267cda333cd238f38754 +commit e535fbe2af893046c28adfcd787c1fdbae36a24a Author: dtucker@openbsd.org -Date: Mon Apr 3 08:10:54 2023 +0000 +Date: Fri Aug 4 06:32:40 2023 +0000 - upstream: Move up null check and simplify process_escapes. + upstream: Apply ConnectTimeout to multiplexing local socket - Based on Coverity CID 291863 which points out we check the channel - pointer for NULLness after dereferencing it. Move this to the start - of the function, and while there simplify initialization of efc a bit. - ok djm@ + connections. If the multiplex socket exists but the connection times out, + ssh will fall back to a direct connection the same way it would if the socket + did not exist at all. ok djm@ - OpenBSD-Commit-ID: de36e5ad6fde0fe263ca134e986b9095dc59380a + OpenBSD-Commit-ID: 2fbe1a36d4a24b98531b2d298a6557c8285dc1b4 -commit b36b162be5e6206f12b734222b7bc517c13a6bc8 -Author: Damien Miller -Date: Fri Mar 31 14:51:20 2023 +1100 +commit 9d92e7b24848fcc605945f7c2e3460c7c31832ce +Author: Darren Tucker +Date: Thu Aug 3 19:35:33 2023 +1000 - need va_end() after va_copy(); ok dtucker + Fix RNG seeding for OpenSSL w/out self seeding. - spotted by Coverity + When sshd is built with an OpenSSL that does not self-seed, it would + fail in the preauth privsep process while handling a new connection. + Sanity checked by djm@ -commit f703757234a5c585553e72bba279b255a272750a -Author: dtucker@openbsd.org -Date: Fri Mar 31 05:56:36 2023 +0000 +commit f70010d9b0b3e7e95de8aa0b961e1d74362cfb5d +Author: djm@openbsd.org +Date: Wed Aug 2 23:04:38 2023 +0000 - upstream: Explicitly ignore return from waitpid here too. + upstream: CheckHostIP has defaulted to 'no' for a while; make the - OpenBSD-Commit-ID: eef2403df083c61028969fc679ee370373eacacb + commented- out config option match. From Ed Maste + + OpenBSD-Commit-ID: e66e934c45a9077cb1d51fc4f8d3df4505db58d9 -commit 6b73aa29035991d1448a1a76f63ac152a6bf931c +commit c88a8788f9865d02b986d00405b9f0be65ad0b5a Author: dtucker@openbsd.org -Date: Fri Mar 31 04:45:08 2023 +0000 +Date: Tue Aug 1 08:15:04 2023 +0000 - upstream: Explictly ignore return codes + upstream: remove unnecessary if statement. - where we don't check them. + github PR#422 from eyalasulin999, ok djm@ - OpenBSD-Commit-ID: 1ffb03038ba1b6b72667be50cf5e5e396b5f2740 + OpenBSD-Commit-ID: 2b6b0dde4407e039f58f86c8d2ff584a8205ea55 -commit 6f0308a3e717ebe68eeb3f95253612fab5dbf20e -Author: dtucker@openbsd.org -Date: Fri Mar 31 04:42:29 2023 +0000 +commit 77b8b865cd5a8c79a47605c0c5b2bacf4692c4d5 +Author: jmc@openbsd.org +Date: Fri Jul 28 05:42:36 2023 +0000 - upstream: Return immediately from get_sock_port + upstream: %C is a callable macro in mdoc(7) - if sock <0 so we don't call getsockname on a negative FD. From Coverity - CID 291840, ok djm@ + so, as we do for %D, escape it; - OpenBSD-Commit-ID: de1c1130646230c2eda559831fc6bfd1b61d9618 + OpenBSD-Commit-ID: 538cfcddbbb59dc3a8739604319491dcb8e0c0c9 -commit 1c1124dc901fca1ea2cb762044b8f1a5793a2bed +commit e0f91aa9c2fbfc951e9ced7e1305455fc614d3f2 Author: djm@openbsd.org -Date: Fri Mar 31 04:23:02 2023 +0000 +Date: Fri Jul 28 05:33:15 2023 +0000 - upstream: don't leak arg2 on parse_pubkey_algos error path; ok + upstream: don't need to start a command here; use ssh -N instead. - dtucker@ + Fixes failure on cygwin spotted by Darren - OpenBSD-Commit-ID: 7d0270ad3dd102412ca76add2b3760518abdef75 + OpenBSD-Regress-ID: ff678a8cc69160a3b862733d935ec4a383f93cfb -commit 8ba2d4764bb6a4701cd447d8b52604622ffe65f4 +commit f446a44f30bc680e0d026a4204844b02646c1c2d Author: djm@openbsd.org -Date: Fri Mar 31 04:22:27 2023 +0000 +Date: Wed May 17 05:52:01 2023 +0000 - upstream: clamp max number of GSSAPI mechanisms to 2048; ok dtucker + upstream: add LTESTS_FROM variable to allow skipping of tests up to - OpenBSD-Commit-ID: ce66db603a913d3dd57063e330cb5494d70722c4 + a specific point. e.g. "make LTESTS_FROM=t-sftp" will only run the sftp.sh + test and subsequent ones. ok dtucker@ + + OpenBSD-Regress-ID: 07f653de731def074b29293db946042706fcead3 -commit 1883841fc13d0eada8743cac5d3abe142ee2efa7 +commit 8eb8899d612440a9b608bee7f916081d3d0b7812 Author: djm@openbsd.org -Date: Fri Mar 31 04:21:56 2023 +0000 +Date: Fri May 12 06:37:42 2023 +0000 - upstream: don't print key if printing hostname failed; with/ok - - dtucker@ + upstream: test ChrootDirectory in Match block - OpenBSD-Commit-ID: ad42971a6ee5a46feab2d79f7f656f8cf4b119f3 + OpenBSD-Regress-ID: a6150262f39065939f025e546af2a346ffe674c1 -commit c6011129cafe4c411f6ef670a4cf271314708eb8 +commit e43f43d3f19516222e9a143468ea0dc1b3ab67b6 Author: djm@openbsd.org -Date: Fri Mar 31 04:04:15 2023 +0000 +Date: Fri May 12 06:36:27 2023 +0000 - upstream: remove redundant test + upstream: better error messages - OpenBSD-Commit-ID: 6a0b719f9b1ae9d42ad8c5b144c7962c93792f7c + OpenBSD-Regress-ID: 55e4186604e80259496d841e690ea2090981bc7a -commit 4fb29eeafb40a2076c0dbe54e46b687c318f87aa +commit 6958f00acf3b9e0b3730f7287e69996bcf3ceda4 Author: djm@openbsd.org -Date: Fri Mar 31 04:00:37 2023 +0000 +Date: Thu Jul 27 22:26:49 2023 +0000 - upstream: don't attempt to decode a ridiculous number of + upstream: don't incorrectly truncate logged strings retrieved from - attributes; harmless because of bounds elsewhere, but better to be explicit + PKCS#11 modules; based on GHPR406 by Jakub Jelen; ok markus - OpenBSD-Commit-ID: 1a34f4b6896155b80327d15dc7ccf294b538a9f2 + OpenBSD-Commit-ID: 7ed1082f23a13b38c373008f856fd301d50012f9 -commit fc437c154ef724621a4af236de9bc7e51a8381ae +commit d1ffde6b55170cd4b9a72bfd9a3f17508e6cf714 Author: djm@openbsd.org -Date: Fri Mar 31 03:22:49 2023 +0000 - - upstream: remove unused variable; prompted by Coverity CID 291879 - - OpenBSD-Commit-ID: 4c7d20ef776887b0ba1aabcfc1b14690e4ad0a40 - -commit 0eb8131e4a53b33a8fc9b9ab694e6b6778b87ade -Author: dtucker@openbsd.org -Date: Fri Mar 31 00:44:29 2023 +0000 +Date: Thu Jul 27 22:25:17 2023 +0000 - upstream: Check fd against >=0 instead of >0 in error path. The + upstream: make sshd_config AuthorizedPrincipalsCommand and - dup could in theory return fd 0 although currently it doesn't in practice. - From Dmitry Belyavskiy vi github PR#238. + AuthorizedKeysCommand accept the %D (routing domain) and a new %C (connection + address/port 4-tuple) as expansion sequences; ok markus - OpenBSD-Commit-ID: 4a95f3f7330394dffee5c749d52713cbf3b54846 + OpenBSD-Commit-ID: ee9a48bf1a74c4ace71b69de69cfdaa2a7388565 -commit 7174ba6f8a431ca4257767a260fc50e204068242 -Author: dtucker@openbsd.org -Date: Thu Mar 30 07:19:50 2023 +0000 +commit 999a2886ca1844a7a74b905e5f2c8c701f9838cd +Author: djm@openbsd.org +Date: Thu Jul 27 22:23:05 2023 +0000 - upstream: Ignore return value from muxclient(). It normally loops + upstream: increase default KDF work-factor for OpenSSH format - without returning, but it if returns on failure we immediately exit. - Coverity CID 405050. + private keys from 16 to 24; { feedback ok } x { deraadt markus } - OpenBSD-Commit-ID: ab3fde6da384ea588226037c38635a6b2e015295 + OpenBSD-Commit-ID: a3afb1383f8ff0a49613d449f02395d9e8d4a9ec -commit a4c1c2513e36f111eeaa1322c510067930e5e51e -Author: Damien Miller -Date: Fri Mar 31 14:17:22 2023 +1100 +commit 0fa803a1dd1c7b546c166000e23a869cf6c4ec10 +Author: Darren Tucker +Date: Thu Jul 27 02:25:09 2023 +1000 - don't call connect() on negative socket + Prefer OpenSSL's SHA256 in sk-dummy.so - Coverity CID 405037 - -commit 34ee842cdd981a759fe8f0d4a37521f9a1c63170 + Previously sk-dummy.so used libc's (or compat's) SHA256 since it may be + built without OpenSSL. In many cases, however, including both libc's + and OpenSSL's headers together caused conflicting definitions. + + We tried working around this (on OpenSSL <1.1 you could define + OPENSSL_NO_SHA, NetBSD had USE_LIBC_SHA2, various #define hacks) with + varying levels of success. Since OpenSSL >=1.1 removed OPENSSL_NO_SHA + and including most OpenSSL headers would bring sha.h in, even if it + wasn't used directly this was a constant hassle. + + Admit defeat and use OpenSSL's SHA256 unless we aren't using OpenSSL at + all. ok djm@ + +commit 36cdb5dbf55c99c0faad06066f56a7c341258c1f +Author: Darren Tucker +Date: Thu Jul 27 10:29:44 2023 +1000 + + Retire dfly58 test VM. Add dfly64. + +commit 2d34205dab08ede9b0676efa57647fc49e6decbe Author: djm@openbsd.org -Date: Thu Mar 30 03:05:01 2023 +0000 +Date: Wed Jul 26 23:06:00 2023 +0000 - upstream: return SSH_ERR_KEY_NOT_FOUND if the allowed_signers file + upstream: make ssh -f (fork after authentication) work properly in - is empty, not SSH_ERR_INTERNAL_ERROR. Also remove some dead code spotted - by Coverity; with/ok dtucker@ + multiplexed cases (inc. ControlPersist). bz3589 bz3589 Based on patches by + Peter Chubb; ok dtucker@ - OpenBSD-Commit-ID: 898a1e817cda9869554b1f586a434f67bcc3b650 + OpenBSD-Commit-ID: a7a2976a54b93e6767dc846b85647e6ec26969ac -commit f108e77a9dc9852e72215af1bf27731c48434557 -Author: dtucker@openbsd.org -Date: Thu Mar 30 00:49:37 2023 +0000 +commit 076aeda86a7ee9be8fd2f0181ec7b9729a6ceb37 +Author: naddy@openbsd.org +Date: Sun Jul 23 20:04:45 2023 +0000 - upstream: Remove dead code from inside if block. - - The only way the if statement can be true is if both dup()s fail, and - in that case the tmp2 can never be set. Coverity CID 291805, ok djm@ + upstream: man page typos; ok jmc@ - OpenBSD-Commit-ID: c0d6089b3fb725015462040cd94e23237449f0c8 + OpenBSD-Commit-ID: e6ddfef94b0eb867ad88abe07cedc8ed581c07f0 -commit 05b8e88ebe23db690abbfb1a91111abea09cde08 -Author: Darren Tucker -Date: Thu Mar 30 13:53:29 2023 +1100 +commit 135e7d5fe31f700e6dfc61ce914970c5ee7175ba +Author: jmc@openbsd.org +Date: Thu Jul 20 05:43:39 2023 +0000 - child_set_eng: verify both env pointer and count. + upstream: tweak the allow-remote-pkcs11 text; - If child_set env was called with a NULL env pointer and a non-zero count - it would end up in a null deref, although we don't currently do this. - Prompted by Coverity CID 291850, tweak & ok djm@ + OpenBSD-Commit-ID: bc965460a89edf76865b7279b45cf9cbdebd558a -commit 28f1b8ef9b84b8cd2f6c9889a0c60aa4a90dadfa -Author: dtucker@openbsd.org -Date: Wed Mar 29 01:07:48 2023 +0000 +commit 5f83342b61d1f76c141de608ed2bd293990416bd +Author: Darren Tucker +Date: Tue Jul 25 13:00:22 2023 +1000 - upstream: Ignore return from sshpkt_disconnect + Handle a couple more OpenSSL no-ecc cases. - since we set our own return value for the function. Coverity CID 291797, ok djm@ - - OpenBSD-Commit-ID: 710b57ba954c139240895e23feea41f203201f04 -commit c3da05d95922f5550bcc7815e799474d6a160175 -Author: dtucker@openbsd.org -Date: Wed Mar 29 00:59:08 2023 +0000 +commit edc2ef4e418e514c99701451fae4428ec04ce538 +Author: Damien Miller +Date: Thu Jul 20 12:53:44 2023 +1000 - upstream: Plug potential mem leak in process_put. - - It allocates abs_dst inside a loop but only frees it on exit, so free - inside the loop if necessary. Coverity CID 291837, ok djm@ - - OpenBSD-Commit-ID: a01616503a185519b16f00dde25d34ceaf4ae1a3 + depend -commit 13ae327eae598b1043e5ec30e4b170edb3c898a5 +commit 51fda734e0d3c2df256fc03e8b060c4305be6e59 +Author: Damien Miller +Date: Thu Jul 20 12:53:21 2023 +1000 + + Bring back OPENSSL_HAS_ECC to ssh-pkcs11-client + +commit 099cdf59ce1e72f55d421c8445bf6321b3004755 Author: djm@openbsd.org -Date: Wed Mar 29 00:18:35 2023 +0000 +Date: Wed Jul 19 14:03:45 2023 +0000 - upstream: fix memory leak; Coverity CID 291848 + upstream: Separate ssh-pkcs11-helpers for each p11 module - with/ok dtucker@ + Make ssh-pkcs11-client start an independent helper for each provider, + providing better isolation between modules and reliability if a single + module misbehaves. - OpenBSD-Commit-ID: 37f80cb5d075ead5a00ad1b74175684ab1156ff8 + This also implements reference counting of PKCS#11-hosted keys, + allowing ssh-pkcs11-helper subprocesses to be automatically reaped + when no remaining keys reference them. This fixes some bugs we have + that make PKCS11 keys unusable after they have been deleted, e.g. + https://bugzilla.mindrot.org/show_bug.cgi?id=3125 + + ok markus@ + + OpenBSD-Commit-ID: 0ce188b14fe271ab0568f4500070d96c5657244e -commit 9ffa76e1284c85bf459c3dcb8e995733a8967e1b -Author: dtucker@openbsd.org -Date: Tue Mar 28 07:44:32 2023 +0000 +commit 29ef8a04866ca14688d5b7fed7b8b9deab851f77 +Author: djm@openbsd.org +Date: Wed Jul 19 14:02:27 2023 +0000 - upstream: Plug more mem leaks in sftp by making + upstream: Ensure FIDO/PKCS11 libraries contain expected symbols - make_absolute_pwd_glob work in the same way as make_absolute: you - pass it a dynamically allocated string and it either returns it, or - frees it and allocates a new one. Patch from emaste at freebsd.org and - https://reviews.freebsd.org/D37253 ok djm@ + This checks via nlist(3) that candidate provider libraries contain one + of the symbols that we will require prior to dlopen(), which can cause + a number of side effects, including execution of constructors. - OpenBSD-Commit-ID: 85f7404e9d47fd28b222fbc412678f3361d2dffc + Feedback deraadt; ok markus + + OpenBSD-Commit-ID: 1508a5fbd74e329e69a55b56c453c292029aefbe -commit 82b2b8326962b1a98af279bc5bbbbbcab15b3e45 -Author: dtucker@openbsd.org -Date: Tue Mar 28 06:12:38 2023 +0000 +commit 1f2731f5d7a8f8a8385c6031667ed29072c0d92a +Author: djm@openbsd.org +Date: Wed Jul 19 13:56:33 2023 +0000 - upstream: Remove compat code for OpenSSL < 1.1.* + upstream: Disallow remote addition of FIDO/PKCS11 provider - since -portable no longer supports them. + libraries to ssh-agent by default. - OpenBSD-Commit-ID: ea2893783331947cd29a67612b4e56f818f185ff + The old behaviour of allowing remote clients from loading providers + can be restored using `ssh-agent -O allow-remote-pkcs11`. + + Detection of local/remote clients requires a ssh(1) that supports + the `session-bind@openssh.com` extension. Forwarding access to a + ssh-agent socket using non-OpenSSH tools may circumvent this control. + + ok markus@ + + OpenBSD-Commit-ID: 4c2bdf79b214ae7e60cc8c39a45501344fa7bd7c -commit b500afcf00ae1b6b73b2ccf171111dfbfeaef74d -Author: dtucker@openbsd.org -Date: Mon Mar 27 23:56:54 2023 +0000 +commit 892506b13654301f69f9545f48213fc210e5c5cc +Author: djm@openbsd.org +Date: Wed Jul 19 13:55:53 2023 +0000 - upstream: Remove compat code for OpenSSL 1.0.* + upstream: terminate process if requested to load a PKCS#11 provider - versions now that -portable has dropped support for those versions. + that isn't a PKCS#11 provider; from / ok markus@ - OpenBSD-Regress-ID: 82a8eacd87aec28e4aa19f17246ddde9d5ce7fe7 + OpenBSD-Commit-ID: 39532cf18b115881bb4cfaee32084497aadfa05c -commit 727560e6011efcb36d2f3ac6910444bc775abaa1 -Author: Darren Tucker -Date: Tue Mar 28 18:06:42 2023 +1100 +commit f3f56df8ec476b2de6cbdbdfdb77a2a61087829d +Author: Damien Miller +Date: Wed Jul 19 12:07:18 2023 +1000 - Prevent conflicts between Solaris SHA2 and OpenSSL. - - We used to prevent conflicts between native SHA2 headers and OpenSSL's - by setting OPENSSL_NO_SHA but that was removed prior to OpenSSL 1.1.0 + agent_fuzz doesn't want stdint.h conditionalised -commit 46db8e14b7f186d32173dcdecd5b785334429b8b -Author: Darren Tucker -Date: Tue Mar 28 12:44:03 2023 +1100 +commit 750911fd31d307a767cc86e3bfa90bbbb77b1a25 +Author: Damien Miller +Date: Tue Jul 18 15:41:12 2023 +1000 - Remove HEADER_SHA_H from previous... + conditionalise stdint.h inclusion on HAVE_STDINT_H - since it causes more problems than it solves. + fixes build on AIX5 at least -commit 72bd68d37387aa5f81da928f6e82f1c88ed8f674 -Author: Darren Tucker -Date: Tue Mar 28 10:35:18 2023 +1100 +commit ff047504fa6e008c4092f8929881816b8993bea0 +Author: Damien Miller +Date: Tue Jul 18 15:30:45 2023 +1000 - Replace OPENSSL_NO_SHA with HEADER_SHA_H. + conditionalise match localnetwork on ifaddrs.h - Since this test doesn't use OpenSSL's SHA2 and may cause conflicts we - don't want to include it, but OPENSSL_NO_SHA was removed beginning in - OpenSSL's 1.1 series. + Fixes build breakage on platforms that lack getifaddrs() -commit 99668f2e6e0deb833e46cfab56db59ff0fc28c7e -Author: Darren Tucker -Date: Tue Mar 28 09:50:06 2023 +1100 +commit b87b03282e466ca2927954ce93f5dbf0bfdc68f6 +Author: djm@openbsd.org +Date: Mon Jul 17 06:16:33 2023 +0000 - Configure with --target instead of deprecated form. + upstream: missing match localnetwork negation check + + OpenBSD-Commit-ID: 9a08ed8dae27d3f38cf280f1b28d4e0ff41a737a -commit f751d9306c62cd1061f966e6a7483d9bab9c379b -Author: Darren Tucker -Date: Mon Mar 27 22:05:29 2023 +1100 +commit 6d6e185ba29ef4274164b77eab4dc763907f8821 +Author: jmc@openbsd.org +Date: Mon Jul 17 05:41:53 2023 +0000 - Pass rpath when building 64bit Solaris. + upstream: - add -P to usage() - sync the arg name to -J in usage() + + with that in ssh.1 - reformat usage() to match what "man ssh" does on 80width + + OpenBSD-Commit-ID: 5235dd7aa42e5bf90ae54579d519f92fc107036e -commit a64b935cd450ee8d04c26c9cd728629cf9ca5c91 -Author: Darren Tucker -Date: Mon Mar 27 19:21:19 2023 +1100 +commit f1a9898283a0638667b587ee4a950afd61ab51b0 +Author: jmc@openbsd.org +Date: Mon Jul 17 05:38:10 2023 +0000 - Explicitly disable OpenSSL on AIX test VM. + upstream: -P before -p in SYNOPSIS; + + OpenBSD-Commit-ID: 535f5257c779e26c6a662a038d241b017f8cab7c -commit 7ebc6f060fc2f70495a56e16d210baae6424cd96 -Author: dtucker@openbsd.org -Date: Mon Mar 27 03:56:50 2023 +0000 +commit eef4d7e873568e1c84c36bb4034e2c3378250a61 +Author: jsg@openbsd.org +Date: Mon Jul 17 05:36:14 2023 +0000 - upstream: Add RevokedHostKeys to percent expansion test. + upstream: configuation -> configuration - OpenBSD-Regress-ID: c077fd12a38005dd53d878c5b944154dec88d2ff + OpenBSD-Commit-ID: 4776ced33b780f1db0b2902faec99312f26a726b -commit f1a17de150f8d309d0c52f9abfaebf11c51a8537 -Author: dtucker@openbsd.org -Date: Mon Mar 27 03:56:11 2023 +0000 +commit dc1dbe94cf6532bd546a3373ad436404f8850e5f +Author: djm@openbsd.org +Date: Mon Jul 17 05:26:38 2023 +0000 - upstream: Add tilde and environment variable expansion to + upstream: move other RCSIDs to before their respective license blocks - RevokedHostKeys. bz#3552, ok djm@ + too no code change - OpenBSD-Commit-ID: ce5d8e0219b63cded594c17d4c2958c06918ec0d + OpenBSD-Commit-ID: ef5bf46b57726e4260a63b032b0b5ac3b4fe9cd4 -commit 009eb4cb48a9708ab9174684dcbcc0f942907abe +commit ebe11044681caff78834ca6b78311ad19c1860b8 Author: djm@openbsd.org -Date: Mon Mar 27 03:31:05 2023 +0000 +Date: Mon Jul 17 05:22:30 2023 +0000 - upstream: fix test: getnameinfo returns a non-zero value on error, not + upstream: Move RCSID to before license block and away from #includes, - (neccessarily) -1. From GHPR#384 + where it caused merge conflict in -portable for each commit :( - OpenBSD-Commit-ID: d35e2b71268f66f5543a7ea68751972b3ae22b25 + OpenBSD-Commit-ID: 756ebac963df3245258b962e88150ebab9d5fc20 -commit 4f0a676486700f10a4788f7e9426e94e39c1c89e +commit 05c08e5f628de3ecf6f7ea20947735bcfa3201e0 Author: djm@openbsd.org -Date: Mon Mar 27 03:25:08 2023 +0000 +Date: Mon Jul 17 05:20:15 2023 +0000 - upstream: scp: when copying local->remote, check that source file + upstream: return SSH_ERR_KRL_BAD_MAGIC when a KRL doesn't contain a - exists before opening SFTP connection to the server. Based on GHPR#370 ok - dtucker, markus + valid magic number and not SSH_ERR_MESSAGE_INCOMPLETE; the former is needed + to fall back to text revocation lists in some cases; fixes t-cert-hostkey. - OpenBSD-Commit-ID: b4dd68e15bfe22ce4fac9960a1066a2b721e54fb + OpenBSD-Commit-ID: 5c670a6c0f027e99b7774ef29f18ba088549c7e1 -commit 154d8baf631327163571760c2c524bc93c37567c -Author: Darren Tucker -Date: Mon Mar 27 12:22:30 2023 +1100 +commit c6fad2c3d19b74f0bd0af1ef040fc74f3a1d9ebb +Author: Damien Miller +Date: Mon Jul 17 14:56:14 2023 +1000 - Also look for gdb error message from OpenIndiana. + avoid AF_LINK on platforms that don't define it -commit fbd3811ddb2b6ce2e6dba91fde7352c8978e5412 -Author: Darren Tucker -Date: Mon Mar 27 11:08:00 2023 +1100 +commit 919bc3d3b712c920de1ae6be5ac6561c98886d7e +Author: djm@openbsd.org +Date: Mon Jul 17 04:08:31 2023 +0000 - Explicitly disable security key test on aix51 VM. + upstream: Add support for configuration tags to ssh(1). - We don't know how to build the shared objects required for the security - key tests so skip them. - -commit 4922ac3be8a996780ef3dc220411da2e27c29d9c -Author: Darren Tucker -Date: Sun Mar 26 14:49:43 2023 +1100 - - Split libcrypto and other config flags. + This adds a ssh_config(5) "Tag" directive and corresponding + "Match tag" predicate that may be used to select blocks of + configuration similar to the pf.conf(5) keywords of the same + name. - This should allow the automatic OpenSSL version selection in the tests - to work better. - -commit 4a948b1469f185e871160a2d70e2a0fce2858f9e -Author: Darren Tucker -Date: Sun Mar 26 14:39:45 2023 +1100 - - Specify test target if we build without OpenSSL. + ok markus - When we decide we can't use the versions of OpenSSL available, also - restrict the tests we run to avoid the ones that need OpenSSL. + OpenBSD-Commit-ID: dc08358e70e702b59ac3e591827e5a96141b06a3 -commit b308c636f5b5d89eecb98be00b3d56306a005a09 -Author: Darren Tucker -Date: Sun Mar 26 14:22:53 2023 +1100 +commit 3071d85a47061c1bdaf11a0ac233b501ecba862c +Author: djm@openbsd.org +Date: Mon Jul 17 04:04:36 2023 +0000 - Find suitable OpenSSL version. + upstream: add a "match localnetwork" predicate. - Check the installed OpenSSL versions for a suitable one, and if there - isn't (and we don't have a specific version configured) then build - without OpenSSL. - -commit 021ea5c2860f133f44790970968e0e73208b3a87 -Author: Damien Miller -Date: Fri Mar 24 15:02:52 2023 +1100 - - Github testing support for BoringSSL - -commit 9a97cd106466a2a9bda2bfaa4c48c4f1b2cc9c1b -Author: Damien Miller -Date: Fri Mar 24 15:34:29 2023 +1100 - - BoringSSL doesn't support EC_POINT_point2bn() + This allows matching on the addresses of available network interfaces + and may be used to vary the effective client configuration based on + network location (e.g. to use a ProxyJump when not on a particular + network). - so don't invoke it in unittest - -commit cc5969c033a032d126ff78e5d95cf20abbede4c7 -Author: Damien Miller -Date: Fri Mar 24 15:34:05 2023 +1100 - - another ERR_load_CRYPTO_strings() vestige - -commit 4974293899a068133e976f81d6693670d2b576ca -Author: Damien Miller -Date: Fri Mar 24 15:24:05 2023 +1100 - - don't use obsolete ERR_load_CRYPTO_strings() + ok markus@ - OpenSSL (and elsewhere in OpenSSH) uses ERR_load_crypto_strings() - -commit 3c527d55f906e6970d17c4cab6db90ae9e013235 -Author: Damien Miller -Date: Fri Mar 24 15:23:05 2023 +1100 - - Allow building with BoringSSL + OpenBSD-Commit-ID: cffb6ff9a3803abfc52b5cad0aa190c5e424c139 -commit b7e27cfd7f163fc16b4c5d041cc28ee488a5eeec -Author: Damien Miller -Date: Fri Mar 24 15:21:18 2023 +1100 +commit beec17bb311365b75a0a5941418d4b96df7d7888 +Author: djm@openbsd.org +Date: Mon Jul 17 04:01:10 2023 +0000 - put back SSLeay_version compat in configure test + upstream: remove vestigal support for KRL signatures - Needed to detect old versions and give good "your version is bad" - messages at configure time; spotted by dtucker@ + When the KRL format was originally defined, it included support for + signing of KRL objects. However, the code to sign KRLs and verify KRL + signatues was never completed in OpenSSH. + + Now, some years later, we have SSHSIG support in ssh-keygen that is + more general, well tested and actually works. So this removes the + semi-finished KRL signing/verification support from OpenSSH and + refactors the remaining code to realise the benefit - primarily, we + no longer need to perform multiple parsing passes over KRL objects. + + ok markus@ + + OpenBSD-Commit-ID: 517437bab3d8180f695c775410c052340e038804 -commit 7280401bdd77ca54be6867a154cc01e0d72612e0 -Author: Damien Miller -Date: Fri Mar 24 13:56:25 2023 +1100 +commit 449566f64c21b4578d5c0c431badd0328adc53ed +Author: djm@openbsd.org +Date: Mon Jul 17 03:57:21 2023 +0000 - remove support for old libcrypto + upstream: Support for KRL extensions. - OpenSSH now requires LibreSSL 3.1.0 or greater or - OpenSSL 1.1.1 or greater + This defines wire formats for optional KRL extensions and implements + parsing of the new submessages. No actual extensions are supported at + this point. - with/ok dtucker@ + ok markus + + OpenBSD-Commit-ID: ae2fcde9a22a9ba7f765bd4f36b3f5901d8c3fa7 -commit abda22fb48302f2142233f71d27c74040288c518 -Author: Darren Tucker -Date: Sun Mar 19 15:36:13 2023 +1100 +commit 18ea857770e84825a3a6238bb37f54864487b59f +Author: dtucker@openbsd.org +Date: Fri Jul 14 07:44:21 2023 +0000 - Test latest OpenSSL 1.1, 3.0 and LibreSSL 3.7. + upstream: Include stdint.h for SIZE_MAX. Fixes OPENSSL=no build. + + OpenBSD-Commit-ID: e7c31034a5434f2ead3579b13a7892960651e6b0 -commit 610ac1cb077cd5a1ebfc21612154bfa13d2ec825 +commit 20b768fcd13effe0f2d3619661b6c8592c773553 Author: Darren Tucker -Date: Thu Mar 16 21:38:04 2023 +1100 +Date: Fri Jul 14 17:07:32 2023 +1000 - Show 9.3 branch instead of 9.2. + Fix typo in declaration of nmesg. -commit cb30fbdbee869f1ce11f06aa97e1cb8717a0b645 +commit 4b94d09542e36ebde2eb9ad89bc68431609932de Author: Damien Miller -Date: Thu Mar 16 08:28:19 2023 +1100 +Date: Fri Jul 14 15:34:47 2023 +1000 - depend + portable-specific int overflow defence-in-depth + + These too are unreachable, but we want the code to be safe regardless of + context. Reported by Yair Mizrahi @ JFrog -commit 1dba63eb10c40b6fda9f5012ed6ae87e2d3d028e -Author: Damien Miller -Date: Thu Mar 16 08:27:54 2023 +1100 +commit 2ee48adb9fc8692e8d6ac679dcc9f35e89ad68f0 +Author: djm@openbsd.org +Date: Fri Jul 14 05:31:44 2023 +0000 - crank version + upstream: add defence-in-depth checks for some unreachable integer + + overflows reported by Yair Mizrahi @ JFrog; feedback/ok millert@ + + OpenBSD-Commit-ID: 52af085f4e7ef9f9d8423d8c1840a6a88bda90bd -commit ba7532d0dac9aaf0ad7270664c43837fc9f64a5f +commit 4b43bc358ae6f6b19a973679246dc5172f6ac41b Author: djm@openbsd.org -Date: Wed Mar 15 21:19:57 2023 +0000 +Date: Mon Jul 10 04:51:26 2023 +0000 - upstream: openssh-9.3 + upstream: misplaced debug message - OpenBSD-Commit-ID: 8011495f2449c1029bb316bd015eab2e00509848 + OpenBSD-Commit-ID: d0f12af0a5067a756aa707bc39a83fa6f58bf7e5 -commit 6fd4daafb949b66bf555f3100f715a9ec64c3390 -Author: dtucker@openbsd.org -Date: Tue Mar 14 07:28:47 2023 +0000 +commit 8c7203bcee4c4f98a22487b4631fe068b992099b +Author: Damien Miller +Date: Wed Jul 12 11:41:19 2023 +1000 - upstream: Free KRL ptr in addition to its contents. + replace deprecate selinux matchpathcon function - From Coverity CID 291841, ok djm@ + This function is apparently deprecated. Documentation on what is the + supposed replacement is is non-existent, so this follows the approach + glibc used https://sourceware.org/git/?p=glibc.git;a=patch;h=f278835f59 - OpenBSD-Commit-ID: f146ba08b1b43af4e0d7ad8c4dae3748b4fa31b6 + ok dtucker@ -commit 1d270bd303afaf6d94e9098cbbf18e5e539e2088 +commit 7e8800f5d701efffa39ccb63ca1e095ea777c31a Author: dtucker@openbsd.org -Date: Tue Mar 14 07:26:25 2023 +0000 +Date: Thu Jul 6 22:17:59 2023 +0000 - upstream: Check pointer for NULL before deref. + upstream: minleft and maxsign are u_int so cast appropriately. Prompted - None of the existing callers seem to do that, but it's worth checking. - From Coverity CID 291834, ok djm@ + by github PR#410, ok deraadt. - OpenBSD-Commit-ID: a0a97113f192a7cb1a2c97b932f677f573cda7a4 + OpenBSD-Commit-ID: 0514cd51db3ec60239966622a0d3495b15406ddd -commit d95af508e78c0cd3dce56b83853baaa59ae295cf -Author: dtucker@openbsd.org -Date: Sun Mar 12 10:40:39 2023 +0000 +commit 94842bfe9b09fc93189c6ed0dc9bbebc1d44a426 +Author: dlg@openbsd.org +Date: Tue Jul 4 03:59:21 2023 +0000 - upstream: Limit number of entries in SSH2_MSG_EXT_INFO + upstream: add support for unix domain sockets to ssh -W - request. This is already constrained by the maximum SSH packet size but this - makes it explicit. Prompted by Coverity CID 291868, ok djm@ markus@ + ok djm@ dtucker@ - OpenBSD-Commit-ID: aea023819aa44a2dcb9dd0fbec10561896fc3a09 + OpenBSD-Commit-ID: 3e6d47567b895c7c28855c7bd614e106c987a6d8 -commit 8f287ba60d342b3e2f750e7332d2131e3ec7ecd0 -Author: dtucker@openbsd.org -Date: Sun Mar 12 09:41:18 2023 +0000 +commit a95fc5eed09a0238fb127b6c50e8498432b79dae +Author: David Seifert +Date: Fri May 12 14:06:01 2023 +0200 - upstream: calloc can return NULL but xcalloc can't. + gss-serv.c: `MAXHOSTNAMELEN` -> `HOST_NAME_MAX` - From Coverity CID 291881, ok djm@ + `MAXHOSTNAMELEN` is not defined in POSIX, which breaks on musl: + https://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html - OpenBSD-Commit-ID: 50204b755f66b2ec7ac3cfe379d07d85ca161d2b + Bug: https://bugs.gentoo.org/834044 -commit 83a56a49fd50f4acf900f934279482e4ef329715 -Author: dtucker@openbsd.org -Date: Fri Mar 10 07:17:08 2023 +0000 +commit 8a6cd08850f576e7527c52a1b086cae82fab290e +Author: Darren Tucker +Date: Fri Jun 23 09:49:02 2023 +1000 - upstream: Explicitly ignore return from fcntl - - (... FD_CLOEXEC) here too. Coverity CID 291853. + Update runner OS version for hardenedmalloc test. - OpenBSD-Commit-ID: 99d8b3da9d0be1d07ca8dd8e98800a890349e9b5 + Hardenedmalloc dropped support for "legacy glibc" versions in their + 64dad0a69 so use a newer Ubuntu version for the runner for that test. -commit 0fda9d704d3bbf54a5e64ce02a6fecb11fe7f047 +commit cfca6f17e64baed6822bb927ed9f372ce64d9c5b Author: Damien Miller -Date: Fri Mar 10 15:59:46 2023 +1100 +Date: Thu Jun 22 15:04:03 2023 +1000 - bounds checking for getrrsetbyname() replacement; + handle sysconf(SC_OPEN_MAX) returning > INT_MAX; - Spotted by Coverity in CID 405033; ok millert@ + bz3581; ok dtucker -commit 89b8df518f21677045599df0ad3e5dd0f39909b5 -Author: dtucker@openbsd.org -Date: Fri Mar 10 04:06:21 2023 +0000 +commit c1c2ca1365b3f7b626683690bd2c68265f6d8ffd +Author: djm@openbsd.org +Date: Wed Jun 21 05:10:26 2023 +0000 - upstream: Plug mem leak on error path. Coverity CID 405026, ok djm@. + upstream: better validate CASignatureAlgorithms in ssh_config and - OpenBSD-Commit-ID: 8212ca05d01966fb5e72205c592b2257708a2aac + sshd_config. + + Previously this directive would accept certificate algorithm names, but + these were unusable in practice as OpenSSH does not support CA chains. + + part of bz3577; ok dtucker@ + + OpenBSD-Commit-ID: a992d410c8a78ec982701bc3f91043dbdb359912 -commit bf4dae0ad192c3e2f03f7223834b00d88ace3d3e -Author: Darren Tucker -Date: Fri Mar 10 14:46:57 2023 +1100 +commit 4e73cd0f4ab3e5b576c56cac9732da62c8fc0565 +Author: djm@openbsd.org +Date: Wed Jun 21 05:08:32 2023 +0000 - Add prototypes for mkstemp replacements. + upstream: make `ssh -Q CASignatureAlgorithms` only list signature - Should prevent warnings due to our wrapper function. + algorithms that are valid for CA signing. Previous behaviour was to list all + signing algorithms, including certificate algorithms (OpenSSH certificates do + not support CA chains). part of bz3577; ok dtucker@ + + OpenBSD-Commit-ID: 99c2b072dbac0f44fd1f2269e3ff6c1b5d7d3e59 -commit 4e04d68d6a33cdc73b831fd4b5e6124175555d3d -Author: dtucker@openbsd.org -Date: Fri Mar 10 03:01:51 2023 +0000 +commit a69062f1695ac9c3c3dea29d3044c72aaa6af0ea +Author: djm@openbsd.org +Date: Wed Jun 21 05:06:04 2023 +0000 - upstream: Expliticly ignore return code from fcntl(.. FD_CLOEXEC) since + upstream: handle rlimits > INT_MAX (rlim_t is u64); ok dtucker - there's not much we can do anyway. From Coverity CID 291857, ok djm@ + bz3581 - OpenBSD-Commit-ID: 051429dd07af8db3fec10d82cdc78d90bb051729 + OpenBSD-Commit-ID: 31cf59c041becc0e5ccb0a77106f812c4cd1cd74 -commit d6d38fd77cbe091c59e1bb720c3a494df4990640 +commit 8d33f2aa6bb895a7f85a47189913639086347b75 Author: djm@openbsd.org -Date: Fri Mar 10 02:32:04 2023 +0000 +Date: Tue Jun 20 23:59:33 2023 +0000 - upstream: Like sshd_config, some ssh_config options are not + upstream: prepare for support for connecting to unix domain sockets - first-match-wins. sshd_config.5 was fixed in r1.348, this is the same for - this file + using ssh -W by explicitly decoding PORT_STREAMLOCAL (a negative number) from + the u32 that's passed over the multiplexing socket; previously code would + just cast, which is UB. - OpenBSD-Commit-ID: 7be55b9351cde449b136afcc52d07aa4113b215e + OpenBSD-Commit-ID: e5ac5f40d354096c51e8c118a5c1b2d2b7a31384 -commit 7187d3f86bf8f2066cc9941f217d23b0cacae25e -Author: dtucker@openbsd.org -Date: Fri Mar 10 02:24:56 2023 +0000 +commit b4ac435b4e67f8eb5932d8f59eb5b3cf7dc38df0 +Author: djm@openbsd.org +Date: Tue Jun 20 00:05:09 2023 +0000 - upstream: Remove no-op (int) > INT_MAX checks + upstream: reset comment=NULL for each key in do_fingerprint(); - since they can never be true. From Coverity CID 405031, ok djm@ + fixes "no comment" not showing on when running `ssh-keygen -l` on multiple + keys where one has a comment and other following keys do not. Patch from + Markus Kuhn via GHPR407, bz3580 - OpenBSD-Commit-ID: 9df3783b181e056595e2bb9edf7ed41d61cf8e84 + OpenBSD-Commit-ID: 3cce84456fdcd67dc6b84e369f92c6686d111d9b -commit 77adde4305542ebe3005dd456122624fe2347b01 -Author: Darren Tucker -Date: Fri Mar 10 13:27:29 2023 +1100 +commit b53a809a549dcd4fbde554c6aa283e597b15ea33 +Author: millert@openbsd.org +Date: Mon Jun 5 13:24:36 2023 +0000 - Wrap mkstemp calls with umask set/restore. + upstream: Store timeouts as int, not u_int as they are limited to - glibc versions 2.06 and earlier did not set a umask on files created by - mkstemp created the world-writable. Wrap mkstemp to set and restore - the umask. From Coverity (CIDs 291826 291886 291891), ok djm@ + INT_MAX. Fixes sign compare warnings systems with 32-bit time_t due to type + promotion. OK djm@ + + OpenBSD-Commit-ID: 48081e9ad35705c5f1705711704a4c2ff94e87b7 -commit 633d3dc2a1e9e2a013d019a0576a0771c8423713 -Author: jcs@openbsd.org -Date: Thu Mar 9 21:06:24 2023 +0000 +commit 2709809fd616a0991dc18e3a58dea10fb383c3f0 +Author: Philip Hands +Date: Wed May 24 19:41:14 2023 +0200 - upstream: modify parentheses in conditionals to make it clearer what is - - being assigned and what is being checked + fixup! if -s & -p specified, mention 'sftp -P' on - ok djm dtucker + success - OpenBSD-Commit-ID: 19c10baa46ae559474409f75a5cb3d0eade7a9b8 + SSH-Copy-ID-Upstream: 32686e7c65b4fa2846e474d3315102dfa0f043b0 -commit 733030840c4772f858de95d5940ec0c37663e8b0 -Author: dtucker@openbsd.org -Date: Thu Mar 9 07:11:05 2023 +0000 +commit 204e0bf05161b7641500d7ab266c21217412379f +Author: Darren Tucker +Date: Tue Aug 3 21:25:48 2021 +1000 - upstream: Re-split the merge of the reorder-hostkeys test. + Make ssh-copy-id(1) consistent with OpenSSH. - In the kex_proposal_populate_entries change I merged the the check for - reordering hostkeys with the actual reordering, but kex_assemble_names - mutates options.hostkeyalgorithms which renders the check ineffective. - Put the check back where it was. Spotted and tested by jsg@, ok djm@ + This makes the ssh-copy-id man page more consistent with the rest of the + OpenSSH man pages: + - new sentence, new line + - no sentences >80 + - N.B. -> NB + - zap unused .Pp + - zap trailing whitespace - OpenBSD-Commit-ID: a7469f25a738db5567395d1881e32479a7ffc9de + Report from Debian via mindrot bz#3331, diff from jmc at openbsd.org. + + SSH-Copy-ID-Upstream: d8974cfb6242316460ed22a1ccc662800a50c5d3 -commit 54ac4ab2b53ce9fcb66b8250dee91c070e4167ed -Author: djm@openbsd.org -Date: Thu Mar 9 06:58:26 2023 +0000 +commit 9de79df66d1430d290fab670bb4b18612875e518 +Author: Philip Hands +Date: Wed May 24 11:45:43 2023 +0200 - upstream: include destination constraints for smartcard keys too. + if -s & -p specified, mention 'sftp -P' on success - Spotted by Luci Stanescu; ok deraadt@ markus@ + This was inspired by this: + https://github.com/openssh/openssh-portable/pull/321 + but I thought that it was better to not do the sed patching. - OpenBSD-Commit-ID: add879fac6903a1cb1d1e42c4309e5359c3d870f + BTW the reason one can get away with using $SSH_OPTS throughout, despite + the lowercase -p in there, even if sftp is in use, is that the sftp call + is using the already-established ssh master connection, so the port was + passed to the earlier ssh. + + SSH-Copy-ID-Upstream: 1c124d9bfafdbe28a00b683367ebf5750ce12eb2 -commit bfd1ad01d974a316b60622759ad17537fa2d92b4 -Author: Darren Tucker -Date: Thu Mar 9 18:24:54 2023 +1100 +commit 801cda54c00e0f4e7d89345a90874c8d05dc233a +Author: Philip Hands +Date: Tue May 23 23:07:11 2023 +0200 - Limit the number of PAM environment variables. + drop whitespace - xcalloc has its own limits, but these are specific to PAM. From - Coverity CID 405198, ok djm@ + SSH-Copy-ID-Upstream: e604fae1cdee35c18055d35dcec530cf12ef00ad -commit a231414970e01a35f45a295d5f93698fa1249b28 -Author: Darren Tucker -Date: Thu Mar 9 18:19:44 2023 +1100 +commit 288482f53613f3e74544eb92deeb24f7c7f1f371 +Author: Philip Hands +Date: Tue May 23 20:52:13 2023 +0200 - Limit the number of PAM environment variables. + make -x also apply to the target script - From Coverity CID 405194, tweaks and ok djm@ + SSH-Copy-ID-Upstream: 3c4214704f427bd0654adf9b0fc079253db21cf4 -commit 36c6c3eff5e4a669ff414b9daf85f919666e8e03 -Author: dtucker@openbsd.org -Date: Wed Mar 8 06:21:32 2023 +0000 +commit b79e7b88ed44f0e4339f0ff35c96c78a92175a8d +Author: Philip Hands +Date: Tue May 23 16:46:42 2023 +0200 - upstream: Plug mem leak. Coverity CID 405196, ok djm@ + add -t option to specify the target path - OpenBSD-Commit-ID: 175f09349387c292f626da68f65f334faaa085f2 + Allow the default target path (.ssh/authorized_files) to be over-riden + + This was inspired by this MR from Panagiotis Cheilaris + + https://gitlab.com/phil_hands/ssh-copy-id/-/merge_requests/8 + + SSH-Copy-ID-Upstream: a942a0e076874adb6d8b2f0fb76d6c7918190fcd -commit dfb9b736e1ccf9e6b03eea21cd961f4fd0634c98 -Author: tb@openbsd.org -Date: Wed Mar 8 05:33:53 2023 +0000 +commit 914f4ad138714c471ba72fb6d5496b6235320edd +Author: Carlos Rodríguez Gili +Date: Tue Apr 20 19:23:57 2021 +0200 - upstream: ssh-pkcs11: synchronize error messages with errors - - A handful of error messages contained incorrect function names or - otherwise inaccurate descriptions. Fix them to match reality. + Fix test error for /bin/sh on Solaris 10 and older - input/ok djm + On Solaris 10 and older targets /bin/sh is not POSIX-compliant. + Test -z `...` fails with error 'sh: test: argument expected'. + Using quotes around backticks fixes this and doesn't break + POSIX compatibility. - OpenBSD-Commit-ID: 165a15db52f75b31e1804b043480c36af09f3411 + SSH-Copy-ID-Upstream: 98394072a3f985b2650c1e8eab2fef84e38cc065 -commit 51875897b81b5c21b80c256a29597916edbde454 -Author: guenther@openbsd.org -Date: Wed Mar 8 04:43:12 2023 +0000 +commit bd382dca316c721aed1e45edcf4c4e0f6374afb0 +Author: Jakub Jelen +Date: Tue Mar 2 21:34:05 2021 +0000 - upstream: Delete obsolete /* ARGSUSED */ lint comments. + Remove outdated comment - ok miod@ millert@ + The commit b068122 removed the code dropping the trailing colon, but the comment stayed leaving the code confusing for future readers - OpenBSD-Commit-ID: 7be168a570264d59e96a7d2d22e927d45fee0e4c + SSH-Copy-ID-Upstream: 930d39f238117cd53810240ec989d0356aa1c1f6 -commit a76085bda883c2104afb33ab0334eca190927362 +commit bdcaf7939029433635d63aade8f9ac762aca2bbe Author: Darren Tucker -Date: Wed Mar 8 17:25:37 2023 +1100 +Date: Wed May 10 18:50:46 2023 +1000 - Extra brackets to prevent warning. + Special case OpenWrt instead of Dropbear. + + OpenWrt overrides the location of authorized_keys for root. Currently we + assume that all Dropbear installations behave this way, which is not the + case. Check for OpenWrt and root user before using that location instead + of assuming that for all Dropbear servers. Prompted by Github PR#250. + + SSH-Copy-ID-Upstream: 0e1f5d443a9967483c33945793107ae3f3e4af2d -commit 147ae57d4dfa0508109f93b78a7d8b92819e1f83 -Author: djm@openbsd.org -Date: Wed Mar 8 00:05:58 2023 +0000 +commit cf84498f67abe93f813a296167b406a0db7b288e +Author: Philip Hands +Date: Thu May 18 18:20:55 2023 +0200 - upstream: use RSA/SHA256 when testing usability of private key in + ssh-copy-id: add -x option (for debugging) - agent; with/ok dtucker + This option causes the ssh-copy-id to run with set -x - OpenBSD-Commit-ID: fe1382e2fdf23fcae631308e72342bad56066a56 + SSH-Copy-ID-Upstream: a0ee367ea8c0a29c8b4515245e408d2d349e7844 -commit 27fd251bc906a763e70ce0f27c8abdf8bbd1e416 -Author: djm@openbsd.org -Date: Wed Mar 8 00:05:37 2023 +0000 +commit b4a1efdcb88f03394c08e7f68ed4e11676830002 +Author: Philip Hands +Date: Thu May 18 17:14:41 2023 +0200 - upstream: use RSA/SHA256 when testing usability of private key; - - based on fix in bz3546 by Dmitry Belyavskiy; with/ok dtucker + update copyright notices - OpenBSD-Commit-ID: 0ef414cc363a832f9fab92a5da0234448bce2eba + SSH-Copy-ID-Upstream: c284ed33b361814ea48ff68cbd01ca525b2bf117 -commit eee9f3fc3d52ae7d2106929bb06b7f291fb0b81a +commit fcd78e31cdd45a7e69ccfe6d8a3b1037dc1de290 Author: djm@openbsd.org -Date: Tue Mar 7 21:47:42 2023 +0000 +Date: Wed May 24 23:01:06 2023 +0000 - upstream: refactor to be more readable top to bottom. Prompted by + upstream: fix AuthorizedPrincipalsCommand when AuthorizedKeysCommand - Coverity CID 405048 which was a false-positive fd leak; ok dtucker@ + appears previously in configuration. Reported by John Meyers in bz3574 ok + dtucker@ - OpenBSD-Commit-ID: fc55ec2af622a017defb9b768bf26faefc792c00 + OpenBSD-Commit-ID: 1c92e4517284386703936e1d3abaa36cfacf1951 -commit 42a06b29a4c99272bf690f9b3be520b08b448dc5 -Author: Darren Tucker -Date: Tue Mar 7 18:34:41 2023 +1100 - - Add header changes missed in previous. - -commit 4710077096edff2e6926dd5b15bf586491d317db +commit 5ec5504f1d328d5bfa64280cd617c3efec4f78f3 Author: dtucker@openbsd.org -Date: Tue Mar 7 06:09:14 2023 +0000 +Date: Wed May 10 10:04:20 2023 +0000 - upstream: Fix mem leak in environment setup. + upstream: Remove unused prototypes for ssh1 RSA functions. - From jjelen at redhat.com via bz#2687, ok djm@ + From lengyijun via github PR#396. - OpenBSD-Commit-ID: 9f9e4ba3cac003e6f81da3bcebd1b9ec43e7f353 + OpenBSD-Commit-ID: 379a5afa8b7a0f3cba0c8a9bcceb4e5e33a5c1ef -commit 03acc50d0ccb78fc91d1570de1cd0fdfea646028 -Author: dtucker@openbsd.org -Date: Mon Mar 6 12:15:47 2023 +0000 +commit fbf362b3891ae4b36052d1b39f37fc618b41c476 +Author: Darren Tucker +Date: Tue May 9 19:26:56 2023 +1000 - upstream: Unit test for kex_proposal_populate_entries. - - OpenBSD-Regress-ID: bdb211d80d572a08bf14b49fe2a58b9ff265c006 + main(void) to prevent unused variable warning. -commit 3f9231c2e1f374ebb08016ba00ea97b47c0ed20b -Author: djm@openbsd.org -Date: Tue Mar 7 05:37:26 2023 +0000 +commit baf854c8bb0a6d0af5c696c801e631a48dabbaba +Author: Darren Tucker +Date: Tue May 9 19:25:45 2023 +1000 - upstream: fix memory leak in process_read() path; Spotted by James - - Robinson in GHPR363; ok markus@ - - OpenBSD-Commit-ID: cdc2d98e6478b7e7f3a36976845adae3820429d8 + Remove warning pragma since clang doesn't like it. -commit c5e6e890839ec520ab9301a92cba56303749dea2 -Author: djm@openbsd.org -Date: Tue Mar 7 01:30:52 2023 +0000 +commit 5fbb7a1349fbbb48ccb1b8cafff2c1854370d87d +Author: Darren Tucker +Date: Tue May 9 17:13:33 2023 +1000 - upstream: correct size for array argument when changing - - UMAC_OUTPUT_LEN Coverity CID 291845; ok dtucker@ - - OpenBSD-Commit-ID: 2eb017d10705bb623d4418691f961c930eafaec0 + Suppress warning for snprintf truncation test. -commit 9641753e0fd146204d57b2a4165f552a81afade4 -Author: dtucker@openbsd.org -Date: Mon Mar 6 12:14:48 2023 +0000 +commit 47742c513e4e045ecc985c6483fc5c8b050acda2 +Author: Darren Tucker +Date: Tue May 9 17:12:50 2023 +1000 - upstream: Refactor creation of KEX proposal. - - This adds kex_proposal_populate_entries (and corresponding free) which - populates the KEX proposal array with dynamically allocated strings. - This replaces the previous mix of static and dynamic that has been the - source of previous leaks and bugs. Remove unused compat functions. - With & ok djm@. - - OpenBSD-Commit-ID: f2f99da4aae2233cb18bf9c749320c5e040a9c7b + Update OpenSSL compat test for 3.x. -commit aa59d6a489fb20973fa461d0fdb1110db412947b -Author: dtucker@openbsd.org -Date: Sun Mar 5 09:24:35 2023 +0000 +commit 86ad25d455a2313126125540e61e0f9314283f88 +Author: Darren Tucker +Date: Mon May 8 20:23:08 2023 +1000 - upstream: Fix mem and FILE leaks in moduli screening. - - If multiple -Ocheckpoint= options are passed, the earlier ones would - be overwritten and leaked. If we use an input file that wasn't stdin, - close that. From Coverity CIDs 291884 and 291894. - - OpenBSD-Commit-ID: a4d9d15f572926f841788912e2b282485ad09e8b + Add macos13 PAM test target. -commit 23b8cb41767af99a1aac24589d1882d9c8c2c205 -Author: dtucker@openbsd.org -Date: Sun Mar 5 08:18:58 2023 +0000 +commit 77cca2c4b13bc6e5f389565583b6202b0d1bccc2 +Author: Darren Tucker +Date: Mon May 8 20:14:46 2023 +1000 - upstream: Plug mem leak in moduli checkpoint option parsing. - - From Coverity CID 291894. + Skip agent-peereid test on macos13. - OpenBSD-Commit-ID: 9b1aba2d049741ae21c8dc4560a7e29ab17310f4 + sudo -S nobody doesn't work on the github runners (probably a + permission issue) so skip that test. -commit fc7f8f2188d4a4fc8ba77eddbe863c7665666db5 -Author: dtucker@openbsd.org -Date: Sun Mar 5 05:34:09 2023 +0000 +commit b356b8e91678ea295bcf44df5248c3fbf499fdcf +Author: Darren Tucker +Date: Mon May 8 20:14:28 2023 +1000 - upstream: Remove unused compat.h includes. - - We've previously removed a lot of the really old compatibility code, - and with it went the need to include compat.h in most of the files that - have it. - - OpenBSD-Commit-ID: 5af8baa194be00a3092d17598e88a5b29f7ea2b4 + Include config.guess in debug output. -commit 6c165c36246d8004c20e1df5cec4961a5ac422d6 -Author: dtucker@openbsd.org -Date: Sat Mar 4 03:22:59 2023 +0000 +commit b7afd8a4ecaca8afd3179b55e9db79c0ff210237 +Author: Darren Tucker +Date: Mon May 8 20:12:59 2023 +1000 - upstream: Use time_t for x11 timeout. - - Use time_t instead of u_int for remaining x11 timeout checks for 64bit - time_t safety. From Coverity CIDs 405197 and 405028, ok djm@ + Handle OpenSSL >=3 ABI compatibility. - OpenBSD-Commit-ID: 356685bfa1fc3d81bd95722d3fc47101cc1a4972 + Beyond OpenSSL 3.0, the ABI compatibility guarantees are wider (only + major must match instead of major and minor in earlier versions). + bz#3548, ok djm@ -commit 4a3918f51bd2d968387e7aa87e33b32c78077fb4 +commit 0e9e2663eb2c6e9c3e10d15d70418312ae67e542 Author: dtucker@openbsd.org -Date: Fri Mar 3 10:23:42 2023 +0000 +Date: Mon May 1 08:57:29 2023 +0000 - upstream: Ensure ms_remain is always initialized - - similar to what we do in ssh_packet_write_wait. bz#2687, from jjelen - at redhat.com. + upstream: Import regenerated moduli. - OpenBSD-Commit-ID: a50e0541cf823f8d1c72f71ccde925d3dbe6dfac + OpenBSD-Commit-ID: 3d5f811cfcaed8cc4a97e1db49ac61bdf118113c -commit e44846a4487d2885ac7f2610be09b1e2bf52249b -Author: dtucker@openbsd.org -Date: Fri Mar 3 09:48:51 2023 +0000 +commit d9687f49682e1e93383fc15ab2018850b2ef38c3 +Author: Darren Tucker +Date: Mon May 1 11:45:14 2023 +1000 - upstream: Check for non-NULL before string - - comparison. From jjelen at redhat.com via bz#2687. + Add macos-13 test target. - OpenBSD-Commit-ID: 0d9b2e0cac88a311b5766b1aef737082583c285f + Also flatten OS list for clarity. -commit 1842d523fae63b862ce8e60725c9b606cddb86a6 +commit aacfd6767497b8fa6d41ecdd3f8e265d1e9ef1f6 Author: djm@openbsd.org -Date: Fri Mar 3 05:00:34 2023 +0000 +Date: Sun Apr 30 22:54:22 2023 +0000 - upstream: guard against getsockname(-1, ...) from Coverity CID + upstream: adjust ftruncate() logic to handle servers that reorder - 291832 + requests. - OpenBSD-Commit-ID: e58d5227327917d189229b7f0b37d2780f360d5f + sftp/scp will ftruncate the destination file after a transfer completes, + to deal with the case where a longer destination file already existed. + We tracked the highest contiguous block transferred to deal with this + case, but our naive tracking doesn't deal with servers that reorder + requests - a misfeature strictly permitted by the protocol but seldom + implemented. + + Adjust the logic to ftruncate() at the highest absolute block received + when the transfer is successful. feedback deraadt@ ok markus@ + + prompted by https://github.com/openssh/openssh-portable/commit/9b733#commitcomment-110679778 + + OpenBSD-Commit-ID: 4af7fac75958ad8507b4fea58706f3ff0cfddb1b -commit 78571a5fe9847d40d7f220c92b707574ae9ec4ce +commit c8eb3941758615c8284a48fff47872db926da63c Author: djm@openbsd.org -Date: Fri Mar 3 04:36:20 2023 +0000 +Date: Wed Apr 26 01:36:03 2023 +0000 - upstream: some options are not first-match-wins. Mention that there + upstream: Check for ProxyJump=none in CanonicalizeHostname logic. - are exceptions at the start of the manpage and label some of them in the - option description. + Previously ssh would incorrectly refuse to canonicalise the hostname + if ProxyJump was explicitly set to "none" when CanonicalizeHostname=yes - OpenBSD-Commit-ID: 3b74728446fa6fc8742769eeb8c3674e233e84c4 + bz3567; ok dtucker + + OpenBSD-Commit-ID: 80a58e43c3a32f97361282f756ec8d3f37989efd -commit d1c1b3272e8895a96c4f5889bd6e07a8525bd9f1 -Author: djm@openbsd.org -Date: Fri Mar 3 04:34:49 2023 +0000 +commit ac383f3a5c6f529a2e8a5bc44af79a08c7da294e +Author: jsg@openbsd.org +Date: Wed Apr 12 14:22:04 2023 +0000 - upstream: actually print "channeltimeout none" in config dump mode; + upstream: remove duplicate signal.h include - spotted via Coverity CID 405022 + OpenBSD-Commit-ID: 30c0a34d74d91ddd0e6992525da70d3293392f70 + +commit 740dafa20f3f3d325f6f5d44e990b8c8a6d3d816 +Author: jsg@openbsd.org +Date: Wed Apr 12 08:53:54 2023 +0000 + + upstream: fix double words ok dtucker@ - OpenBSD-Commit-ID: b074b52bf138b75f08264e8da15880b29c7a630f + OpenBSD-Commit-ID: 44d3223902fbce5276422bdc8063ab72a4078489 -commit 8bf61e95610b48192d4e1720cc15d9004617301d +commit 6452f89577ec4f22440c31b8e19b061d1a7c4b2a Author: Darren Tucker -Date: Fri Mar 3 14:50:03 2023 +1100 +Date: Tue Apr 11 16:49:19 2023 +1000 - Add Coverity badges. + Test against LibreSSL 3.7.2. -commit 93291bd723959adf462b1df958106cf07a7734dd -Author: dtucker@openbsd.org -Date: Fri Mar 3 03:12:24 2023 +0000 +commit 2138f6be595ca106fe4805a1e3ab9c4d8acc697b +Author: Damien Miller +Date: Thu Apr 6 14:33:10 2023 +1000 - upstream: Check return values of dup2. Spotted by Coverity, ok djm@ + remove unused upper-case const strings in fmtfp - OpenBSD-Commit-ID: 19fb1b53072826d00c67df677731d2f6c1dd602b + no float format that uses upper-case is supported nor are hex floats. + ok dtucker -commit e37261dff33af23f37202cfce0848d36f5c1055c -Author: dtucker@openbsd.org -Date: Fri Mar 3 02:37:58 2023 +0000 +commit 484c5e6168fdb22cbcd73c4ff987cf9ca47989ca +Author: djm@openbsd.org +Date: Thu Apr 6 03:56:02 2023 +0000 - upstream: Use time_t for x11_refuse_time timeout. We need + upstream: simplify sshsig_find_principals() similar to what happened to - SSH_TIME_T_MAX for this, so move from misc.c to misc.h so it's available. - Fixes a Coverity warning for 64bit time_t safety, ok djm@ + sshsig_check_allowed_keys() in r1.31, removing some dead code - OpenBSD-Commit-ID: c69c4c3152cdaab953706db4ccf4d5fd682f7d8d + OpenBSD-Commit-ID: a493e628d4d6c08f878c276d998f4313ba61702d -commit 32755a98c29114b13f4c9d47454bbb265b932ad7 -Author: dtucker@openbsd.org -Date: Fri Mar 3 02:34:29 2023 +0000 +commit 3a7b110fbc7e096423f8f7b459deffe4c65d70f4 +Author: djm@openbsd.org +Date: Thu Apr 6 03:21:31 2023 +0000 - upstream: Check return value from fctnl and warn on failure. + upstream: remove redundant ssh!=NULL check; we'd already - Spotted by Coverity, ok djm@ + dereferenced it - OpenBSD-Commit-ID: 2097c7db3cf657f1e3a6c5077041bacc63143cab + OpenBSD-Commit-ID: 852bf12591ec5a9fb12dcbde9b1fd3945ad0df3c -commit 5fc60e8246c36b8255f72a937ebe9787b39648c6 -Author: dtucker@openbsd.org -Date: Thu Mar 2 11:10:27 2023 +0000 +commit 2519110659a1efac6c976895a86659d1b341c91b +Author: djm@openbsd.org +Date: Thu Apr 6 03:19:32 2023 +0000 - upstream: Remove SUDO in proxy command wrapper. Anything that needs + upstream: match_user() shouldn't be called with user==NULL unless - sudo is already run by it, and it breaks if root isn't in sudoers. + host and ipaddr are also NULL - OpenBSD-Regress-ID: 6cf22fda32a89c16915f31a6ed9bbdbef2a3bac9 + OpenBSD-Commit-ID: fa3518346c21483e9e01a2e4b9436ae501daf8ea -commit 0d514659b23a257247491179cfbb53a6dd64e164 -Author: dtucker@openbsd.org -Date: Thu Mar 2 08:24:41 2023 +0000 +commit 3b9ceaad7ad63c1c03c2a89e148340ad3a62a482 +Author: djm@openbsd.org +Date: Thu Apr 6 03:12:32 2023 +0000 - upstream: Fix breakage on dhgex test. + upstream: don't care about glob() return value here. - This was due to the sshd logs being written to the wrong log file. - While there, make save_debug_logs less verbose, write the name of the - tarball to regress.log and use $SUDO to remove the old symlinks (which - shouldn't be needed, but won't hurt). Initial problem spotted by anton@. + OpenBSD-Commit-ID: 85bb82fea90478a482e9f65a1bec0aa24227fd66 + +commit 09d8da0849e2791b2500267cda333cd238f38754 +Author: dtucker@openbsd.org +Date: Mon Apr 3 08:10:54 2023 +0000 + + upstream: Move up null check and simplify process_escapes. - OpenBSD-Regress-ID: 9c44fb9cd418e6ff31165e7a6c1f9f11a6d19f5b + Based on Coverity CID 291863 which points out we check the channel + pointer for NULLness after dereferencing it. Move this to the start + of the function, and while there simplify initialization of efc a bit. + ok djm@ + + OpenBSD-Commit-ID: de36e5ad6fde0fe263ca134e986b9095dc59380a -commit 860201201d4ae655702807966901682cff30a171 +commit b36b162be5e6206f12b734222b7bc517c13a6bc8 +Author: Damien Miller +Date: Fri Mar 31 14:51:20 2023 +1100 + + need va_end() after va_copy(); ok dtucker + + spotted by Coverity + +commit f703757234a5c585553e72bba279b255a272750a Author: dtucker@openbsd.org -Date: Thu Mar 2 08:14:52 2023 +0000 +Date: Fri Mar 31 05:56:36 2023 +0000 - upstream: Quote grep and log message better. + upstream: Explicitly ignore return from waitpid here too. - OpenBSD-Regress-ID: 3823d9063127169736aa274b1784cb28e15b64d4 + OpenBSD-Commit-ID: eef2403df083c61028969fc679ee370373eacacb -commit 03a03c6002525f5ad9c8fc874a5d5826a35d9858 +commit 6b73aa29035991d1448a1a76f63ac152a6bf931c Author: dtucker@openbsd.org -Date: Thu Mar 2 06:41:56 2023 +0000 +Date: Fri Mar 31 04:45:08 2023 +0000 - upstream: Always call fclose on checkpoints. + upstream: Explictly ignore return codes - In the case of an fprintf failure we would not call fclose which would - leak the FILE pointer. While we're there, try to clean up the temp file - on failure. Spotted by Coverity, ok djm@ + where we don't check them. - OpenBSD-Commit-ID: 73c7ccc5d4fcc235f54c6b20767a2815408525ef + OpenBSD-Commit-ID: 1ffb03038ba1b6b72667be50cf5e5e396b5f2740 -commit 13fe8f9785e6d90400ce548939a0b0ddc11fcb3c +commit 6f0308a3e717ebe68eeb3f95253612fab5dbf20e Author: dtucker@openbsd.org -Date: Wed Mar 1 21:54:50 2023 +0000 +Date: Fri Mar 31 04:42:29 2023 +0000 - upstream: Remove old log symlinks + upstream: Return immediately from get_sock_port - before creating new ones. In -portable some platforms don't like - overwriting existing symlinks. + if sock <0 so we don't call getsockname on a negative FD. From Coverity + CID 291840, ok djm@ - OpenBSD-Regress-ID: 7e7ddc0beb73e945e1c4c58d51c8a125b518120f + OpenBSD-Commit-ID: de1c1130646230c2eda559831fc6bfd1b61d9618 -commit 131fcbcaffd1e3bcf5ab766ec497b5d768955310 -Author: Darren Tucker -Date: Wed Mar 1 23:23:02 2023 +1100 +commit 1c1124dc901fca1ea2cb762044b8f1a5793a2bed +Author: djm@openbsd.org +Date: Fri Mar 31 04:23:02 2023 +0000 - Adjust test jobs for new log directory. + upstream: don't leak arg2 on parse_pubkey_algos error path; ok + + dtucker@ + + OpenBSD-Commit-ID: 7d0270ad3dd102412ca76add2b3760518abdef75 -commit a6f4ac8a2baf77e5361cfa017d0dc250d1409bec -Author: dtucker@openbsd.org -Date: Wed Mar 1 09:29:32 2023 +0000 +commit 8ba2d4764bb6a4701cd447d8b52604622ffe65f4 +Author: djm@openbsd.org +Date: Fri Mar 31 04:22:27 2023 +0000 - upstream: Rework logging for the regression tests. + upstream: clamp max number of GSSAPI mechanisms to 2048; ok dtucker - Previously we would log to ssh.log and sshd.log, but that is insufficient - for tests that have more than one concurent ssh/sshd. + OpenBSD-Commit-ID: ce66db603a913d3dd57063e330cb5494d70722c4 + +commit 1883841fc13d0eada8743cac5d3abe142ee2efa7 +Author: djm@openbsd.org +Date: Fri Mar 31 04:21:56 2023 +0000 + + upstream: don't print key if printing hostname failed; with/ok - Instead, we'll log to separate datestamped files in a $OBJ/log/ and - leave a symlink at the previous location pointing at the most recent - instance with an entry in regress.log showing which files were created - at each point. This should be sufficient to reconstruct what happened - even for tests that use multiple instances of each program. If the test - fails, tar up all of the logs for later analysis. + dtucker@ - This will let us also capture the output from some of the other tools - which was previously sent to /dev/null although most of those will be - in future commits. + OpenBSD-Commit-ID: ad42971a6ee5a46feab2d79f7f656f8cf4b119f3 + +commit c6011129cafe4c411f6ef670a4cf271314708eb8 +Author: djm@openbsd.org +Date: Fri Mar 31 04:04:15 2023 +0000 + + upstream: remove redundant test - OpenBSD-Regress-ID: f802aa9e7fa51d1a01225c05fb0412d015c33e24 + OpenBSD-Commit-ID: 6a0b719f9b1ae9d42ad8c5b144c7962c93792f7c -commit 8ead62ed5e86c7df597d8604f332f49cd1527b85 -Author: dtucker@openbsd.org -Date: Tue Feb 28 21:31:50 2023 +0000 +commit 4fb29eeafb40a2076c0dbe54e46b687c318f87aa +Author: djm@openbsd.org +Date: Fri Mar 31 04:00:37 2023 +0000 - upstream: fatal out if allocating banner string fails to avoid + upstream: don't attempt to decode a ridiculous number of - potential null deref later in sscanf. Spotted by Coverity, ok deraadt@ + attributes; harmless because of bounds elsewhere, but better to be explicit - OpenBSD-Commit-ID: 74e8d228ac00552e96e9e968dfcccf8dd1f46ad5 + OpenBSD-Commit-ID: 1a34f4b6896155b80327d15dc7ccf294b538a9f2 -commit 44ca56ba0b3f531f1d85730cc701097cd49e6868 +commit fc437c154ef724621a4af236de9bc7e51a8381ae +Author: djm@openbsd.org +Date: Fri Mar 31 03:22:49 2023 +0000 + + upstream: remove unused variable; prompted by Coverity CID 291879 + + OpenBSD-Commit-ID: 4c7d20ef776887b0ba1aabcfc1b14690e4ad0a40 + +commit 0eb8131e4a53b33a8fc9b9ab694e6b6778b87ade Author: dtucker@openbsd.org -Date: Tue Feb 28 08:45:24 2023 +0000 +Date: Fri Mar 31 00:44:29 2023 +0000 - upstream: Explicitly ignore return from fchmod + upstream: Check fd against >=0 instead of >0 in error path. The - similar to other calls to prevent warning. + dup could in theory return fd 0 although currently it doesn't in practice. + From Dmitry Belyavskiy vi github PR#238. - OpenBSD-Commit-ID: fdc5287dcee0860b5a493186414226c655b0eb0a + OpenBSD-Commit-ID: 4a95f3f7330394dffee5c749d52713cbf3b54846 -commit 803392933a3a6f09f834aa5f0c2aab06a3b382f4 +commit 7174ba6f8a431ca4257767a260fc50e204068242 Author: dtucker@openbsd.org -Date: Mon Feb 27 22:12:40 2023 +0000 +Date: Thu Mar 30 07:19:50 2023 +0000 - upstream: Plug mem leak on globbed ls error path. + upstream: Ignore return value from muxclient(). It normally loops - Spotted by Coverity, ok deraadt@ + without returning, but it if returns on failure we immediately exit. + Coverity CID 405050. - OpenBSD-Commit-ID: de28476025db29820a9a2e56e98b964d8a02861c + OpenBSD-Commit-ID: ab3fde6da384ea588226037c38635a6b2e015295 -commit aa33b4d396abf47a2a45f982f28d054fb1dcb5c3 -Author: Darren Tucker -Date: Mon Feb 27 21:04:22 2023 +1100 +commit a4c1c2513e36f111eeaa1322c510067930e5e51e +Author: Damien Miller +Date: Fri Mar 31 14:17:22 2023 +1100 - Cast time_t's in debug output to long long. + don't call connect() on negative socket - Should fix Coverity warning about truncation of 64bit time_t. + Coverity CID 405037 -commit b0fd60a9de62a03189ad57d0c07f0ac51dc00e95 -Author: Darren Tucker -Date: Mon Feb 27 17:28:59 2023 +1100 +commit 34ee842cdd981a759fe8f0d4a37521f9a1c63170 +Author: djm@openbsd.org +Date: Thu Mar 30 03:05:01 2023 +0000 - Do shadow expiry calcs using "long long". + upstream: return SSH_ERR_KEY_NOT_FOUND if the allowed_signers file - Coverity flags these as potentially not 64bit time_t safe so use - long long for the calculations and debug output. ok djm@ + is empty, not SSH_ERR_INTERNAL_ERROR. Also remove some dead code spotted + by Coverity; with/ok dtucker@ + + OpenBSD-Commit-ID: 898a1e817cda9869554b1f586a434f67bcc3b650 -commit 01dbeb3084d714bbd001ff9d03b9de542e8cdf58 -Author: Damien Miller -Date: Mon Feb 27 17:07:52 2023 +1100 +commit f108e77a9dc9852e72215af1bf27731c48434557 +Author: dtucker@openbsd.org +Date: Thu Mar 30 00:49:37 2023 +0000 - avoid clash between for getopt's struct option + upstream: Remove dead code from inside if block. - Since we don't use getopt_long() nothing outside the getopt() - implementation itself uses this structure, so move it into the - source to remove it from visibility and clashes with libc's + The only way the if statement can be true is if both dup()s fail, and + in that case the tmp2 can never be set. Coverity CID 291805, ok djm@ - ok dtucker@ + OpenBSD-Commit-ID: c0d6089b3fb725015462040cd94e23237449f0c8 -commit eb88d07c43afe407094e7d609248d85a15e148ef +commit 05b8e88ebe23db690abbfb1a91111abea09cde08 Author: Darren Tucker -Date: Sat Feb 25 14:45:41 2023 +1100 +Date: Thu Mar 30 13:53:29 2023 +1100 - Revert explicit chmods on private keys. + child_set_eng: verify both env pointer and count. - This should no longer be needed on Cygwin test runners due to previous - commit. + If child_set env was called with a NULL env pointer and a non-zero count + it would end up in a null deref, although we don't currently do this. + Prompted by Coverity CID 291850, tweak & ok djm@ -commit 52b75db61030a6c8baf66b73644380cf3f58e26a -Author: Darren Tucker -Date: Sat Feb 25 14:43:28 2023 +1100 +commit 28f1b8ef9b84b8cd2f6c9889a0c60aa4a90dadfa +Author: dtucker@openbsd.org +Date: Wed Mar 29 01:07:48 2023 +0000 - Remove extended ACLs from working dirs. + upstream: Ignore return from sshpkt_disconnect - This should allow umask to work as expected and prevent tests from - failing due to excessive permissions on private keys. + since we set our own return value for the function. Coverity CID 291797, + ok djm@ + + OpenBSD-Commit-ID: 710b57ba954c139240895e23feea41f203201f04 -commit 0c5d4c843df5605b043a758d69f9a611ef63c479 -Author: Darren Tucker -Date: Fri Feb 24 13:44:13 2023 +1100 +commit c3da05d95922f5550bcc7815e799474d6a160175 +Author: dtucker@openbsd.org +Date: Wed Mar 29 00:59:08 2023 +0000 - Explicitly set permissions on user and host keys. + upstream: Plug potential mem leak in process_put. - On cygwin, the umask might not be sufficient. Should fix tests on - Github runners. + It allocates abs_dst inside a loop but only frees it on exit, so free + inside the loop if necessary. Coverity CID 291837, ok djm@ + + OpenBSD-Commit-ID: a01616503a185519b16f00dde25d34ceaf4ae1a3 -commit 6c9fc9d7a9f7abf82c3294d74e6d4a25735862ce +commit 13ae327eae598b1043e5ec30e4b170edb3c898a5 Author: djm@openbsd.org -Date: Wed Feb 22 03:56:43 2023 +0000 +Date: Wed Mar 29 00:18:35 2023 +0000 - upstream: fix progressmeter corruption on wide displays; bz3534 + upstream: fix memory leak; Coverity CID 291848 - feedback/ok dtucker@ + with/ok dtucker@ - OpenBSD-Commit-ID: f4affee067cec7c182f3e0b307d758e0472762a3 + OpenBSD-Commit-ID: 37f80cb5d075ead5a00ad1b74175684ab1156ff8 -commit fe0bd3cde9665d364e5eedd2c2c2e60d4cdc3786 +commit 9ffa76e1284c85bf459c3dcb8e995733a8967e1b Author: dtucker@openbsd.org -Date: Tue Feb 21 06:48:18 2023 +0000 +Date: Tue Mar 28 07:44:32 2023 +0000 - upstream: fseek to end of known_hosts before writing to it. + upstream: Plug more mem leaks in sftp by making - POSIX and ANSI C require that applications call fseek or similar between - read and writing to a RW file. OpenBSD doesn't enforce this, but some - (System V derived) platforms need this to prevent it from writing a - spurious extra byte (in this case, a newline). ok djm@ deraadt@ + make_absolute_pwd_glob work in the same way as make_absolute: you + pass it a dynamically allocated string and it either returns it, or + frees it and allocates a new one. Patch from emaste at freebsd.org and + https://reviews.freebsd.org/D37253 ok djm@ - OpenBSD-Commit-ID: 33e680dcd8110582a93a40a8491024e961f45137 + OpenBSD-Commit-ID: 85f7404e9d47fd28b222fbc412678f3361d2dffc -commit 357fb8ae14c07cd025eeed66e73de91bab569849 -Author: Darren Tucker -Date: Tue Feb 21 17:51:09 2023 +1100 +commit 82b2b8326962b1a98af279bc5bbbbbcab15b3e45 +Author: dtucker@openbsd.org +Date: Tue Mar 28 06:12:38 2023 +0000 - Also run unit tests on AIX VMs. + upstream: Remove compat code for OpenSSL < 1.1.* - In the past these tests took too long, but these days it only adds - about 5 min to the run. + since -portable no longer supports them. + + OpenBSD-Commit-ID: ea2893783331947cd29a67612b4e56f818f185ff -commit 17781aaa5188ee1477f7779b280d105512e3dbed -Author: Darren Tucker -Date: Tue Feb 21 17:38:55 2023 +1100 +commit b500afcf00ae1b6b73b2ccf171111dfbfeaef74d +Author: dtucker@openbsd.org +Date: Mon Mar 27 23:56:54 2023 +0000 - Wrap stdint.h inside ifdef. + upstream: Remove compat code for OpenSSL 1.0.* + + versions now that -portable has dropped support for those versions. + + OpenBSD-Regress-ID: 82a8eacd87aec28e4aa19f17246ddde9d5ce7fe7 -commit ef798bad38505f7bf1b5fa5c0843dfc5a2b192b9 -Author: Mayank Sharma -Date: Mon Feb 20 17:37:15 2023 +0530 +commit 727560e6011efcb36d2f3ac6910444bc775abaa1 +Author: Darren Tucker +Date: Tue Mar 28 18:06:42 2023 +1100 - Add includes to ptimeout test. + Prevent conflicts between Solaris SHA2 and OpenSSL. - Fixes test failures on AIX due to type mismatches. + We used to prevent conflicts between native SHA2 headers and OpenSSL's + by setting OPENSSL_NO_SHA but that was removed prior to OpenSSL 1.1.0 -commit ab69dda05d5268454209f529fa80f477e60d846a +commit 46db8e14b7f186d32173dcdecd5b785334429b8b Author: Darren Tucker -Date: Mon Feb 20 18:24:39 2023 +1100 +Date: Tue Mar 28 12:44:03 2023 +1100 - Always use the openssl binary configure tells us. + Remove HEADER_SHA_H from previous... - This fixes tests on platforms that do not have the openssl tool - installed at all. + since it causes more problems than it solves. -commit 2a7e3449908571af601a4c2d12ab140096442e47 -Author: dtucker@openbsd.org -Date: Fri Feb 17 04:22:50 2023 +0000 +commit 72bd68d37387aa5f81da928f6e82f1c88ed8f674 +Author: Darren Tucker +Date: Tue Mar 28 10:35:18 2023 +1100 - upstream: Remove now-unused compat bit SSH_BUG_RSASIGMD5. The code - - to set this was removed in OpenSSH 7.7 when support for SSH implementations - dating back to before RFC standardization were removed. "burn it all" djm@ + Replace OPENSSL_NO_SHA with HEADER_SHA_H. - OpenBSD-Commit-ID: 6330935fbe23dd00be79891505e06d1ffdac7cda + Since this test doesn't use OpenSSL's SHA2 and may cause conflicts we + don't want to include it, but OPENSSL_NO_SHA was removed beginning in + OpenSSL's 1.1 series. -commit 0833ccf2c8b7ae08b296c06f17bd53e3ab94b0b0 -Author: dtucker@openbsd.org -Date: Fri Feb 17 03:06:18 2023 +0000 +commit 99668f2e6e0deb833e46cfab56db59ff0fc28c7e +Author: Darren Tucker +Date: Tue Mar 28 09:50:06 2023 +1100 - upstream: Remove now-unused compat bit SSH_BUG_BIGENDIANAES. This - - was previously set for OpenSSH 2.3 (released in 2000) but this check was - removed in OpenSSH 7.7 (2018). ok djm@ deraadt@ - - OpenBSD-Commit-ID: 326426ea328707fc9e83305291ab135c87f678af + Configure with --target instead of deprecated form. -commit c81c2bea6e828d52b62b448b4ffdd3c163177975 -Author: Damien Miller -Date: Fri Feb 17 10:12:40 2023 +1100 +commit f751d9306c62cd1061f966e6a7483d9bab9c379b +Author: Darren Tucker +Date: Mon Mar 27 22:05:29 2023 +1100 - whitespace fixes + Pass rpath when building 64bit Solaris. -commit 500f90b39db5f0014e6b0c49ff1f45c994b69293 -Author: Damien Miller -Date: Fri Feb 17 10:02:08 2023 +1100 +commit a64b935cd450ee8d04c26c9cd728629cf9ca5c91 +Author: Darren Tucker +Date: Mon Mar 27 19:21:19 2023 +1100 - whitespace at EOL + Explicitly disable OpenSSL on AIX test VM. -commit 68350152406339170721c15e97afdf827a5e4001 +commit 7ebc6f060fc2f70495a56e16d210baae6424cd96 Author: dtucker@openbsd.org -Date: Thu Feb 16 10:10:00 2023 +0000 +Date: Mon Mar 27 03:56:50 2023 +0000 - upstream: Remove SSH_BUG_PASSWORDPAD compat bit - - since it's no longer used. ok markus@ + upstream: Add RevokedHostKeys to percent expansion test. - OpenBSD-Commit-ID: b92c21f56fe4b7f9a54790d6a9650725c226820b + OpenBSD-Regress-ID: c077fd12a38005dd53d878c5b944154dec88d2ff -commit 537cccd804eaf65f32bdce037cc31db4e0ab0f44 +commit f1a17de150f8d309d0c52f9abfaebf11c51a8537 Author: dtucker@openbsd.org -Date: Thu Feb 16 07:55:15 2023 +0000 +Date: Mon Mar 27 03:56:11 2023 +0000 - upstream: Remove SSH_BUG_IGNOREMSG compat flag + upstream: Add tilde and environment variable expansion to - since it's only applicable to SSH1 and thus no longer used. ok markus@ - "kill it with fire" djm@ + RevokedHostKeys. bz#3552, ok djm@ - OpenBSD-Commit-ID: ea13318b1937795d9db4790d3ce0a6ed01584dab + OpenBSD-Commit-ID: ce5d8e0219b63cded594c17d4c2958c06918ec0d -commit 285cf6cd4b91a0a0ce33193c358c99085af33e43 -Author: jmc@openbsd.org -Date: Fri Feb 10 06:41:53 2023 +0000 +commit 009eb4cb48a9708ab9174684dcbcc0f942907abe +Author: djm@openbsd.org +Date: Mon Mar 27 03:31:05 2023 +0000 - upstream: space between macro and punctuation; sort usage(); + upstream: fix test: getnameinfo returns a non-zero value on error, not - OpenBSD-Commit-ID: 6141610cfca037700730e41f868d1d9124958f8c - -commit d39a96f70f81878c77336ed35f5c648c1804b71a -Author: jmc@openbsd.org -Date: Fri Feb 10 06:40:48 2023 +0000 - - upstream: space between macro and punctuation; + (neccessarily) -1. From GHPR#384 - OpenBSD-Commit-ID: abc95e550be9e6d9a7ff64b65c104c7be21ab19e + OpenBSD-Commit-ID: d35e2b71268f66f5543a7ea68751972b3ae22b25 -commit 16e82bf53fc34e43e3b948d43b68d5b27a7335e6 -Author: jmc@openbsd.org -Date: Fri Feb 10 06:39:27 2023 +0000 +commit 4f0a676486700f10a4788f7e9426e94e39c1c89e +Author: djm@openbsd.org +Date: Mon Mar 27 03:25:08 2023 +0000 - upstream: sort SYNOPSIS; + upstream: scp: when copying local->remote, check that source file - OpenBSD-Commit-ID: dacd9da33277d5669a51213d880632599c890c1e + exists before opening SFTP connection to the server. Based on GHPR#370 ok + dtucker, markus + + OpenBSD-Commit-ID: b4dd68e15bfe22ce4fac9960a1066a2b721e54fb -commit d9685121ff6d57b8797411f3cb123884a4b96e30 +commit 154d8baf631327163571760c2c524bc93c37567c Author: Darren Tucker -Date: Sat Feb 11 12:32:19 2023 +1100 +Date: Mon Mar 27 12:22:30 2023 +1100 - Improve seccomp compat on older systems. - - Check if flags to mmap and madvise are defined before using them. - Should fix problems building on older Linux systems that don't have - these. bz#3537, with & ok djm@. + Also look for gdb error message from OpenIndiana. -commit 6180b0fa4f7996687678702806257e661fd5931e -Author: djm@openbsd.org -Date: Fri Feb 10 05:06:03 2023 +0000 +commit fbd3811ddb2b6ce2e6dba91fde7352c8978e5412 +Author: Darren Tucker +Date: Mon Mar 27 11:08:00 2023 +1100 - upstream: test -Ohashalg=... and that the default output contains both - - specified hash algorithms; prompted by dtucker@ + Explicitly disable security key test on aix51 VM. - OpenBSD-Regress-ID: 26f309208c8d8b8fa9c5f419767b85f1e9b22f51 + We don't know how to build the shared objects required for the security + key tests so skip them. -commit d651f5c9fe37e61491eee46c49ba9fa03dbc0e6a -Author: djm@openbsd.org -Date: Fri Feb 10 04:56:30 2023 +0000 +commit 4922ac3be8a996780ef3dc220411da2e27c29d9c +Author: Darren Tucker +Date: Sun Mar 26 14:49:43 2023 +1100 - upstream: let ssh-keygen and ssh-keyscan accept - - -Ohashalg=sha1|sha256 when outputting SSHFP fingerprints to allow algorithm - selection. bz3493 ok dtucker@ + Split libcrypto and other config flags. - OpenBSD-Commit-ID: e6e07fe21318a873bd877f333e189eb963a11b3d + This should allow the automatic OpenSSL version selection in the tests + to work better. -commit 18938d11a90b74d63c20b2d3c965d5bd64786ab1 -Author: djm@openbsd.org -Date: Fri Feb 10 04:47:19 2023 +0000 +commit 4a948b1469f185e871160a2d70e2a0fce2858f9e +Author: Darren Tucker +Date: Sun Mar 26 14:39:45 2023 +1100 - upstream: add a `sshd -G` option that parses and prints the - - effective configuration without attempting to load private keys and perform - other checks. This allows usage of the option before keys have been - generated. - - bz3460 feedback/ok dtucker@ + Specify test target if we build without OpenSSL. - OpenBSD-Commit-ID: 774504f629023fc25a559ab1d95401adb3a7fb29 + When we decide we can't use the versions of OpenSSL available, also + restrict the tests we run to avoid the ones that need OpenSSL. -commit df7d3dbf7194db8e97730ee0425d4d9d7bdb8b10 -Author: djm@openbsd.org -Date: Fri Feb 10 04:40:28 2023 +0000 +commit b308c636f5b5d89eecb98be00b3d56306a005a09 +Author: Darren Tucker +Date: Sun Mar 26 14:22:53 2023 +1100 - upstream: make `ssh -Q CASignatureAlgorithms` work as the manpage says - - it should bz3532 + Find suitable OpenSSL version. - OpenBSD-Commit-ID: 0ddb17b3fcbd99bfb5baea4ac5e449620cbd3adc + Check the installed OpenSSL versions for a suitable one, and if there + isn't (and we don't have a specific version configured) then build + without OpenSSL. -commit d3b8d4198b6595f23b5859d43dc8fc701f97429b -Author: Darren Tucker -Date: Fri Feb 10 14:26:44 2023 +1100 +commit 021ea5c2860f133f44790970968e0e73208b3a87 +Author: Damien Miller +Date: Fri Mar 24 15:02:52 2023 +1100 - Add CentOS 7 test targets. + Github testing support for BoringSSL -commit 22efb01e355bba4755b730ed417f91c081445bfc -Author: dtucker@openbsd.org -Date: Thu Feb 9 09:55:33 2023 +0000 +commit 9a97cd106466a2a9bda2bfaa4c48c4f1b2cc9c1b +Author: Damien Miller +Date: Fri Mar 24 15:34:29 2023 +1100 - upstream: Test adding terminating newline to known_hosts. + BoringSSL doesn't support EC_POINT_point2bn() - OpenBSD-Regress-ID: 5fc3010ac450195b3fbdeb68e875564968800365 + so don't invoke it in unittest -commit caec6da1a583ed8c32c6ad3b81bbcaab46ac8b61 -Author: dtucker@openbsd.org -Date: Wed Feb 8 08:06:03 2023 +0000 +commit cc5969c033a032d126ff78e5d95cf20abbede4c7 +Author: Damien Miller +Date: Fri Mar 24 15:34:05 2023 +1100 - upstream: ssh-agent doesn't actually take -v, - - so the recently-added ones will result in the test not cleaning up - after itself. Patch from cjwatson at debian.org vi bz#3536. - - OpenBSD-Regress-ID: 1fc8283568f5bf2f918517c2c1e778072cf61b1a + another ERR_load_CRYPTO_strings() vestige -commit 3c379c9a849a635cc7f05cbe49fe473ccf469ef9 -Author: dtucker@openbsd.org -Date: Thu Feb 9 09:54:11 2023 +0000 +commit 4974293899a068133e976f81d6693670d2b576ca +Author: Damien Miller +Date: Fri Mar 24 15:24:05 2023 +1100 - upstream: Ensure that there is a terminating newline when adding a new - - entry to known_hosts. bz#3529, with git+openssh at limpsquid.nl, ok deraadt@ - markus@ + don't use obsolete ERR_load_CRYPTO_strings() - OpenBSD-Commit-ID: fa8d90698da1886570512b96f051e266eac105e0 + OpenSSL (and elsewhere in OpenSSH) uses ERR_load_crypto_strings() -commit 95b6bbd2553547260b324b39d602061c88b774bc -Author: Darren Tucker -Date: Tue Feb 7 08:43:47 2023 +1100 +commit 3c527d55f906e6970d17c4cab6db90ae9e013235 +Author: Damien Miller +Date: Fri Mar 24 15:23:05 2023 +1100 - Replace 9.1 with 9.2 on CI status page. + Allow building with BoringSSL -commit 195313dfe10a23c82e9d56d5fdd2f59beee1bdcf +commit b7e27cfd7f163fc16b4c5d041cc28ee488a5eeec Author: Damien Miller -Date: Fri Feb 3 16:33:09 2023 +1100 +Date: Fri Mar 24 15:21:18 2023 +1100 - harden Linux seccomp sandbox - - Linux mmap(2) and madvise(2) syscalls support quite a number of funky - flags that we don't expect that sshd/libc will ever need. We can - exclude this kernel attack surface by filtering the mmap(2) flags - and the madvise(2) advice arguments. + put back SSLeay_version compat in configure test - Similarly, the sandboxed process in sshd is a single-threaded program - that does not use shared memory for synchronisation or communication. - Therefore, there should be no reason for the advanced priority - inheritance futex(2) operations to be necessary. These can also be - excluded. + Needed to detect old versions and give good "your version is bad" + messages at configure time; spotted by dtucker@ + +commit 7280401bdd77ca54be6867a154cc01e0d72612e0 +Author: Damien Miller +Date: Fri Mar 24 13:56:25 2023 +1100 + + remove support for old libcrypto - Motivated by Jann Horn pointing out that there have been kernel bugs - in nearby Linux kernel code, e.g. CVE-2020-29368, CVE-2020-29374 and - CVE-2022-42703. + OpenSSH now requires LibreSSL 3.1.0 or greater or + OpenSSL 1.1.1 or greater - Feedback Jann Horn, ok dtucker@ + with/ok dtucker@ -commit 6dfb65de949cdd0a5d198edee9a118f265924f33 -Author: Damien Miller -Date: Thu Feb 2 23:21:54 2023 +1100 +commit abda22fb48302f2142233f71d27c74040288c518 +Author: Darren Tucker +Date: Sun Mar 19 15:36:13 2023 +1100 - crank versions in RPM specs + Test latest OpenSSL 1.1, 3.0 and LibreSSL 3.7. -commit d07cfb11a0ca574eb68a3931d8c46fbe862a2021 +commit 610ac1cb077cd5a1ebfc21612154bfa13d2ec825 +Author: Darren Tucker +Date: Thu Mar 16 21:38:04 2023 +1100 + + Show 9.3 branch instead of 9.2. + +commit cb30fbdbee869f1ce11f06aa97e1cb8717a0b645 Author: Damien Miller -Date: Thu Feb 2 23:21:45 2023 +1100 +Date: Thu Mar 16 08:28:19 2023 +1100 - update version in README + depend -commit 9fe207565b4ab0fe5d1ac5bb85e39188d96fb214 +commit 1dba63eb10c40b6fda9f5012ed6ae87e2d3d028e Author: Damien Miller -Date: Thu Feb 2 23:17:49 2023 +1100 +Date: Thu Mar 16 08:27:54 2023 +1100 - adapt compat_kex_proposal() test to portable + crank version -commit 903c556b938fff2d7bff8da2cc460254430963c5 +commit ba7532d0dac9aaf0ad7270664c43837fc9f64a5f Author: djm@openbsd.org -Date: Thu Feb 2 12:12:52 2023 +0000 +Date: Wed Mar 15 21:19:57 2023 +0000 - upstream: test compat_kex_proposal(); by dtucker@ + upstream: openssh-9.3 - OpenBSD-Regress-ID: 0e404ee264db546f9fdbf53390689ab5f8d38bf2 + OpenBSD-Commit-ID: 8011495f2449c1029bb316bd015eab2e00509848 -commit 405fba71962dec8409c0c962408e09049e5624b5 +commit 6fd4daafb949b66bf555f3100f715a9ec64c3390 Author: dtucker@openbsd.org -Date: Thu Jan 19 07:53:45 2023 +0000 +Date: Tue Mar 14 07:28:47 2023 +0000 - upstream: Check if we can copy sshd or need to use sudo to do so + upstream: Free KRL ptr in addition to its contents. - during reexec test. Skip test if neither can work. Patch from anton@, tweaks - from me. + From Coverity CID 291841, ok djm@ - OpenBSD-Regress-ID: 731b96ae74d02d5744e1f1a8e51d09877ffd9b6d + OpenBSD-Commit-ID: f146ba08b1b43af4e0d7ad8c4dae3748b4fa31b6 -commit b2a2a8f69fd7737ea17dc044353c514f2f962f35 -Author: djm@openbsd.org -Date: Thu Feb 2 12:10:22 2023 +0000 +commit 1d270bd303afaf6d94e9098cbbf18e5e539e2088 +Author: dtucker@openbsd.org +Date: Tue Mar 14 07:26:25 2023 +0000 - upstream: openssh-9.2 + upstream: Check pointer for NULL before deref. - OpenBSD-Commit-ID: f7389f32413c74d6e2055f05cf65e7082de03923 + None of the existing callers seem to do that, but it's worth checking. + From Coverity CID 291834, ok djm@ + + OpenBSD-Commit-ID: a0a97113f192a7cb1a2c97b932f677f573cda7a4 -commit 12da7823336434a403f25c7cc0c2c6aed0737a35 -Author: djm@openbsd.org -Date: Thu Feb 2 12:10:05 2023 +0000 +commit d95af508e78c0cd3dce56b83853baaa59ae295cf +Author: dtucker@openbsd.org +Date: Sun Mar 12 10:40:39 2023 +0000 - upstream: fix double-free caused by compat_kex_proposal(); bz3522 + upstream: Limit number of entries in SSH2_MSG_EXT_INFO - by dtucker@, ok me + request. This is already constrained by the maximum SSH packet size but this + makes it explicit. Prompted by Coverity CID 291868, ok djm@ markus@ - OpenBSD-Commit-ID: 2bfc37cd2d41f67dad64c17a64cf2cd3806a5c80 + OpenBSD-Commit-ID: aea023819aa44a2dcb9dd0fbec10561896fc3a09 -commit 79efd95ab5ff99f4cb3a955e2d713b3f54fb807e -Author: Darren Tucker -Date: Wed Feb 1 17:17:26 2023 +1100 +commit 8f287ba60d342b3e2f750e7332d2131e3ec7ecd0 +Author: dtucker@openbsd.org +Date: Sun Mar 12 09:41:18 2023 +0000 - Skip connection-timeout test on minix3. + upstream: calloc can return NULL but xcalloc can't. - Minix 3's Unix domain sockets don't seem to work the way we expect, so - skip connection-timeout test on that platform. While there, group - together all similarly skipped tests and explicitly comment. - -commit 6b508c4e039619842bcf5a16f8a6b08dd6bec44a -Author: Damien Miller -Date: Wed Feb 1 12:12:05 2023 +1100 - - fix libfido2 detection without pkg-config + From Coverity CID 291881, ok djm@ - Place libfido2 before additional libraries (that it may depend upon) - and not after. bz3530 from James Zhang; ok dtucker@ + OpenBSD-Commit-ID: 50204b755f66b2ec7ac3cfe379d07d85ca161d2b -commit 358e300fed5e6def233a2c06326e51e20ebed621 -Author: deraadt@openbsd.org -Date: Wed Jan 18 20:56:36 2023 +0000 +commit 83a56a49fd50f4acf900f934279482e4ef329715 +Author: dtucker@openbsd.org +Date: Fri Mar 10 07:17:08 2023 +0000 - upstream: delete useless dependency + upstream: Explicitly ignore return from fcntl - OpenBSD-Commit-ID: e1dc11143f83082e3154d6094f9136d0dc2637ad + (... FD_CLOEXEC) here too. Coverity CID 291853. + + OpenBSD-Commit-ID: 99d8b3da9d0be1d07ca8dd8e98800a890349e9b5 -commit a4cb9be1b021b511e281ee55c356f964487d9e82 -Author: deraadt@openbsd.org -Date: Wed Jan 18 20:43:15 2023 +0000 +commit 0fda9d704d3bbf54a5e64ce02a6fecb11fe7f047 +Author: Damien Miller +Date: Fri Mar 10 15:59:46 2023 +1100 - upstream: Create and install sshd random relink kit. - - ../Makefile.inc and Makfile are concatenated for reuse, which hopefully won't - be too fragile, we'll see if we need a different approach. The resulting sshd - binary is tested with the new sshd -V option before installation. As the - binary layout is now semi-unknown (meaning relative, fixed, and gadget - offsets are not precisely known), change the filesystem permissions to 511 to - prevent what I call "logged in BROP". I have ideas for improving this further - but this is a first step ok djm + bounds checking for getrrsetbyname() replacement; - OpenBSD-Commit-ID: 1e0a2692b7e20b126dda60bf04999d1d30d959d8 + Spotted by Coverity in CID 405033; ok millert@ -commit bc7de6f91a9a0ae2f148a9d31a4027d441a51999 -Author: jmc@openbsd.org -Date: Wed Jan 18 06:55:32 2023 +0000 +commit 89b8df518f21677045599df0ad3e5dd0f39909b5 +Author: dtucker@openbsd.org +Date: Fri Mar 10 04:06:21 2023 +0000 - upstream: tweak previous; ok djm + upstream: Plug mem leak on error path. Coverity CID 405026, ok djm@. - OpenBSD-Commit-ID: df71ce4180c58202dfdc1d92626cfe900b91b7c3 + OpenBSD-Commit-ID: 8212ca05d01966fb5e72205c592b2257708a2aac -commit a20b7e999773e6333c8aa9b0a7fa41966e63b037 +commit bf4dae0ad192c3e2f03f7223834b00d88ace3d3e Author: Darren Tucker -Date: Tue Jan 31 19:35:44 2023 +1100 +Date: Fri Mar 10 14:46:57 2023 +1100 - Skip connection-timeout test under Valgrind. + Add prototypes for mkstemp replacements. - Valgrind slows things down so much that the timeout test fails. Skip - this test until we figure out if we can make it work. + Should prevent warnings due to our wrapper function. -commit c3ffb54b4fc5e608206037921db6ccbc2f5ab25f -Author: Darren Tucker -Date: Wed Jan 25 21:58:40 2023 +1100 +commit 4e04d68d6a33cdc73b831fd4b5e6124175555d3d +Author: dtucker@openbsd.org +Date: Fri Mar 10 03:01:51 2023 +0000 - Skip connection-timeout when missing FD passing. + upstream: Expliticly ignore return code from fcntl(.. FD_CLOEXEC) since - This tests uses multiplexing which uses file descriptor passing, so - skip it if we don't have that. Fixes test failures on Cygwin. + there's not much we can do anyway. From Coverity CID 291857, ok djm@ + + OpenBSD-Commit-ID: 051429dd07af8db3fec10d82cdc78d90bb051729 -commit 35253af01d8c0ab444c8377402121816e71c71f5 +commit d6d38fd77cbe091c59e1bb720c3a494df4990640 Author: djm@openbsd.org -Date: Wed Jan 18 02:00:10 2023 +0000 +Date: Fri Mar 10 02:32:04 2023 +0000 - upstream: when restoring non-blocking mode to stdio fds, restore - - exactly the flags that ssh started with and don't just clobber them with - zero, as this could also remove the append flag from the set; + upstream: Like sshd_config, some ssh_config options are not - bz3523; ok dtucker@ + first-match-wins. sshd_config.5 was fixed in r1.348, this is the same for + this file - OpenBSD-Commit-ID: 1336b03e881db7564a4b66014eb24c5230e9a0c0 + OpenBSD-Commit-ID: 7be55b9351cde449b136afcc52d07aa4113b215e -commit 7d17ea151c0b2519f023bd9cc7f141128833ac47 -Author: millert@openbsd.org -Date: Wed Jan 18 01:50:21 2023 +0000 +commit 7187d3f86bf8f2066cc9941f217d23b0cacae25e +Author: dtucker@openbsd.org +Date: Fri Mar 10 02:24:56 2023 +0000 - upstream: Add a -V (version) option to sshd like the ssh client + upstream: Remove no-op (int) > INT_MAX checks - has. OK markus@ deraadt@ + since they can never be true. From Coverity CID 405031, ok djm@ - OpenBSD-Commit-ID: abe990ec3e636fb040132aab8cbbede98f0c413e + OpenBSD-Commit-ID: 9df3783b181e056595e2bb9edf7ed41d61cf8e84 -commit 62360feb7f08f2a4c6fc36f3b3449309203c42c9 -Author: millert@openbsd.org -Date: Tue Jan 17 18:52:44 2023 +0000 +commit 77adde4305542ebe3005dd456122624fe2347b01 +Author: Darren Tucker +Date: Fri Mar 10 13:27:29 2023 +1100 - upstream: For "ssh -V" always exit 0, there is no need to check opt - - again. This was missed when the fallthrough in the switch case above it was - removed. OK deraadt@ + Wrap mkstemp calls with umask set/restore. - OpenBSD-Commit-ID: 5583e5d8f6d62a8a4215cfa95a69932f344c8120 + glibc versions 2.06 and earlier did not set a umask on files created by + mkstemp created the world-writable. Wrap mkstemp to set and restore + the umask. From Coverity (CIDs 291826 291886 291891), ok djm@ -commit 12492c0abf1eb415d08a897cc1d8b9e789888230 -Author: djm@openbsd.org -Date: Tue Jan 17 10:15:10 2023 +0000 +commit 633d3dc2a1e9e2a013d019a0576a0771c8423713 +Author: jcs@openbsd.org +Date: Thu Mar 9 21:06:24 2023 +0000 - upstream: also check that an active session inhibits + upstream: modify parentheses in conditionals to make it clearer what is - UnusedConnectionTimeout idea markus@ + being assigned and what is being checked - OpenBSD-Regress-ID: 55c0fb61f3bf9e092b0a53f9041d3d2012f14003 + ok djm dtucker + + OpenBSD-Commit-ID: 19c10baa46ae559474409f75a5cb3d0eade7a9b8 -commit cef2593c33ac46a58238ff998818754eabdf64ff -Author: djm@openbsd.org -Date: Tue Jan 17 10:02:34 2023 +0000 +commit 733030840c4772f858de95d5940ec0c37663e8b0 +Author: dtucker@openbsd.org +Date: Thu Mar 9 07:11:05 2023 +0000 - upstream: regression test for UnusedConnectionTimeout + upstream: Re-split the merge of the reorder-hostkeys test. - OpenBSD-Regress-ID: 7f29001374a68e71e5e078f69e4520cf4bcca084 - -commit aff9493a89c71d6a080419b49ac64eead9730491 -Author: djm@openbsd.org -Date: Mon Jan 16 04:11:29 2023 +0000 - - upstream: unbreak test: cannot access shell positional parameters - - past $9 without wrapping the position in braces (i.e. need ${10}, etc.) + In the kex_proposal_populate_entries change I merged the the check for + reordering hostkeys with the actual reordering, but kex_assemble_names + mutates options.hostkeyalgorithms which renders the check ineffective. + Put the check back where it was. Spotted and tested by jsg@, ok djm@ - OpenBSD-Regress-ID: 3750ec98d5d409ce6a93406fedde6f220d2ea2ac + OpenBSD-Commit-ID: a7469f25a738db5567395d1881e32479a7ffc9de -commit 0293c19807f83141cdf33b443154459f9ee471f6 +commit 54ac4ab2b53ce9fcb66b8250dee91c070e4167ed Author: djm@openbsd.org -Date: Tue Jan 17 09:44:48 2023 +0000 +Date: Thu Mar 9 06:58:26 2023 +0000 - upstream: Add a sshd_config UnusedConnectionTimeout option to terminate - - client connections that have no open channels for some length of time. This - complements the recently-added ChannelTimeout option that terminates inactive - channels after a timeout. - - ok markus@ + upstream: include destination constraints for smartcard keys too. - OpenBSD-Commit-ID: ca983be74c0350364c11f8ba3bd692f6f24f5da9 - -commit 8ec2e3123802d2beeca06c1644b0b647f6d36dab -Author: djm@openbsd.org -Date: Sun Jan 15 23:35:10 2023 +0000 - - upstream: adapt to ed25519 changes in src/usr.bin/ssh + Spotted by Luci Stanescu; ok deraadt@ markus@ - OpenBSD-Regress-ID: 4b3e7ba7ee486ae8a0b4790f8112eded2bb7dcd5 + OpenBSD-Commit-ID: add879fac6903a1cb1d1e42c4309e5359c3d870f -commit 9fbbfeca1ce4c7ec0001c827bbf4189a3ba0964b -Author: djm@openbsd.org -Date: Sun Jan 15 23:05:32 2023 +0000 +commit bfd1ad01d974a316b60622759ad17537fa2d92b4 +Author: Darren Tucker +Date: Thu Mar 9 18:24:54 2023 +1100 - upstream: update OpenSSH's Ed25519 code to the last version of SUPERCOP - - (20221122) and change the import approach to the same one we use for - Streamlined NTRUPrime: use a shell script to extract the bits we need from - SUPERCOP, make some minor adjustments and squish them all into a single file. - - ok tb@ tobhe@ + Limit the number of PAM environment variables. - OpenBSD-Commit-ID: 1bc0fd624cb6af440905b8ba74ac7c03311b8e3b + xcalloc has its own limits, but these are specific to PAM. From + Coverity CID 405198, ok djm@ -commit 6283f4bd83eee714d0f5fc55802eff836b06fea8 +commit a231414970e01a35f45a295d5f93698fa1249b28 Author: Darren Tucker -Date: Sat Jan 14 22:02:44 2023 +1100 +Date: Thu Mar 9 18:19:44 2023 +1100 - Allow writev is seccomp sandbox. + Limit the number of PAM environment variables. - This seems to be used by recent glibcs at least in some configurations. - From bz#3512, ok djm@ + From Coverity CID 405194, tweaks and ok djm@ -commit 923c3f437f439cfca238fba37e97a7041782f615 +commit 36c6c3eff5e4a669ff414b9daf85f919666e8e03 Author: dtucker@openbsd.org -Date: Sat Jan 14 10:05:54 2023 +0000 +Date: Wed Mar 8 06:21:32 2023 +0000 - upstream: Shell syntax fix. From ren mingshuai vi github PR#369. + upstream: Plug mem leak. Coverity CID 405196, ok djm@ - OpenBSD-Regress-ID: 6696b2eeefe128099fc3d7ea9f23252cc35156f9 + OpenBSD-Commit-ID: 175f09349387c292f626da68f65f334faaa085f2 -commit 4d87a00f704e0365e11c3c38b170c1275ec461fc -Author: dtucker@openbsd.org -Date: Sat Jan 14 09:57:08 2023 +0000 +commit dfb9b736e1ccf9e6b03eea21cd961f4fd0634c98 +Author: tb@openbsd.org +Date: Wed Mar 8 05:33:53 2023 +0000 - upstream: Instead of skipping the all-tokens test if we don't have + upstream: ssh-pkcs11: synchronize error messages with errors - OpenSSL (since we use it to compute the hash), put the hash at the end and - just omit it if we don't have it. Prompted by bz#3521. + A handful of error messages contained incorrect function names or + otherwise inaccurate descriptions. Fix them to match reality. - OpenBSD-Regress-ID: c79ecba64250ed3b6417294b6c965e6b12ca5eea - -commit b05406d6f93b8c8ec11ec8b27e7c76cc7a5a55fb -Author: jmc@openbsd.org -Date: Fri Jan 13 07:13:40 2023 +0000 - - upstream: fix double phrase in previous; + input/ok djm - OpenBSD-Commit-ID: 671e6c8dc5e9230518b2bbfa143daaa88adc66c2 + OpenBSD-Commit-ID: 165a15db52f75b31e1804b043480c36af09f3411 -commit 40564812b659c530eb1f4b62d09e85612aef3107 -Author: dtucker@openbsd.org -Date: Fri Jan 13 03:16:29 2023 +0000 +commit 51875897b81b5c21b80c256a29597916edbde454 +Author: guenther@openbsd.org +Date: Wed Mar 8 04:43:12 2023 +0000 - upstream: Document "UserKnownHostsFile none". ok djm@ + upstream: Delete obsolete /* ARGSUSED */ lint comments. - OpenBSD-Commit-ID: f695742d39e34ecdcc3c861c3739a84648a4bce5 + ok miod@ millert@ + + OpenBSD-Commit-ID: 7be168a570264d59e96a7d2d22e927d45fee0e4c -commit d03e245e034019a37388f6f5f893ce848ab6d2e2 +commit a76085bda883c2104afb33ab0334eca190927362 Author: Darren Tucker -Date: Fri Jan 13 23:02:34 2023 +1100 +Date: Wed Mar 8 17:25:37 2023 +1100 - Retry package installation 3 times. + Extra brackets to prevent warning. + +commit 147ae57d4dfa0508109f93b78a7d8b92819e1f83 +Author: djm@openbsd.org +Date: Wed Mar 8 00:05:58 2023 +0000 + + upstream: use RSA/SHA256 when testing usability of private key in - When setting up the CI environment, retry package installation 3 times - before going up. Should help prevent spurious failures during - infrastructure issues. + agent; with/ok dtucker + + OpenBSD-Commit-ID: fe1382e2fdf23fcae631308e72342bad56066a56 -commit 625f6bc39840167dafb3bf5b6a3e18503ac986e8 -Author: dtucker@openbsd.org -Date: Fri Jan 13 04:47:34 2023 +0000 +commit 27fd251bc906a763e70ce0f27c8abdf8bbd1e416 +Author: djm@openbsd.org +Date: Wed Mar 8 00:05:37 2023 +0000 - upstream: Move scp path setting to a helper function. The previous + upstream: use RSA/SHA256 when testing usability of private key; - commit to add scp to the test sshd's path causes the t-envpass test to fail - when the test scp is given using a fully qualified path. Put this in a - helper function and only call it from the scp tests. + based on fix in bz3546 by Dmitry Belyavskiy; with/ok dtucker - OpenBSD-Regress-ID: 7533dc1c4265c1de716abb062957994195b36df4 + OpenBSD-Commit-ID: 0ef414cc363a832f9fab92a5da0234448bce2eba -commit 6e6f88647042b3cde54a628545c2f5fb656a9327 -Author: dtucker@openbsd.org -Date: Fri Jan 13 04:23:00 2023 +0000 +commit eee9f3fc3d52ae7d2106929bb06b7f291fb0b81a +Author: djm@openbsd.org +Date: Tue Mar 7 21:47:42 2023 +0000 - upstream: Add scp's path to test sshd's PATH. + upstream: refactor to be more readable top to bottom. Prompted by - If the scp we're testing is fully qualified (eg it's not in the system - PATH) then add its path to the under-test sshd's PATH so we can find - it. Prompted by bz#3518. + Coverity CID 405048 which was a false-positive fd leak; ok dtucker@ - OpenBSD-Regress-ID: 7df4f5a0be3aa135495b7e5a6719d3cbc26cc4c0 + OpenBSD-Commit-ID: fc55ec2af622a017defb9b768bf26faefc792c00 -commit 8a5e99a70fcf9b022a8aa175ebf6a71f58511da3 +commit 42a06b29a4c99272bf690f9b3be520b08b448dc5 Author: Darren Tucker -Date: Fri Jan 13 15:49:48 2023 +1100 +Date: Tue Mar 7 18:34:41 2023 +1100 - Remove skipping test when scp not in path. - - An upcoming change renders this obsolete by adding scp's path to the - test sshd's PATH, and removing this first will make the subsequent sync - easier. + Add header changes missed in previous. -commit 41f36dd896c8fb8337d403fcf476762986976e9d +commit 4710077096edff2e6926dd5b15bf586491d317db Author: dtucker@openbsd.org -Date: Fri Jan 13 02:58:20 2023 +0000 +Date: Tue Mar 7 06:09:14 2023 +0000 - upstream: Add a "Host" line to the output of ssh -G showing the + upstream: Fix mem leak in environment setup. - original host arg. Inspired by patch from vincent at bernat.ch via bz#3343, - ok djm@ + From jjelen at redhat.com via bz#2687, ok djm@ - OpenBSD-Commit-ID: 59c0f60a222113a44d0650cd394376e3beecc883 + OpenBSD-Commit-ID: 9f9e4ba3cac003e6f81da3bcebd1b9ec43e7f353 -commit f673b49f3be3eb51074fbb8a405beb6cd0f7d93e -Author: djm@openbsd.org -Date: Fri Jan 13 02:44:02 2023 +0000 +commit 03acc50d0ccb78fc91d1570de1cd0fdfea646028 +Author: dtucker@openbsd.org +Date: Mon Mar 6 12:15:47 2023 +0000 - upstream: avoid printf("%s", NULL) if using ssh - - -oUserKnownHostsFile=none and a hostkey in one of the system known hosts file - changes; ok dtucker@ + upstream: Unit test for kex_proposal_populate_entries. - OpenBSD-Commit-ID: 7ca87614bfc6da491315536a7f2301434a9fe614 + OpenBSD-Regress-ID: bdb211d80d572a08bf14b49fe2a58b9ff265c006 -commit 93fc7c576563e3d88a1dc019dd213f65607784cc +commit 3f9231c2e1f374ebb08016ba00ea97b47c0ed20b Author: djm@openbsd.org -Date: Wed Jan 11 05:39:38 2023 +0000 +Date: Tue Mar 7 05:37:26 2023 +0000 - upstream: clamp the minimum buffer lengths and number of inflight + upstream: fix memory leak in process_read() path; Spotted by James - requests too + Robinson in GHPR363; ok markus@ - OpenBSD-Commit-ID: c4965f62fa0ba850940fd66ae3f60cf516bbcd56 + OpenBSD-Commit-ID: cdc2d98e6478b7e7f3a36976845adae3820429d8 -commit 48bf234322e639d279c5a28435eae50155e9b514 +commit c5e6e890839ec520ab9301a92cba56303749dea2 Author: djm@openbsd.org -Date: Wed Jan 11 05:36:50 2023 +0000 +Date: Tue Mar 7 01:30:52 2023 +0000 - upstream: ignore bogus upload/download buffer lengths in the limits + upstream: correct size for array argument when changing - extension + UMAC_OUTPUT_LEN Coverity CID 291845; ok dtucker@ - OpenBSD-Commit-ID: c5b023e0954693ba9a5376e4280c739b5db575f8 + OpenBSD-Commit-ID: 2eb017d10705bb623d4418691f961c930eafaec0 -commit 36b00d31833ca74cb0f7c7d8eda1bde55700f929 -Author: djm@openbsd.org -Date: Wed Jan 11 02:13:52 2023 +0000 +commit 9641753e0fd146204d57b2a4165f552a81afade4 +Author: dtucker@openbsd.org +Date: Mon Mar 6 12:14:48 2023 +0000 - upstream: remove whitespace at EOL from code extracted from SUPERCOP + upstream: Refactor creation of KEX proposal. - OpenBSD-Commit-ID: 1ec524ff2fbb9387d731601437c82008f35a60f4 + This adds kex_proposal_populate_entries (and corresponding free) which + populates the KEX proposal array with dynamically allocated strings. + This replaces the previous mix of static and dynamic that has been the + source of previous leaks and bugs. Remove unused compat functions. + With & ok djm@. + + OpenBSD-Commit-ID: f2f99da4aae2233cb18bf9c749320c5e040a9c7b -commit d888de06c5e4d7dbf2f2b85f2b5bf028c570cf78 -Author: djm@openbsd.org -Date: Wed Jan 11 00:51:27 2023 +0000 +commit aa59d6a489fb20973fa461d0fdb1110db412947b +Author: dtucker@openbsd.org +Date: Sun Mar 5 09:24:35 2023 +0000 - upstream: rewrite this test to use a multiplexed ssh session so we can + upstream: Fix mem and FILE leaks in moduli screening. - control its lifecycle without risk of race conditions; fixes some of the - Github integration tests for openssh-portable + If multiple -Ocheckpoint= options are passed, the earlier ones would + be overwritten and leaked. If we use an input file that wasn't stdin, + close that. From Coverity CIDs 291884 and 291894. - OpenBSD-Regress-ID: 5451cad59ba0d43ae9eeda48ec80f54405fee969 + OpenBSD-Commit-ID: a4d9d15f572926f841788912e2b282485ad09e8b -commit 4bcc737a35fdd9cc4af7423d6c23dfd0c7ef4786 -Author: Damien Miller -Date: Wed Jan 11 11:45:17 2023 +1100 +commit 23b8cb41767af99a1aac24589d1882d9c8c2c205 +Author: dtucker@openbsd.org +Date: Sun Mar 5 08:18:58 2023 +0000 - remove buffer len workaround for NetBSD 4.x + upstream: Plug mem leak in moduli checkpoint option parsing. - Switching to from pipes to a socketpair for communicating with the - ssh process avoids the (kernel bug?) problem. + From Coverity CID 291894. + + OpenBSD-Commit-ID: 9b1aba2d049741ae21c8dc4560a7e29ab17310f4 -commit f5154d2aac3e6a32a1b13dec23a701a087850cdc -Author: Damien Miller -Date: Wed Jan 11 11:44:19 2023 +1100 +commit fc7f8f2188d4a4fc8ba77eddbe863c7665666db5 +Author: dtucker@openbsd.org +Date: Sun Mar 5 05:34:09 2023 +0000 - add back use of pipes in scp.c under USE_PIPES + upstream: Remove unused compat.h includes. - This matches sftp.c which prefers socketpair but uses pipes on - some older platforms. + We've previously removed a lot of the really old compatibility code, + and with it went the need to include compat.h in most of the files that + have it. + + OpenBSD-Commit-ID: 5af8baa194be00a3092d17598e88a5b29f7ea2b4 -commit eec737b59cf13841de46134967a206607000acd4 -Author: millert@openbsd.org -Date: Tue Jan 10 23:22:15 2023 +0000 +commit 6c165c36246d8004c20e1df5cec4961a5ac422d6 +Author: dtucker@openbsd.org +Date: Sat Mar 4 03:22:59 2023 +0000 - upstream: Switch scp from using pipes to a socketpair for + upstream: Use time_t for x11 timeout. - communication with it's ssh sub-processes. We no longer need to reserve two - descriptors to ensure that we don't end up using fd 0-2 unexpectedly, that is - handled by sanitise_stdfd() in main(). Based on an original diff from djm@. - OK deraadt@ djm@ + Use time_t instead of u_int for remaining x11 timeout checks for 64bit + time_t safety. From Coverity CIDs 405197 and 405028, ok djm@ - OpenBSD-Commit-ID: b80c372faac462471e955ddeab9480d668a2e48d + OpenBSD-Commit-ID: 356685bfa1fc3d81bd95722d3fc47101cc1a4972 -commit d213d126a4a343abd3a1eb13687d39c1891fe5c8 -Author: jmc@openbsd.org -Date: Fri Jan 6 08:44:11 2023 +0000 +commit 4a3918f51bd2d968387e7aa87e33b32c78077fb4 +Author: dtucker@openbsd.org +Date: Fri Mar 3 10:23:42 2023 +0000 - upstream: tweak previous; ok djm + upstream: Ensure ms_remain is always initialized - OpenBSD-Commit-ID: 229c493452766d70a78b0f02f6ff9894f9028858 - -commit 4a5590a5ee47b7dfd49773e9fdba48ad3089fe64 -Author: Damien Miller -Date: Mon Jan 9 16:33:56 2023 +1100 - - try to improve logging for dynamic-forward test + similar to what we do in ssh_packet_write_wait. bz#2687, from jjelen + at redhat.com. - previously the logs from the ssh used to exercise the forwarding - channel would clobber the logs from the ssh actually doing the - forwarding + OpenBSD-Commit-ID: a50e0541cf823f8d1c72f71ccde925d3dbe6dfac -commit 715bc25dcfccf9fb2bee820155fe071d01a618db -Author: Darren Tucker -Date: Sat Jan 7 23:24:50 2023 +1100 +commit e44846a4487d2885ac7f2610be09b1e2bf52249b +Author: dtucker@openbsd.org +Date: Fri Mar 3 09:48:51 2023 +0000 - Skip dynamic-forward test on minix3. + upstream: Check for non-NULL before string - This test relies on loopback addresses which minix does not have. - Previously the test would not run at all since it also doesn't have - netcat, but now we use our own netcat it tries and fails. - -commit dd1249bd5c45128a908395c61b26996a70f82205 -Author: Damien Miller -Date: Sun Jan 8 12:08:59 2023 +1100 - - don't test IPv6 addresses if platform lacks support + comparison. From jjelen at redhat.com via bz#2687. + + OpenBSD-Commit-ID: 0d9b2e0cac88a311b5766b1aef737082583c285f -commit d77fc611a62f2dfee0b654c31a50a814b13310dd -Author: dtucker@openbsd.org -Date: Fri Jan 6 12:33:33 2023 +0000 +commit 1842d523fae63b862ce8e60725c9b606cddb86a6 +Author: djm@openbsd.org +Date: Fri Mar 3 05:00:34 2023 +0000 - upstream: When OpenSSL is not available, skip parts of percent test + upstream: guard against getsockname(-1, ...) from Coverity CID - that require it. Based on github pr#368 from ren mingshuai. + 291832 - OpenBSD-Regress-ID: 49a375b2cf61ccb95b52e75e2e025cd10988ebb2 + OpenBSD-Commit-ID: e58d5227327917d189229b7f0b37d2780f360d5f -commit 1cd2aac312af9172f1b5cb06c2e1cd090abb83cf -Author: Darren Tucker -Date: Sat Jan 7 23:01:11 2023 +1100 +commit 78571a5fe9847d40d7f220c92b707574ae9ec4ce +Author: djm@openbsd.org +Date: Fri Mar 3 04:36:20 2023 +0000 - Use our own netcat for dynamic-forward test. + upstream: some options are not first-match-wins. Mention that there - That way we can be surer about its behaviour rather than trying to - second-guess the behaviour of various netcat implementations. + are exceptions at the start of the manpage and label some of them in the + option description. + + OpenBSD-Commit-ID: 3b74728446fa6fc8742769eeb8c3674e233e84c4 -commit 26cab41c05d7b0859d2a1ea5b6ed253d91848a80 -Author: Darren Tucker -Date: Sat Jan 7 14:30:43 2023 +1100 +commit d1c1b3272e8895a96c4f5889bd6e07a8525bd9f1 +Author: djm@openbsd.org +Date: Fri Mar 3 04:34:49 2023 +0000 - Use autoconf to find openssl binary. + upstream: actually print "channeltimeout none" in config dump mode; - It's possible to install an OpenSSL in a path not in the system's - default library search path. OpenSSH can still use this (eg if you - specify an rpath) but the openssl binary there may not work. If one is - available on the system path just use that. + spotted via Coverity CID 405022 + + OpenBSD-Commit-ID: b074b52bf138b75f08264e8da15880b29c7a630f -commit 5532e010a0eeb6aa264396514f9aed7948471538 +commit 8bf61e95610b48192d4e1720cc15d9004617301d Author: Darren Tucker -Date: Sat Jan 7 10:34:18 2023 +1100 +Date: Fri Mar 3 14:50:03 2023 +1100 - Check openssl_bin path is executable before using. + Add Coverity badges. -commit 5d7b16cff48598d5908db970bfdc9ff9326142c8 -Author: Darren Tucker -Date: Fri Jan 6 23:19:07 2023 +1100 +commit 93291bd723959adf462b1df958106cf07a7734dd +Author: dtucker@openbsd.org +Date: Fri Mar 3 03:12:24 2023 +0000 - Set OPENSSL_BIN from OpenSSL directory. + upstream: Check return values of dup2. Spotted by Coverity, ok djm@ + + OpenBSD-Commit-ID: 19fb1b53072826d00c67df677731d2f6c1dd602b -commit 344a0e8240eaf08da5d46a5e3a9ecad6e4f64c35 +commit e37261dff33af23f37202cfce0848d36f5c1055c Author: dtucker@openbsd.org -Date: Fri Jan 6 08:50:33 2023 +0000 +Date: Fri Mar 3 02:37:58 2023 +0000 - upstream: Save debug logs from ssh for debugging purposes. + upstream: Use time_t for x11_refuse_time timeout. We need - OpenBSD-Regress-ID: 109e40b06de1c006a3b8e0d8745b790b2c5870a0 + SSH_TIME_T_MAX for this, so move from misc.c to misc.h so it's available. + Fixes a Coverity warning for 64bit time_t safety, ok djm@ + + OpenBSD-Commit-ID: c69c4c3152cdaab953706db4ccf4d5fd682f7d8d -commit e1ef172646f7f49c80807eea90225ef5e0be55a8 -Author: djm@openbsd.org -Date: Fri Jan 6 08:07:39 2023 +0000 +commit 32755a98c29114b13f4c9d47454bbb265b932ad7 +Author: dtucker@openbsd.org +Date: Fri Mar 3 02:34:29 2023 +0000 - upstream: regression test for ChannelTimeout + upstream: Check return value from fctnl and warn on failure. - OpenBSD-Regress-ID: 280bfbefcfa415428ad744e43f69a8dede8ad685 + Spotted by Coverity, ok djm@ + + OpenBSD-Commit-ID: 2097c7db3cf657f1e3a6c5077041bacc63143cab -commit 2393ea8daf25853459eb07a528d7577688847777 -Author: djm@openbsd.org -Date: Fri Jan 6 07:18:18 2023 +0000 +commit 5fc60e8246c36b8255f72a937ebe9787b39648c6 +Author: dtucker@openbsd.org +Date: Thu Mar 2 11:10:27 2023 +0000 - upstream: fix typo in verbose logging + upstream: Remove SUDO in proxy command wrapper. Anything that needs - OpenBSD-Regress-ID: 0497cdb66e003b2f50ed77291a9104fba2e017e9 + sudo is already run by it, and it breaks if root isn't in sudoers. + + OpenBSD-Regress-ID: 6cf22fda32a89c16915f31a6ed9bbdbef2a3bac9 -commit 161a5378a3cc2e7aa3f9674cb7f4686ae6ce9586 -Author: djm@openbsd.org -Date: Fri Jan 6 02:59:50 2023 +0000 +commit 0d514659b23a257247491179cfbb53a6dd64e164 +Author: dtucker@openbsd.org +Date: Thu Mar 2 08:24:41 2023 +0000 - upstream: unit tests for misc.c:ptimeout_* API + upstream: Fix breakage on dhgex test. - OpenBSD-Regress-ID: 01f8fb12d08e5aaadd4bd4e71f456b6588be9a94 + This was due to the sshd logs being written to the wrong log file. + While there, make save_debug_logs less verbose, write the name of the + tarball to regress.log and use $SUDO to remove the old symlinks (which + shouldn't be needed, but won't hurt). Initial problem spotted by anton@. + + OpenBSD-Regress-ID: 9c44fb9cd418e6ff31165e7a6c1f9f11a6d19f5b -commit 018d671d78145f03d6f07ae9d64d51321da70325 -Author: tb@openbsd.org -Date: Wed Jan 4 22:48:57 2023 +0000 +commit 860201201d4ae655702807966901682cff30a171 +Author: dtucker@openbsd.org +Date: Thu Mar 2 08:14:52 2023 +0000 - upstream: Copy bytes from the_banana[] rather than banana() + upstream: Quote grep and log message better. - Fixes test failure due to segfault seen on arm64 with xonly snap. + OpenBSD-Regress-ID: 3823d9063127169736aa274b1784cb28e15b64d4 + +commit 03a03c6002525f5ad9c8fc874a5d5826a35d9858 +Author: dtucker@openbsd.org +Date: Thu Mar 2 06:41:56 2023 +0000 + + upstream: Always call fclose on checkpoints. - ok djm + In the case of an fprintf failure we would not call fclose which would + leak the FILE pointer. While we're there, try to clean up the temp file + on failure. Spotted by Coverity, ok djm@ - OpenBSD-Regress-ID: 86e2aa4bbd1dff1bc4ebb2969c0d6474485be046 + OpenBSD-Commit-ID: 73c7ccc5d4fcc235f54c6b20767a2815408525ef -commit ab6bb69e251faa8b24f81b25c72ec0120f20cad4 -Author: Damien Miller -Date: Fri Jan 6 19:13:36 2023 +1100 +commit 13fe8f9785e6d90400ce548939a0b0ddc11fcb3c +Author: dtucker@openbsd.org +Date: Wed Mar 1 21:54:50 2023 +0000 - unbreak scp on NetBSD 4.x - - e555d5cad5 effectively increased the default copy buffer size for SFTP - transfers. This caused NetBSD 4.x to hang during the "copy local file to - remote file in place" scp.sh regression test. + upstream: Remove old log symlinks - This puts back the original 32KB copy buffer size until we can properly - figure out why. + before creating new ones. In -portable some platforms don't like + overwriting existing symlinks. - lots of debugging assistance from dtucker@ + OpenBSD-Regress-ID: 7e7ddc0beb73e945e1c4c58d51c8a125b518120f -commit 2d1ff2b9431393ad99ef496d5e3b9dd0d4f5ac8c -Author: djm@openbsd.org -Date: Fri Jan 6 02:47:18 2023 +0000 +commit 131fcbcaffd1e3bcf5ab766ec497b5d768955310 +Author: Darren Tucker +Date: Wed Mar 1 23:23:02 2023 +1100 - upstream: Implement channel inactivity timeouts + Adjust test jobs for new log directory. + +commit a6f4ac8a2baf77e5361cfa017d0dc250d1409bec +Author: dtucker@openbsd.org +Date: Wed Mar 1 09:29:32 2023 +0000 + + upstream: Rework logging for the regression tests. - This adds a sshd_config ChannelTimeouts directive that allows channels that - have not seen traffic in a configurable interval to be automatically closed. - Different timeouts may be applied to session, X11, agent and TCP forwarding - channels. + Previously we would log to ssh.log and sshd.log, but that is insufficient + for tests that have more than one concurent ssh/sshd. - Note: this only affects channels over an opened SSH connection and not - the connection itself. Most clients close the connection when their channels - go away, with a notable exception being ssh(1) in multiplexing mode. + Instead, we'll log to separate datestamped files in a $OBJ/log/ and + leave a symlink at the previous location pointing at the most recent + instance with an entry in regress.log showing which files were created + at each point. This should be sufficient to reconstruct what happened + even for tests that use multiple instances of each program. If the test + fails, tar up all of the logs for later analysis. - ok markus dtucker + This will let us also capture the output from some of the other tools + which was previously sent to /dev/null although most of those will be + in future commits. - OpenBSD-Commit-ID: ae8bba3ed9d9f95ff2e2dc8dcadfa36b48e6c0b8 + OpenBSD-Regress-ID: f802aa9e7fa51d1a01225c05fb0412d015c33e24 -commit 0e34348d0bc0b1522f75d6212a53d6d1d1367980 -Author: djm@openbsd.org -Date: Fri Jan 6 02:42:34 2023 +0000 +commit 8ead62ed5e86c7df597d8604f332f49cd1527b85 +Author: dtucker@openbsd.org +Date: Tue Feb 28 21:31:50 2023 +0000 - upstream: Add channel_set_xtype() + upstream: fatal out if allocating banner string fails to avoid - This sets an "extended" channel type after channel creation (e.g. - "session:subsystem:sftp") that will be used for setting channel inactivity - timeouts. - - ok markus dtucker + potential null deref later in sscanf. Spotted by Coverity, ok deraadt@ - OpenBSD-Commit-ID: 42564aa92345045b4a74300528f960416a15d4ca + OpenBSD-Commit-ID: 74e8d228ac00552e96e9e968dfcccf8dd1f46ad5 -commit ceedf09b2977f3a756c759a6e7eb8f8e9db86a18 -Author: djm@openbsd.org -Date: Fri Jan 6 02:41:49 2023 +0000 +commit 44ca56ba0b3f531f1d85730cc701097cd49e6868 +Author: dtucker@openbsd.org +Date: Tue Feb 28 08:45:24 2023 +0000 - upstream: tweak channel ctype names - - These are now used by sshd_config:ChannelTimeouts to specify timeouts by - channel type, so force them all to use a similar format without whitespace. + upstream: Explicitly ignore return from fchmod - ok dtucker markus + similar to other calls to prevent warning. - OpenBSD-Commit-ID: 66834765bb4ae14f96d2bb981ac98a7dae361b65 + OpenBSD-Commit-ID: fdc5287dcee0860b5a493186414226c655b0eb0a -commit c60438158ad4b2f83d8504257aba1be7d0b0bb4b -Author: djm@openbsd.org -Date: Fri Jan 6 02:39:59 2023 +0000 +commit 803392933a3a6f09f834aa5f0c2aab06a3b382f4 +Author: dtucker@openbsd.org +Date: Mon Feb 27 22:12:40 2023 +0000 - upstream: Add channel_force_close() + upstream: Plug mem leak on globbed ls error path. - This will forcibly close an open channel by simulating read/write errors, - draining the IO buffers and calling the detach function. + Spotted by Coverity, ok deraadt@ - Previously the detach function was only ever called during channel garbage - collection, but there was no way to signal the user of a channel (e.g. - session.c) that its channel was being closed deliberately (vs. by the - usual state-machine logic). So this adds an extra "force" argument to the - channel cleanup callback to indicate this condition. + OpenBSD-Commit-ID: de28476025db29820a9a2e56e98b964d8a02861c + +commit aa33b4d396abf47a2a45f982f28d054fb1dcb5c3 +Author: Darren Tucker +Date: Mon Feb 27 21:04:22 2023 +1100 + + Cast time_t's in debug output to long long. - ok markus dtucker + Should fix Coverity warning about truncation of 64bit time_t. + +commit b0fd60a9de62a03189ad57d0c07f0ac51dc00e95 +Author: Darren Tucker +Date: Mon Feb 27 17:28:59 2023 +1100 + + Do shadow expiry calcs using "long long". - OpenBSD-Commit-ID: 23052707a42bdc62fda2508636e624afd466324b + Coverity flags these as potentially not 64bit time_t safe so use + long long for the calculations and debug output. ok djm@ -commit d478cdc7ad6edd4b1bcd1e86fb2f23194ff33d5a -Author: djm@openbsd.org -Date: Fri Jan 6 02:38:23 2023 +0000 +commit 01dbeb3084d714bbd001ff9d03b9de542e8cdf58 +Author: Damien Miller +Date: Mon Feb 27 17:07:52 2023 +1100 - upstream: replace manual poll/ppoll timeout math with ptimeout API + avoid clash between for getopt's struct option - feedback markus / ok markus dtucker + Since we don't use getopt_long() nothing outside the getopt() + implementation itself uses this structure, so move it into the + source to remove it from visibility and clashes with libc's - OpenBSD-Commit-ID: c5ec4f2d52684cdb788cd9cbc1bcf89464014be2 + ok dtucker@ -commit 4adf3817a24efe99b06e62630577d683c7cd8065 -Author: djm@openbsd.org -Date: Fri Jan 6 02:37:04 2023 +0000 +commit eb88d07c43afe407094e7d609248d85a15e148ef +Author: Darren Tucker +Date: Sat Feb 25 14:45:41 2023 +1100 - upstream: add ptimeout API for keeping track of poll/ppoll - - timeouts; ok dtucker markus + Revert explicit chmods on private keys. - OpenBSD-Commit-ID: 3335268ca135b3ec15a947547d7cfbb8ff929ead + This should no longer be needed on Cygwin test runners due to previous + commit. -commit 8c7c69d32375d2f3ce9da0109c9bffc560842316 -Author: djm@openbsd.org -Date: Thu Jan 5 05:49:13 2023 +0000 +commit 52b75db61030a6c8baf66b73644380cf3f58e26a +Author: Darren Tucker +Date: Sat Feb 25 14:43:28 2023 +1100 - upstream: suppress "Connection closed" message when in quiet mode + Remove extended ACLs from working dirs. - OpenBSD-Commit-ID: 8a3ab7176764da55f60bfacfeae9b82d84e3908f + This should allow umask to work as expected and prevent tests from + failing due to excessive permissions on private keys. -commit 845ceecea2ac311b0c267f9ecbd34862e1876fc6 -Author: djm@openbsd.org -Date: Mon Jan 2 07:03:57 2023 +0000 +commit 0c5d4c843df5605b043a758d69f9a611ef63c479 +Author: Darren Tucker +Date: Fri Feb 24 13:44:13 2023 +1100 - upstream: regression test for PermitRemoteOpen + Explicitly set permissions on user and host keys. - OpenBSD-Regress-ID: 8271aafbf5c21950cd5bf966f08e585cebfe630c + On cygwin, the umask might not be sufficient. Should fix tests on + Github runners. -commit b3daa8dc582348d6ab8150bc1e571b7aa08c5388 +commit 6c9fc9d7a9f7abf82c3294d74e6d4a25735862ce Author: djm@openbsd.org -Date: Mon Jan 2 07:03:30 2023 +0000 +Date: Wed Feb 22 03:56:43 2023 +0000 - upstream: fix bug in PermitRemoteOpen which caused it to ignore its - - first argument unless it was one of the special keywords "any" or "none". + upstream: fix progressmeter corruption on wide displays; bz3534 - Reported by Georges Chaudy in bz3515; ok dtucker@ + feedback/ok dtucker@ - OpenBSD-Commit-ID: c5678a39f1ff79993d5ae3cfac5746a4ae148ea5 + OpenBSD-Commit-ID: f4affee067cec7c182f3e0b307d758e0472762a3 -commit 0872663a7be0301bcc3d49acdbc9b740a3d972d4 -Author: jmc@openbsd.org -Date: Mon Dec 26 19:16:03 2022 +0000 +commit fe0bd3cde9665d364e5eedd2c2c2e60d4cdc3786 +Author: dtucker@openbsd.org +Date: Tue Feb 21 06:48:18 2023 +0000 - upstream: spelling fixes; from paul tagliamonte amendments to his + upstream: fseek to end of known_hosts before writing to it. - diff are noted on tech + POSIX and ANSI C require that applications call fseek or similar between + read and writing to a RW file. OpenBSD doesn't enforce this, but some + (System V derived) platforms need this to prevent it from writing a + spurious extra byte (in this case, a newline). ok djm@ deraadt@ - OpenBSD-Commit-ID: d776dd03d0b882ca9c83b84f6b384f6f9bd7de4a + OpenBSD-Commit-ID: 33e680dcd8110582a93a40a8491024e961f45137 -commit 797da2812a71785b34890bb6eb44767a7d09cd34 -Author: djm@openbsd.org -Date: Fri Dec 16 07:13:22 2022 +0000 +commit 357fb8ae14c07cd025eeed66e73de91bab569849 +Author: Darren Tucker +Date: Tue Feb 21 17:51:09 2023 +1100 - upstream: Mention that scp uses the SFTP protocol and remove - - reference to legacy flag. Spotted by, feedback and ok jmc@ + Also run unit tests on AIX VMs. - OpenBSD-Commit-ID: 9dfe04966f52e941966b46c7a2972147f95281b3 + In the past these tests took too long, but these days it only adds + about 5 min to the run. -commit 93f2ce8c050a7a2a628646c00b40b9b53fef93ef -Author: djm@openbsd.org -Date: Fri Dec 16 06:56:47 2022 +0000 +commit 17781aaa5188ee1477f7779b280d105512e3dbed +Author: Darren Tucker +Date: Tue Feb 21 17:38:55 2023 +1100 - upstream: Clear signal mask early in main(); sshd may have been - - started with one or more signals masked (sigprocmask(2) is not cleared - on fork/exec) and this could interfere with various things, e.g. the - login grace timer. - - Execution environments that fail to clear the signal mask before running - sshd are clearly broken, but apparently they do exist. - - Reported by Sreedhar Balasubramanian; ok dtucker@ - - OpenBSD-Commit-ID: 77078c0b1c53c780269fc0c416f121d05e3010ae + Wrap stdint.h inside ifdef. -commit 4acfaabfae41badb9d334a2ee88c5c6ad041c0d5 -Author: jmc@openbsd.org -Date: Fri Dec 16 06:52:48 2022 +0000 +commit ef798bad38505f7bf1b5fa5c0843dfc5a2b192b9 +Author: Mayank Sharma +Date: Mon Feb 20 17:37:15 2023 +0530 - upstream: add -X to usage(); + Add includes to ptimeout test. - OpenBSD-Commit-ID: 1bdc3df7de11d766587b0428318336dbffe4a9d0 + Fixes test failures on AIX due to type mismatches. -commit e555d5cad5afae7d5ef2bbc02ca591178fe16fed -Author: djm@openbsd.org -Date: Fri Dec 16 03:40:03 2022 +0000 +commit ab69dda05d5268454209f529fa80f477e60d846a +Author: Darren Tucker +Date: Mon Feb 20 18:24:39 2023 +1100 - upstream: add a -X option to both scp(1) and sftp(1) to allow - - control over some SFTP protocol knobs: the copy buffer length and - the number of inflight requests, both of which are used during - upload/download. - - Previously these could be controlled in sftp(1) using the -b/-R options. - This makes them available in both SFTP protocol clients using the same - option character sequence. - - ok dtucker@ + Always use the openssl binary configure tells us. - OpenBSD-Commit-ID: 27502bffc589776f5da1f31df8cb51abe9a15f1c + This fixes tests on platforms that do not have the openssl tool + installed at all. -commit 5a7a7acab2f466dc1d7467b5d05d35268c3137aa -Author: deraadt@openbsd.org -Date: Thu Dec 15 18:20:39 2022 +0000 +commit 2a7e3449908571af601a4c2d12ab140096442e47 +Author: dtucker@openbsd.org +Date: Fri Feb 17 04:22:50 2023 +0000 - upstream: The idiomatic way of coping with signed char vs unsigned + upstream: Remove now-unused compat bit SSH_BUG_RSASIGMD5. The code - char (which did not come from stdio read functions) in the presence of - ctype macros, is to always cast to (unsigned char). casting to (int) - for a "macro" which is documented to take int, is weird. And sadly wrong, - because of the sing extension risk.. same diff from florian + to set this was removed in OpenSSH 7.7 when support for SSH implementations + dating back to before RFC standardization were removed. "burn it all" djm@ - OpenBSD-Commit-ID: 65b9a49a68e22ff3a0ebd593f363e9f22dd73fea + OpenBSD-Commit-ID: 6330935fbe23dd00be79891505e06d1ffdac7cda -commit b0b58222c7cc62efd8212c4fb65a545f58ebb22d -Author: Darren Tucker -Date: Mon Dec 19 18:49:51 2022 +1100 +commit 0833ccf2c8b7ae08b296c06f17bd53e3ab94b0b0 +Author: dtucker@openbsd.org +Date: Fri Feb 17 03:06:18 2023 +0000 - Simply handling of SSH_CONNECTION PAM env var. + upstream: Remove now-unused compat bit SSH_BUG_BIGENDIANAES. This - Prompted by bz#3508: there's no need to cache the value of - sshpam_conninfo so remove the global. While there, add check of - return value from pam_putenv. ok djm@ + was previously set for OpenSSH 2.3 (released in 2000) but this check was + removed in OpenSSH 7.7 (2018). ok djm@ deraadt@ + + OpenBSD-Commit-ID: 326426ea328707fc9e83305291ab135c87f678af -commit ed8444572ae684fdb892f97bae342c6cb6456f04 -Author: Darren Tucker -Date: Mon Dec 19 18:42:34 2022 +1100 +commit c81c2bea6e828d52b62b448b4ffdd3c163177975 +Author: Damien Miller +Date: Fri Feb 17 10:12:40 2023 +1100 - Add tests for LibreSSL 3.7.0 and OpenSSL 1.1.1s. + whitespace fixes -commit abb9a8aaddfcacbd12641f6e4f203da0fa85a287 -Author: Darren Tucker -Date: Sun Dec 18 21:36:25 2022 +1100 +commit 500f90b39db5f0014e6b0c49ff1f45c994b69293 +Author: Damien Miller +Date: Fri Feb 17 10:02:08 2023 +1100 - Use sudo when resetting perms on directories. + whitespace at EOL -commit 2f5664c5908d84697cbe91302d5d5c4d83cb2121 -Author: Darren Tucker -Date: Sun Dec 18 21:19:33 2022 +1100 +commit 68350152406339170721c15e97afdf827a5e4001 +Author: dtucker@openbsd.org +Date: Thu Feb 16 10:10:00 2023 +0000 - Set group perms on regress dir. + upstream: Remove SSH_BUG_PASSWORDPAD compat bit - This ensures that the tests don't fail due to StrictMode checks. - -commit 137196300fc1540affadde880210f02ba6cb4abf -Author: Darren Tucker -Date: Sun Dec 18 21:13:42 2022 +1100 + since it's no longer used. ok markus@ + + OpenBSD-Commit-ID: b92c21f56fe4b7f9a54790d6a9650725c226820b - Fetch regress logs from obj dir. - -commit 5f93c4836527d9fda05de8944a1c7b4a205080c7 -Author: Darren Tucker -Date: Tue Dec 13 20:59:54 2022 +1100 +commit 537cccd804eaf65f32bdce037cc31db4e0ab0f44 +Author: dtucker@openbsd.org +Date: Thu Feb 16 07:55:15 2023 +0000 - obsdsnap test VMs runs-on libvirt too. + upstream: Remove SSH_BUG_IGNOREMSG compat flag + + since it's only applicable to SSH1 and thus no longer used. ok markus@ + "kill it with fire" djm@ + + OpenBSD-Commit-ID: ea13318b1937795d9db4790d3ce0a6ed01584dab -commit 8386886fb1ab7fda73069fb0db1dbe0e5a52f758 -Author: Darren Tucker -Date: Tue Dec 13 20:55:37 2022 +1100 +commit 285cf6cd4b91a0a0ce33193c358c99085af33e43 +Author: jmc@openbsd.org +Date: Fri Feb 10 06:41:53 2023 +0000 - Run upstream obsdsnap tests on ephemeral runners. + upstream: space between macro and punctuation; sort usage(); + + OpenBSD-Commit-ID: 6141610cfca037700730e41f868d1d9124958f8c -commit b6e01459b55ece85d7f296b2bc719d1841e1009e -Author: Darren Tucker -Date: Tue Dec 13 20:48:56 2022 +1100 +commit d39a96f70f81878c77336ed35f5c648c1804b71a +Author: jmc@openbsd.org +Date: Fri Feb 10 06:40:48 2023 +0000 - Move obsdsnap test VMs to ephemeral runners. + upstream: space between macro and punctuation; + + OpenBSD-Commit-ID: abc95e550be9e6d9a7ff64b65c104c7be21ab19e -commit ea6fdf9a1aa71a411f7db218a986392c4fb55693 -Author: Damien Miller -Date: Fri Dec 9 18:00:21 2022 +1100 +commit 16e82bf53fc34e43e3b948d43b68d5b27a7335e6 +Author: jmc@openbsd.org +Date: Fri Feb 10 06:39:27 2023 +0000 - use calloc for allocating arc4random structs + upstream: sort SYNOPSIS; - ok dtucker + OpenBSD-Commit-ID: dacd9da33277d5669a51213d880632599c890c1e -commit 4403b62f5548e91389cb3339d26a9d0c4bb07b34 -Author: dtucker@openbsd.org -Date: Fri Dec 9 00:22:29 2022 +0000 +commit d9685121ff6d57b8797411f3cb123884a4b96e30 +Author: Darren Tucker +Date: Sat Feb 11 12:32:19 2023 +1100 - upstream: Warn if no host keys for hostbased auth can be loaded. + Improve seccomp compat on older systems. - OpenBSD-Commit-ID: 2a0a13132000cf8d3593133c1b49768aa3c95977 + Check if flags to mmap and madvise are defined before using them. + Should fix problems building on older Linux systems that don't have + these. bz#3537, with & ok djm@. -commit a6183e25e3f1842e21999fe88bc40bb99b121dc3 -Author: dtucker@openbsd.org -Date: Fri Dec 9 00:17:40 2022 +0000 +commit 6180b0fa4f7996687678702806257e661fd5931e +Author: djm@openbsd.org +Date: Fri Feb 10 05:06:03 2023 +0000 - upstream: Add server debugging for hostbased auth. + upstream: test -Ohashalg=... and that the default output contains both - auth_debug_add queues messages about the auth process which is sent to - the client after successful authentication. This also sends those to - the server debug log to aid in debugging. From bz#3507, ok djm@ + specified hash algorithms; prompted by dtucker@ - OpenBSD-Commit-ID: 46ff67518cccf9caf47e06393e2a121ee5aa258a + OpenBSD-Regress-ID: 26f309208c8d8b8fa9c5f419767b85f1e9b22f51 -commit b85c3581c16aaf6e83b9a797c80705a56b1f312e -Author: cheloha@openbsd.org -Date: Sun Dec 4 23:50:49 2022 +0000 +commit d651f5c9fe37e61491eee46c49ba9fa03dbc0e6a +Author: djm@openbsd.org +Date: Fri Feb 10 04:56:30 2023 +0000 - upstream: remove '?' from getopt(3) loops - - userspace: remove vestigial '?' cases from top-level getopt(3) loops + upstream: let ssh-keygen and ssh-keyscan accept - getopt(3) returns '?' when it encounters a flag not present in the in - the optstring or if a flag is missing its option argument. We can - handle this case with the "default" failure case with no loss of - legibility. Hence, remove all the redundant "case '?':" lines. + -Ohashalg=sha1|sha256 when outputting SSHFP fingerprints to allow algorithm + selection. bz3493 ok dtucker@ - Prompted by dlg@. With help from dlg@ and millert@. + OpenBSD-Commit-ID: e6e07fe21318a873bd877f333e189eb963a11b3d + +commit 18938d11a90b74d63c20b2d3c965d5bd64786ab1 +Author: djm@openbsd.org +Date: Fri Feb 10 04:47:19 2023 +0000 + + upstream: add a `sshd -G` option that parses and prints the - Link: https://marc.info/?l=openbsd-tech&m=167011979726449&w=2 + effective configuration without attempting to load private keys and perform + other checks. This allows usage of the option before keys have been + generated. - ok naddy@ millert@ dlg@ + bz3460 feedback/ok dtucker@ - OpenBSD-Commit-ID: b2f89346538ce4f5b33ab8011a23e0626a67e66e + OpenBSD-Commit-ID: 774504f629023fc25a559ab1d95401adb3a7fb29 -commit 9a067e8d28a2249fd73f004961e30c113ee85e5d -Author: dtucker@openbsd.org -Date: Wed Dec 7 11:45:43 2022 +0000 +commit df7d3dbf7194db8e97730ee0425d4d9d7bdb8b10 +Author: djm@openbsd.org +Date: Fri Feb 10 04:40:28 2023 +0000 - upstream: Fix comment typo. + upstream: make `ssh -Q CASignatureAlgorithms` work as the manpage says - OpenBSD-Regress-ID: 3b04faced6511bb5e74648c6a4ef4bf2c4decf03 + it should bz3532 + + OpenBSD-Commit-ID: 0ddb17b3fcbd99bfb5baea4ac5e449620cbd3adc -commit ce3c3e78ce45d68a82c7c8dc89895f297a67f225 +commit d3b8d4198b6595f23b5859d43dc8fc701f97429b Author: Darren Tucker -Date: Wed Dec 7 18:58:25 2022 +1100 +Date: Fri Feb 10 14:26:44 2023 +1100 - Add SANDBOX_DEBUG to the kitchensink test build. + Add CentOS 7 test targets. -commit bc234605fa3eb10f56bf0d74c8ecb0d91ada9d05 -Author: Damien Miller -Date: Wed Dec 7 18:38:25 2022 +1100 +commit 22efb01e355bba4755b730ed417f91c081445bfc +Author: dtucker@openbsd.org +Date: Thu Feb 9 09:55:33 2023 +0000 - disable SANDBOX_SECCOMP_FILTER_DEBUG + upstream: Test adding terminating newline to known_hosts. - It was mistakenly enabled in 2580916e4872 + OpenBSD-Regress-ID: 5fc3010ac450195b3fbdeb68e875564968800365 + +commit caec6da1a583ed8c32c6ad3b81bbcaab46ac8b61 +Author: dtucker@openbsd.org +Date: Wed Feb 8 08:06:03 2023 +0000 + + upstream: ssh-agent doesn't actually take -v, - Reported by Peter sec-openssh-com.22.fichtner AT 0sg.net + so the recently-added ones will result in the test not cleaning up + after itself. Patch from cjwatson at debian.org vi bz#3536. + + OpenBSD-Regress-ID: 1fc8283568f5bf2f918517c2c1e778072cf61b1a -commit b087c5cfa011b27992e01589314fec830266f99d -Author: Rose <83477269+AtariDreams@users.noreply.github.com> -Date: Tue Nov 29 15:12:54 2022 -0500 +commit 3c379c9a849a635cc7f05cbe49fe473ccf469ef9 +Author: dtucker@openbsd.org +Date: Thu Feb 9 09:54:11 2023 +0000 - Update autotools + upstream: Ensure that there is a terminating newline when adding a new - Regenerate config files using latest autotools + entry to known_hosts. bz#3529, with git+openssh at limpsquid.nl, ok deraadt@ + markus@ + + OpenBSD-Commit-ID: fa8d90698da1886570512b96f051e266eac105e0 -commit d63f5494978a185c7421d492b9c2f6f05bb54138 +commit 95b6bbd2553547260b324b39d602061c88b774bc Author: Darren Tucker -Date: Tue Dec 6 12:22:36 2022 +1100 +Date: Tue Feb 7 08:43:47 2023 +1100 - Fix typo in comment. Spotted by tim@ + Replace 9.1 with 9.2 on CI status page. -commit 73dcca12115aa12ed0d123b914d473c384e52651 -Author: dtucker@openbsd.org -Date: Sun Dec 4 11:03:11 2022 +0000 +commit 195313dfe10a23c82e9d56d5fdd2f59beee1bdcf +Author: Damien Miller +Date: Fri Feb 3 16:33:09 2023 +1100 - upstream: Remove duplicate includes. + harden Linux seccomp sandbox - Patch from AtariDreams via github PR#364. + Linux mmap(2) and madvise(2) syscalls support quite a number of funky + flags that we don't expect that sshd/libc will ever need. We can + exclude this kernel attack surface by filtering the mmap(2) flags + and the madvise(2) advice arguments. - OpenBSD-Commit-ID: b9186638a05cb8b56ef7c0de521922b6723644ea - -commit 3cec15543010bc8d6997d896b1717a650afb7e92 -Author: djm@openbsd.org -Date: Fri Dec 2 04:40:27 2022 +0000 - - upstream: make struct sshbuf private + Similarly, the sandboxed process in sshd is a single-threaded program + that does not use shared memory for synchronisation or communication. + Therefore, there should be no reason for the advanced priority + inheritance futex(2) operations to be necessary. These can also be + excluded. - and remove an unused field; ok dtucker + Motivated by Jann Horn pointing out that there have been kernel bugs + in nearby Linux kernel code, e.g. CVE-2020-29368, CVE-2020-29374 and + CVE-2022-42703. - OpenBSD-Commit-ID: c7a3d77c0b8c153d463398606a8d57569186a0c3 + Feedback Jann Horn, ok dtucker@ -commit 5796bf8ca9535f9fa7d01829a540d2550e05c860 -Author: Darren Tucker -Date: Fri Dec 2 11:43:36 2022 +1100 +commit 6dfb65de949cdd0a5d198edee9a118f265924f33 +Author: Damien Miller +Date: Thu Feb 2 23:21:54 2023 +1100 - Restore ssh-agent permissions on exit. - - ...enough that subsequent builds can overwrite ssh-agent if necessary. + crank versions in RPM specs -commit ccf5a13868cbb4659107458cac1e017c98abcbda -Author: dtucker@openbsd.org -Date: Thu Dec 1 02:22:13 2022 +0000 +commit d07cfb11a0ca574eb68a3931d8c46fbe862a2021 +Author: Damien Miller +Date: Thu Feb 2 23:21:45 2023 +1100 - upstream: Clean up ssh-add and ssh-agent logs. + update version in README + +commit 9fe207565b4ab0fe5d1ac5bb85e39188d96fb214 +Author: Damien Miller +Date: Thu Feb 2 23:17:49 2023 +1100 + + adapt compat_kex_proposal() test to portable + +commit 903c556b938fff2d7bff8da2cc460254430963c5 +Author: djm@openbsd.org +Date: Thu Feb 2 12:12:52 2023 +0000 + + upstream: test compat_kex_proposal(); by dtucker@ - OpenBSD-Regress-ID: 9eda8e4c3714d7f943ab2e73ed58a233bd29cd2c + OpenBSD-Regress-ID: 0e404ee264db546f9fdbf53390689ab5f8d38bf2 -commit 7a8b40cf6a5eda80173140cc6750a6db8412fa87 +commit 405fba71962dec8409c0c962408e09049e5624b5 Author: dtucker@openbsd.org -Date: Thu Dec 1 02:19:29 2022 +0000 +Date: Thu Jan 19 07:53:45 2023 +0000 - upstream: Log output of ssh-agent and ssh-add + upstream: Check if we can copy sshd or need to use sudo to do so - This should make debugging easier. + during reexec test. Skip test if neither can work. Patch from anton@, tweaks + from me. - OpenBSD-Regress-ID: 5974b02651f428d7e1079b41304c498ca7e306c8 + OpenBSD-Regress-ID: 731b96ae74d02d5744e1f1a8e51d09877ffd9b6d -commit 4a1805d532616233dd6072e5cd273b96dd3062e6 -Author: dtucker@openbsd.org -Date: Tue Nov 29 22:41:14 2022 +0000 +commit b2a2a8f69fd7737ea17dc044353c514f2f962f35 +Author: djm@openbsd.org +Date: Thu Feb 2 12:10:22 2023 +0000 - upstream: Add void to client_repledge args to fix compiler warning. ok djm@ + upstream: openssh-9.2 - OpenBSD-Commit-ID: 7e964a641ce4a0a0a11f047953b29929d7a4b866 + OpenBSD-Commit-ID: f7389f32413c74d6e2055f05cf65e7082de03923 -commit 815c4704930aa449edf6e812e99d69e9ffd31f01 +commit 12da7823336434a403f25c7cc0c2c6aed0737a35 Author: djm@openbsd.org -Date: Mon Nov 28 01:38:22 2022 +0000 +Date: Thu Feb 2 12:10:05 2023 +0000 - upstream: tighten pledge(2) after session establishment + upstream: fix double-free caused by compat_kex_proposal(); bz3522 - feedback, ok & testing in snaps deraadt@ + by dtucker@, ok me - OpenBSD-Commit-ID: aecf4d49d28586dfbcc74328d9333398fef9eb58 + OpenBSD-Commit-ID: 2bfc37cd2d41f67dad64c17a64cf2cd3806a5c80 -commit f7cebbbf407d772ed71403d314343766782fe540 -Author: djm@openbsd.org -Date: Mon Nov 28 01:37:36 2022 +0000 +commit 79efd95ab5ff99f4cb3a955e2d713b3f54fb807e +Author: Darren Tucker +Date: Wed Feb 1 17:17:26 2023 +1100 - upstream: New EnableEscapeCommandline ssh_config(5) option - - This option (default "no") controls whether the ~C escape is available. - Turning it off by default means we will soon be able to use a stricter - default pledge(2) in the client. - - feedback deraadt@ dtucker@; tested in snaps for a while + Skip connection-timeout test on minix3. - OpenBSD-Commit-ID: 7e277595d60acb8263118dcb66554472257b387a + Minix 3's Unix domain sockets don't seem to work the way we expect, so + skip connection-timeout test on that platform. While there, group + together all similarly skipped tests and explicitly comment. -commit d323f7ecf52e3d4ec1f4939bf31693e02f891dca -Author: mbuhl@openbsd.org -Date: Fri Nov 18 19:47:40 2022 +0000 +commit 6b508c4e039619842bcf5a16f8a6b08dd6bec44a +Author: Damien Miller +Date: Wed Feb 1 12:12:05 2023 +1100 - upstream: In channel_request_remote_forwarding the parameters for - - permission_set_add are leaked as they are also duplicated in the call. Found - by CodeChecker. ok djm + fix libfido2 detection without pkg-config - OpenBSD-Commit-ID: 4aef50fa9be7c0b138188814c8fe3dccc196f61e + Place libfido2 before additional libraries (that it may depend upon) + and not after. bz3530 from James Zhang; ok dtucker@ -commit 62cc33e6eed847aafdc29e34aa69e9bd82a0ee16 -Author: Darren Tucker -Date: Wed Nov 30 11:23:11 2022 +1100 +commit 358e300fed5e6def233a2c06326e51e20ebed621 +Author: deraadt@openbsd.org +Date: Wed Jan 18 20:56:36 2023 +0000 - Use -fzero-call-used-regs=used on clang 15. - - clang 15 seems to have a problem with -fzero-call-used-reg=all which - causes spurious "incorrect signature" failures with ED25519. On those - versions, use -fzero-call-used-regs=used instead. (We may add exceptions - later if specific versions prove to be OK). Also move the GCC version - check to match. + upstream: delete useless dependency - Initial investigation by Daniel Pouzzner (douzzer at mega nu), workaround - suggested by Bill Wendling (morbo at google com). bz#3475, ok djm@ - -commit f84b9cffd52c9c5c359a54a1929f9948e803ab1d -Author: Darren Tucker -Date: Mon Nov 28 21:09:28 2022 +1100 - - Skip unit tests on slow riscv64 hardware. + OpenBSD-Commit-ID: e1dc11143f83082e3154d6094f9136d0dc2637ad -commit 9f2747e0bed3faca92679eae69aef10c95dc82f5 -Author: Darren Tucker -Date: Sun Nov 27 15:26:22 2022 +1100 +commit a4cb9be1b021b511e281ee55c356f964487d9e82 +Author: deraadt@openbsd.org +Date: Wed Jan 18 20:43:15 2023 +0000 - Rework how selfhosted tests interact with runners. - - Previously there was one runner per test target (mostly VMs). This had - a few limitations: - - multiple tests that ran on the same target (eg multiple build - configs) were serialized on availability or that runner. - - it needed manual balancing of VMs over host machines. + upstream: Create and install sshd random relink kit. - To address this, make VMs that use ephemeral disks (ie most of them) - all use a pool of runners with the "libvirt" label. This requires that - we distinguish between "host" and "target" for those. Native runners - and VMs with persistent disks (eg the constantly-updated snapshot ones) - specify the same host and target. + ../Makefile.inc and Makfile are concatenated for reuse, which hopefully won't + be too fragile, we'll see if we need a different approach. The resulting sshd + binary is tested with the new sshd -V option before installation. As the + binary layout is now semi-unknown (meaning relative, fixed, and gadget + offsets are not precisely known), change the filesystem permissions to 511 to + prevent what I call "logged in BROP". I have ideas for improving this further + but this is a first step ok djm - This should improve test throughput. + OpenBSD-Commit-ID: 1e0a2692b7e20b126dda60bf04999d1d30d959d8 -commit d664ddaec87bdc7385be8ef7f1337793e1679d48 -Author: Darren Tucker -Date: Sun Nov 27 12:19:37 2022 +1100 +commit bc7de6f91a9a0ae2f148a9d31a4027d441a51999 +Author: jmc@openbsd.org +Date: Wed Jan 18 06:55:32 2023 +0000 - Run vmstartup from temp dir. + upstream: tweak previous; ok djm - This will allow us to create ephemeral disk images per-runner. + OpenBSD-Commit-ID: df71ce4180c58202dfdc1d92626cfe900b91b7c3 -commit 0fa16e952b1fc1c4cf65e3dd138b0e87003e2e45 +commit a20b7e999773e6333c8aa9b0a7fa41966e63b037 Author: Darren Tucker -Date: Sun Nov 27 12:14:00 2022 +1100 +Date: Tue Jan 31 19:35:44 2023 +1100 - Make "config" in matrix singular and pass in env. + Skip connection-timeout test under Valgrind. - This will allow the startup scripts to adapt their behaviour based on - the type and config. - -commit e8857043af54809187be1e8b06749db61112899f -Author: Darren Tucker -Date: Sun Nov 27 11:42:22 2022 +1100 - - Add "libvirt" label to dfly30. + Valgrind slows things down so much that the timeout test fails. Skip + this test until we figure out if we can make it work. -commit 9775473d84902dc37753686cd10ae71fbe67efda +commit c3ffb54b4fc5e608206037921db6ccbc2f5ab25f Author: Darren Tucker -Date: Sun Nov 27 09:28:20 2022 +1100 +Date: Wed Jan 25 21:58:40 2023 +1100 - Rename "os" in matrix to "target". + Skip connection-timeout when missing FD passing. - This is in preparation to distinguish this from the host that the runner - runs on in case where they are separate (eg VMs). - -commit 04fd00ceff39f4544ced6f5342060abe584835d0 -Author: Darren Tucker -Date: Sun Nov 27 09:23:04 2022 +1100 - - Remove unused self-hosted test targets. + This tests uses multiplexing which uses file descriptor passing, so + skip it if we don't have that. Fixes test failures on Cygwin. -commit c9d9fcad2a11c1cd1550a541f44091d65f0b5584 -Author: Darren Tucker -Date: Sun Nov 27 09:16:15 2022 +1100 +commit 35253af01d8c0ab444c8377402121816e71c71f5 +Author: djm@openbsd.org +Date: Wed Jan 18 02:00:10 2023 +0000 - Remove explicit "default" test config argument. + upstream: when restoring non-blocking mode to stdio fds, restore - Not specifying the test config implicitly selects default args. - -commit 15a01cf15f396f87c6d221c5a6af98331c818962 -Author: Darren Tucker -Date: Wed Nov 23 13:18:54 2022 +1100 - - Add fallback for old platforms w/out MAP_ANON. - -commit 6b9bbbfe8b26db6e9a30a7e08c223e85421aed98 -Author: Darren Tucker -Date: Wed Nov 23 13:09:11 2022 +1100 - - If we haven't found it yet, recheck for sys/stat.h. + exactly the flags that ssh started with and don't just clobber them with + zero, as this could also remove the append flag from the set; - On some very old platforms, sys/stat.h needs sys/types.h, however - autoconf 2.71's AC_CHECK_INCLUDES_DEFAULT checks for them in the - opposite order, which in combination with modern autoconf's - "present but cannot be compiled" behaviour causes it to not be - detected. - -commit 8926956f22639132a9f2433fcd25224e01b900f5 -Author: Darren Tucker -Date: Fri Nov 11 11:25:37 2022 +1100 - - Add dfly62 test target. + bz3523; ok dtucker@ + + OpenBSD-Commit-ID: 1336b03e881db7564a4b66014eb24c5230e9a0c0 -commit 650de7ecd3567b5a5dbf16dd1eb598bd8c20bca8 -Author: dtucker@openbsd.org -Date: Thu Nov 10 23:03:10 2022 +0000 +commit 7d17ea151c0b2519f023bd9cc7f141128833ac47 +Author: millert@openbsd.org +Date: Wed Jan 18 01:50:21 2023 +0000 - upstream: Handle dynamic remote port forwarding in escape commandline's + upstream: Add a -V (version) option to sshd like the ssh client - -R processing. bz#3499, ok djm@ + has. OK markus@ deraadt@ - OpenBSD-Commit-ID: 194ee4cfe7ed0e2b8ad0727f493c798a50454208 + OpenBSD-Commit-ID: abe990ec3e636fb040132aab8cbbede98f0c413e -commit 5372db7e7985ba2c00f20fdff8942145ca99e033 -Author: Darren Tucker -Date: Thu Nov 10 12:44:51 2022 +1100 +commit 62360feb7f08f2a4c6fc36f3b3449309203c42c9 +Author: millert@openbsd.org +Date: Tue Jan 17 18:52:44 2023 +0000 - Remove seed passing over reexec. + upstream: For "ssh -V" always exit 0, there is no need to check opt - This was added for the benefit of platforms using ssh-rand-helper to - prevent a delay on each connection as sshd reseeded itself. + again. This was missed when the fallthrough in the switch case above it was + removed. OK deraadt@ - ssh-random-helper is long gone, and since the re-exec happens before the - chroot the re-execed sshd can reseed itself normally. ok djm@ + OpenBSD-Commit-ID: 5583e5d8f6d62a8a4215cfa95a69932f344c8120 -commit ca98d3f8c64cfc51af81e1b01c36a919d5947ec2 -Author: Darren Tucker -Date: Wed Nov 9 20:59:20 2022 +1100 +commit 12492c0abf1eb415d08a897cc1d8b9e789888230 +Author: djm@openbsd.org +Date: Tue Jan 17 10:15:10 2023 +0000 - Skip reexec test on OpenSSL 1.1.1 specifically. + upstream: also check that an active session inhibits - OpenSSL 1.1.1 has a bug in its RNG that breaks reexec fallback, so skip - that test. See bz#3483 for details. + UnusedConnectionTimeout idea markus@ + + OpenBSD-Regress-ID: 55c0fb61f3bf9e092b0a53f9041d3d2012f14003 -commit 5ec4ebc2548e5f7f1b55b2a5cef5b67bdca8146f -Author: dtucker@openbsd.org -Date: Wed Nov 9 09:04:12 2022 +0000 +commit cef2593c33ac46a58238ff998818754eabdf64ff +Author: djm@openbsd.org +Date: Tue Jan 17 10:02:34 2023 +0000 - upstream: Fix typo in fatal error message. - - Patch from vapier at chromium.org. + upstream: regression test for UnusedConnectionTimeout - OpenBSD-Commit-ID: 8a0c164a6a25eef0eedfc30df95bfa27644e35cf + OpenBSD-Regress-ID: 7f29001374a68e71e5e078f69e4520cf4bcca084 -commit e6abafe9a6d809422d3432b95b3f9747b0acaa71 -Author: dtucker@openbsd.org -Date: Wed Nov 9 09:01:52 2022 +0000 +commit aff9493a89c71d6a080419b49ac64eead9730491 +Author: djm@openbsd.org +Date: Mon Jan 16 04:11:29 2023 +0000 - upstream: Remove errant colon and simplify format + upstream: unbreak test: cannot access shell positional parameters - string in error messages. Patch from vapier at chromium.org. + past $9 without wrapping the position in braces (i.e. need ${10}, etc.) - OpenBSD-Commit-ID: fc28466ebc7b74e0072331947a89bdd239c160d3 + OpenBSD-Regress-ID: 3750ec98d5d409ce6a93406fedde6f220d2ea2ac -commit db2027a687516f87c3fb141e87154bb3d8a7807c +commit 0293c19807f83141cdf33b443154459f9ee471f6 Author: djm@openbsd.org -Date: Wed Nov 9 01:37:44 2022 +0000 +Date: Tue Jan 17 09:44:48 2023 +0000 - upstream: rename client_global_hostkeys_private_confirm() to + upstream: Add a sshd_config UnusedConnectionTimeout option to terminate - client_global_hostkeys_prove_confirm(), as it handles the - "hostkeys-prove00@openssh.com" message; no functional change + client connections that have no open channels for some length of time. This + complements the recently-added ChannelTimeout option that terminates inactive + channels after a timeout. - OpenBSD-Commit-ID: 31e09bd3cca6eed26855b88fb8beed18e9bd026d + ok markus@ + + OpenBSD-Commit-ID: ca983be74c0350364c11f8ba3bd692f6f24f5da9 -commit 1c2be7c2004cf1abcd172fee9fe3eab57cd4c426 +commit 8ec2e3123802d2beeca06c1644b0b647f6d36dab Author: djm@openbsd.org -Date: Wed Nov 9 00:15:59 2022 +0000 +Date: Sun Jan 15 23:35:10 2023 +0000 - upstream: typo in comment + upstream: adapt to ed25519 changes in src/usr.bin/ssh - OpenBSD-Commit-ID: 39c58f41e0f32d1ff31731fa6f5bbbc3ad25084a + OpenBSD-Regress-ID: 4b3e7ba7ee486ae8a0b4790f8112eded2bb7dcd5 -commit cf1a9852d7fc93e4abc4168aed09529a57427cdc -Author: Darren Tucker -Date: Wed Nov 9 09:23:47 2022 +1100 +commit 9fbbfeca1ce4c7ec0001c827bbf4189a3ba0964b +Author: djm@openbsd.org +Date: Sun Jan 15 23:05:32 2023 +0000 - Defer seed_rng until after closefrom call. + upstream: update OpenSSH's Ed25519 code to the last version of SUPERCOP - seed_rng will initialize OpenSSL, and some engine providers (eg Intel's - QAT) will open descriptors for their own use. bz#3483, patch from - joel.d.schuetze at intel.com, ok djm@ + (20221122) and change the import approach to the same one we use for + Streamlined NTRUPrime: use a shell script to extract the bits we need from + SUPERCOP, make some minor adjustments and squish them all into a single file. + + ok tb@ tobhe@ + + OpenBSD-Commit-ID: 1bc0fd624cb6af440905b8ba74ac7c03311b8e3b -commit dffa64480163fbf76af7e4fb62c26bb0dd6642aa +commit 6283f4bd83eee714d0f5fc55802eff836b06fea8 Author: Darren Tucker -Date: Wed Nov 9 08:27:47 2022 +1100 - - Fix comment text. From emaste at freebsd.org. - -commit d9df5689c29823ab830ec4f54c83c6cc3c0077ad -Author: Pierre Ossman -Date: Wed Jul 6 13:52:10 2022 +0200 +Date: Sat Jan 14 22:02:44 2023 +1100 - Avoid assuming layout of fd_set - - POSIX doesn't specify the internal layout of the fd_set object, so let's - not assume it is just a bit mask. This increases compatibility with - systems that have a different layout. + Allow writev is seccomp sandbox. - The assumption is also worthless as we already refuse to use file - descriptors over FD_SETSIZE anyway. Meaning that the default size of - fd_set is quite sufficient. + This seems to be used by recent glibcs at least in some configurations. + From bz#3512, ok djm@ -commit 419aa8a312e8d8f491933ca3d5933e602cb05aae -Author: Darren Tucker -Date: Tue Nov 8 12:42:52 2022 +1100 +commit 923c3f437f439cfca238fba37e97a7041782f615 +Author: dtucker@openbsd.org +Date: Sat Jan 14 10:05:54 2023 +0000 - Shutdown any VM before trying to check out repo. + upstream: Shell syntax fix. From ren mingshuai vi github PR#369. - In the case where the previous run did not clean up, the checkout will - fail as it'll leave a stale mount. + OpenBSD-Regress-ID: 6696b2eeefe128099fc3d7ea9f23252cc35156f9 -commit a32c07cbb78f65d8527642b96474a83b413f8108 -Author: Darren Tucker -Date: Tue Nov 8 11:33:25 2022 +1100 +commit 4d87a00f704e0365e11c3c38b170c1275ec461fc +Author: dtucker@openbsd.org +Date: Sat Jan 14 09:57:08 2023 +0000 - Run vm startup and shutdown from runner temp dir. + upstream: Instead of skipping the all-tokens test if we don't have - Should work even if the github workspace dir is on a stale sshfs mount. + OpenSSL (since we use it to compute the hash), put the hash at the end and + just omit it if we don't have it. Prompted by bz#3521. + + OpenBSD-Regress-ID: c79ecba64250ed3b6417294b6c965e6b12ca5eea -commit 2b40a7dfcdb8e616155b9504145aa52b271455aa -Author: Darren Tucker -Date: Tue Nov 8 11:03:31 2022 +1100 +commit b05406d6f93b8c8ec11ec8b27e7c76cc7a5a55fb +Author: jmc@openbsd.org +Date: Fri Jan 13 07:13:40 2023 +0000 - Add valrind-5 test here too. + upstream: fix double phrase in previous; + + OpenBSD-Commit-ID: 671e6c8dc5e9230518b2bbfa143daaa88adc66c2 -commit 2ea03d1f6d0a05ee2b63ed2dc0f2d54f1e4655a1 -Author: Darren Tucker -Date: Tue Nov 8 09:21:10 2022 +1100 +commit 40564812b659c530eb1f4b62d09e85612aef3107 +Author: dtucker@openbsd.org +Date: Fri Jan 13 03:16:29 2023 +0000 - Update checkout and upload actions. + upstream: Document "UserKnownHostsFile none". ok djm@ - Update actions/checkout and actions/upload-artifact to main branch for - compatibility with node.js v16. + OpenBSD-Commit-ID: f695742d39e34ecdcc3c861c3739a84648a4bce5 -commit 4e316ff0f18a118232bb9ac6512ee62773a9e8ea +commit d03e245e034019a37388f6f5f893ce848ab6d2e2 Author: Darren Tucker -Date: Tue Nov 8 09:17:04 2022 +1100 +Date: Fri Jan 13 23:02:34 2023 +1100 - Split out rekey test since it runs the longest. + Retry package installation 3 times. + + When setting up the CI environment, retry package installation 3 times + before going up. Should help prevent spurious failures during + infrastructure issues. -commit 21625a6424258a92a96a3bb73ae6aabc5ed8a6b4 +commit 625f6bc39840167dafb3bf5b6a3e18503ac986e8 Author: dtucker@openbsd.org -Date: Mon Nov 7 10:09:28 2022 +0000 +Date: Fri Jan 13 04:47:34 2023 +0000 - upstream: The IdentityFile option in ssh_config can also be used to + upstream: Move scp path setting to a helper function. The previous - specify a public key file, as documented in ssh.1 for the -i option. Document - this also for IdentityFile in ssh_config.5, for documentation completeness. - From laalsaas at systemli.org via portable github PR#352, ok jmc@ djm@ + commit to add scp to the test sshd's path causes the t-envpass test to fail + when the test scp is given using a fully qualified path. Put this in a + helper function and only call it from the scp tests. - OpenBSD-Commit-ID: 2f943be9f96e60ef81a9a4faa25b009999f9883b + OpenBSD-Regress-ID: 7533dc1c4265c1de716abb062957994195b36df4 -commit 747691604d3325ed2b62bad85b6fd8563ad32f6c +commit 6e6f88647042b3cde54a628545c2f5fb656a9327 Author: dtucker@openbsd.org -Date: Mon Nov 7 10:05:38 2022 +0000 +Date: Fri Jan 13 04:23:00 2023 +0000 - upstream: Remove some set but otherwise unused variables, spotted + upstream: Add scp's path to test sshd's PATH. - in -portable by clang 16's -Wunused-but-set-variable. ok djm@ + If the scp we're testing is fully qualified (eg it's not in the system + PATH) then add its path to the under-test sshd's PATH so we can find + it. Prompted by bz#3518. - OpenBSD-Commit-ID: 3d943ddf2369b38fbf89f5f19728e7dc1daf3982 + OpenBSD-Regress-ID: 7df4f5a0be3aa135495b7e5a6719d3cbc26cc4c0 -commit 1d78d25653805aefc7a8dd9d86cd7359ada3823c +commit 8a5e99a70fcf9b022a8aa175ebf6a71f58511da3 +Author: Darren Tucker +Date: Fri Jan 13 15:49:48 2023 +1100 + + Remove skipping test when scp not in path. + + An upcoming change renders this obsolete by adding scp's path to the + test sshd's PATH, and removing this first will make the subsequent sync + easier. + +commit 41f36dd896c8fb8337d403fcf476762986976e9d Author: dtucker@openbsd.org -Date: Mon Nov 7 10:02:59 2022 +0000 +Date: Fri Jan 13 02:58:20 2023 +0000 - upstream: Check for and disallow MaxStartups values less than or + upstream: Add a "Host" line to the output of ssh -G showing the - equal to zero during config parsing, rather than faling later at runtime. - bz#3489, ok djm@ + original host arg. Inspired by patch from vincent at bernat.ch via bz#3343, + ok djm@ - OpenBSD-Commit-ID: d79c2b7a8601eb9be493629a91245d761154308b + OpenBSD-Commit-ID: 59c0f60a222113a44d0650cd394376e3beecc883 -commit a00f59a645072e5f5a8d207af15916a7b23e2642 +commit f673b49f3be3eb51074fbb8a405beb6cd0f7d93e Author: djm@openbsd.org -Date: Mon Nov 7 04:04:40 2022 +0000 +Date: Fri Jan 13 02:44:02 2023 +0000 - upstream: fix parsing of hex cert expiry time; was checking whether the - - start time began with "0x", not the expiry time. + upstream: avoid printf("%s", NULL) if using ssh - from Ed Maste + -oUserKnownHostsFile=none and a hostkey in one of the system known hosts file + changes; ok dtucker@ - OpenBSD-Commit-ID: 6269242c3e1a130b47c92cfca4d661df15f05739 + OpenBSD-Commit-ID: 7ca87614bfc6da491315536a7f2301434a9fe614 -commit f58acaf8c7315483f4ac87d46a1aa2142a713cd8 -Author: Darren Tucker -Date: Mon Nov 7 15:10:59 2022 +1100 +commit 93fc7c576563e3d88a1dc019dd213f65607784cc +Author: djm@openbsd.org +Date: Wed Jan 11 05:39:38 2023 +0000 - Fix merge conflict. + upstream: clamp the minimum buffer lengths and number of inflight + + requests too + + OpenBSD-Commit-ID: c4965f62fa0ba850940fd66ae3f60cf516bbcd56 -commit 162e5741020a8d996c0c12b988b118e71ed728e6 -Author: Darren Tucker -Date: Mon Nov 7 15:04:33 2022 +1100 +commit 48bf234322e639d279c5a28435eae50155e9b514 +Author: djm@openbsd.org +Date: Wed Jan 11 05:36:50 2023 +0000 - Branch-specific links for master status badges. + upstream: ignore bogus upload/download buffer lengths in the limits + + extension + + OpenBSD-Commit-ID: c5b023e0954693ba9a5376e4280c739b5db575f8 -commit e4b7c12ab24579312aa3ed38ce7041a439ec2d56 -Author: Darren Tucker -Date: Mon Nov 7 14:46:38 2022 +1100 +commit 36b00d31833ca74cb0f7c7d8eda1bde55700f929 +Author: djm@openbsd.org +Date: Wed Jan 11 02:13:52 2023 +0000 - Add CIFuzz status badge. + upstream: remove whitespace at EOL from code extracted from SUPERCOP + + OpenBSD-Commit-ID: 1ec524ff2fbb9387d731601437c82008f35a60f4 -commit b496b9f831acd1e5bcd875e26e797488beef494a -Author: Darren Tucker -Date: Mon Nov 7 14:45:16 2022 +1100 +commit d888de06c5e4d7dbf2f2b85f2b5bf028c570cf78 +Author: djm@openbsd.org +Date: Wed Jan 11 00:51:27 2023 +0000 - Do not run CIFuzz on selfhosted tree. + upstream: rewrite this test to use a multiplexed ssh session so we can - We already run it on the regular tree, no need to double up. + control its lifecycle without risk of race conditions; fixes some of the + Github integration tests for openssh-portable + + OpenBSD-Regress-ID: 5451cad59ba0d43ae9eeda48ec80f54405fee969 -commit 2138b1c4ddb300129a41a5104627b0d561184c7b -Author: Darren Tucker -Date: Mon Nov 7 14:41:58 2022 +1100 +commit 4bcc737a35fdd9cc4af7423d6c23dfd0c7ef4786 +Author: Damien Miller +Date: Wed Jan 11 11:45:17 2023 +1100 - Whitespace change to trigger CIFuzz workflow. + remove buffer len workaround for NetBSD 4.x + + Switching to from pipes to a socketpair for communicating with the + ssh process avoids the (kernel bug?) problem. -commit 4670b97ef87c7b0f21283c9b07c7191be88dda05 -Author: Darren Tucker -Date: Mon Nov 7 14:34:04 2022 +1100 +commit f5154d2aac3e6a32a1b13dec23a701a087850cdc +Author: Damien Miller +Date: Wed Jan 11 11:44:19 2023 +1100 - Run cifuzz workflow on the actions as regular CI. + add back use of pipes in scp.c under USE_PIPES + + This matches sftp.c which prefers socketpair but uses pipes on + some older platforms. -commit 79391e66ce851ace1baf3c6a35e83a23f08ec2ba -Author: David Korczynski -Date: Tue Nov 30 11:45:20 2021 +0000 +commit eec737b59cf13841de46134967a206607000acd4 +Author: millert@openbsd.org +Date: Tue Jan 10 23:22:15 2023 +0000 - Add CIFuzz integration + upstream: Switch scp from using pipes to a socketpair for + + communication with it's ssh sub-processes. We no longer need to reserve two + descriptors to ensure that we don't end up using fd 0-2 unexpectedly, that is + handled by sanitise_stdfd() in main(). Based on an original diff from djm@. + OK deraadt@ djm@ + + OpenBSD-Commit-ID: b80c372faac462471e955ddeab9480d668a2e48d -commit c1893364a0be243270014d7d34362a8101d55112 -Author: dtucker@openbsd.org -Date: Mon Nov 7 02:21:22 2022 +0000 +commit d213d126a4a343abd3a1eb13687d39c1891fe5c8 +Author: jmc@openbsd.org +Date: Fri Jan 6 08:44:11 2023 +0000 - upstream: Import regenerated moduli. + upstream: tweak previous; ok djm - OpenBSD-Commit-ID: b0e54ee4d703bd6929bbc624068666a7a42ecb1f + OpenBSD-Commit-ID: 229c493452766d70a78b0f02f6ff9894f9028858 -commit 5c3f18fb994ef27e685b205ee2351851b80fdbd1 -Author: dtucker@openbsd.org -Date: Mon Nov 7 01:53:01 2022 +0000 +commit 4a5590a5ee47b7dfd49773e9fdba48ad3089fe64 +Author: Damien Miller +Date: Mon Jan 9 16:33:56 2023 +1100 - upstream: Fix typo. From pablomh via -portable github PR#344. + try to improve logging for dynamic-forward test - OpenBSD-Commit-ID: d056ee2e73691dc3ecdb44a6de68e6b88cd93827 + previously the logs from the ssh used to exercise the forwarding + channel would clobber the logs from the ssh actually doing the + forwarding -commit e1c6fcc142066417c9832e634463faa3dd5d116c +commit 715bc25dcfccf9fb2bee820155fe071d01a618db Author: Darren Tucker -Date: Mon Nov 7 12:46:58 2022 +1100 - - Link to branch-specific queries for V_9_1 status. - -commit 4f4a5fad6d8892c3f8ee9cd81ec7de6458210c9f -Author: Darren Tucker -Date: Sun Nov 6 10:55:59 2022 +1100 - - Use "prohibit-password" in -portable comments. - - "without-password" is the deprecated alias for "prohibit-password", - so we should reference the latter. From emaste at freebsd.org. - -commit 0f7e1eba55259ec037f515000b4c4afbf446230a -Author: Darren Tucker -Date: Sun Nov 6 10:50:01 2022 +1100 - - Fix tracing disable on FreeBSD. - - Some versions of FreeBSD do not support using id 0 to refer to the - current pid for procctl, so pass getpid() explicitly. From - emaste at freebsd.org. - -commit 32fddb982fd61b11a2f218a115975a87ab126d43 -Author: Darren Tucker -Date: Mon Nov 7 10:39:01 2022 +1100 - - Fix setres*id checks to work with clang-16. - - glibc has the prototypes for setresuid and setresgid behind _GNU_SOURCE, - and clang 16 will error out on implicit function definitions, so add - _GNU_SOURCE and the required headers to the configure checks. From - sam at @gentoo.org via bz#3497. - -commit 12af712d116f42164bcfa56db901d06e4fa27199 -Author: Sam James -Date: Sun Nov 6 04:52:38 2022 +0000 - - configure.ac: Fix -Wstrict-prototypes - - Clang 16 now warns on this and it'll be removed in C23, so let's - just be future proof. It also reduces noise when doing general - Clang 16 porting work (which is a big job as it is). github PR#355. - - Signed-off-by: Sam James - -commit 40b0a5eb6e3edfa2886b60c09c7803353b0cc7f5 -Author: Sam James -Date: Sun Nov 6 04:47:35 2022 +0000 +Date: Sat Jan 7 23:24:50 2023 +1100 - configure.ac: Add include for openpty - - Another Clang 16ish fix (which makes -Wimplicit-function-declaration - an error by default). github PR#355. + Skip dynamic-forward test on minix3. - See: 2efd71da49b9cfeab7987058cf5919e473ff466b - See: be197635329feb839865fdc738e34e24afd1fca8 - -commit 6b17e128879ec6cc32ca2c28b5d894b4aa72e32d -Author: Rochdi Nassah -Date: Fri Oct 28 01:26:31 2022 +0100 - - Fix broken zlib link. + This test relies on loopback addresses which minix does not have. + Previously the test would not run at all since it also doesn't have + netcat, but now we use our own netcat it tries and fails. -commit 99500df246ccb736ddbdd04160dcc82165d81a77 -Author: Darren Tucker -Date: Fri Nov 4 16:59:26 2022 +1100 +commit dd1249bd5c45128a908395c61b26996a70f82205 +Author: Damien Miller +Date: Sun Jan 8 12:08:59 2023 +1100 - Don't run openbsd-compat tests on Cygwin. - - Add "compat-tests" to the default TEST_TARGET so we can override as - necessary. Override TEST_TARGET for Cygwin as the tests don't currently - compile there. + don't test IPv6 addresses if platform lacks support -commit 3cae9f92a31897409666aa1e6f696f779759332b -Author: djm@openbsd.org -Date: Thu Nov 3 21:59:20 2022 +0000 +commit d77fc611a62f2dfee0b654c31a50a814b13310dd +Author: dtucker@openbsd.org +Date: Fri Jan 6 12:33:33 2023 +0000 - upstream: replace recently-added valid_domain() check for hostnames + upstream: When OpenSSL is not available, skip parts of percent test - going to known_hosts with a more relaxed check for bad characters; previous - commit broke address literals. Reported by/feedback from florian@ + that require it. Based on github pr#368 from ren mingshuai. - OpenBSD-Commit-ID: 10b86dc6a4b206adaa0c11b58b6d5933898d43e0 - -commit 9655217231c9056200bea7ae2dffcc9c0c3eb265 -Author: Darren Tucker -Date: Thu Nov 3 23:07:50 2022 +1100 - - Rerun tests on changes to Makefile.in in any dir. + OpenBSD-Regress-ID: 49a375b2cf61ccb95b52e75e2e025cd10988ebb2 -commit 3500f0405a3ab16b59a26f3508c4257a3fc3bce6 +commit 1cd2aac312af9172f1b5cb06c2e1cd090abb83cf Author: Darren Tucker -Date: Thu Nov 3 23:04:08 2022 +1100 +Date: Sat Jan 7 23:01:11 2023 +1100 - Link libssh into compat tests. + Use our own netcat for dynamic-forward test. - The cygwin compat code uses xmalloc, so add libssh.a so pick up that. - -commit ec59effcf65b8a4c85d47ff5a271123259dd0ab8 -Author: Darren Tucker -Date: Thu Nov 3 21:44:23 2022 +1100 - - Fix compat regress to work with non-GNU make. + That way we can be surer about its behaviour rather than trying to + second-guess the behaviour of various netcat implementations. -commit 73550a218e7dfbbd599534cbf856309bc924f6fd +commit 26cab41c05d7b0859d2a1ea5b6ed253d91848a80 Author: Darren Tucker -Date: Thu Nov 3 13:41:16 2022 +1100 +Date: Sat Jan 7 14:30:43 2023 +1100 - Increase selfhosted job timeout. + Use autoconf to find openssl binary. - The default job timeout of 360 (6h) is not enough to complete the - regress tests for some of the slow VMs depending on the load on the host. - Increase to 600 (10h). - -commit db97d8d0b90c6ce52b94b153d6f8f5f7d3b11777 -Author: Darren Tucker -Date: Thu Nov 3 10:00:43 2022 +1100 - - Only run opensslver tests if built with OpenSSL. + It's possible to install an OpenSSL in a path not in the system's + default library search path. OpenSSH can still use this (eg if you + specify an rpath) but the openssl binary there may not work. If one is + available on the system path just use that. -commit ba053709638dff2f6603df0c1f340352261d63ea +commit 5532e010a0eeb6aa264396514f9aed7948471538 Author: Darren Tucker -Date: Wed Nov 2 14:16:04 2022 +1100 +Date: Sat Jan 7 10:34:18 2023 +1100 - Add tests for OpenSSL 3.0.7 and LibreSSL 3.6.1. + Check openssl_bin path is executable before using. -commit edd24101c7e17d1a8f6576e1aaf62233b47ad6f5 +commit 5d7b16cff48598d5908db970bfdc9ff9326142c8 Author: Darren Tucker -Date: Thu Nov 3 08:17:39 2022 +1100 +Date: Fri Jan 6 23:19:07 2023 +1100 - Run compat regress tests too. + Set OPENSSL_BIN from OpenSSL directory. -commit fe88d67e7599b0bc73f6e4524add28d743e7f977 -Author: Darren Tucker -Date: Thu Nov 3 08:14:05 2022 +1100 +commit 344a0e8240eaf08da5d46a5e3a9ecad6e4f64c35 +Author: dtucker@openbsd.org +Date: Fri Jan 6 08:50:33 2023 +0000 - Compat tests need libcrypto. + upstream: Save debug logs from ssh for debugging purposes. - This was moved to CHANNELLIBS during the libs refactor. Spotted by - rapier at psc.edu. + OpenBSD-Regress-ID: 109e40b06de1c006a3b8e0d8745b790b2c5870a0 -commit 96b519726b7944eee3c23a54eee3d5c031ba1533 -Author: Darren Tucker -Date: Thu Nov 3 04:24:39 2022 +1100 +commit e1ef172646f7f49c80807eea90225ef5e0be55a8 +Author: djm@openbsd.org +Date: Fri Jan 6 08:07:39 2023 +0000 - Include time.h when defining timegm. + upstream: regression test for ChannelTimeout - Fixes build on some platforms eg recent AIX. + OpenBSD-Regress-ID: 280bfbefcfa415428ad744e43f69a8dede8ad685 -commit da6038bd5cd55eb212eb2aec1fc8ae79bbf76156 -Author: Darren Tucker -Date: Tue Nov 1 19:10:30 2022 +1100 +commit 2393ea8daf25853459eb07a528d7577688847777 +Author: djm@openbsd.org +Date: Fri Jan 6 07:18:18 2023 +0000 - Always use compat getentropy. + upstream: fix typo in verbose logging - Have it call native getentropy and fall back as required. Should fix - issues of platforms where libc has getentropy but it is not implemented - in the kernel. Based on github PR#354 from simsergey. + OpenBSD-Regress-ID: 0497cdb66e003b2f50ed77291a9104fba2e017e9 -commit 5ebe18cab6be3247b44c807ac145164010465b82 -Author: Darren Tucker -Date: Wed Nov 2 10:51:48 2022 +1100 +commit 161a5378a3cc2e7aa3f9674cb7f4686ae6ce9586 +Author: djm@openbsd.org +Date: Fri Jan 6 02:59:50 2023 +0000 - Check for sockaddr_in.sin_len. + upstream: unit tests for misc.c:ptimeout_* API - If found, set SOCK_HAS_LEN which is used in addr.c. Should fix keyscan - tests on platforms with this (eg old NetBSD). + OpenBSD-Regress-ID: 01f8fb12d08e5aaadd4bd4e71f456b6588be9a94 -commit a1febadf426536612c2734168d409147c392e7cf -Author: dtucker@openbsd.org -Date: Sun Oct 30 18:42:07 2022 +0000 +commit 018d671d78145f03d6f07ae9d64d51321da70325 +Author: tb@openbsd.org +Date: Wed Jan 4 22:48:57 2023 +0000 - upstream: Use variable for diff options + upstream: Copy bytes from the_banana[] rather than banana() - instead of unconditionally specifying "-rN". This will make life easier - in -portable where not all diff's understand -N. + Fixes test failure due to segfault seen on arm64 with xonly snap. - OpenBSD-Regress-ID: 8b8a407115546be1c6d72d350b1e4f1f960d3cd3 - -commit f6d3ed9a8a9280cbb68d6a499850cfe810e92bd0 -Author: Darren Tucker -Date: Mon Oct 31 05:13:02 2022 +1100 - - OpenSSL dev branch is 302 not 320. + ok djm - While there, also accept 301 which it shat it was previously. + OpenBSD-Regress-ID: 86e2aa4bbd1dff1bc4ebb2969c0d6474485be046 -commit 25c8a2bbcc10c493d27faea57c42a6bf13fa51f2 -Author: djm@openbsd.org -Date: Fri Oct 28 02:47:04 2022 +0000 +commit ab6bb69e251faa8b24f81b25c72ec0120f20cad4 +Author: Damien Miller +Date: Fri Jan 6 19:13:36 2023 +1100 - upstream: put sshkey_check_rsa_length() back in sshkey.c to unbreak + unbreak scp on NetBSD 4.x - OPENSSL=no builds + e555d5cad5 effectively increased the default copy buffer size for SFTP + transfers. This caused NetBSD 4.x to hang during the "copy local file to + remote file in place" scp.sh regression test. - OpenBSD-Commit-ID: 99eec58abe382ecd14b14043b195ee1babb9cf6e + This puts back the original 32KB copy buffer size until we can properly + figure out why. + + lots of debugging assistance from dtucker@ -commit 1192588546c29ceec10775125f396555ea71850f +commit 2d1ff2b9431393ad99ef496d5e3b9dd0d4f5ac8c Author: djm@openbsd.org -Date: Fri Oct 28 02:29:34 2022 +0000 +Date: Fri Jan 6 02:47:18 2023 +0000 - upstream: allow ssh-keyscan(1) to accept CIDR address ranges, e.g. + upstream: Implement channel inactivity timeouts - ssh-keyscan 192.168.0.0/24 + This adds a sshd_config ChannelTimeouts directive that allows channels that + have not seen traffic in a configurable interval to be automatically closed. + Different timeouts may be applied to session, X11, agent and TCP forwarding + channels. - If a CIDR range is passed, then it will be expanded to all possible - addresses in the range including the all-0s and all-1s addresses. + Note: this only affects channels over an opened SSH connection and not + the connection itself. Most clients close the connection when their channels + go away, with a notable exception being ssh(1) in multiplexing mode. - bz#976 feedback/ok markus@ + ok markus dtucker - OpenBSD-Commit-ID: ce6c5211f936ac0053fd4a2ddb415277931e6c4b - -commit 64af4209309461c79c39eda2d13f9d77816c6398 -Author: Damien Miller -Date: Fri Oct 28 12:54:35 2022 +1100 - - fix merge botch + OpenBSD-Commit-ID: ae8bba3ed9d9f95ff2e2dc8dcadfa36b48e6c0b8 -commit 27267642699342412964aa785b98afd69d952c88 +commit 0e34348d0bc0b1522f75d6212a53d6d1d1367980 Author: djm@openbsd.org -Date: Fri Oct 28 00:44:44 2022 +0000 +Date: Fri Jan 6 02:42:34 2023 +0000 - upstream: refactor sshkey_private_deserialize + upstream: Add channel_set_xtype() - feedback/ok markus@ - - OpenBSD-Commit-ID: f5ca6932fdaf840a5e8250becb38315a29b5fc9f - -commit 2519a7077a9332f70935e5242ba91ee670ed6b87 -Author: djm@openbsd.org -Date: Fri Oct 28 00:44:17 2022 +0000 - - upstream: refactor sshkey_private_serialize_opt() + This sets an "extended" channel type after channel creation (e.g. + "session:subsystem:sftp") that will be used for setting channel inactivity + timeouts. - feedback/ok markus@ + ok markus dtucker - OpenBSD-Commit-ID: 61e0fe989897901294efe7c3b6d670cefaf44cbd + OpenBSD-Commit-ID: 42564aa92345045b4a74300528f960416a15d4ca -commit 11a768adf98371fe4e43f3b06014024c033385d5 +commit ceedf09b2977f3a756c759a6e7eb8f8e9db86a18 Author: djm@openbsd.org -Date: Fri Oct 28 00:43:30 2022 +0000 +Date: Fri Jan 6 02:41:49 2023 +0000 - upstream: refactor certify - - feedback/ok markus@ + upstream: tweak channel ctype names - OpenBSD-Commit-ID: 35d742992e223eaca3537e6fb3d3002c08eed4f6 - -commit 3fbc58bb249d967cc43ebdc554f6781bb73d4a58 -Author: djm@openbsd.org -Date: Fri Oct 28 00:43:08 2022 +0000 - - upstream: refactor sshkey_sign() and sshkey_verify() + These are now used by sshd_config:ChannelTimeouts to specify timeouts by + channel type, so force them all to use a similar format without whitespace. - feedback/ok markus@ + ok dtucker markus - OpenBSD-Commit-ID: 368e662c128c99d05cc043b1308d2b6c71a4d3cc + OpenBSD-Commit-ID: 66834765bb4ae14f96d2bb981ac98a7dae361b65 -commit a1deb6cdbbe6afaab74ecb08fcb62db5739267be +commit c60438158ad4b2f83d8504257aba1be7d0b0bb4b Author: djm@openbsd.org -Date: Fri Oct 28 00:41:52 2022 +0000 +Date: Fri Jan 6 02:39:59 2023 +0000 - upstream: refactor sshkey_from_blob_internal() + upstream: Add channel_force_close() - feedback/ok markus@ + This will forcibly close an open channel by simulating read/write errors, + draining the IO buffers and calling the detach function. - OpenBSD-Commit-ID: 1f46c0cbb8060ee9666a02749594ad6658c8e283 - -commit 7d00799c935271ce89300494c5677190779f6453 -Author: djm@openbsd.org -Date: Fri Oct 28 00:41:17 2022 +0000 - - upstream: refactor sshkey_from_private() + Previously the detach function was only ever called during channel garbage + collection, but there was no way to signal the user of a channel (e.g. + session.c) that its channel was being closed deliberately (vs. by the + usual state-machine logic). So this adds an extra "force" argument to the + channel cleanup callback to indicate this condition. - feedback/ok markus@ + ok markus dtucker - OpenBSD-Commit-ID: e5dbe7a3545930c50f70ee75c867a1e08b382b53 + OpenBSD-Commit-ID: 23052707a42bdc62fda2508636e624afd466324b -commit 262647c2e920492ca57f1b9320d74f4a0f6e482b +commit d478cdc7ad6edd4b1bcd1e86fb2f23194ff33d5a Author: djm@openbsd.org -Date: Fri Oct 28 00:39:29 2022 +0000 +Date: Fri Jan 6 02:38:23 2023 +0000 - upstream: factor out key generation + upstream: replace manual poll/ppoll timeout math with ptimeout API - feedback/ok markus@ + feedback markus / ok markus dtucker - OpenBSD-Commit-ID: 5b4211bff4de8d9adb84bc72857a8c42c44e7ceb + OpenBSD-Commit-ID: c5ec4f2d52684cdb788cd9cbc1bcf89464014be2 -commit 401c74e7dc15eab60540653d2f94d9306a927bab +commit 4adf3817a24efe99b06e62630577d683c7cd8065 Author: djm@openbsd.org -Date: Fri Oct 28 00:38:58 2022 +0000 +Date: Fri Jan 6 02:37:04 2023 +0000 - upstream: refactor and simplify sshkey_read() + upstream: add ptimeout API for keeping track of poll/ppoll - feedback/ok markus@ + timeouts; ok dtucker markus - OpenBSD-Commit-ID: 0d93b7a56e31cd06a8bb0d2191d084ce254b0971 + OpenBSD-Commit-ID: 3335268ca135b3ec15a947547d7cfbb8ff929ead -commit 591fed94e66a016acf87f4b7cd416ce812f2abe8 +commit 8c7c69d32375d2f3ce9da0109c9bffc560842316 Author: djm@openbsd.org -Date: Fri Oct 28 00:37:24 2022 +0000 +Date: Thu Jan 5 05:49:13 2023 +0000 - upstream: factor out public key serialization - - feedback/ok markus@ + upstream: suppress "Connection closed" message when in quiet mode - OpenBSD-Commit-ID: a3570c4b97290c5662890aea7328d87f55939033 + OpenBSD-Commit-ID: 8a3ab7176764da55f60bfacfeae9b82d84e3908f -commit 1e78844ae2b2dc01ba735d5ae740904c57e13685 +commit 845ceecea2ac311b0c267f9ecbd34862e1876fc6 Author: djm@openbsd.org -Date: Fri Oct 28 00:36:31 2022 +0000 +Date: Mon Jan 2 07:03:57 2023 +0000 - upstream: factor out sshkey_equal_public() - - feedback/ok markus@ + upstream: regression test for PermitRemoteOpen - OpenBSD-Commit-ID: 1368ba114cb37732fe6ec3d89c7e6d27ea6fdc94 + OpenBSD-Regress-ID: 8271aafbf5c21950cd5bf966f08e585cebfe630c -commit 25de1c01a8b9a2c8ab9b1da22444a03e89c982de +commit b3daa8dc582348d6ab8150bc1e571b7aa08c5388 Author: djm@openbsd.org -Date: Fri Oct 28 00:35:40 2022 +0000 +Date: Mon Jan 2 07:03:30 2023 +0000 - upstream: begin big refactor of sshkey + upstream: fix bug in PermitRemoteOpen which caused it to ignore its - Move keytype data and some of the type-specific code (allocation, - cleanup, etc) out into each key type's implementation. Subsequent - commits will move more, with the goal of having each key-*.c file - owning as much of its keytype's implementation as possible. + first argument unless it was one of the special keywords "any" or "none". - lots of feedback + ok markus@ + Reported by Georges Chaudy in bz3515; ok dtucker@ - OpenBSD-Commit-ID: 0f2b4334f73914344e9e5b3d33522d41762a57ec + OpenBSD-Commit-ID: c5678a39f1ff79993d5ae3cfac5746a4ae148ea5 -commit 445363433ba20b8a3e655b113858c836da46a1cb -Author: djm@openbsd.org -Date: Mon Oct 24 22:43:36 2022 +0000 +commit 0872663a7be0301bcc3d49acdbc9b740a3d972d4 +Author: jmc@openbsd.org +Date: Mon Dec 26 19:16:03 2022 +0000 - upstream: Be more paranoid with host/domain names coming from the - - never write a name with bad characters to a known_hosts file. + upstream: spelling fixes; from paul tagliamonte amendments to his - reported by David Leadbeater, ok deraadt@ + diff are noted on tech - OpenBSD-Commit-ID: ba9b25fa8b5490b49398471e0c9657b0cbc7a5ad + OpenBSD-Commit-ID: d776dd03d0b882ca9c83b84f6b384f6f9bd7de4a -commit 7190154de2c9fe135f0cc1ad349cb2fa45152b89 +commit 797da2812a71785b34890bb6eb44767a7d09cd34 Author: djm@openbsd.org -Date: Mon Oct 24 21:52:50 2022 +0000 +Date: Fri Dec 16 07:13:22 2022 +0000 - upstream: regress test for unmatched glob characters; fails before + upstream: Mention that scp uses the SFTP protocol and remove - previous commit but passes now. bz3488; prodded by dtucker@ + reference to legacy flag. Spotted by, feedback and ok jmc@ - OpenBSD-Regress-ID: 0cc5cc9ea4a6fd170dc61b9212f15badaafb3bbd + OpenBSD-Commit-ID: 9dfe04966f52e941966b46c7a2972147f95281b3 -commit a4821a592456c3add3cd325db433110cdaaa3e5c +commit 93f2ce8c050a7a2a628646c00b40b9b53fef93ef Author: djm@openbsd.org -Date: Mon Oct 24 21:51:55 2022 +0000 +Date: Fri Dec 16 06:56:47 2022 +0000 - upstream: when scp(1) is using the SFTP protocol for transport (the + upstream: Clear signal mask early in main(); sshd may have been - default), better match scp/rcp's handling of globs that don't match the - globbed characters but do match literally (e.g. trying to transfer - "foo.[1]"). + started with one or more signals masked (sigprocmask(2) is not cleared + on fork/exec) and this could interfere with various things, e.g. the + login grace timer. - Previously scp(1) in SFTP mode would not match these pathnames but - legacy scp/rcp mode would. + Execution environments that fail to clear the signal mask before running + sshd are clearly broken, but apparently they do exist. - Reported by Michael Yagliyan in bz3488; ok dtucker@ + Reported by Sreedhar Balasubramanian; ok dtucker@ - OpenBSD-Commit-ID: d8a3773f53015ba811fddba7473769a2fd343e11 + OpenBSD-Commit-ID: 77078c0b1c53c780269fc0c416f121d05e3010ae -commit 18376847b8043ba967eabbe23692ef74c9a3fddc -Author: jsg@openbsd.org -Date: Thu Oct 13 09:09:28 2022 +0000 +commit 4acfaabfae41badb9d334a2ee88c5c6ad041c0d5 +Author: jmc@openbsd.org +Date: Fri Dec 16 06:52:48 2022 +0000 - upstream: use correct type with sizeof ok djm@ + upstream: add -X to usage(); - OpenBSD-Commit-ID: d6c882c2e8a42ff831a5b3cbc2c961ecb2dd6143 + OpenBSD-Commit-ID: 1bdc3df7de11d766587b0428318336dbffe4a9d0 -commit 4a4883664d6b4e9e4e459a8cdc16bd8d4b735de9 -Author: jmc@openbsd.org -Date: Fri Oct 7 06:00:58 2022 +0000 +commit e555d5cad5afae7d5ef2bbc02ca591178fe16fed +Author: djm@openbsd.org +Date: Fri Dec 16 03:40:03 2022 +0000 - upstream: ssh-agent.1: - use Nm not Xr for self-ref - while here, + upstream: add a -X option to both scp(1) and sftp(1) to allow - wrap a long line + control over some SFTP protocol knobs: the copy buffer length and + the number of inflight requests, both of which are used during + upload/download. - ssh-agent.c: - - add -O to usage() + Previously these could be controlled in sftp(1) using the -b/-R options. + This makes them available in both SFTP protocol clients using the same + option character sequence. - OpenBSD-Commit-ID: 855dac4695cef22e96d69c53436496bc408ca389 + ok dtucker@ + + OpenBSD-Commit-ID: 27502bffc589776f5da1f31df8cb51abe9a15f1c -commit 9fd2441113fce2a83fc7470968c3b27809cc7f10 -Author: djm@openbsd.org -Date: Fri Oct 7 04:06:26 2022 +0000 +commit 5a7a7acab2f466dc1d7467b5d05d35268c3137aa +Author: deraadt@openbsd.org +Date: Thu Dec 15 18:20:39 2022 +0000 - upstream: document "-O no-restrict-websafe"; spotted by Ross L + upstream: The idiomatic way of coping with signed char vs unsigned - Richardson + char (which did not come from stdio read functions) in the presence of + ctype macros, is to always cast to (unsigned char). casting to (int) + for a "macro" which is documented to take int, is weird. And sadly wrong, + because of the sing extension risk.. same diff from florian - OpenBSD-Commit-ID: fe9eaa50237693a14ebe5b5614bf32a02145fe8b + OpenBSD-Commit-ID: 65b9a49a68e22ff3a0ebd593f363e9f22dd73fea -commit 614252b05d70f798a0929b1cd3d213030ad4d007 +commit b0b58222c7cc62efd8212c4fb65a545f58ebb22d Author: Darren Tucker -Date: Tue Oct 18 06:29:16 2022 +1100 +Date: Mon Dec 19 18:49:51 2022 +1100 - OpenSSL dev branch now identifies as 3.2.0. + Simply handling of SSH_CONNECTION PAM env var. + + Prompted by bz#3508: there's no need to cache the value of + sshpam_conninfo so remove the global. While there, add check of + return value from pam_putenv. ok djm@ -commit 195e5a65fd793a738ea8451ebfdd1919db5aff3e -Author: Damien Miller -Date: Mon Oct 17 09:41:47 2022 +1100 +commit ed8444572ae684fdb892f97bae342c6cb6456f04 +Author: Darren Tucker +Date: Mon Dec 19 18:42:34 2022 +1100 - revert c64b62338b4 and guard POLL* defines instead - - c64b62338b4 broke OSX builds, which do have poll.h but lack ppoll(2) - Spotted by dtucker + Add tests for LibreSSL 3.7.0 and OpenSSL 1.1.1s. -commit bc2e480d99613bd59720edae244d1764636544c4 -Author: Damien Miller -Date: Fri Oct 14 14:52:22 2022 +1100 +commit abb9a8aaddfcacbd12641f6e4f203da0fa85a287 +Author: Darren Tucker +Date: Sun Dec 18 21:36:25 2022 +1100 - undef _get{short,long} before redefining + Use sudo when resetting perms on directories. -commit 5eb796a369c64f18d55a6ae9b1fa9b35eea237fb -Author: Harmen Stoppels -Date: Thu Oct 13 16:08:46 2022 +0200 +commit 2f5664c5908d84697cbe91302d5d5c4d83cb2121 +Author: Darren Tucker +Date: Sun Dec 18 21:19:33 2022 +1100 - Fix snprintf configure test for clang 15 + Set group perms on regress dir. - Clang 15 -Wimplicit-int defaults to an error in C99 mode and above. - A handful of tests have "main(..." and not "int main(..." which caused - the tests to produce incorrect results. + This ensures that the tests don't fail due to StrictMode checks. -commit c64b62338b46ffa08839f05f21ad69fa6234dc17 -Author: Damien Miller -Date: Mon Oct 10 12:32:43 2022 +1100 +commit 137196300fc1540affadde880210f02ba6cb4abf +Author: Darren Tucker +Date: Sun Dec 18 21:13:42 2022 +1100 - skip bsd-poll.h if poll.h found; ok dtucker + Fetch regress logs from obj dir. -commit 5ee2b8ccfcf4b606f450eb0ff2305e311f68b0be -Author: djm@openbsd.org -Date: Thu Oct 6 22:42:37 2022 +0000 +commit 5f93c4836527d9fda05de8944a1c7b4a205080c7 +Author: Darren Tucker +Date: Tue Dec 13 20:59:54 2022 +1100 - upstream: honour user's umask if it is more restrictive then the ssh - - default (022); based on patch from Alex Henrie, ok dtucker@ deraadt@ - - OpenBSD-Commit-ID: fe1b9e15fc9a4f49fc338e848ce14d8727abe82d + obsdsnap test VMs runs-on libvirt too. -commit a75cffc2700cebd3e2dd9093f7f7388d2be95cb7 +commit 8386886fb1ab7fda73069fb0db1dbe0e5a52f758 Author: Darren Tucker -Date: Fri Oct 7 03:54:56 2022 +1100 +Date: Tue Dec 13 20:55:37 2022 +1100 - Add LibreSSL 3.6.0 to test suite. - - While there, bump OpenSSL to latest 1.1.1q release. + Run upstream obsdsnap tests on ephemeral runners. -commit fcc0f0c0e96a30076683fea9a7c9eedc72931742 +commit b6e01459b55ece85d7f296b2bc719d1841e1009e Author: Darren Tucker -Date: Thu Oct 6 21:18:16 2022 +1100 +Date: Tue Dec 13 20:48:56 2022 +1100 - Add 9.1 branch to CI status page. + Move obsdsnap test VMs to ephemeral runners. -commit ef211eee63821d894a8bf81f22bfba9f6899d0fe -Author: Darren Tucker -Date: Tue Oct 4 23:20:23 2022 +1100 +commit ea6fdf9a1aa71a411f7db218a986392c4fb55693 +Author: Damien Miller +Date: Fri Dec 9 18:00:21 2022 +1100 - Test commits to all branches of portable. + use calloc for allocating arc4random structs - Only test OpenBSD upstream on commits to master since that's what it - tracks. + ok dtucker -commit fe646de03cafb6593ff4e4954bca9ec4b4b753a8 -Author: Damien Miller -Date: Wed Oct 5 03:47:26 2022 +1100 +commit 4403b62f5548e91389cb3339d26a9d0c4bb07b34 +Author: dtucker@openbsd.org +Date: Fri Dec 9 00:22:29 2022 +0000 - whitespace at EOL + upstream: Warn if no host keys for hostbased auth can be loaded. + + OpenBSD-Commit-ID: 2a0a13132000cf8d3593133c1b49768aa3c95977 -commit a6e1852d10c63a830196e82168dadd957aaf28ec -Author: Damien Miller -Date: Wed Oct 5 03:40:01 2022 +1100 +commit a6183e25e3f1842e21999fe88bc40bb99b121dc3 +Author: dtucker@openbsd.org +Date: Fri Dec 9 00:17:40 2022 +0000 - mention libfido2 autodetection + upstream: Add server debugging for hostbased auth. + + auth_debug_add queues messages about the auth process which is sent to + the client after successful authentication. This also sends those to + the server debug log to aid in debugging. From bz#3507, ok djm@ + + OpenBSD-Commit-ID: 46ff67518cccf9caf47e06393e2a121ee5aa258a -commit 7360c2c206f33d309edbaf64036c96fadf74d640 -Author: Damien Miller -Date: Wed Oct 5 03:37:36 2022 +1100 +commit b85c3581c16aaf6e83b9a797c80705a56b1f312e +Author: cheloha@openbsd.org +Date: Sun Dec 4 23:50:49 2022 +0000 - remove mention of --with-security-key-builtin + upstream: remove '?' from getopt(3) loops - it is enabled by default when libfido2 is installed + userspace: remove vestigial '?' cases from top-level getopt(3) loops + + getopt(3) returns '?' when it encounters a flag not present in the in + the optstring or if a flag is missing its option argument. We can + handle this case with the "default" failure case with no loss of + legibility. Hence, remove all the redundant "case '?':" lines. + + Prompted by dlg@. With help from dlg@ and millert@. + + Link: https://marc.info/?l=openbsd-tech&m=167011979726449&w=2 + + ok naddy@ millert@ dlg@ + + OpenBSD-Commit-ID: b2f89346538ce4f5b33ab8011a23e0626a67e66e -commit 0ffb46f2ee2ffcc4daf45ee679e484da8fcf338c -Author: Damien Miller -Date: Tue Oct 4 01:51:42 2022 +1100 +commit 9a067e8d28a2249fd73f004961e30c113ee85e5d +Author: dtucker@openbsd.org +Date: Wed Dec 7 11:45:43 2022 +0000 - update .depend + upstream: Fix comment typo. + + OpenBSD-Regress-ID: 3b04faced6511bb5e74648c6a4ef4bf2c4decf03 -commit 657e676ff696c7bb787bffb0e249ea1be3b474e1 -Author: Damien Miller -Date: Tue Oct 4 01:45:52 2022 +1100 +commit ce3c3e78ce45d68a82c7c8dc89895f297a67f225 +Author: Darren Tucker +Date: Wed Dec 7 18:58:25 2022 +1100 - update release notes URL + Add SANDBOX_DEBUG to the kitchensink test build. -commit f059da2b29840c0f048448809c317ce2ae014da7 +commit bc234605fa3eb10f56bf0d74c8ecb0d91ada9d05 Author: Damien Miller -Date: Tue Oct 4 01:45:41 2022 +1100 +Date: Wed Dec 7 18:38:25 2022 +1100 - crank versions in RPM spec files + disable SANDBOX_SECCOMP_FILTER_DEBUG + + It was mistakenly enabled in 2580916e4872 + + Reported by Peter sec-openssh-com.22.fichtner AT 0sg.net -commit b51f3f172d87cbdb80ca4eb7b2149e56a7647557 -Author: djm@openbsd.org -Date: Mon Sep 26 22:18:40 2022 +0000 +commit b087c5cfa011b27992e01589314fec830266f99d +Author: Rose <83477269+AtariDreams@users.noreply.github.com> +Date: Tue Nov 29 15:12:54 2022 -0500 - upstream: openssh-9.1 + Update autotools - OpenBSD-Commit-ID: 5a467b2ee81da01a86adf1ad93b62b1728494e56 + Regenerate config files using latest autotools -commit 4cf8d0c0f3030f594a238bab21a0695735515487 +commit d63f5494978a185c7421d492b9c2f6f05bb54138 +Author: Darren Tucker +Date: Tue Dec 6 12:22:36 2022 +1100 + + Fix typo in comment. Spotted by tim@ + +commit 73dcca12115aa12ed0d123b914d473c384e52651 Author: dtucker@openbsd.org -Date: Wed Sep 21 22:26:50 2022 +0000 +Date: Sun Dec 4 11:03:11 2022 +0000 - upstream: Fix typo. From AlexanderStohr via github PR#343. + upstream: Remove duplicate includes. - OpenBSD-Commit-ID: a134c9b4039e48803fc6a87f955b0f4a03181497 + Patch from AtariDreams via github PR#364. + + OpenBSD-Commit-ID: b9186638a05cb8b56ef7c0de521922b6723644ea -commit 8179fed3264d5919899900ed8881d5f9bb57ca33 +commit 3cec15543010bc8d6997d896b1717a650afb7e92 Author: djm@openbsd.org -Date: Mon Sep 19 21:39:16 2022 +0000 +Date: Fri Dec 2 04:40:27 2022 +0000 - upstream: add RequiredRSASize to the list of keywords accepted by + upstream: make struct sshbuf private - -o; spotted by jmc@ + and remove an unused field; ok dtucker - OpenBSD-Commit-ID: fe871408cf6f9d3699afeda876f8adbac86a035e + OpenBSD-Commit-ID: c7a3d77c0b8c153d463398606a8d57569186a0c3 -commit 5f954929e9f173dd1e279e07d0e8b14fa845814d -Author: Damien Miller -Date: Mon Sep 19 20:59:34 2022 +1000 +commit 5796bf8ca9535f9fa7d01829a540d2550e05c860 +Author: Darren Tucker +Date: Fri Dec 2 11:43:36 2022 +1100 - no need for glob.h here + Restore ssh-agent permissions on exit. - it also causes portability problems + ...enough that subsequent builds can overwrite ssh-agent if necessary. -commit 03d94a47207d58b3db37eba4f87eb6ae5a63168a -Author: Damien Miller -Date: Mon Sep 19 20:59:04 2022 +1000 +commit ccf5a13868cbb4659107458cac1e017c98abcbda +Author: dtucker@openbsd.org +Date: Thu Dec 1 02:22:13 2022 +0000 - avoid Wuninitialized false positive in gcc-12ish + upstream: Clean up ssh-add and ssh-agent logs. + + OpenBSD-Regress-ID: 9eda8e4c3714d7f943ab2e73ed58a233bd29cd2c -commit 9d952529113831fb3071ab6e408d2726fd72e771 -Author: djm@openbsd.org -Date: Mon Sep 19 10:46:00 2022 +0000 +commit 7a8b40cf6a5eda80173140cc6750a6db8412fa87 +Author: dtucker@openbsd.org +Date: Thu Dec 1 02:19:29 2022 +0000 - upstream: use users-groups-by-id@openssh.com sftp-server extension + upstream: Log output of ssh-agent and ssh-add - (when available) to fill in user/group names for directory listings. - Implement a client-side cache of see uid/gid=>user/group names. ok markus@ + This should make debugging easier. - OpenBSD-Commit-ID: f239aeeadfa925a37ceee36ee8b256b8ccf4466e + OpenBSD-Regress-ID: 5974b02651f428d7e1079b41304c498ca7e306c8 -commit 8ff680368b0bccf88ae85d4c99de69387fbad7a6 -Author: djm@openbsd.org -Date: Mon Sep 19 10:43:12 2022 +0000 +commit 4a1805d532616233dd6072e5cd273b96dd3062e6 +Author: dtucker@openbsd.org +Date: Tue Nov 29 22:41:14 2022 +0000 - upstream: sftp client library support for - - users-groups-by-id@openssh.com; ok markus@ + upstream: Add void to client_repledge args to fix compiler warning. ok djm@ - OpenBSD-Commit-ID: ddb2f33a2da6349a9a89a8b5bcb9ca7c999394de + OpenBSD-Commit-ID: 7e964a641ce4a0a0a11f047953b29929d7a4b866 -commit 488f6e1c582212c2374a4bf8cd1b703d2e70fb8b +commit 815c4704930aa449edf6e812e99d69e9ffd31f01 Author: djm@openbsd.org -Date: Mon Sep 19 10:41:58 2022 +0000 +Date: Mon Nov 28 01:38:22 2022 +0000 - upstream: extend sftp-common.c:extend ls_file() to support supplied + upstream: tighten pledge(2) after session establishment - user/group names; ok markus@ + feedback, ok & testing in snaps deraadt@ - OpenBSD-Commit-ID: c70c70498b1fdcf158531117e405b6245863bfb0 + OpenBSD-Commit-ID: aecf4d49d28586dfbcc74328d9333398fef9eb58 -commit 74b77f7497dba3a58315c8f308883de448078057 +commit f7cebbbf407d772ed71403d314343766782fe540 Author: djm@openbsd.org -Date: Mon Sep 19 10:40:52 2022 +0000 +Date: Mon Nov 28 01:37:36 2022 +0000 - upstream: sftp-server(8): add a "users-groups-by-id@openssh.com" - - extension request that allows the client to obtain user/group names that - correspond to a set of uids/gids. + upstream: New EnableEscapeCommandline ssh_config(5) option - Will be used to make directory listings more useful and consistent - in sftp(1). + This option (default "no") controls whether the ~C escape is available. + Turning it off by default means we will soon be able to use a stricter + default pledge(2) in the client. - ok markus@ + feedback deraadt@ dtucker@; tested in snaps for a while - OpenBSD-Commit-ID: 7ebabde0bcb95ef949c4840fe89e697e30df47d3 + OpenBSD-Commit-ID: 7e277595d60acb8263118dcb66554472257b387a -commit 231a346c0c67cc7ca098360f9a554fa7d4f1eddb -Author: djm@openbsd.org -Date: Mon Sep 19 08:49:50 2022 +0000 +commit d323f7ecf52e3d4ec1f4939bf31693e02f891dca +Author: mbuhl@openbsd.org +Date: Fri Nov 18 19:47:40 2022 +0000 - upstream: better debugging for connect_next() + upstream: In channel_request_remote_forwarding the parameters for - OpenBSD-Commit-ID: d16a307a0711499c971807f324484ed3a6036640 + permission_set_add are leaked as they are also duplicated in the call. Found + by CodeChecker. ok djm + + OpenBSD-Commit-ID: 4aef50fa9be7c0b138188814c8fe3dccc196f61e -commit 1875042c52a3b950ae5963c9ca3774a4cc7f0380 -Author: djm@openbsd.org -Date: Sat Sep 17 10:34:29 2022 +0000 +commit 62cc33e6eed847aafdc29e34aa69e9bd82a0ee16 +Author: Darren Tucker +Date: Wed Nov 30 11:23:11 2022 +1100 - upstream: Add RequiredRSASize for sshd(8); RSA keys that fall - - beneath this limit will be ignored for user and host-based authentication. + Use -fzero-call-used-regs=used on clang 15. - Feedback deraadt@ ok markus@ + clang 15 seems to have a problem with -fzero-call-used-reg=all which + causes spurious "incorrect signature" failures with ED25519. On those + versions, use -fzero-call-used-regs=used instead. (We may add exceptions + later if specific versions prove to be OK). Also move the GCC version + check to match. - OpenBSD-Commit-ID: 187931dfc19d51873df5930a04f2d972adf1f7f1 + Initial investigation by Daniel Pouzzner (douzzer at mega nu), workaround + suggested by Bill Wendling (morbo at google com). bz#3475, ok djm@ -commit 54b333d12e55e6560b328c737d514ff3511f1afd -Author: djm@openbsd.org -Date: Sat Sep 17 10:33:18 2022 +0000 +commit f84b9cffd52c9c5c359a54a1929f9948e803ab1d +Author: Darren Tucker +Date: Mon Nov 28 21:09:28 2022 +1100 - upstream: add a RequiredRSASize for checking RSA key length in + Skip unit tests on slow riscv64 hardware. + +commit 9f2747e0bed3faca92679eae69aef10c95dc82f5 +Author: Darren Tucker +Date: Sun Nov 27 15:26:22 2022 +1100 + + Rework how selfhosted tests interact with runners. - ssh(1). User authentication keys that fall beneath this limit will be - ignored. If a host presents a host key beneath this limit then the connection - will be terminated (unfortunately there are no fallbacks in the protocol for - host authentication). + Previously there was one runner per test target (mostly VMs). This had + a few limitations: + - multiple tests that ran on the same target (eg multiple build + configs) were serialized on availability or that runner. + - it needed manual balancing of VMs over host machines. - feedback deraadt, Dmitry Belyavskiy; ok markus@ + To address this, make VMs that use ephemeral disks (ie most of them) + all use a pool of runners with the "libvirt" label. This requires that + we distinguish between "host" and "target" for those. Native runners + and VMs with persistent disks (eg the constantly-updated snapshot ones) + specify the same host and target. - OpenBSD-Commit-ID: 430e339b2a79fa9ecc63f2837b06fdd88a7da13a + This should improve test throughput. -commit 07d8771bacfefbcfb37fa8a6dc6103bcc097e0ab -Author: djm@openbsd.org -Date: Sat Sep 17 10:30:45 2022 +0000 +commit d664ddaec87bdc7385be8ef7f1337793e1679d48 +Author: Darren Tucker +Date: Sun Nov 27 12:19:37 2022 +1100 - upstream: Add a sshkey_check_rsa_length() call for checking the + Run vmstartup from temp dir. - length of an RSA key; ok markus@ + This will allow us to create ephemeral disk images per-runner. + +commit 0fa16e952b1fc1c4cf65e3dd138b0e87003e2e45 +Author: Darren Tucker +Date: Sun Nov 27 12:14:00 2022 +1100 + + Make "config" in matrix singular and pass in env. - OpenBSD-Commit-ID: de77cd5b11594297eda82edc594b0d32b8535134 + This will allow the startup scripts to adapt their behaviour based on + the type and config. -commit 3991a0cf947cf3ae0f0373bcec5a90e86a7152f5 -Author: djm@openbsd.org -Date: Sat Sep 17 10:11:29 2022 +0000 +commit e8857043af54809187be1e8b06749db61112899f +Author: Darren Tucker +Date: Sun Nov 27 11:42:22 2022 +1100 - upstream: actually hook up restrict_websafe; the command-line flag + Add "libvirt" label to dfly30. + +commit 9775473d84902dc37753686cd10ae71fbe67efda +Author: Darren Tucker +Date: Sun Nov 27 09:28:20 2022 +1100 + + Rename "os" in matrix to "target". - was never actually used. Spotted by Matthew Garrett + This is in preparation to distinguish this from the host that the runner + runs on in case where they are separate (eg VMs). + +commit 04fd00ceff39f4544ced6f5342060abe584835d0 +Author: Darren Tucker +Date: Sun Nov 27 09:23:04 2022 +1100 + + Remove unused self-hosted test targets. + +commit c9d9fcad2a11c1cd1550a541f44091d65f0b5584 +Author: Darren Tucker +Date: Sun Nov 27 09:16:15 2022 +1100 + + Remove explicit "default" test config argument. - OpenBSD-Commit-ID: 0b363518ac4c2819dbaa3dfad4028633ab9cdff1 + Not specifying the test config implicitly selects default args. -commit 30b2a7e4291fb9e357f80a237931ff008d686d3b +commit 15a01cf15f396f87c6d221c5a6af98331c818962 +Author: Darren Tucker +Date: Wed Nov 23 13:18:54 2022 +1100 + + Add fallback for old platforms w/out MAP_ANON. + +commit 6b9bbbfe8b26db6e9a30a7e08c223e85421aed98 +Author: Darren Tucker +Date: Wed Nov 23 13:09:11 2022 +1100 + + If we haven't found it yet, recheck for sys/stat.h. + + On some very old platforms, sys/stat.h needs sys/types.h, however + autoconf 2.71's AC_CHECK_INCLUDES_DEFAULT checks for them in the + opposite order, which in combination with modern autoconf's + "present but cannot be compiled" behaviour causes it to not be + detected. + +commit 8926956f22639132a9f2433fcd25224e01b900f5 +Author: Darren Tucker +Date: Fri Nov 11 11:25:37 2022 +1100 + + Add dfly62 test target. + +commit 650de7ecd3567b5a5dbf16dd1eb598bd8c20bca8 +Author: dtucker@openbsd.org +Date: Thu Nov 10 23:03:10 2022 +0000 + + upstream: Handle dynamic remote port forwarding in escape commandline's + + -R processing. bz#3499, ok djm@ + + OpenBSD-Commit-ID: 194ee4cfe7ed0e2b8ad0727f493c798a50454208 + +commit 5372db7e7985ba2c00f20fdff8942145ca99e033 +Author: Darren Tucker +Date: Thu Nov 10 12:44:51 2022 +1100 + + Remove seed passing over reexec. + + This was added for the benefit of platforms using ssh-rand-helper to + prevent a delay on each connection as sshd reseeded itself. + + ssh-random-helper is long gone, and since the re-exec happens before the + chroot the re-execed sshd can reseed itself normally. ok djm@ + +commit ca98d3f8c64cfc51af81e1b01c36a919d5947ec2 +Author: Darren Tucker +Date: Wed Nov 9 20:59:20 2022 +1100 + + Skip reexec test on OpenSSL 1.1.1 specifically. + + OpenSSL 1.1.1 has a bug in its RNG that breaks reexec fallback, so skip + that test. See bz#3483 for details. + +commit 5ec4ebc2548e5f7f1b55b2a5cef5b67bdca8146f +Author: dtucker@openbsd.org +Date: Wed Nov 9 09:04:12 2022 +0000 + + upstream: Fix typo in fatal error message. + + Patch from vapier at chromium.org. + + OpenBSD-Commit-ID: 8a0c164a6a25eef0eedfc30df95bfa27644e35cf + +commit e6abafe9a6d809422d3432b95b3f9747b0acaa71 +Author: dtucker@openbsd.org +Date: Wed Nov 9 09:01:52 2022 +0000 + + upstream: Remove errant colon and simplify format + + string in error messages. Patch from vapier at chromium.org. + + OpenBSD-Commit-ID: fc28466ebc7b74e0072331947a89bdd239c160d3 + +commit db2027a687516f87c3fb141e87154bb3d8a7807c Author: djm@openbsd.org -Date: Fri Sep 16 06:55:37 2022 +0000 +Date: Wed Nov 9 01:37:44 2022 +0000 - upstream: correct error value + upstream: rename client_global_hostkeys_private_confirm() to - OpenBSD-Commit-ID: 780efcbad76281f11f14b2a5ff04eb6db3dfdad4 + client_global_hostkeys_prove_confirm(), as it handles the + "hostkeys-prove00@openssh.com" message; no functional change + + OpenBSD-Commit-ID: 31e09bd3cca6eed26855b88fb8beed18e9bd026d -commit ac1ec9545947d9f9657259f55d04cb49d3a94c8a +commit 1c2be7c2004cf1abcd172fee9fe3eab57cd4c426 Author: djm@openbsd.org -Date: Fri Sep 16 03:33:14 2022 +0000 +Date: Wed Nov 9 00:15:59 2022 +0000 - upstream: sftp: Be a bit more clever about completions + upstream: typo in comment - There are commands (e.g. "get" or "put") that accept two - arguments, a local path and a remote path. However, the way - current completion is written doesn't take this distinction into - account and always completes remote or local paths. + OpenBSD-Commit-ID: 39c58f41e0f32d1ff31731fa6f5bbbc3ad25084a + +commit cf1a9852d7fc93e4abc4168aed09529a57427cdc +Author: Darren Tucker +Date: Wed Nov 9 09:23:47 2022 +1100 + + Defer seed_rng until after closefrom call. - By expanding CMD struct and "cmds" array this distinction can be - reflected and with small adjustment to completer code the correct - path can be completed. + seed_rng will initialize OpenSSL, and some engine providers (eg Intel's + QAT) will open descriptors for their own use. bz#3483, patch from + joel.d.schuetze at intel.com, ok djm@ + +commit dffa64480163fbf76af7e4fb62c26bb0dd6642aa +Author: Darren Tucker +Date: Wed Nov 9 08:27:47 2022 +1100 + + Fix comment text. From emaste at freebsd.org. + +commit d9df5689c29823ab830ec4f54c83c6cc3c0077ad +Author: Pierre Ossman +Date: Wed Jul 6 13:52:10 2022 +0200 + + Avoid assuming layout of fd_set - By Michal Privoznik, ok dtucker@ + POSIX doesn't specify the internal layout of the fd_set object, so let's + not assume it is just a bit mask. This increases compatibility with + systems that have a different layout. - OpenBSD-Commit-ID: 1396d921c4eb1befd531f5c4a8ab47e7a74b610b + The assumption is also worthless as we already refuse to use file + descriptors over FD_SETSIZE anyway. Meaning that the default size of + fd_set is quite sufficient. -commit 590db83384f9d99fc51c84505792d26d1ef60df9 +commit 419aa8a312e8d8f491933ca3d5933e602cb05aae +Author: Darren Tucker +Date: Tue Nov 8 12:42:52 2022 +1100 + + Shutdown any VM before trying to check out repo. + + In the case where the previous run did not clean up, the checkout will + fail as it'll leave a stale mount. + +commit a32c07cbb78f65d8527642b96474a83b413f8108 +Author: Darren Tucker +Date: Tue Nov 8 11:33:25 2022 +1100 + + Run vm startup and shutdown from runner temp dir. + + Should work even if the github workspace dir is on a stale sshfs mount. + +commit 2b40a7dfcdb8e616155b9504145aa52b271455aa +Author: Darren Tucker +Date: Tue Nov 8 11:03:31 2022 +1100 + + Add valrind-5 test here too. + +commit 2ea03d1f6d0a05ee2b63ed2dc0f2d54f1e4655a1 +Author: Darren Tucker +Date: Tue Nov 8 09:21:10 2022 +1100 + + Update checkout and upload actions. + + Update actions/checkout and actions/upload-artifact to main branch for + compatibility with node.js v16. + +commit 4e316ff0f18a118232bb9ac6512ee62773a9e8ea +Author: Darren Tucker +Date: Tue Nov 8 09:17:04 2022 +1100 + + Split out rekey test since it runs the longest. + +commit 21625a6424258a92a96a3bb73ae6aabc5ed8a6b4 +Author: dtucker@openbsd.org +Date: Mon Nov 7 10:09:28 2022 +0000 + + upstream: The IdentityFile option in ssh_config can also be used to + + specify a public key file, as documented in ssh.1 for the -i option. Document + this also for IdentityFile in ssh_config.5, for documentation completeness. + From laalsaas at systemli.org via portable github PR#352, ok jmc@ djm@ + + OpenBSD-Commit-ID: 2f943be9f96e60ef81a9a4faa25b009999f9883b + +commit 747691604d3325ed2b62bad85b6fd8563ad32f6c +Author: dtucker@openbsd.org +Date: Mon Nov 7 10:05:38 2022 +0000 + + upstream: Remove some set but otherwise unused variables, spotted + + in -portable by clang 16's -Wunused-but-set-variable. ok djm@ + + OpenBSD-Commit-ID: 3d943ddf2369b38fbf89f5f19728e7dc1daf3982 + +commit 1d78d25653805aefc7a8dd9d86cd7359ada3823c +Author: dtucker@openbsd.org +Date: Mon Nov 7 10:02:59 2022 +0000 + + upstream: Check for and disallow MaxStartups values less than or + + equal to zero during config parsing, rather than faling later at runtime. + bz#3489, ok djm@ + + OpenBSD-Commit-ID: d79c2b7a8601eb9be493629a91245d761154308b + +commit a00f59a645072e5f5a8d207af15916a7b23e2642 Author: djm@openbsd.org -Date: Fri Sep 16 03:13:34 2022 +0000 +Date: Mon Nov 7 04:04:40 2022 +0000 - upstream: sftp: Don't attempt to complete arguments for + upstream: fix parsing of hex cert expiry time; was checking whether the - non-existent commands + start time began with "0x", not the expiry time. - If user entered a non-existent command (e.g. because they made a - typo) there is no point in trying to complete its arguments. Skip - calling complete_match() if that's the case. + from Ed Maste - From Michal Privoznik + OpenBSD-Commit-ID: 6269242c3e1a130b47c92cfca4d661df15f05739 + +commit f58acaf8c7315483f4ac87d46a1aa2142a713cd8 +Author: Darren Tucker +Date: Mon Nov 7 15:10:59 2022 +1100 + + Fix merge conflict. + +commit 162e5741020a8d996c0c12b988b118e71ed728e6 +Author: Darren Tucker +Date: Mon Nov 7 15:04:33 2022 +1100 + + Branch-specific links for master status badges. + +commit e4b7c12ab24579312aa3ed38ce7041a439ec2d56 +Author: Darren Tucker +Date: Mon Nov 7 14:46:38 2022 +1100 + + Add CIFuzz status badge. + +commit b496b9f831acd1e5bcd875e26e797488beef494a +Author: Darren Tucker +Date: Mon Nov 7 14:45:16 2022 +1100 + + Do not run CIFuzz on selfhosted tree. - OpenBSD-Commit-ID: cf39c811a68cde2aeb98fc85addea4000ef6b07a + We already run it on the regular tree, no need to double up. + +commit 2138b1c4ddb300129a41a5104627b0d561184c7b +Author: Darren Tucker +Date: Mon Nov 7 14:41:58 2022 +1100 + + Whitespace change to trigger CIFuzz workflow. + +commit 4670b97ef87c7b0f21283c9b07c7191be88dda05 +Author: Darren Tucker +Date: Mon Nov 7 14:34:04 2022 +1100 + + Run cifuzz workflow on the actions as regular CI. + +commit 79391e66ce851ace1baf3c6a35e83a23f08ec2ba +Author: David Korczynski +Date: Tue Nov 30 11:45:20 2021 +0000 + + Add CIFuzz integration -commit ff9809fdfd1d9a91067bb14a77d176002edb153c -Author: djm@openbsd.org -Date: Wed Sep 14 00:14:37 2022 +0000 +commit c1893364a0be243270014d7d34362a8101d55112 +Author: dtucker@openbsd.org +Date: Mon Nov 7 02:21:22 2022 +0000 - upstream: sk_enroll: never drop SSH_SK_USER_VERIFICATION_REQD flag + upstream: Import regenerated moduli. - from response + OpenBSD-Commit-ID: b0e54ee4d703bd6929bbc624068666a7a42ecb1f + +commit 5c3f18fb994ef27e685b205ee2351851b80fdbd1 +Author: dtucker@openbsd.org +Date: Mon Nov 7 01:53:01 2022 +0000 + + upstream: Fix typo. From pablomh via -portable github PR#344. - Now that all FIDO signing calls attempt first without PIN and then - fall back to trying PIN only if that attempt fails, we can remove the - hack^wtrick that removed the UV flag from the keys returned during - enroll. + OpenBSD-Commit-ID: d056ee2e73691dc3ecdb44a6de68e6b88cd93827 + +commit e1c6fcc142066417c9832e634463faa3dd5d116c +Author: Darren Tucker +Date: Mon Nov 7 12:46:58 2022 +1100 + + Link to branch-specific queries for V_9_1 status. + +commit 4f4a5fad6d8892c3f8ee9cd81ec7de6458210c9f +Author: Darren Tucker +Date: Sun Nov 6 10:55:59 2022 +1100 + + Use "prohibit-password" in -portable comments. - By Corinna Vinschen + "without-password" is the deprecated alias for "prohibit-password", + so we should reference the latter. From emaste at freebsd.org. + +commit 0f7e1eba55259ec037f515000b4c4afbf446230a +Author: Darren Tucker +Date: Sun Nov 6 10:50:01 2022 +1100 + + Fix tracing disable on FreeBSD. - OpenBSD-Commit-ID: 684517608c8491503bf80cd175425f0178d91d7f + Some versions of FreeBSD do not support using id 0 to refer to the + current pid for procctl, so pass getpid() explicitly. From + emaste at freebsd.org. -commit 940dc10729cb5a95b7ee82c10184e2b9621c8a1d -Author: djm@openbsd.org -Date: Wed Sep 14 00:13:13 2022 +0000 +commit 32fddb982fd61b11a2f218a115975a87ab126d43 +Author: Darren Tucker +Date: Mon Nov 7 10:39:01 2022 +1100 - upstream: a little extra debugging + Fix setres*id checks to work with clang-16. - OpenBSD-Commit-ID: edf1601c1d0905f6da4c713f4d9cecc7d1c0295a + glibc has the prototypes for setresuid and setresgid behind _GNU_SOURCE, + and clang 16 will error out on implicit function definitions, so add + _GNU_SOURCE and the required headers to the configure checks. From + sam at @gentoo.org via bz#3497. -commit 4b5f91cb959358141181b934156513fcb8a6c1e3 -Author: djm@openbsd.org -Date: Wed Sep 14 00:02:03 2022 +0000 +commit 12af712d116f42164bcfa56db901d06e4fa27199 +Author: Sam James +Date: Sun Nov 6 04:52:38 2022 +0000 - upstream: ssh-agent: attempt FIDO key signing without PIN and use + configure.ac: Fix -Wstrict-prototypes - the error to determine whether a PIN is required and prompt only if - necessary. from Corinna Vinschen + Clang 16 now warns on this and it'll be removed in C23, so let's + just be future proof. It also reduces noise when doing general + Clang 16 porting work (which is a big job as it is). github PR#355. - OpenBSD-Commit-ID: dd6be6a0b7148608e834ee737c3479b3270b00dd + Signed-off-by: Sam James -commit 113523bf0bc33600b07ebb083572c8c346b6fdf4 -Author: jmc@openbsd.org -Date: Sun Sep 11 06:38:11 2022 +0000 +commit 40b0a5eb6e3edfa2886b60c09c7803353b0cc7f5 +Author: Sam James +Date: Sun Nov 6 04:47:35 2022 +0000 - upstream: .Li -> .Vt where appropriate; from josiah frentsos, - - tweaked by schwarze + configure.ac: Add include for openpty - ok schwarze + Another Clang 16ish fix (which makes -Wimplicit-function-declaration + an error by default). github PR#355. - OpenBSD-Commit-ID: 565046e3ce68b46c2f440a93d67c2a92726de8ed + See: 2efd71da49b9cfeab7987058cf5919e473ff466b + See: be197635329feb839865fdc738e34e24afd1fca8 -commit 86af013b56cecb5ee58ae0bd9d495cd586fc5918 -Author: jsg@openbsd.org -Date: Sat Sep 10 08:50:53 2022 +0000 +commit 6b17e128879ec6cc32ca2c28b5d894b4aa72e32d +Author: Rochdi Nassah +Date: Fri Oct 28 01:26:31 2022 +0100 - upstream: fix repeated words ok miod@ jmc@ + Fix broken zlib link. + +commit 99500df246ccb736ddbdd04160dcc82165d81a77 +Author: Darren Tucker +Date: Fri Nov 4 16:59:26 2022 +1100 + + Don't run openbsd-compat tests on Cygwin. - OpenBSD-Commit-ID: 6765daefe26a6b648cc15cadbbe337596af709b7 + Add "compat-tests" to the default TEST_TARGET so we can override as + necessary. Override TEST_TARGET for Cygwin as the tests don't currently + compile there. -commit 0ba39b93b326a7d5dfab776cc9b9d326161a9b16 +commit 3cae9f92a31897409666aa1e6f696f779759332b Author: djm@openbsd.org -Date: Fri Sep 9 03:31:42 2022 +0000 +Date: Thu Nov 3 21:59:20 2022 +0000 - upstream: notifier_complete(NULL, ...) is a noop, so no need to test + upstream: replace recently-added valid_domain() check for hostnames - that ctx!=NULL; from Corinna Vinschen + going to known_hosts with a more relaxed check for bad characters; previous + commit broke address literals. Reported by/feedback from florian@ - OpenBSD-Commit-ID: ade2f2e9cc519d01a586800c25621d910bce384a + OpenBSD-Commit-ID: 10b86dc6a4b206adaa0c11b58b6d5933898d43e0 -commit be197635329feb839865fdc738e34e24afd1fca8 -Author: Sam James -Date: Thu Sep 8 02:49:29 2022 +0100 +commit 9655217231c9056200bea7ae2dffcc9c0c3eb265 +Author: Darren Tucker +Date: Thu Nov 3 23:07:50 2022 +1100 - openbsd-compat/bsd-asprintf: add include for vsnprintf - - Fixes the following build failure with Clang 15 on musl: - ``` - bsd-asprintf.c:51:8: error: call to undeclared library function 'vsnprintf' with type 'int (char *, unsigned long, const char *, struct __va_list_tag *)'; ISO C99 and laterclang -O2 -pipe -fdiagnostics-color=always -frecord-gcc-switches -pipe -Wunknown-warning-option -Qunused-arguments -Wall -Wpointer-arith -Wuninitialized -Wsign-compare -Wformat-security -Wsizeof-pointer-memaccess -Wno-pointer-sign -Wno-unused-result -Wmisleading-indentation -Wbitwise-instead-of-logical -fno-strict-aliasing -mretpoline -ftrapv -fzero-call-used-regs=all -fno-builtin-memset -fstack-protector-strong -fPIE -I. -I. -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE -DSSHDIR=\"/etc/ssh\" -D_PATH_SSH_PROGRAM=\"/usr/bin/ssh\" -D_PATH_SSH_ASKPASS_DEFAULT=\"/usr/lib/misc/ssh-askpass\" -D_PATH_SFTP_SERVER=\"/usr/lib/misc/sftp-server\" -D_PATH_SSH_KEY_SIGN=\"/usr/lib/misc/ssh-keysign\" -D_PATH_SSH_PKCS11_HELPER=\"/usr/lib/misc/ssh-pkcs11-helper\" -D_PATH_SSH_SK_HELPER=\"/usr/lib/misc/ssh-sk-helper\" -D_PATH_SSH_PIDDIR=\"/run\" -D_PATH_PRIVSEP_CHROOT_DIR=\"/var/empty\" -DHAVE_CONFIG_H -c cipher-aes.c -o cipher-aes.o - do not support - implicit function declarations [-Wimplicit-function-declaration] - ret = vsnprintf(string, INIT_SZ, fmt, ap2); - ^ - bsd-asprintf.c:51:8: note: include the header or explicitly provide a declaration for 'vsnprintf' - 1 error generated. - ``` + Rerun tests on changes to Makefile.in in any dir. -commit 6cb6f660bb35f77a0456dd2581ddf39c29398a5e +commit 3500f0405a3ab16b59a26f3508c4257a3fc3bce6 Author: Darren Tucker -Date: Fri Sep 2 16:43:27 2022 +1000 +Date: Thu Nov 3 23:04:08 2022 +1100 - Remove DEF_WEAK, it's already in defines.h. + Link libssh into compat tests. + + The cygwin compat code uses xmalloc, so add libssh.a so pick up that. -commit ce39e7d8b70c4726defde5d3bc4cb7d40d131153 +commit ec59effcf65b8a4c85d47ff5a271123259dd0ab8 Author: Darren Tucker -Date: Fri Sep 2 14:28:14 2022 +1000 +Date: Thu Nov 3 21:44:23 2022 +1100 - Resync arc4random with OpenBSD. - - This brings us up to current, including djm's random-reseeding change, - as prompted by logan at cyberstorm.mu in bz#3467. It brings the - platform-specific hooks from LibreSSL Portable, simplified to match our - use case. ok djm@. + Fix compat regress to work with non-GNU make. -commit beaddde26f30e2195b8aa4f3193970e140e17305 +commit 73550a218e7dfbbd599534cbf856309bc924f6fd Author: Darren Tucker -Date: Fri Sep 2 14:20:04 2022 +1000 +Date: Thu Nov 3 13:41:16 2022 +1100 - Move OPENBSD ORIGINAL marker. + Increase selfhosted job timeout. - Putting this after the copyright statement (which doesn't change) - instead of before the version identifier (which does) prevents merge - conflicts when resyncing changes. + The default job timeout of 360 (6h) is not enough to complete the + regress tests for some of the slow VMs depending on the load on the host. + Increase to 600 (10h). -commit c83e467ead67a8cb48ef4bec8085d6fb880a2ff4 +commit db97d8d0b90c6ce52b94b153d6f8f5f7d3b11777 Author: Darren Tucker -Date: Fri Sep 2 14:17:28 2022 +1000 +Date: Thu Nov 3 10:00:43 2022 +1100 - Remove arc4random_uniform from arc4random.c - - This was previously moved into its own file (matching OpenBSD) which - prematurely committed in commit 73541f2. + Only run opensslver tests if built with OpenSSL. -commit 5f45c2395c60865e59fa44152ff1d003a128c5bc -Author: djm@openbsd.org -Date: Fri Sep 2 04:20:02 2022 +0000 +commit ba053709638dff2f6603df0c1f340352261d63ea +Author: Darren Tucker +Date: Wed Nov 2 14:16:04 2022 +1100 - upstream: sk-usbhid: fix key_lookup() on tokens with built-in UV - - explicitly test whether the token performs built-in UV (e.g. biometric - tokens) and enable UV in that case. From Pedro Martelletto via GHPR#388 - - OpenBSD-Commit-ID: 007eb7e387d27cf3029ab06b88224e03eca62ccd + Add tests for OpenSSL 3.0.7 and LibreSSL 3.6.1. -commit 03277a4aa49b80af541a3e691f264c0c0d8f9cec +commit edd24101c7e17d1a8f6576e1aaf62233b47ad6f5 Author: Darren Tucker -Date: Wed Aug 31 20:26:30 2022 +1000 +Date: Thu Nov 3 08:17:39 2022 +1100 - Move sftp from valgrind-2 to 3 to rebalance. + Run compat regress tests too. -commit fcf5365da69c516817321ba89c3a91df98d098df -Author: djm@openbsd.org -Date: Wed Aug 31 02:56:40 2022 +0000 +commit fe88d67e7599b0bc73f6e4524add28d743e7f977 +Author: Darren Tucker +Date: Thu Nov 3 08:14:05 2022 +1100 - upstream: whitespace + Compat tests need libcrypto. - OpenBSD-Commit-ID: c2bcbf93610d3d62ed206cdf9bf9ff98c6aaf232 + This was moved to CHANNELLIBS during the libs refactor. Spotted by + rapier at psc.edu. -commit e60136a3d7a223dd8e84ba8a6895bc3142360993 -Author: Damien Miller -Date: Mon Aug 29 13:27:45 2022 +1000 +commit 96b519726b7944eee3c23a54eee3d5c031ba1533 +Author: Darren Tucker +Date: Thu Nov 3 04:24:39 2022 +1100 - additional keys + Include time.h when defining timegm. + + Fixes build on some platforms eg recent AIX. -commit 2b02dcb505288c462d1b5dd1ac04e603d01340eb -Author: Damien Miller -Date: Mon Aug 29 13:23:43 2022 +1000 +commit da6038bd5cd55eb212eb2aec1fc8ae79bbf76156 +Author: Darren Tucker +Date: Tue Nov 1 19:10:30 2022 +1100 - cross-sign allowed_signers with PGP key + Always use compat getentropy. - Provides continuity of trust from legacy PGP release key to - the SSHSIG signing keys that we will use henceforth for git - signing. + Have it call native getentropy and fall back as required. Should fix + issues of platforms where libc has getentropy but it is not implemented + in the kernel. Based on github PR#354 from simsergey. -commit 51b345f177ae981b8755f6bdf8358b1cc5e83d67 +commit 5ebe18cab6be3247b44c807ac145164010465b82 Author: Darren Tucker -Date: Sat Aug 27 21:49:27 2022 +1000 +Date: Wed Nov 2 10:51:48 2022 +1100 - Add libcrypt-devel to cygwin-release deps. + Check for sockaddr_in.sin_len. - Based on feedback from vinschen at redhat.com. + If found, set SOCK_HAS_LEN which is used in addr.c. Should fix keyscan + tests on platforms with this (eg old NetBSD). -commit 9f81736cf16dd8dda1c8942f1973a5f80b8cd78c -Author: Darren Tucker -Date: Sat Aug 27 09:37:40 2022 +1000 +commit a1febadf426536612c2734168d409147c392e7cf +Author: dtucker@openbsd.org +Date: Sun Oct 30 18:42:07 2022 +0000 - Add Windows 2022 test targets. + upstream: Use variable for diff options + + instead of unconditionally specifying "-rN". This will make life easier + in -portable where not all diff's understand -N. + + OpenBSD-Regress-ID: 8b8a407115546be1c6d72d350b1e4f1f960d3cd3 -commit 85e1a69243f12be8520438ad6a3cfdc0b7fcbb2d +commit f6d3ed9a8a9280cbb68d6a499850cfe810e92bd0 Author: Darren Tucker -Date: Fri Aug 26 16:26:06 2022 +1000 +Date: Mon Oct 31 05:13:02 2022 +1100 - Add cygwin-release test target. + OpenSSL dev branch is 302 not 320. - This also moves the cygwin package install from the workflow file to - setup_ci.sh so that we can install different sets of Cygwin packages - for different test configs. + While there, also accept 301 which it shat it was previously. -commit 92382dbe8bf9ea1225b16858f9b9b208c15c7e8d +commit 25c8a2bbcc10c493d27faea57c42a6bf13fa51f2 Author: djm@openbsd.org -Date: Fri Aug 26 08:16:27 2022 +0000 +Date: Fri Oct 28 02:47:04 2022 +0000 - upstream: whitespace + upstream: put sshkey_check_rsa_length() back in sshkey.c to unbreak - OpenBSD-Commit-ID: a5d015efbfd228dc598ffdef612d2da3a579e5d8 + OPENSSL=no builds + + OpenBSD-Commit-ID: 99eec58abe382ecd14b14043b195ee1babb9cf6e -commit 70a5de0a50e84d7250eb4e4537f765599f64c4af +commit 1192588546c29ceec10775125f396555ea71850f Author: djm@openbsd.org -Date: Fri Aug 26 08:12:56 2022 +0000 +Date: Fri Oct 28 02:29:34 2022 +0000 - upstream: whitespace + upstream: allow ssh-keyscan(1) to accept CIDR address ranges, e.g. - OpenBSD-Commit-ID: d297e4387935d4aef091c5e9432578c2e513f538 + ssh-keyscan 192.168.0.0/24 + + If a CIDR range is passed, then it will be expanded to all possible + addresses in the range including the all-0s and all-1s addresses. + + bz#976 feedback/ok markus@ + + OpenBSD-Commit-ID: ce6c5211f936ac0053fd4a2ddb415277931e6c4b -commit 3a683a19fd116ea15ebf8aa13d02646cceb302a9 +commit 64af4209309461c79c39eda2d13f9d77816c6398 Author: Damien Miller -Date: Fri Aug 26 14:23:55 2022 +1000 - - initial list of allowed signers - -commit 6851f4b8c3fc1b3e1114c56106e4dc31369c8513 -Author: Darren Tucker -Date: Fri Aug 19 17:22:18 2022 +1000 +Date: Fri Oct 28 12:54:35 2022 +1100 - Install Cygwin packages based on OS not config. + fix merge botch -commit f96480906893ed93665df8cdf9065865c51c1475 +commit 27267642699342412964aa785b98afd69d952c88 Author: djm@openbsd.org -Date: Fri Aug 19 06:07:47 2022 +0000 +Date: Fri Oct 28 00:44:44 2022 +0000 - upstream: attemp FIDO key signing without PIN and use the error + upstream: refactor sshkey_private_deserialize - code returned to fall back only if necessary. Avoids PIN prompts for FIDO - tokens that don't require them; part of GHPR#302 + feedback/ok markus@ - OpenBSD-Commit-ID: 4f752aaf9f2e7c28bcaaf3d4f8fc290131bd038e + OpenBSD-Commit-ID: f5ca6932fdaf840a5e8250becb38315a29b5fc9f -commit 5453333b5d28e313284cb9aae82899704103f98d +commit 2519a7077a9332f70935e5242ba91ee670ed6b87 Author: djm@openbsd.org -Date: Fri Aug 19 05:53:28 2022 +0000 +Date: Fri Oct 28 00:44:17 2022 +0000 - upstream: remove incorrect check that can break enrolling a + upstream: refactor sshkey_private_serialize_opt() - resident key (introduced in r1.40) + feedback/ok markus@ - OpenBSD-Commit-ID: 4cab364d518470e29e624af3d3f9ffa9c92b6f01 + OpenBSD-Commit-ID: 61e0fe989897901294efe7c3b6d670cefaf44cbd -commit ff89b1bed80721295555bd083b173247a9c0484e -Author: dtucker@openbsd.org -Date: Fri Aug 19 04:02:46 2022 +0000 +commit 11a768adf98371fe4e43f3b06014024c033385d5 +Author: djm@openbsd.org +Date: Fri Oct 28 00:43:30 2022 +0000 - upstream: Strictly enforce the maximum allowed SSH2 banner size in + upstream: refactor certify - ssh-keyscan and prevent a one-byte buffer overflow. Patch from Qualys, ok - djm@ + feedback/ok markus@ - OpenBSD-Commit-ID: 6ae664f9f4db6e8a0589425f74cd0bbf3aeef4e4 + OpenBSD-Commit-ID: 35d742992e223eaca3537e6fb3d3002c08eed4f6 -commit 1b470b9036639cef4f32fb303bb35ea0b711178d -Author: Darren Tucker -Date: Fri Aug 19 15:18:09 2022 +1000 +commit 3fbc58bb249d967cc43ebdc554f6781bb73d4a58 +Author: djm@openbsd.org +Date: Fri Oct 28 00:43:08 2022 +0000 - Fix cygwin conditional steps. + upstream: refactor sshkey_sign() and sshkey_verify() + + feedback/ok markus@ + + OpenBSD-Commit-ID: 368e662c128c99d05cc043b1308d2b6c71a4d3cc -commit fd6ee741ab16714b7035d60aca924123ba28135a -Author: Darren Tucker -Date: Fri Aug 19 15:12:57 2022 +1000 +commit a1deb6cdbbe6afaab74ecb08fcb62db5739267be +Author: djm@openbsd.org +Date: Fri Oct 28 00:41:52 2022 +0000 - Add a bit more debug output. + upstream: refactor sshkey_from_blob_internal() + + feedback/ok markus@ + + OpenBSD-Commit-ID: 1f46c0cbb8060ee9666a02749594ad6658c8e283 -commit a9305c4c739f4d91a3d3a92c0b6d4949404a36c5 -Author: Darren Tucker -Date: Fri Aug 12 15:08:47 2022 +1000 +commit 7d00799c935271ce89300494c5677190779f6453 +Author: djm@openbsd.org +Date: Fri Oct 28 00:41:17 2022 +0000 - Add Cygwin (on windows-2019) test target. + upstream: refactor sshkey_from_private() - In addition to installing the requisite Cygwin packages, we also need to - explicitly invoke "sh" for steps that run other scripts since the runner - environment doesn't understand #! paths. + feedback/ok markus@ + + OpenBSD-Commit-ID: e5dbe7a3545930c50f70ee75c867a1e08b382b53 -commit 5062ad48814b06162511c4f5924a33d97b6b2566 +commit 262647c2e920492ca57f1b9320d74f4a0f6e482b Author: djm@openbsd.org -Date: Fri Aug 19 03:06:30 2022 +0000 +Date: Fri Oct 28 00:39:29 2022 +0000 - upstream: double free() in error path; from Eusgor via GHPR333 + upstream: factor out key generation - OpenBSD-Commit-ID: 39f35e16ba878c8d02b4d01d8826d9b321be26d4 + feedback/ok markus@ + + OpenBSD-Commit-ID: 5b4211bff4de8d9adb84bc72857a8c42c44e7ceb -commit 5a5c580b48fc6006bdfa731fc2f6d4945c2c0e4e -Author: Darren Tucker -Date: Thu Aug 18 21:36:39 2022 +1000 +commit 401c74e7dc15eab60540653d2f94d9306a927bab +Author: djm@openbsd.org +Date: Fri Oct 28 00:38:58 2022 +0000 - Check for perms to run agent-getpeereid test. + upstream: refactor and simplify sshkey_read() - Ubuntu 22.04 defaults to private home dirs which prevents "nobody" - running ssh-add during the agent-getpeereid test. Check for this and - add the necessary permissions. + feedback/ok markus@ + + OpenBSD-Commit-ID: 0d93b7a56e31cd06a8bb0d2191d084ce254b0971 -commit cd06a76b7ccc706e2bb4f1cc4aa9e9796a28a812 -Author: Damien Miller -Date: Wed Aug 17 16:04:16 2022 +1000 +commit 591fed94e66a016acf87f4b7cd416ce812f2abe8 +Author: djm@openbsd.org +Date: Fri Oct 28 00:37:24 2022 +0000 - on Cygwin, prefer WinHello FIDO device + upstream: factor out public key serialization - If no FIDO device was explictly specified, then prefer the - windows://hello FIDO device. An exception to this is when - probing resident FIDO keys, in which case hardware FIDO - devices are preferred. + feedback/ok markus@ + + OpenBSD-Commit-ID: a3570c4b97290c5662890aea7328d87f55939033 -commit 47f72f534ac5cc2cd3027675a3df7b00a8f77575 +commit 1e78844ae2b2dc01ba735d5ae740904c57e13685 Author: djm@openbsd.org -Date: Wed Aug 17 06:01:57 2022 +0000 +Date: Fri Oct 28 00:36:31 2022 +0000 - upstream: add an extra flag to sk_probe() to indicate whether we're + upstream: factor out sshkey_equal_public() - probing for a FIDO resident key or not. Unused here, but will make like - easier for portable + feedback/ok markus@ - OpenBSD-Commit-ID: 432c8ff70e270378df9dbceb9bdeaa5b43b5a832 + OpenBSD-Commit-ID: 1368ba114cb37732fe6ec3d89c7e6d27ea6fdc94 -commit edb0bcb3c79b16031dc87a8e57aecc3c4a3414f0 -Author: jmc@openbsd.org -Date: Tue Aug 16 20:24:08 2022 +0000 +commit 25de1c01a8b9a2c8ab9b1da22444a03e89c982de +Author: djm@openbsd.org +Date: Fri Oct 28 00:35:40 2022 +0000 - upstream: use .Cm for "sign"; from josiah frentsos + upstream: begin big refactor of sshkey - OpenBSD-Commit-ID: 7f80a53d54857ac6ae49ea6ad93c5bd12231d1e4 + Move keytype data and some of the type-specific code (allocation, + cleanup, etc) out into each key type's implementation. Subsequent + commits will move more, with the goal of having each key-*.c file + owning as much of its keytype's implementation as possible. + + lots of feedback + ok markus@ + + OpenBSD-Commit-ID: 0f2b4334f73914344e9e5b3d33522d41762a57ec -commit cccb011e130cbbac538b1689d10e4a067298df8b -Author: Corinna Vinschen -Date: Thu Aug 11 20:19:35 2022 +0200 +commit 445363433ba20b8a3e655b113858c836da46a1cb +Author: djm@openbsd.org +Date: Mon Oct 24 22:43:36 2022 +0000 - Revert "check_sk_options: add temporary WinHello workaround" + upstream: Be more paranoid with host/domain names coming from the - Cygwin now comes with libfido2 1.11.0, so this workaround - isn't required anymore. + never write a name with bad characters to a known_hosts file. - This reverts commit 242c044ab111a37aad3b0775727c36a4c5f0102c. + reported by David Leadbeater, ok deraadt@ - Signed-off-by: Corinna Vinschen + OpenBSD-Commit-ID: ba9b25fa8b5490b49398471e0c9657b0cbc7a5ad -commit 9468cd7cf9d989dfa2ac20e2a0268ba6e93bfa5a -Author: Corinna Vinschen -Date: Thu Aug 11 20:18:17 2022 +0200 +commit 7190154de2c9fe135f0cc1ad349cb2fa45152b89 +Author: djm@openbsd.org +Date: Mon Oct 24 21:52:50 2022 +0000 - fido_dev_is_winhello: return 0, not "false" + upstream: regress test for unmatched glob characters; fails before - "false" is not used anywhere in OpenSSH, so return 0 like - everywhere else. + previous commit but passes now. bz3488; prodded by dtucker@ - Signed-off-by: Corinna Vinschen + OpenBSD-Regress-ID: 0cc5cc9ea4a6fd170dc61b9212f15badaafb3bbd -commit 730a80609472ee0451c99482d75c9c41f3ebc42d +commit a4821a592456c3add3cd325db433110cdaaa3e5c Author: djm@openbsd.org -Date: Fri Aug 12 05:20:28 2022 +0000 +Date: Mon Oct 24 21:51:55 2022 +0000 - upstream: sftp-server: support home-directory request + upstream: when scp(1) is using the SFTP protocol for transport (the - Add support to the sftp-server for the home-directory extension defined - in draft-ietf-secsh-filexfer-extensions-00. This overlaps a bit with the - existing expand-path@openssh.com, but uses a more official protocol name, - and so is a bit more likely to be implemented by non-OpenSSH clients. + default), better match scp/rcp's handling of globs that don't match the + globbed characters but do match literally (e.g. trying to transfer + "foo.[1]"). + + Previously scp(1) in SFTP mode would not match these pathnames but + legacy scp/rcp mode would. + + Reported by Michael Yagliyan in bz3488; ok dtucker@ + + OpenBSD-Commit-ID: d8a3773f53015ba811fddba7473769a2fd343e11 + +commit 18376847b8043ba967eabbe23692ef74c9a3fddc +Author: jsg@openbsd.org +Date: Thu Oct 13 09:09:28 2022 +0000 + + upstream: use correct type with sizeof ok djm@ + + OpenBSD-Commit-ID: d6c882c2e8a42ff831a5b3cbc2c961ecb2dd6143 + +commit 4a4883664d6b4e9e4e459a8cdc16bd8d4b735de9 +Author: jmc@openbsd.org +Date: Fri Oct 7 06:00:58 2022 +0000 + + upstream: ssh-agent.1: - use Nm not Xr for self-ref - while here, + + wrap a long line + + ssh-agent.c: + - add -O to usage() + + OpenBSD-Commit-ID: 855dac4695cef22e96d69c53436496bc408ca389 + +commit 9fd2441113fce2a83fc7470968c3b27809cc7f10 +Author: djm@openbsd.org +Date: Fri Oct 7 04:06:26 2022 +0000 + + upstream: document "-O no-restrict-websafe"; spotted by Ross L - From Mike Frysinger, ok dtucker@ + Richardson - OpenBSD-Commit-ID: bfc580d05cc0c817831ae7ecbac4a481c23566ab + OpenBSD-Commit-ID: fe9eaa50237693a14ebe5b5614bf32a02145fe8b -commit 5e820bf79ce3ce99ef7e98b0ab642b0a0a4f396c +commit 614252b05d70f798a0929b1cd3d213030ad4d007 Author: Darren Tucker -Date: Fri Aug 12 14:56:55 2022 +1000 +Date: Tue Oct 18 06:29:16 2022 +1100 - Replace deprecated ubuntu-18.04 runners with 22.04 + OpenSSL dev branch now identifies as 3.2.0. -commit 87b0d9c1b789d3ff958ec45df2ac912e24461bae -Author: Darren Tucker -Date: Thu Aug 11 22:48:23 2022 +1000 +commit 195e5a65fd793a738ea8451ebfdd1919db5aff3e +Author: Damien Miller +Date: Mon Oct 17 09:41:47 2022 +1100 - Add a timegm implementation from Heimdal via Samba. + revert c64b62338b4 and guard POLL* defines instead - Fixes build on (at least Solaris 10). + c64b62338b4 broke OSX builds, which do have poll.h but lack ppoll(2) + Spotted by dtucker -commit d0c4fa58594577994921b593f10037c5282597ca -Author: Darren Tucker -Date: Thu Aug 11 14:23:58 2022 +1000 +commit bc2e480d99613bd59720edae244d1764636544c4 +Author: Damien Miller +Date: Fri Oct 14 14:52:22 2022 +1100 - Rerun tests if any .github config file changes. + undef _get{short,long} before redefining -commit 113fe6c77ab43769fc61e953d07cb619fd7ea54b -Author: Darren Tucker -Date: Thu Aug 11 13:33:51 2022 +1000 +commit 5eb796a369c64f18d55a6ae9b1fa9b35eea237fb +Author: Harmen Stoppels +Date: Thu Oct 13 16:08:46 2022 +0200 - Skip hostbased during Valgrind tests. - - Valgrind doesn't let ssh exec ssh-keysign (because it's setuid) so skip - it during the Valgrind based tests. + Fix snprintf configure test for clang 15 - See https://bugs.kde.org/show_bug.cgi?id=119404 for a discussion of this - (ironically there the problematic binary was ssh(1) back when it could - still be setuid). + Clang 15 -Wimplicit-int defaults to an error in C99 mode and above. + A handful of tests have "main(..." and not "int main(..." which caused + the tests to produce incorrect results. -commit b98a42afb69d60891eb0488935990df6ee571c4d -Author: djm@openbsd.org -Date: Thu Aug 11 01:57:50 2022 +0000 +commit c64b62338b46ffa08839f05f21ad69fa6234dc17 +Author: Damien Miller +Date: Mon Oct 10 12:32:43 2022 +1100 - upstream: add some tests for parse_absolute_time(), including cases - - where it is forced to the UTC timezone. bz3468 ok dtucker - - OpenBSD-Regress-ID: ea07ca31c2f3847a38df028ca632763ae44e8759 + skip bsd-poll.h if poll.h found; ok dtucker -commit ec1ddb72a146fd66d18df9cd423517453a5d8044 +commit 5ee2b8ccfcf4b606f450eb0ff2305e311f68b0be Author: djm@openbsd.org -Date: Thu Aug 11 01:56:51 2022 +0000 +Date: Thu Oct 6 22:42:37 2022 +0000 - upstream: allow certificate validity intervals, sshsig verification - - times and authorized_keys expiry-time options to accept dates in the UTC time - zone in addition to the default of interpreting them in the system time zone. - YYYYMMDD and YYMMDDHHMM[SS] dates/times will be interpreted as UTC if - suffixed with a 'Z' character. - - Also allow certificate validity intervals to be specified in raw - seconds-since-epoch as hex value, e.g. -V 0x1234:0x4567890. This - is intended for use by regress tests and other tools that call - ssh-keygen as part of a CA workflow. + upstream: honour user's umask if it is more restrictive then the ssh - bz3468 ok dtucker + default (022); based on patch from Alex Henrie, ok dtucker@ deraadt@ - OpenBSD-Commit-ID: 454db1cdffa9fa346aea5211223a2ce0588dfe13 + OpenBSD-Commit-ID: fe1b9e15fc9a4f49fc338e848ce14d8727abe82d -commit 4df246ec75751da7eb925e1880498300d8bda187 +commit a75cffc2700cebd3e2dd9093f7f7388d2be95cb7 Author: Darren Tucker -Date: Thu Aug 11 10:23:55 2022 +1000 - - Fix conditional for running hostbased tests. - -commit 2580916e48721802220c61ce9e0df1297c00bc07 -Author: Damien Miller -Date: Thu Aug 11 08:58:28 2022 +1000 +Date: Fri Oct 7 03:54:56 2022 +1100 - fix SANDBOX_SECCOMP_FILTER_DEBUG + Add LibreSSL 3.6.0 to test suite. + + While there, bump OpenSSL to latest 1.1.1q release. -commit fdbd5bf507fc271ff813714fab8a72ff2c6cb5ca +commit fcc0f0c0e96a30076683fea9a7c9eedc72931742 Author: Darren Tucker -Date: Wed Aug 10 17:35:52 2022 +1000 +Date: Thu Oct 6 21:18:16 2022 +1100 - Test hostbased auth on github runners. + Add 9.1 branch to CI status page. -commit 7e2f51940ba48a1c0fae1107801ea643fa83c971 +commit ef211eee63821d894a8bf81f22bfba9f6899d0fe Author: Darren Tucker -Date: Wed Aug 10 17:25:24 2022 +1000 +Date: Tue Oct 4 23:20:23 2022 +1100 - Rename our getentropy to prevent possible loops. + Test commits to all branches of portable. - Since arc4random seeds from getentropy, and we use OpenSSL for that - if enabled, there's the possibility that if we build on a system that - does not have getentropy then run on a system that does have it, then - OpenSSL could end up calling our getentropy and getting stuck in a loop. - Pointed out by deraadt@, ok djm@ + Only test OpenBSD upstream on commits to master since that's what it + tracks. -commit 7a01f61be8d0aca0e975e7417f26371495fe7674 -Author: Darren Tucker -Date: Mon Aug 8 12:17:04 2022 +1000 +commit fe646de03cafb6593ff4e4954bca9ec4b4b753a8 +Author: Damien Miller +Date: Wed Oct 5 03:47:26 2022 +1100 - Actually put HAVE_STDINT_H around the stdint.h. + whitespace at EOL -commit 73541f29f0b50480da6c20dceb7a7191bd8ea7d3 -Author: Darren Tucker -Date: Mon Aug 8 10:30:34 2022 +1000 +commit a6e1852d10c63a830196e82168dadd957aaf28ec +Author: Damien Miller +Date: Wed Oct 5 03:40:01 2022 +1100 - Give unused param a name. - - Fixes builds on platforms that do have fido2 but don't have - fido_dev_is_winhello. + mention libfido2 autodetection -commit 2a108c0ea960381bd9b14ee0d84e818a23df4482 -Author: djm@openbsd.org -Date: Fri Aug 5 05:01:40 2022 +0000 +commit 7360c2c206f33d309edbaf64036c96fadf74d640 +Author: Damien Miller +Date: Wed Oct 5 03:37:36 2022 +1100 - upstream: don't prompt for FIDO passphrase before attempting to enroll - - the credential, just let the enroll operating fail and we'll attempt to get a - PIN anyway. Might avoid some unneccessary PIN prompts. - - Part of GHPR#302 from Corinna Vinschen; ok dtucker@ + remove mention of --with-security-key-builtin - OpenBSD-Commit-ID: bd5342ffc353ee37d39617906867c305564d1ce2 + it is enabled by default when libfido2 is installed -commit 2886975c0ad9244e60dc5e4be34fde3aa573a4b5 -Author: Corinna Vinschen -Date: Fri Feb 11 14:33:41 2022 +0100 +commit 0ffb46f2ee2ffcc4daf45ee679e484da8fcf338c +Author: Damien Miller +Date: Tue Oct 4 01:51:42 2022 +1100 - sk_sign: set FIDO2 uv attribute explicitely for WinHello - - WinHello via libfido2 performs user verification by default. - However, if we stick to that, there's no way to differentiate - between keys created with or without "-O verify-required". - Set FIDO2 uv attribute explicitely to FIDO_OPT_FALSE, then check - if user verification has been requested. - - Signed-off-by: Corinna Vinschen + update .depend -commit 242c044ab111a37aad3b0775727c36a4c5f0102c -Author: Corinna Vinschen -Date: Tue Feb 15 11:28:08 2022 +0100 +commit 657e676ff696c7bb787bffb0e249ea1be3b474e1 +Author: Damien Miller +Date: Tue Oct 4 01:45:52 2022 +1100 - check_sk_options: add temporary WinHello workaround - - Up to libfido 1.10.0, WinHello advertises "clientPin" rather - than "uv" capability. This is fixed in 1.11.0. For the time - being, workaround it here. - - Signed-off-by: Corinna Vinschen + update release notes URL -commit 78774c08cc4b4997382975b0f414a86e06b6780c -Author: Corinna Vinschen -Date: Thu Feb 10 18:19:29 2022 +0100 +commit f059da2b29840c0f048448809c317ce2ae014da7 +Author: Damien Miller +Date: Tue Oct 4 01:45:41 2022 +1100 - compat code for fido_dev_is_winhello() - - Signed-off-by: Corinna Vinschen + crank versions in RPM spec files -commit 3d3a932a019aedfb891e0779bb4990cd5008a390 -Author: Darren Tucker -Date: Fri Aug 5 13:12:27 2022 +1000 +commit b51f3f172d87cbdb80ca4eb7b2149e56a7647557 +Author: djm@openbsd.org +Date: Mon Sep 26 22:18:40 2022 +0000 - Factor out getrnd() and rename to getentropy(). + upstream: openssh-9.1 - Factor out the arc4random seeding into its own file and change the - interface to match getentropy. Use native getentropy if available. - This will make it easier to resync OpenBSD changes to arc4random. - Prompted by bz#3467, ok djm@. + OpenBSD-Commit-ID: 5a467b2ee81da01a86adf1ad93b62b1728494e56 -commit 9385d277b787403be9dfcb229cf372202496d2f3 -Author: Darren Tucker -Date: Thu Aug 4 18:55:48 2022 +1000 +commit 4cf8d0c0f3030f594a238bab21a0695735515487 +Author: dtucker@openbsd.org +Date: Wed Sep 21 22:26:50 2022 +0000 - Include CHANNEL and FIDO2 libs in configure output + upstream: Fix typo. From AlexanderStohr via github PR#343. + + OpenBSD-Commit-ID: a134c9b4039e48803fc6a87f955b0f4a03181497 -commit 141535b904b6fba01724444f38193a8599201f82 +commit 8179fed3264d5919899900ed8881d5f9bb57ca33 Author: djm@openbsd.org -Date: Mon Aug 1 11:09:26 2022 +0000 +Date: Mon Sep 19 21:39:16 2022 +0000 - upstream: avoid double-free in error path introduced in r1.70; report + upstream: add RequiredRSASize to the list of keywords accepted by - and fix based on GHPR#332 by v-rzh ok dtucker@ + -o; spotted by jmc@ - OpenBSD-Commit-ID: 3d21aa127b1f37cfc5bdc21461db369a663a951f - -commit dba7099ffcba3ca07b3946f017ba6a4c3158d9b1 -Author: Darren Tucker -Date: Wed Jul 27 18:40:12 2022 +1000 - - Remove deprecated MacOS 10.15 runners. + OpenBSD-Commit-ID: fe871408cf6f9d3699afeda876f8adbac86a035e -commit 722a56439aa5972c830e4a9a724cf52aff4a950a -Author: Darren Tucker -Date: Wed Jul 27 18:31:14 2022 +1000 +commit 5f954929e9f173dd1e279e07d0e8b14fa845814d +Author: Damien Miller +Date: Mon Sep 19 20:59:34 2022 +1000 - Move stale-configure check as early as possible. + no need for glob.h here - We added a check in Makefile to catch the case where configure needs to - be rebuilt, however this did not happen until a build was attempted in - which case all of the work done by configure was wasted. Move this check - to the start of configure to catch it as early as possible. ok djm@ + it also causes portability problems -commit 099d6b56288b421ba38531d26dc1bd6bb685e311 -Author: Darren Tucker -Date: Fri Jul 22 10:47:19 2022 +1000 +commit 03d94a47207d58b3db37eba4f87eb6ae5a63168a +Author: Damien Miller +Date: Mon Sep 19 20:59:04 2022 +1000 - Move libcrypto into CHANNELLIBS. - - This will result in sftp, sftp-server and scp no longer being linked - against libcrypto. ok djm@ + avoid Wuninitialized false positive in gcc-12ish -commit 1bdf86725b77733bb5f17c54888b88a10b2f6538 -Author: Darren Tucker -Date: Fri Jul 22 10:45:47 2022 +1000 +commit 9d952529113831fb3071ab6e408d2726fd72e771 +Author: djm@openbsd.org +Date: Mon Sep 19 10:46:00 2022 +0000 - Remove seed_rng calls from scp, sftp, sftp-server. + upstream: use users-groups-by-id@openssh.com sftp-server extension - These binaries don't use OpenSSL's random functions. The next step - will be to stop linking them against libcrypto. ok djm@ + (when available) to fill in user/group names for directory listings. + Implement a client-side cache of see uid/gid=>user/group names. ok markus@ + + OpenBSD-Commit-ID: f239aeeadfa925a37ceee36ee8b256b8ccf4466e -commit d73f77b8cb9b422f1ac4facee7890aa10ff2bc21 -Author: Darren Tucker -Date: Fri Jul 22 09:51:51 2022 +1000 +commit 8ff680368b0bccf88ae85d4c99de69387fbad7a6 +Author: djm@openbsd.org +Date: Mon Sep 19 10:43:12 2022 +0000 - Group libcrypto and PRNGD checks together. + upstream: sftp client library support for - They're related more than the libcrypt or libiaf checks which are - currently between them. ok djm@ + users-groups-by-id@openssh.com; ok markus@ + + OpenBSD-Commit-ID: ddb2f33a2da6349a9a89a8b5bcb9ca7c999394de -commit f117e372b3f42f2fbdb0a578d063b2609ab58e1f -Author: Darren Tucker -Date: Fri Jul 22 09:24:45 2022 +1000 +commit 488f6e1c582212c2374a4bf8cd1b703d2e70fb8b +Author: djm@openbsd.org +Date: Mon Sep 19 10:41:58 2022 +0000 - Do not link scp, sftp and sftp-server w/ zlib. + upstream: extend sftp-common.c:extend ls_file() to support supplied - Some of our binaries (eg sftp, sftp-server, scp) do not interact with - the channels code and thus do use libraries such as zlib and libcrypto - although they are linked with them. This adds a CHANNELLIBS and starts - by moving zlib into it, which means the aformentioned binaries are no - longer linked against zlib. ok djm@ + user/group names; ok markus@ + + OpenBSD-Commit-ID: c70c70498b1fdcf158531117e405b6245863bfb0 -commit 800c2483e68db38bd1566ff69677124be974aceb -Author: Darren Tucker -Date: Mon Jul 25 21:49:04 2022 +1000 +commit 74b77f7497dba3a58315c8f308883de448078057 +Author: djm@openbsd.org +Date: Mon Sep 19 10:40:52 2022 +0000 - Remove workarounds for OpenSSL missing AES-CTR. + upstream: sftp-server(8): add a "users-groups-by-id@openssh.com" - We have some compatibility hacks that were added to support OpenSSL - versions that do not support AES CTR mode. Since that time, however, - the minimum OpenSSL version that we support has moved to 1.0.1 which - *does* have CTR, so this is no longer needed. ok djm@ + extension request that allows the client to obtain user/group names that + correspond to a set of uids/gids. + + Will be used to make directory listings more useful and consistent + in sftp(1). + + ok markus@ + + OpenBSD-Commit-ID: 7ebabde0bcb95ef949c4840fe89e697e30df47d3 -commit b7c56b65c12f51fe0dbae798d19c8f58224a5d95 -Author: Darren Tucker -Date: Mon Jul 25 21:43:00 2022 +1000 +commit 231a346c0c67cc7ca098360f9a554fa7d4f1eddb +Author: djm@openbsd.org +Date: Mon Sep 19 08:49:50 2022 +0000 - Remove workarounds for OpenSSL missing AES-GCM. + upstream: better debugging for connect_next() - We have some compatibility hacks that were added to support OpenSSL - versions that do not support AES GCM mode. Since that time, however, - the minimum OpenSSL version that we support has moved to 1.0.1 which - *does* have GCM, so this is no longer needed. ok djm@ + OpenBSD-Commit-ID: d16a307a0711499c971807f324484ed3a6036640 -commit 5a4a9f7a968fbf92cc1eac519c65638e79ae9f1f -Author: dtucker@openbsd.org -Date: Mon Jul 25 07:12:45 2022 +0000 +commit 1875042c52a3b950ae5963c9ca3774a4cc7f0380 +Author: djm@openbsd.org +Date: Sat Sep 17 10:34:29 2022 +0000 - upstream: Restore missing "!" in TEST_SSH_ELAPSED_TIMES test. + upstream: Add RequiredRSASize for sshd(8); RSA keys that fall - OpenBSD-Regress-ID: 38783f9676ec348c5a792caecee9a16e354b37b0 + beneath this limit will be ignored for user and host-based authentication. + + Feedback deraadt@ ok markus@ + + OpenBSD-Commit-ID: 187931dfc19d51873df5930a04f2d972adf1f7f1 -commit 0ff886be132299386cc29d87c2aa16ff68a1aa08 -Author: dtucker@openbsd.org -Date: Sun Jul 24 23:29:10 2022 +0000 +commit 54b333d12e55e6560b328c737d514ff3511f1afd +Author: djm@openbsd.org +Date: Sat Sep 17 10:33:18 2022 +0000 - upstream: Test TEST_SSH_ELAPSED_TIMES for empty string not + upstream: add a RequiredRSASize for checking RSA key length in - executable. No-op on most platforms but should prevent warnings in -portable - on systems that don't have 'date %s'. + ssh(1). User authentication keys that fall beneath this limit will be + ignored. If a host presents a host key beneath this limit then the connection + will be terminated (unfortunately there are no fallbacks in the protocol for + host authentication). - OpenBSD-Regress-ID: e39d79867b8065e33d0c5926fa1a31f85659d2a4 + feedback deraadt, Dmitry Belyavskiy; ok markus@ + + OpenBSD-Commit-ID: 430e339b2a79fa9ecc63f2837b06fdd88a7da13a -commit f69319ad8ad1dd50f90bbcf5912e11cc8ed3e037 -Author: Darren Tucker -Date: Sat Jul 23 14:38:22 2022 +1000 +commit 07d8771bacfefbcfb37fa8a6dc6103bcc097e0ab +Author: djm@openbsd.org +Date: Sat Sep 17 10:30:45 2022 +0000 - Convert "have_prog" function into "which". + upstream: Add a sshkey_check_rsa_length() call for checking the - "which" and its behaviour is not standardized, so convert the existing - have_prog function into "which" so we can rely on it being available - and what its semantics are. Add a have_prog wrapper that maintains the - existing behaviour. + length of an RSA key; ok markus@ + + OpenBSD-Commit-ID: de77cd5b11594297eda82edc594b0d32b8535134 -commit ea7ecc2c3ae39fdf5c6ad97b7bc0b47a98847f43 -Author: Darren Tucker -Date: Sat Jul 23 14:36:38 2022 +1000 +commit 3991a0cf947cf3ae0f0373bcec5a90e86a7152f5 +Author: djm@openbsd.org +Date: Sat Sep 17 10:11:29 2022 +0000 - Skip scp3 test if there's no scp on remote path. + upstream: actually hook up restrict_websafe; the command-line flag - scp -3 ends up using the scp that's in the remote path and will fail if - one is not available. Based on a patch from rapier at psc.edu. + was never actually used. Spotted by Matthew Garrett + + OpenBSD-Commit-ID: 0b363518ac4c2819dbaa3dfad4028633ab9cdff1 -commit c46f6fed419167c1671e4227459e108036c760f8 -Author: Damien Miller -Date: Wed Jul 20 13:39:14 2022 +1000 +commit 30b2a7e4291fb9e357f80a237931ff008d686d3b +Author: djm@openbsd.org +Date: Fri Sep 16 06:55:37 2022 +0000 - crank SSH_SK_VERSION_MAJOR in sk-dummy.so + upstream: correct error value + + OpenBSD-Commit-ID: 780efcbad76281f11f14b2a5ff04eb6db3dfdad4 -commit f208e3b9ffb5ee76cf9c95df7ff967adc7f51c7d +commit ac1ec9545947d9f9657259f55d04cb49d3a94c8a Author: djm@openbsd.org -Date: Wed Jul 20 03:33:22 2022 +0000 +Date: Fri Sep 16 03:33:14 2022 +0000 - upstream: ssh-keygen: fix touch prompt, pin retries; + upstream: sftp: Be a bit more clever about completions - part of GHPR329 from Pedro Martelletto + There are commands (e.g. "get" or "put") that accept two + arguments, a local path and a remote path. However, the way + current completion is written doesn't take this distinction into + account and always completes remote or local paths. - OpenBSD-Commit-ID: 75d1005bd2ef8f29fa834c90d2684e73556fffe8 + By expanding CMD struct and "cmds" array this distinction can be + reflected and with small adjustment to completer code the correct + path can be completed. + + By Michal Privoznik, ok dtucker@ + + OpenBSD-Commit-ID: 1396d921c4eb1befd531f5c4a8ab47e7a74b610b -commit 8638a2ce7e90c8a51d9af3143404282126c524f8 +commit 590db83384f9d99fc51c84505792d26d1ef60df9 Author: djm@openbsd.org -Date: Wed Jul 20 03:31:42 2022 +0000 +Date: Fri Sep 16 03:13:34 2022 +0000 - upstream: sk-usbhid: preserve error code returned by key_lookup() + upstream: sftp: Don't attempt to complete arguments for - it conveys useful information, such as the supplied pin being wrong. + non-existent commands - Part of GHPR329 from Pedro Martelletto + If user entered a non-existent command (e.g. because they made a + typo) there is no point in trying to complete its arguments. Skip + calling complete_match() if that's the case. - OpenBSD-Commit-ID: c0647eb9290f793add363d81378439b273756c1b + From Michal Privoznik + + OpenBSD-Commit-ID: cf39c811a68cde2aeb98fc85addea4000ef6b07a -commit 9ab929ca2d820520327b41929372bcb9e261534c +commit ff9809fdfd1d9a91067bb14a77d176002edb153c Author: djm@openbsd.org -Date: Wed Jul 20 03:29:14 2022 +0000 +Date: Wed Sep 14 00:14:37 2022 +0000 - upstream: when enrolling a resident key on a security token, check + upstream: sk_enroll: never drop SSH_SK_USER_VERIFICATION_REQD flag - if a credential with matching application and user ID strings already exists. - if so, prompt the user for confirmation before overwriting the credential. + from response - patch from Pedro Martelletto via GHPR329 + Now that all FIDO signing calls attempt first without PIN and then + fall back to trying PIN only if that attempt fails, we can remove the + hack^wtrick that removed the UV flag from the keys returned during + enroll. - NB. cranks SSH_SK_VERSION_MAJOR, so any third-party FIDO middleware - implementations will need to adjust + By Corinna Vinschen - OpenBSD-Commit-ID: e45e9f1bf2b2f32d9850669e7a8dbd64acc5fca4 + OpenBSD-Commit-ID: 684517608c8491503bf80cd175425f0178d91d7f -commit 5bcfc788b38d5b64e4c347bdc04bd9a01bbc36da +commit 940dc10729cb5a95b7ee82c10184e2b9621c8a1d Author: djm@openbsd.org -Date: Wed Jul 20 03:13:04 2022 +0000 +Date: Wed Sep 14 00:13:13 2022 +0000 - upstream: pull passphrase reading and confirmation into a separate + upstream: a little extra debugging - function so it can be used for FIDO2 PINs; no functional change + OpenBSD-Commit-ID: edf1601c1d0905f6da4c713f4d9cecc7d1c0295a + +commit 4b5f91cb959358141181b934156513fcb8a6c1e3 +Author: djm@openbsd.org +Date: Wed Sep 14 00:02:03 2022 +0000 + + upstream: ssh-agent: attempt FIDO key signing without PIN and use - OpenBSD-Commit-ID: bf34f76b8283cc1d3f54633e0d4f13613d87bb2f + the error to determine whether a PIN is required and prompt only if + necessary. from Corinna Vinschen + + OpenBSD-Commit-ID: dd6be6a0b7148608e834ee737c3479b3270b00dd -commit eb679e2959bdb15454eb94751930eb4c9110da94 -Author: Darren Tucker -Date: Fri Jul 15 21:31:48 2022 +1000 +commit 113523bf0bc33600b07ebb083572c8c346b6fdf4 +Author: jmc@openbsd.org +Date: Sun Sep 11 06:38:11 2022 +0000 - Move vmshutdown to first step. + upstream: .Li -> .Vt where appropriate; from josiah frentsos, - If a previous run on a physical runner has failed to clean up, the next - run will fail because it'll try to check out the code to a broken - directory mount. Make cleanup the first step. + tweaked by schwarze + + ok schwarze + + OpenBSD-Commit-ID: 565046e3ce68b46c2f440a93d67c2a92726de8ed -commit 46b91b70ff3cb9c147e2875ef5dc609fd64c0c96 -Author: Darren Tucker -Date: Fri Jul 15 20:25:27 2022 +1000 +commit 86af013b56cecb5ee58ae0bd9d495cd586fc5918 +Author: jsg@openbsd.org +Date: Sat Sep 10 08:50:53 2022 +0000 - Rename bbone test target to ARM. + upstream: fix repeated words ok miod@ jmc@ + + OpenBSD-Commit-ID: 6765daefe26a6b648cc15cadbbe337596af709b7 -commit 751d22cdeffed9fe921db78eedc32a29f9e80510 -Author: Darren Tucker -Date: Fri Jul 15 13:37:29 2022 +1000 +commit 0ba39b93b326a7d5dfab776cc9b9d326161a9b16 +Author: djm@openbsd.org +Date: Fri Sep 9 03:31:42 2022 +0000 + + upstream: notifier_complete(NULL, ...) is a noop, so no need to test + + that ctx!=NULL; from Corinna Vinschen + + OpenBSD-Commit-ID: ade2f2e9cc519d01a586800c25621d910bce384a + +commit be197635329feb839865fdc738e34e24afd1fca8 +Author: Sam James +Date: Thu Sep 8 02:49:29 2022 +0100 - Add AUDIT_ARCH_PPC to supported seccomp arches. + openbsd-compat/bsd-asprintf: add include for vsnprintf - Patch from dries.deschout at dodeco.eu. + Fixes the following build failure with Clang 15 on musl: + ``` + bsd-asprintf.c:51:8: error: call to undeclared library function 'vsnprintf' with type 'int (char *, unsigned long, const char *, struct __va_list_tag *)'; ISO C99 and laterclang -O2 -pipe -fdiagnostics-color=always -frecord-gcc-switches -pipe -Wunknown-warning-option -Qunused-arguments -Wall -Wpointer-arith -Wuninitialized -Wsign-compare -Wformat-security -Wsizeof-pointer-memaccess -Wno-pointer-sign -Wno-unused-result -Wmisleading-indentation -Wbitwise-instead-of-logical -fno-strict-aliasing -mretpoline -ftrapv -fzero-call-used-regs=all -fno-builtin-memset -fstack-protector-strong -fPIE -I. -I. -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE -DSSHDIR=\"/etc/ssh\" -D_PATH_SSH_PROGRAM=\"/usr/bin/ssh\" -D_PATH_SSH_ASKPASS_DEFAULT=\"/usr/lib/misc/ssh-askpass\" -D_PATH_SFTP_SERVER=\"/usr/lib/misc/sftp-server\" -D_PATH_SSH_KEY_SIGN=\"/usr/lib/misc/ssh-keysign\" -D_PATH_SSH_PKCS11_HELPER=\"/usr/lib/misc/ssh-pkcs11-helper\" -D_PATH_SSH_SK_HELPER=\"/usr/lib/misc/ssh-sk-helper\" -D_PATH_SSH_PIDDIR=\"/run\" -D_PATH_PRIVSEP_CHROOT_DIR=\"/var/empty\" -DHAVE_CONFIG_H -c cipher-aes.c -o cipher-aes.o + do not support + implicit function declarations [-Wimplicit-function-declaration] + ret = vsnprintf(string, INIT_SZ, fmt, ap2); + ^ + bsd-asprintf.c:51:8: note: include the header or explicitly provide a declaration for 'vsnprintf' + 1 error generated. + ``` -commit a061792a6e8d235fc40a9b5d4c22a1762bb75a7b +commit 6cb6f660bb35f77a0456dd2581ddf39c29398a5e Author: Darren Tucker -Date: Thu Jul 14 19:20:24 2022 +1000 +Date: Fri Sep 2 16:43:27 2022 +1000 - Remove unintended changes. - - I inadvertently included a couple of local changes with the OpenSSL - 3.0.4 change. Revert, anything that should be there will be committed - separately. + Remove DEF_WEAK, it's already in defines.h. -commit 527cb43fa1b4e55df661feabbac51b8e608b6519 +commit ce39e7d8b70c4726defde5d3bc4cb7d40d131153 Author: Darren Tucker -Date: Thu Jul 14 11:22:08 2022 +1000 +Date: Fri Sep 2 14:28:14 2022 +1000 - Return ERANGE from getcwd() if buffer size is 1. - - If getcwd() is supplied a buffer size of exactly 1 and a path of "/", it - could result in a nul byte being written out of array bounds. POSIX says - it should return ERANGE if the path will not fit in the available buffer - (with terminating nul). 1 byte cannot fit any possible path with its nul, - so immediately return ERANGE in that case. + Resync arc4random with OpenBSD. - OpenSSH never uses getcwd() with this buffer size, and all current - (and even quite old) platforms that we are currently known to work - on have a native getcwd() so this code is not used on those anyway. - Reported by Qualys, ok djm@ + This brings us up to current, including djm's random-reseeding change, + as prompted by logan at cyberstorm.mu in bz#3467. It brings the + platform-specific hooks from LibreSSL Portable, simplified to match our + use case. ok djm@. -commit 36857fefd8849c4b0e877cfd9d1eb22f79b76650 +commit beaddde26f30e2195b8aa4f3193970e140e17305 Author: Darren Tucker -Date: Thu Jul 14 10:02:35 2022 +1000 +Date: Fri Sep 2 14:20:04 2022 +1000 - Split README.platform into its own line. + Move OPENBSD ORIGINAL marker. - README.platform has general platform-specific information, having it - following text about FIDO2 on the same line could imply that it only - has information about FIDO2. + Putting this after the copyright statement (which doesn't change) + instead of before the version identifier (which does) prevents merge + conflicts when resyncing changes. -commit 00a496c6c14f2d41f2a9365714d494dd5f3aac9f +commit c83e467ead67a8cb48ef4bec8085d6fb880a2ff4 Author: Darren Tucker -Date: Thu Jul 14 09:56:01 2022 +1000 +Date: Fri Sep 2 14:17:28 2022 +1000 - Clarify README.md text. + Remove arc4random_uniform from arc4random.c - Clarify the text about the implications of building without OpenSSL, and - prefix the "configure --help" example command with a "./" so it's likely - to work as-is in more shells. From bz#3461. + This was previously moved into its own file (matching OpenBSD) which + prematurely committed in commit 73541f2. -commit f40b52f21fbc52eb513279168a49d3285c65256c -Author: Darren Tucker -Date: Tue Jul 12 19:48:44 2022 +1000 +commit 5f45c2395c60865e59fa44152ff1d003a128c5bc +Author: djm@openbsd.org +Date: Fri Sep 2 04:20:02 2022 +0000 - Remove special casing of crypt(). + upstream: sk-usbhid: fix key_lookup() on tokens with built-in UV - Configure goes to some lengths to pick crypt() from either libcrypt - or OpenSSL's libcrypto because they can more or less featureful (eg - supporting md5-style passwords). + explicitly test whether the token performs built-in UV (e.g. biometric + tokens) and enable UV in that case. From Pedro Martelletto via GHPR#388 - OpenSSL removed its crypt() interface in 2002: - https://github.com/openssl/openssl/commit/69deec58 so these hijinks - should no longer be necessary. This also only links sshd with libcrypt - which is the only thing that needs it. ok djm@ + OpenBSD-Commit-ID: 007eb7e387d27cf3029ab06b88224e03eca62ccd -commit 76f4e48631d7b09fb243b47d7b393d100d3741b7 +commit 03277a4aa49b80af541a3e691f264c0c0d8f9cec Author: Darren Tucker -Date: Wed Jul 13 13:17:47 2022 +1000 +Date: Wed Aug 31 20:26:30 2022 +1000 - Only refuse to use OpenSSL 3.0.4 on x86_64. + Move sftp from valgrind-2 to 3 to rebalance. + +commit fcf5365da69c516817321ba89c3a91df98d098df +Author: djm@openbsd.org +Date: Wed Aug 31 02:56:40 2022 +0000 + + upstream: whitespace - The potential RCE only impacts x86_64, so only refuse to use it if we're - targetting a potentially impacted architecture. ok djm@ + OpenBSD-Commit-ID: c2bcbf93610d3d62ed206cdf9bf9ff98c6aaf232 -commit e75bbc1d88491fa85e61b2cc8783d4bbd00cd131 -Author: Darren Tucker -Date: Tue Jul 12 14:37:15 2022 +1000 +commit e60136a3d7a223dd8e84ba8a6895bc3142360993 +Author: Damien Miller +Date: Mon Aug 29 13:27:45 2022 +1000 - Capture stderr output from configure. + additional keys -commit d9eaea4bea6271bcee6a2b9428f1271faf2d033b -Author: Darren Tucker -Date: Tue Jul 12 12:54:49 2022 +1000 +commit 2b02dcb505288c462d1b5dd1ac04e603d01340eb +Author: Damien Miller +Date: Mon Aug 29 13:23:43 2022 +1000 - Refuse to use OpenSSL 3.0.4 due to potential RCE. + cross-sign allowed_signers with PGP key - OpenSSL has a potential RCE in its RSA implementation (CVE-2022-2274) - so refuse to use that specific version. + Provides continuity of trust from legacy PGP release key to + the SSHSIG signing keys that we will use henceforth for git + signing. -commit fb2f3a61bf3d28fff285524535f7ffcd177c9235 +commit 51b345f177ae981b8755f6bdf8358b1cc5e83d67 Author: Darren Tucker -Date: Tue Jul 12 12:54:24 2022 +1000 +Date: Sat Aug 27 21:49:27 2022 +1000 - Move unset to before we set anything. + Add libcrypt-devel to cygwin-release deps. + + Based on feedback from vinschen at redhat.com. -commit c483a5c0fb8e8b8915fad85c5f6113386a4341ca +commit 9f81736cf16dd8dda1c8942f1973a5f80b8cd78c Author: Darren Tucker -Date: Wed Jul 6 11:52:54 2022 +1000 +Date: Sat Aug 27 09:37:40 2022 +1000 - Test against openssl-3.0.5. + Add Windows 2022 test targets. -commit 669a56bcfe73f8b985f2bba476ba834d55253acf +commit 85e1a69243f12be8520438ad6a3cfdc0b7fcbb2d Author: Darren Tucker -Date: Tue Jul 5 18:35:53 2022 +1000 +Date: Fri Aug 26 16:26:06 2022 +1000 - Update sanitizer test targets: + Add cygwin-release test target. - - remove clang-sanitize-memory for now. It takes so long that the test - times out. - - add gcc sanitize-address and sanitize-undefined test targets. + This also moves the cygwin package install from the workflow file to + setup_ci.sh so that we can install different sets of Cygwin packages + for different test configs. -commit 48cc68b69118b3ce8d07fd4f82e00d58667d5379 -Author: Darren Tucker -Date: Tue Jul 5 16:23:28 2022 +1000 +commit 92382dbe8bf9ea1225b16858f9b9b208c15c7e8d +Author: djm@openbsd.org +Date: Fri Aug 26 08:16:27 2022 +0000 - Add GCC address sanitizer build/test. + upstream: whitespace + + OpenBSD-Commit-ID: a5d015efbfd228dc598ffdef612d2da3a579e5d8 -commit 55c60bdd39b82457e92efa77da8d16cfa6a49391 -Author: Darren Tucker -Date: Tue Jul 5 12:02:33 2022 +1000 +commit 70a5de0a50e84d7250eb4e4537f765599f64c4af +Author: djm@openbsd.org +Date: Fri Aug 26 08:12:56 2022 +0000 - Move sanitizer logs into regress for collection. + upstream: whitespace + + OpenBSD-Commit-ID: d297e4387935d4aef091c5e9432578c2e513f538 -commit 35ef2b3b6ef198f8574904a45780487ec2f17858 -Author: dtucker@openbsd.org -Date: Mon Jul 4 09:10:31 2022 +0000 +commit 3a683a19fd116ea15ebf8aa13d02646cceb302a9 +Author: Damien Miller +Date: Fri Aug 26 14:23:55 2022 +1000 - upstream: Add TEST_REGRESS_CACHE_DIR. - - If set, it is used to cache regress test names that have succeeded and - skip those on a re-run. - - OpenBSD-Regress-ID: a7570dd29a58df59f2cca647c3c2ec989b49f247 + initial list of allowed signers -commit 7394ed80c4de8b228a43c8956cf2fa1b9c6b2622 +commit 6851f4b8c3fc1b3e1114c56106e4dc31369c8513 Author: Darren Tucker -Date: Sun Jul 3 21:46:44 2022 +1000 +Date: Fri Aug 19 17:22:18 2022 +1000 - Add clang sanitizer tests. + Install Cygwin packages based on OS not config. -commit bfce0e66b6017a9bfab450b9dc7d4b16f90de817 -Author: Darren Tucker -Date: Sun Jul 3 18:14:09 2022 +1000 +commit f96480906893ed93665df8cdf9065865c51c1475 +Author: djm@openbsd.org +Date: Fri Aug 19 06:07:47 2022 +0000 - Skip all rlimit tests when sandboxing disabled. + upstream: attemp FIDO key signing without PIN and use the error - The rlimit tests can hang when being run with some compiler sanitizers - so skip all of them if sandbox=no. + code returned to fall back only if necessary. Avoids PIN prompts for FIDO + tokens that don't require them; part of GHPR#302 + + OpenBSD-Commit-ID: 4f752aaf9f2e7c28bcaaf3d4f8fc290131bd038e -commit 6208d611520f9ea94d5369f9da404b709930029d -Author: Darren Tucker -Date: Sun Jul 3 17:54:49 2022 +1000 +commit 5453333b5d28e313284cb9aae82899704103f98d +Author: djm@openbsd.org +Date: Fri Aug 19 05:53:28 2022 +0000 - Move checks for pollfd.fd and nfds_t. + upstream: remove incorrect check that can break enrolling a - Move the checks for struct pollfd.fd and nfds_t to before the sandboxing - checks. This groups all the sandbox checks together so we can skip them - all when sandboxing is disabled. + resident key (introduced in r1.40) + + OpenBSD-Commit-ID: 4cab364d518470e29e624af3d3f9ffa9c92b6f01 -commit 322964f8f2e9c321e77ebae1e4d2cd0ccc5c5a0b +commit ff89b1bed80721295555bd083b173247a9c0484e Author: dtucker@openbsd.org -Date: Fri Jul 1 05:08:23 2022 +0000 +Date: Fri Aug 19 04:02:46 2022 +0000 - upstream: Remove leftover line. + upstream: Strictly enforce the maximum allowed SSH2 banner size in - Remove extra line leftover from merge conflict. ok djm@ + ssh-keyscan and prevent a one-byte buffer overflow. Patch from Qualys, ok + djm@ - OpenBSD-Commit-ID: 460e2290875d7ae64971a7e669c244b1d1c0ae2e + OpenBSD-Commit-ID: 6ae664f9f4db6e8a0589425f74cd0bbf3aeef4e4 -commit 7ec81daad0e03a64e8d91c5590960c48c1a899a3 -Author: djm@openbsd.org -Date: Fri Jul 1 04:45:50 2022 +0000 +commit 1b470b9036639cef4f32fb303bb35ea0b711178d +Author: Darren Tucker +Date: Fri Aug 19 15:18:09 2022 +1000 - upstream: use consistent field names (s/char/byte) - - in format description - - OpenBSD-Commit-ID: 3de33572733ee7fcfd7db33d37db23d2280254f0 + Fix cygwin conditional steps. -commit 32e82a392d9f263485effdd606ff5862d289a4a0 +commit fd6ee741ab16714b7035d60aca924123ba28135a Author: Darren Tucker -Date: Fri Jul 1 13:55:19 2022 +1000 +Date: Fri Aug 19 15:12:57 2022 +1000 - Skip select+rlimit check if sandboxing is disabled + Add a bit more debug output. + +commit a9305c4c739f4d91a3d3a92c0b6d4949404a36c5 +Author: Darren Tucker +Date: Fri Aug 12 15:08:47 2022 +1000 + + Add Cygwin (on windows-2019) test target. - It's not needed in that case, and the test can fail when being built - with some compiler memory sanitizer flags. bz#3441 + In addition to installing the requisite Cygwin packages, we also need to + explicitly invoke "sh" for steps that run other scripts since the runner + environment doesn't understand #! paths. -commit 4be7184ebe2a2ccef175983517a35ee06766e1b4 +commit 5062ad48814b06162511c4f5924a33d97b6b2566 Author: djm@openbsd.org -Date: Fri Jul 1 03:52:57 2022 +0000 +Date: Fri Aug 19 03:06:30 2022 +0000 - upstream: bump up loglevel from debug to info when unable to open - - authorized keys/principals file for errno != ENOENT; bz2042 ok dtucker + upstream: double free() in error path; from Eusgor via GHPR333 - OpenBSD-Commit-ID: e79aa550d91ade6a80f081bda689da24c086d66b + OpenBSD-Commit-ID: 39f35e16ba878c8d02b4d01d8826d9b321be26d4 -commit 6c31ba10e97b6953c4f325f526f3e846dfea647a -Author: dtucker@openbsd.org -Date: Fri Jul 1 03:39:44 2022 +0000 +commit 5a5c580b48fc6006bdfa731fc2f6d4945c2c0e4e +Author: Darren Tucker +Date: Thu Aug 18 21:36:39 2022 +1000 - upstream: Don't leak the strings allocated by order_hostkeyalgs() - - and list_hostkey_types() that are passed to compat_pkalg_proposal(). Part of - github PR#324 from ZoltanFridrich, ok djm@ - - This is a roll-forward of the previous rollback now that the required - changes in compat.c have been done. + Check for perms to run agent-getpeereid test. - OpenBSD-Commit-ID: c7cd93730b3b9f53cdad3ae32462922834ef73eb + Ubuntu 22.04 defaults to private home dirs which prevents "nobody" + running ssh-add during the agent-getpeereid test. Check for this and + add the necessary permissions. -commit 486c4dc3b83b4b67d663fb0fa62bc24138ec3946 -Author: dtucker@openbsd.org -Date: Fri Jul 1 03:35:45 2022 +0000 +commit cd06a76b7ccc706e2bb4f1cc4aa9e9796a28a812 +Author: Damien Miller +Date: Wed Aug 17 16:04:16 2022 +1000 - upstream: Always return allocated strings from the kex filtering so - - that we can free them later. Fix one leak in compat_kex_proposal. Based on - github PR#324 from ZoltanFridrich with some simplications by me. ok djm@ + on Cygwin, prefer WinHello FIDO device - OpenBSD-Commit-ID: 9171616da3307612d0ede086fd511142f91246e4 + If no FIDO device was explictly specified, then prefer the + windows://hello FIDO device. An exception to this is when + probing resident FIDO keys, in which case hardware FIDO + devices are preferred. -commit 96faa0de6c673a2ce84736eba37fc9fb723d9e5c +commit 47f72f534ac5cc2cd3027675a3df7b00a8f77575 Author: djm@openbsd.org -Date: Fri Jul 1 00:36:30 2022 +0000 +Date: Wed Aug 17 06:01:57 2022 +0000 - upstream: ignore SIGPIPE earlier in main(), specifically before + upstream: add an extra flag to sk_probe() to indicate whether we're - muxclient() which performs operations that could cause one; Reported by Noam - Lewis via bz3454, ok dtucker@ + probing for a FIDO resident key or not. Unused here, but will make like + easier for portable - OpenBSD-Commit-ID: 63d8e13276869eebac6d7a05d5a96307f9026e47 + OpenBSD-Commit-ID: 432c8ff70e270378df9dbceb9bdeaa5b43b5a832 -commit 33efac790f6b09d54894ba6c3e17dfb08b6fc7e1 +commit edb0bcb3c79b16031dc87a8e57aecc3c4a3414f0 Author: jmc@openbsd.org -Date: Tue Jun 28 06:09:14 2022 +0000 +Date: Tue Aug 16 20:24:08 2022 +0000 - upstream: reflect the update to -D arg name in usage(); + upstream: use .Cm for "sign"; from josiah frentsos - OpenBSD-Commit-ID: abdcde4f92b1ef094ae44210ee99d3b0155aad9c - -commit c71a1442d02f0a3586109dfe2cb366de36dee08e -Author: Darren Tucker -Date: Wed Jun 29 18:28:47 2022 +1000 - - Update OpenSSL tests to the most recent releases. + OpenBSD-Commit-ID: 7f80a53d54857ac6ae49ea6ad93c5bd12231d1e4 -commit 2a822f29300b2de7335fbff65f0b187a0c582304 -Author: djm@openbsd.org -Date: Mon Jun 27 21:41:55 2022 +0000 +commit cccb011e130cbbac538b1689d10e4a067298df8b +Author: Corinna Vinschen +Date: Thu Aug 11 20:19:35 2022 +0200 - upstream: allow arguments to sftp -D option, e.g. sftp -D + Revert "check_sk_options: add temporary WinHello workaround" - "/usr/libexec/sftp-server -el debug3" + Cygwin now comes with libfido2 1.11.0, so this workaround + isn't required anymore. - ok markus@ + This reverts commit 242c044ab111a37aad3b0775727c36a4c5f0102c. - OpenBSD-Commit-ID: 5a002b9f3a7aef2731fc0ffa9c921cf15f38ecce + Signed-off-by: Corinna Vinschen -commit 2369a2810187e08f2af5d58b343956062fb96ee8 -Author: dtucker@openbsd.org -Date: Fri Jun 24 10:45:06 2022 +0000 +commit 9468cd7cf9d989dfa2ac20e2a0268ba6e93bfa5a +Author: Corinna Vinschen +Date: Thu Aug 11 20:18:17 2022 +0200 - upstream: Roll back previous KEX changes as they aren't safe until + fido_dev_is_winhello: return 0, not "false" - compat_pkalg_proposal and friends always allocate their returned strings. - Reported by Qualys. + "false" is not used anywhere in OpenSSH, so return 0 like + everywhere else. - OpenBSD-Commit-ID: 1c7a88a0d5033f42f88ab9bec58ef1cf72c81ad0 + Signed-off-by: Corinna Vinschen -commit 646686136c34c2dbf6a01296dfaa9ebee029386d -Author: dtucker@openbsd.org -Date: Fri Jun 24 04:37:00 2022 +0000 +commit 730a80609472ee0451c99482d75c9c41f3ebc42d +Author: djm@openbsd.org +Date: Fri Aug 12 05:20:28 2022 +0000 - upstream: Don't leak the strings allocated by order_hostkeyalgs() + upstream: sftp-server: support home-directory request - and list_hostkey_types() that are passed to compat_pkalg_proposal(). Part of - github PR#324 from ZoltanFridrich, ok djm@ + Add support to the sftp-server for the home-directory extension defined + in draft-ietf-secsh-filexfer-extensions-00. This overlaps a bit with the + existing expand-path@openssh.com, but uses a more official protocol name, + and so is a bit more likely to be implemented by non-OpenSSH clients. - OpenBSD-Commit-ID: b2f6e5f60f2bba293b831654328a8a0035ef4a1b + From Mike Frysinger, ok dtucker@ + + OpenBSD-Commit-ID: bfc580d05cc0c817831ae7ecbac4a481c23566ab -commit 193c6d8d905dde836b628fc07a7b9cf2d347e2a3 +commit 5e820bf79ce3ce99ef7e98b0ab642b0a0a4f396c Author: Darren Tucker -Date: Sat Jun 25 12:16:15 2022 +1000 +Date: Fri Aug 12 14:56:55 2022 +1000 - Zero out LIBFIDO2 when SK support not usable. - - Prevents us from trying to link them into ssh-sk-helper and failing to - build. + Replace deprecated ubuntu-18.04 runners with 22.04 -commit 40f5d849d25c60b4ae21261e78484d435f5cfd51 +commit 87b0d9c1b789d3ff958ec45df2ac912e24461bae Author: Darren Tucker -Date: Sat Jun 25 11:47:28 2022 +1000 +Date: Thu Aug 11 22:48:23 2022 +1000 - Disable SK support if FIDO libs not found. + Add a timegm implementation from Heimdal via Samba. + + Fixes build on (at least Solaris 10). -commit 5fd922ade1b25880fe8a8249f5c0385e413108f9 -Author: Damien Miller -Date: Fri Jun 24 14:43:54 2022 +1000 +commit d0c4fa58594577994921b593f10037c5282597ca +Author: Darren Tucker +Date: Thu Aug 11 14:23:58 2022 +1000 - fix broken case statement in previous + Rerun tests if any .github config file changes. -commit f51423bdaf0008d46b6af082bcfd7a22a87375f0 -Author: Damien Miller -Date: Fri Jun 24 14:40:42 2022 +1000 +commit 113fe6c77ab43769fc61e953d07cb619fd7ea54b +Author: Darren Tucker +Date: Thu Aug 11 13:33:51 2022 +1000 - request 1.1x API compatibility for OpenSSL >=3.x + Skip hostbased during Valgrind tests. - idea/patch from Pedro Martelletto via GHPR#322; ok dtucker@ + Valgrind doesn't let ssh exec ssh-keysign (because it's setuid) so skip + it during the Valgrind based tests. + + See https://bugs.kde.org/show_bug.cgi?id=119404 for a discussion of this + (ironically there the problematic binary was ssh(1) back when it could + still be setuid). -commit 455cee8d6c2e4c48c5af9faead3599c49948411e +commit b98a42afb69d60891eb0488935990df6ee571c4d Author: djm@openbsd.org -Date: Fri Jun 24 04:27:14 2022 +0000 +Date: Thu Aug 11 01:57:50 2022 +0000 - upstream: make it clear that RekeyLimit applies to both transmitted + upstream: add some tests for parse_absolute_time(), including cases - and received data. GHPR#328 from Jan Pazdziora + where it is forced to the UTC timezone. bz3468 ok dtucker - OpenBSD-Commit-ID: d180a905fec9ff418a75c07bb96ea41c9308c3f9 + OpenBSD-Regress-ID: ea07ca31c2f3847a38df028ca632763ae44e8759 -commit 17904f05802988d0bb9ed3c8d1d37411e8f459c3 -Author: tobhe@openbsd.org -Date: Tue Jun 21 14:52:13 2022 +0000 +commit ec1ddb72a146fd66d18df9cd423517453a5d8044 +Author: djm@openbsd.org +Date: Thu Aug 11 01:56:51 2022 +0000 - upstream: Make sure not to fclose() the same fd twice in case of an - - error. + upstream: allow certificate validity intervals, sshsig verification - ok dtucker@ + times and authorized_keys expiry-time options to accept dates in the UTC time + zone in addition to the default of interpreting them in the system time zone. + YYYYMMDD and YYMMDDHHMM[SS] dates/times will be interpreted as UTC if + suffixed with a 'Z' character. - OpenBSD-Commit-ID: e384c4e05d5521e7866b3d53ca59acd2a86eef99 - -commit f29d6cf98c25bf044079032d22c1a57c63ab9d8e -Author: dtucker@openbsd.org -Date: Sat Jun 18 02:17:16 2022 +0000 - - upstream: Don't attempt to fprintf a null identity comment. From + Also allow certificate validity intervals to be specified in raw + seconds-since-epoch as hex value, e.g. -V 0x1234:0x4567890. This + is intended for use by regress tests and other tools that call + ssh-keygen as part of a CA workflow. - Martin Vahlensieck via tech@. + bz3468 ok dtucker - OpenBSD-Commit-ID: 4c54d20a8e8e4e9912c38a7b4ef5bfc5ca2e05c2 + OpenBSD-Commit-ID: 454db1cdffa9fa346aea5211223a2ce0588dfe13 -commit ad1762173bb38716a106e8979806149fd0f2753e -Author: dtucker@openbsd.org -Date: Fri Jun 17 01:00:03 2022 +0000 +commit 4df246ec75751da7eb925e1880498300d8bda187 +Author: Darren Tucker +Date: Thu Aug 11 10:23:55 2022 +1000 - upstream: Log an error if pipe() fails while accepting a - - connection. bz#3447, from vincent-openssh at vinc17 net, ok djm@ - - OpenBSD-Commit-ID: 9d59f19872b94900a5c79da2d57850241ac5df94 + Fix conditional for running hostbased tests. -commit 9c59e7486cc8691401228b43b96a3edbb06e0412 +commit 2580916e48721802220c61ce9e0df1297c00bc07 Author: Damien Miller -Date: Fri Jun 24 14:20:43 2022 +1000 +Date: Thu Aug 11 08:58:28 2022 +1000 - automatically enable built-in FIDO support - - If libfido2 is found and usable, then enable the built-in - security key support unless --without-security-key-builtin - was requested. - - ok dtucker@ + fix SANDBOX_SECCOMP_FILTER_DEBUG -commit 7d25b37fb2a5ff4dadabcbdac6087a97479434f5 -Author: Damien Miller -Date: Fri Jun 24 13:46:39 2022 +1000 +commit fdbd5bf507fc271ff813714fab8a72ff2c6cb5ca +Author: Darren Tucker +Date: Wed Aug 10 17:35:52 2022 +1000 - fix possible NULL deref when built without FIDO - - Analysis/fix from kircher in bz3443; ok dtucker@ + Test hostbased auth on github runners. -commit f5ba85daddfc2da6a8dab6038269e02c0695be44 -Author: djm@openbsd.org -Date: Wed Jun 15 16:08:25 2022 +0000 +commit 7e2f51940ba48a1c0fae1107801ea643fa83c971 +Author: Darren Tucker +Date: Wed Aug 10 17:25:24 2022 +1000 - upstream: make sure that UseDNS hostname lookup happens in the monitor - - and not in the pledge(2)'d unprivileged process; fixes regression caused by - recent refactoring spotted by henning@ + Rename our getentropy to prevent possible loops. - OpenBSD-Commit-ID: a089870b95101cd8881a2dff65b2f1627d13e88d - -commit acb2059febaddd71ee06c2ebf63dcf211d9ab9f2 -Author: djm@openbsd.org -Date: Fri Jun 3 04:47:21 2022 +0000 + Since arc4random seeds from getentropy, and we use OpenSSL for that + if enabled, there's the possibility that if we build on a system that + does not have getentropy then run on a system that does have it, then + OpenSSL could end up calling our getentropy and getting stuck in a loop. + Pointed out by deraadt@, ok djm@ - upstream: move auth_openprincipals() and auth_openkeyfile() over to - - auth2-pubkeyfile.c too; they make more sense there. - - OpenBSD-Commit-ID: 9970d99f900e1117fdaab13e9e910a621b7c60ee +commit 7a01f61be8d0aca0e975e7417f26371495fe7674 +Author: Darren Tucker +Date: Mon Aug 8 12:17:04 2022 +1000 -commit 3d9b0845f34510111cc693bb99a667662ca50cd8 -Author: djm@openbsd.org -Date: Fri Jun 3 04:31:54 2022 +0000 + Actually put HAVE_STDINT_H around the stdint.h. - upstream: test setenv in both client and server, test first-match-wins - - too +commit 73541f29f0b50480da6c20dceb7a7191bd8ea7d3 +Author: Darren Tucker +Date: Mon Aug 8 10:30:34 2022 +1000 + + Give unused param a name. - OpenBSD-Regress-ID: 4c8804f9db38a02db480b9923317457b377fe34b + Fixes builds on platforms that do have fido2 but don't have + fido_dev_is_winhello. -commit 22e1a3a71ad6d108ff0c5f07f93c3fcbd30f8b40 +commit 2a108c0ea960381bd9b14ee0d84e818a23df4482 Author: djm@openbsd.org -Date: Fri Jun 3 04:30:46 2022 +0000 +Date: Fri Aug 5 05:01:40 2022 +0000 - upstream: Make SetEnv directives first-match-wins in both - - sshd_config and sshd_config; previously if the same name was reused then the - last would win (which is the opposite to how the config is supposed to work). + upstream: don't prompt for FIDO passphrase before attempting to enroll - While there, make the ssh_config parsing more like sshd_config. + the credential, just let the enroll operating fail and we'll attempt to get a + PIN anyway. Might avoid some unneccessary PIN prompts. - bz3438, ok dtucker + Part of GHPR#302 from Corinna Vinschen; ok dtucker@ - OpenBSD-Commit-ID: 797909c1e0262c0d00e09280459d7ab00f18273b + OpenBSD-Commit-ID: bd5342ffc353ee37d39617906867c305564d1ce2 -commit 38ed6c57e9e592c08e020fa6e82b45b4e1040970 -Author: dtucker@openbsd.org -Date: Fri Jun 3 04:00:15 2022 +0000 +commit 2886975c0ad9244e60dc5e4be34fde3aa573a4b5 +Author: Corinna Vinschen +Date: Fri Feb 11 14:33:41 2022 +0100 - upstream: Add missing *-sk types to ssh-keyscan manpage. From + sk_sign: set FIDO2 uv attribute explicitely for WinHello - skazi0 via github PR#294. + WinHello via libfido2 performs user verification by default. + However, if we stick to that, there's no way to differentiate + between keys created with or without "-O verify-required". + Set FIDO2 uv attribute explicitely to FIDO_OPT_FALSE, then check + if user verification has been requested. - OpenBSD-Commit-ID: fda2c869cdb871f3c90a89fb3f985370bb5d25c0 + Signed-off-by: Corinna Vinschen -commit ea97ec98c41ec2b755dfab459347db674ff9a5de -Author: dtucker@openbsd.org -Date: Fri Jun 3 03:21:09 2022 +0000 +commit 242c044ab111a37aad3b0775727c36a4c5f0102c +Author: Corinna Vinschen +Date: Tue Feb 15 11:28:08 2022 +0100 - upstream: Add period at end of "not known by any other names" + check_sk_options: add temporary WinHello workaround - message. github PR#320 from jschauma, ok djm@ + Up to libfido 1.10.0, WinHello advertises "clientPin" rather + than "uv" capability. This is fixed in 1.11.0. For the time + being, workaround it here. - OpenBSD-Commit-ID: bd60809803c4bfd3ebb7c5c4d918b10e275266f2 + Signed-off-by: Corinna Vinschen -commit 88e376fcd67478ad1660d94bc73ab348ac9f4527 -Author: dtucker@openbsd.org -Date: Fri Jun 3 03:17:42 2022 +0000 +commit 78774c08cc4b4997382975b0f414a86e06b6780c +Author: Corinna Vinschen +Date: Thu Feb 10 18:19:29 2022 +0100 - upstream: ssh-keygen -A: do not generate DSA keys by default. - - Based on github PR#303 from jsegitz with man page text from jmc@, ok markus@ - djm@ + compat code for fido_dev_is_winhello() - OpenBSD-Commit-ID: 5c4c57bdd7063ff03381cfb6696659dd3f9f5b9f + Signed-off-by: Corinna Vinschen -commit 6b3fb624675082a1e5aa615d1b8479873d8b5731 -Author: naddy@openbsd.org -Date: Tue May 31 14:05:12 2022 +0000 +commit 3d3a932a019aedfb891e0779bb4990cd5008a390 +Author: Darren Tucker +Date: Fri Aug 5 13:12:27 2022 +1000 - upstream: ssh-keygen: implement "verify-required" certificate option. - - This was already documented when support for user-verified FIDO - keys was added, but the ssh-keygen(1) code was missing. - - ok djm@ + Factor out getrnd() and rename to getentropy(). - OpenBSD-Commit-ID: f660f973391b593fea4b7b25913c9a15c3eb8a06 + Factor out the arc4random seeding into its own file and change the + interface to match getentropy. Use native getentropy if available. + This will make it easier to resync OpenBSD changes to arc4random. + Prompted by bz#3467, ok djm@. -commit b7f86ffc301be105bba9a3e0618b6fab3ae379bd -Author: jmc@openbsd.org -Date: Sat May 28 05:57:56 2022 +0000 +commit 9385d277b787403be9dfcb229cf372202496d2f3 +Author: Darren Tucker +Date: Thu Aug 4 18:55:48 2022 +1000 - upstream: keywords ref ssh_config.5; + Include CHANNEL and FIDO2 libs in configure output + +commit 141535b904b6fba01724444f38193a8599201f82 +Author: djm@openbsd.org +Date: Mon Aug 1 11:09:26 2022 +0000 + + upstream: avoid double-free in error path introduced in r1.70; report - from caspar schutijser + and fix based on GHPR#332 by v-rzh ok dtucker@ - OpenBSD-Commit-ID: f146a19d7d5c9374c3b9c520da43b2732d7d1a4e + OpenBSD-Commit-ID: 3d21aa127b1f37cfc5bdc21461db369a663a951f -commit dc7bc52372f2744fa39191577be5306ee57aacd4 -Author: Damien Miller -Date: Mon May 30 09:29:09 2022 +1000 +commit dba7099ffcba3ca07b3946f017ba6a4c3158d9b1 +Author: Darren Tucker +Date: Wed Jul 27 18:40:12 2022 +1000 - fix some bugs in the fuzzer + Remove deprecated MacOS 10.15 runners. -commit 1781f507c113667613351c19898efaf1e311a865 +commit 722a56439aa5972c830e4a9a724cf52aff4a950a Author: Darren Tucker -Date: Fri May 27 18:19:48 2022 +1000 +Date: Wed Jul 27 18:31:14 2022 +1000 - Test against OpenSSL 1.1.1o and 3.0.3. + Move stale-configure check as early as possible. + + We added a check in Makefile to catch the case where configure needs to + be rebuilt, however this did not happen until a build was attempted in + which case all of the work done by configure was wasted. Move this check + to the start of configure to catch it as early as possible. ok djm@ -commit c53906e0c59e569691b4095d3e8db79cf78fa058 +commit 099d6b56288b421ba38531d26dc1bd6bb685e311 Author: Darren Tucker -Date: Fri May 27 18:18:31 2022 +1000 +Date: Fri Jul 22 10:47:19 2022 +1000 - Test against LibreSSL 3.5.3. + Move libcrypto into CHANNELLIBS. + + This will result in sftp, sftp-server and scp no longer being linked + against libcrypto. ok djm@ -commit 9b3ad432ad2f19319bcc089370e356c6315d682f -Author: Damien Miller -Date: Fri May 27 17:00:43 2022 +1000 +commit 1bdf86725b77733bb5f17c54888b88a10b2f6538 +Author: Darren Tucker +Date: Fri Jul 22 10:45:47 2022 +1000 - fuzzer for authorized_keys parsing + Remove seed_rng calls from scp, sftp, sftp-server. - mostly redundant to authopt_fuzz, but it's sensitive code so IMO it - makes sense to test this layer too + These binaries don't use OpenSSL's random functions. The next step + will be to stop linking them against libcrypto. ok djm@ -commit c83d8c4d6f3ccceef84d46de107f6b71cda06359 -Author: djm@openbsd.org -Date: Fri May 27 05:02:46 2022 +0000 +commit d73f77b8cb9b422f1ac4facee7890aa10ff2bc21 +Author: Darren Tucker +Date: Fri Jul 22 09:51:51 2022 +1000 - upstream: split the low-level file handling functions out from - - auth2-pubkey.c - - Put them in a new auth2-pubkeyfile.c to make it easier to refer to them - (e.g. in unit/fuzz tests) without having to refer to everything else - pubkey auth brings in. - - ok dtucker@ + Group libcrypto and PRNGD checks together. - OpenBSD-Commit-ID: 3fdca2c61ad97dc1b8d4a7346816f83dc4ce2217 + They're related more than the libcrypt or libiaf checks which are + currently between them. ok djm@ -commit 3b0b142d2a0767d8cd838e2f3aefde8a0aaa41e1 -Author: djm@openbsd.org -Date: Fri May 27 05:01:25 2022 +0000 +commit f117e372b3f42f2fbdb0a578d063b2609ab58e1f +Author: Darren Tucker +Date: Fri Jul 22 09:24:45 2022 +1000 - upstream: refactor authorized_keys/principals handling - - remove "struct ssh *" from arguments - this was only used to pass the - remote host/address. These can be passed in instead and the resulting - code is less tightly coupled to ssh_api.[ch] - - ok dtucker@ + Do not link scp, sftp and sftp-server w/ zlib. - OpenBSD-Commit-ID: 9d4373d013edc4cc4b5c21a599e1837ac31dda0d + Some of our binaries (eg sftp, sftp-server, scp) do not interact with + the channels code and thus do use libraries such as zlib and libcrypto + although they are linked with them. This adds a CHANNELLIBS and starts + by moving zlib into it, which means the aformentioned binaries are no + longer linked against zlib. ok djm@ -commit 2c334fd36f80cb91cc42e4b978b10aa35e0df236 -Author: dtucker@openbsd.org -Date: Fri May 27 04:29:40 2022 +0000 +commit 800c2483e68db38bd1566ff69677124be974aceb +Author: Darren Tucker +Date: Mon Jul 25 21:49:04 2022 +1000 - upstream: f sshpkt functions fail, then password is not cleared - - with freezero. Unconditionally call freezero to guarantee that password is - removed from RAM. - - From tobias@ and c3h2_ctf via github PR#286, ok djm@ + Remove workarounds for OpenSSL missing AES-CTR. - OpenBSD-Commit-ID: 6b093619c9515328e25b0f8093779c52402c89cd + We have some compatibility hacks that were added to support OpenSSL + versions that do not support AES CTR mode. Since that time, however, + the minimum OpenSSL version that we support has moved to 1.0.1 which + *does* have CTR, so this is no longer needed. ok djm@ -commit 5d3a77f4c5ae774c6796387266503f52c7cdc7c2 -Author: dtucker@openbsd.org -Date: Fri May 27 04:27:49 2022 +0000 +commit b7c56b65c12f51fe0dbae798d19c8f58224a5d95 +Author: Darren Tucker +Date: Mon Jul 25 21:43:00 2022 +1000 - upstream: Avoid kill with -1 argument. The out_ctx label can be - - reached before fork has been called. If this happens, then kill -1 would be - called, sending SIGTERM to all processes reachable by the current process. - - From tobias@ and c3h2_ctf via github PR#286, ok djm@ + Remove workarounds for OpenSSL missing AES-GCM. - OpenBSD-Commit-ID: 6277af1207d81202f5daffdccfeeaed4c763b1a8 + We have some compatibility hacks that were added to support OpenSSL + versions that do not support AES GCM mode. Since that time, however, + the minimum OpenSSL version that we support has moved to 1.0.1 which + *does* have GCM, so this is no longer needed. ok djm@ -commit 533b31cd08e4b97f455466f91c36915e2924c15a +commit 5a4a9f7a968fbf92cc1eac519c65638e79ae9f1f Author: dtucker@openbsd.org -Date: Fri May 27 04:13:24 2022 +0000 +Date: Mon Jul 25 07:12:45 2022 +0000 - upstream: Note that ProxyJump also accepts the same tokens as - - ProxyCommand. From pallxk via github PR#305. + upstream: Restore missing "!" in TEST_SSH_ELAPSED_TIMES test. - OpenBSD-Commit-ID: 7115ac351b129205f1f1ffa6bbfd62abd76be7c5 + OpenBSD-Regress-ID: 38783f9676ec348c5a792caecee9a16e354b37b0 -commit 9d8c80f8a304babe61ca28f2e3fb5eb6dc9c39bf -Author: djm@openbsd.org -Date: Wed May 25 06:03:44 2022 +0000 +commit 0ff886be132299386cc29d87c2aa16ff68a1aa08 +Author: dtucker@openbsd.org +Date: Sun Jul 24 23:29:10 2022 +0000 - upstream: revert previous; it was broken (spotted by Theo) + upstream: Test TEST_SSH_ELAPSED_TIMES for empty string not - OpenBSD-Commit-ID: 457c79afaca2f89ec2606405c1059b98b30d8b0d + executable. No-op on most platforms but should prevent warnings in -portable + on systems that don't have 'date %s'. + + OpenBSD-Regress-ID: e39d79867b8065e33d0c5926fa1a31f85659d2a4 -commit 9e0d02ef7ce88b67643bfb1c2272c9f5f04cc680 -Author: djm@openbsd.org -Date: Wed May 25 00:31:13 2022 +0000 +commit f69319ad8ad1dd50f90bbcf5912e11cc8ed3e037 +Author: Darren Tucker +Date: Sat Jul 23 14:38:22 2022 +1000 - upstream: make SSHBUF_DBG/SSHBUF_TELL (off by default and only enabled - - via #define) dump to stderr rather than stdout + Convert "have_prog" function into "which". - OpenBSD-Commit-ID: 10298513ee32db8390aecb0397d782d68cb14318 + "which" and its behaviour is not standardized, so convert the existing + have_prog function into "which" so we can rely on it being available + and what its semantics are. Add a have_prog wrapper that maintains the + existing behaviour. -commit 2487163630f28be28b7e2396b4bd6511b98f1d3e -Author: Tim Rice -Date: Tue May 24 10:21:25 2022 -0700 +commit ea7ecc2c3ae39fdf5c6ad97b7bc0b47a98847f43 +Author: Darren Tucker +Date: Sat Jul 23 14:36:38 2022 +1000 - configure.ac: Add missing AC_DEFINE for caph_cache_tzdata test causing - HAVE_CAPH_CACHE_TZDATA to be missing from config.h.in. - Spotted by Bryan Drewery + Skip scp3 test if there's no scp on remote path. + + scp -3 ends up using the scp that's in the remote path and will fail if + one is not available. Based on a patch from rapier at psc.edu. -commit bedb93415b60db3dfd704a3d525e82adb14a2481 -Author: djm@openbsd.org -Date: Sun May 15 23:48:07 2022 +0000 +commit c46f6fed419167c1671e4227459e108036c760f8 +Author: Damien Miller +Date: Wed Jul 20 13:39:14 2022 +1000 - upstream: regress test for in-place transfers and clobbering larger - - files with smaller ones; would have caught last regression in scp(1) - - OpenBSD-Regress-ID: 19de4e88dd3a4f7e5c1618c9be3c32415bd93bc2 + crank SSH_SK_VERSION_MAJOR in sk-dummy.so -commit b4f0d719c2548cb74da509fb65f384dada4ebd37 -Author: anton@openbsd.org -Date: Fri Apr 22 05:08:43 2022 +0000 +commit f208e3b9ffb5ee76cf9c95df7ff967adc7f51c7d +Author: djm@openbsd.org +Date: Wed Jul 20 03:33:22 2022 +0000 - upstream: Only run agent-ptrace.sh if gdb is available as all + upstream: ssh-keygen: fix touch prompt, pin retries; - architectures do not ship with gdb. + part of GHPR329 from Pedro Martelletto - OpenBSD-Regress-ID: ec53e928803e6b87f9ac142d38888ca79a45348d + OpenBSD-Commit-ID: 75d1005bd2ef8f29fa834c90d2684e73556fffe8 -commit 9b73345f80255a7f3048026462f2c0c6a241eeac +commit 8638a2ce7e90c8a51d9af3143404282126c524f8 Author: djm@openbsd.org -Date: Sun May 15 23:47:21 2022 +0000 +Date: Wed Jul 20 03:31:42 2022 +0000 - upstream: fix in-place copies; r1.163 incorrectly skipped truncation in + upstream: sk-usbhid: preserve error code returned by key_lookup() - all cases, not just at the start of a transfer. This could cause overwrites - of larger files to leave junk at the end. Spotted by tb@ + it conveys useful information, such as the supplied pin being wrong. - OpenBSD-Commit-ID: b189f19cd68119548c8e24e39c79f61e115bf92c + Part of GHPR329 from Pedro Martelletto + + OpenBSD-Commit-ID: c0647eb9290f793add363d81378439b273756c1b -commit 56a0697fe079ff3e1ba30a2d5c26b5e45f7b71f8 +commit 9ab929ca2d820520327b41929372bcb9e261534c Author: djm@openbsd.org -Date: Fri May 13 06:31:50 2022 +0000 +Date: Wed Jul 20 03:29:14 2022 +0000 - upstream: arrange for scp, when in sftp mode, to not ftruncate(3) files - - early + upstream: when enrolling a resident key on a security token, check - previous behavious of unconditionally truncating the destination file - would cause "scp ~/foo localhost:" and "scp localhost:foo ~/" to - delete all the contents of their destination. + if a credential with matching application and user ID strings already exists. + if so, prompt the user for confirmation before overwriting the credential. - spotted by solene@ sthen@, also bz3431; ok dtucker@ + patch from Pedro Martelletto via GHPR329 - OpenBSD-Commit-ID: ca39fdd39e0ec1466b9666f15cbcfddea6aaa179 - -commit fbcef70c2832712f027bccea1aa9bc4b4103da93 -Author: dtucker@openbsd.org -Date: Mon May 9 08:25:27 2022 +0000 - - upstream: Remove errant apostrophe. From haruyama at queen-ml org. + NB. cranks SSH_SK_VERSION_MAJOR, so any third-party FIDO middleware + implementations will need to adjust - OpenBSD-Commit-ID: dc6b294567cb84b384ad6ced9ca469f2bbf0bd10 + OpenBSD-Commit-ID: e45e9f1bf2b2f32d9850669e7a8dbd64acc5fca4 -commit 0086a286ea6bbd11ca9b664ac3bb12b27443d6eb +commit 5bcfc788b38d5b64e4c347bdc04bd9a01bbc36da Author: djm@openbsd.org -Date: Mon May 9 03:09:53 2022 +0000 +Date: Wed Jul 20 03:13:04 2022 +0000 - upstream: Allow existing -U (use agent) flag to work with "-Y sign" + upstream: pull passphrase reading and confirmation into a separate - operations, where it will be interpreted to require that the private keys is - hosted in an agent; bz3429, suggested by Adam Szkoda; ok dtucker@ + function so it can be used for FIDO2 PINs; no functional change - OpenBSD-Commit-ID: a7bc69873b99c32c42c7628ed9ea91565ba08c2f + OpenBSD-Commit-ID: bf34f76b8283cc1d3f54633e0d4f13613d87bb2f -commit cb010744cc98f651b1029bb09efa986eb54e4ccf -Author: djm@openbsd.org -Date: Sun May 8 22:58:35 2022 +0000 +commit eb679e2959bdb15454eb94751930eb4c9110da94 +Author: Darren Tucker +Date: Fri Jul 15 21:31:48 2022 +1000 - upstream: improve error message when 'ssh-keygen -Y sign' is unable to - - load a private key; bz3429, reported by Adam Szkoda ok dtucker@ + Move vmshutdown to first step. - OpenBSD-Commit-ID: bb57b285e67bea536ef81b1055467be2fc380e74 + If a previous run on a physical runner has failed to clean up, the next + run will fail because it'll try to check out the code to a broken + directory mount. Make cleanup the first step. -commit aa61fc82c63d309a90c22ca74fb1da6c6f4372fd -Author: Tobias Heider -Date: Mon May 9 02:00:01 2022 +0200 +commit 46b91b70ff3cb9c147e2875ef5dc609fd64c0c96 +Author: Darren Tucker +Date: Fri Jul 15 20:25:27 2022 +1000 - Remove duplicate bcrypt_pbkdf.o from Makefile - - bcrypt_pbkdf.o is duplicated in the openbsd-compat Makefile's object - file list. + Rename bbone test target to ARM. -commit deb506d00da8d11fb04c1e7b9b1e1cc379c1705c -Author: djm@openbsd.org -Date: Sun May 8 22:32:36 2022 +0000 +commit 751d22cdeffed9fe921db78eedc32a29f9e80510 +Author: Darren Tucker +Date: Fri Jul 15 13:37:29 2022 +1000 - upstream: When performing operations that glob(3) a remote path, ensure - - that the implicit working directory used to construct that path escapes - glob(3) characters. - - This prevents glob characters from being processed in places they - shouldn't, e.g. "cd /tmp/a*/", "get *.txt" should have the get operation - treat the path "/tmp/a*" literally and not attempt to expand it. - - Reported by Lusia Kundel; ok markus@ + Add AUDIT_ARCH_PPC to supported seccomp arches. - OpenBSD-Commit-ID: 4f647f58482cbad3d58b1eab7f6a1691433deeef + Patch from dries.deschout at dodeco.eu. -commit f38cf74f20b5da113cfa823afd5bfb5c6ba65f3d +commit a061792a6e8d235fc40a9b5d4c22a1762bb75a7b Author: Darren Tucker -Date: Fri May 6 14:50:18 2022 +1000 +Date: Thu Jul 14 19:20:24 2022 +1000 - Also retest OpenBSD upstream on .yml changes. + Remove unintended changes. + + I inadvertently included a couple of local changes with the OpenSSL + 3.0.4 change. Revert, anything that should be there will be committed + separately. -commit f87a132800ba3710ab130d703448a31ef1128d77 +commit 527cb43fa1b4e55df661feabbac51b8e608b6519 Author: Darren Tucker -Date: Fri May 6 14:46:09 2022 +1000 +Date: Thu Jul 14 11:22:08 2022 +1000 - Note that, for now, we need variadic macros. + Return ERANGE from getcwd() if buffer size is 1. + + If getcwd() is supplied a buffer size of exactly 1 and a path of "/", it + could result in a nul byte being written out of array bounds. POSIX says + it should return ERANGE if the path will not fit in the available buffer + (with terminating nul). 1 byte cannot fit any possible path with its nul, + so immediately return ERANGE in that case. + + OpenSSH never uses getcwd() with this buffer size, and all current + (and even quite old) platforms that we are currently known to work + on have a native getcwd() so this code is not used on those anyway. + Reported by Qualys, ok djm@ -commit 217b518e0f7c52c4b909e935141a55344c61e644 +commit 36857fefd8849c4b0e877cfd9d1eb22f79b76650 Author: Darren Tucker -Date: Fri May 6 14:39:34 2022 +1000 +Date: Thu Jul 14 10:02:35 2022 +1000 - Add ubsan minimal testcase on OpenBSD. + Split README.platform into its own line. - As suggested by djm@. + README.platform has general platform-specific information, having it + following text about FIDO2 on the same line could imply that it only + has information about FIDO2. -commit 457dce2cfef6a48f5442591cd8b21c7e8cba13f8 -Author: djm@openbsd.org -Date: Thu May 5 01:04:14 2022 +0000 +commit 00a496c6c14f2d41f2a9365714d494dd5f3aac9f +Author: Darren Tucker +Date: Thu Jul 14 09:56:01 2022 +1000 - upstream: sshkey_unshield_private() contains a exact duplicate of - - the code in private2_check_padding(). Pull private2_check_padding() up so the - code can be reused. From Martin Vahlensieck, ok deraadt@ + Clarify README.md text. - OpenBSD-Commit-ID: 876884c3f0e62e8fd8d1594bab06900f971c9c85 + Clarify the text about the implications of building without OpenSSL, and + prefix the "configure --help" example command with a "./" so it's likely + to work as-is in more shells. From bz#3461. -commit 0e44db4d9cb313e68a59a44d27884af66c02356e -Author: djm@openbsd.org -Date: Thu May 5 00:56:58 2022 +0000 +commit f40b52f21fbc52eb513279168a49d3285c65256c +Author: Darren Tucker +Date: Tue Jul 12 19:48:44 2022 +1000 - upstream: channel_new no longer frees remote_name. So update the + Remove special casing of crypt(). - comment accordingly. As remote_name is not modified, it can be const as - well. From Martin Vahlensieck + Configure goes to some lengths to pick crypt() from either libcrypt + or OpenSSL's libcrypto because they can more or less featureful (eg + supporting md5-style passwords). - OpenBSD-Commit-ID: e4e10dc8dc9f40c166ea5a8e991942bedc75a76a + OpenSSL removed its crypt() interface in 2002: + https://github.com/openssl/openssl/commit/69deec58 so these hijinks + should no longer be necessary. This also only links sshd with libcrypt + which is the only thing that needs it. ok djm@ -commit 37b62fd5caf19c85a48241535277cefff65adace -Author: djm@openbsd.org -Date: Thu May 5 00:55:11 2022 +0000 +commit 76f4e48631d7b09fb243b47d7b393d100d3741b7 +Author: Darren Tucker +Date: Wed Jul 13 13:17:47 2022 +1000 - upstream: mux.c: mark argument as const; from Martin Vahlensieck + Only refuse to use OpenSSL 3.0.4 on x86_64. - OpenBSD-Commit-ID: 69a1a93a55986c7c2ad9f733c093b46a47184341 + The potential RCE only impacts x86_64, so only refuse to use it if we're + targetting a potentially impacted architecture. ok djm@ -commit f4e67c0ad259b4cf10177277a5827fa5545bac53 -Author: markus@openbsd.org -Date: Wed May 4 07:31:22 2022 +0000 +commit e75bbc1d88491fa85e61b2cc8783d4bbd00cd131 +Author: Darren Tucker +Date: Tue Jul 12 14:37:15 2022 +1000 - upstream: make sure stdout is non-blocking; ok djm@ - - OpenBSD-Commit-ID: 64940fffbd1b882eda2d7c8c7a43c79368309c0d + Capture stderr output from configure. -commit e5c036d2092c00bef395e9161dc5ce42d4be9565 -Author: florian@openbsd.org -Date: Tue May 3 07:42:27 2022 +0000 +commit d9eaea4bea6271bcee6a2b9428f1271faf2d033b +Author: Darren Tucker +Date: Tue Jul 12 12:54:49 2022 +1000 - upstream: Add FIDO AUTHENTICATOR section and explain a bit how FIDO - - works. The wording came mostly from the 8.2 OpenSSH release notes, addapted - to fit the man page. Then move the -O bits into the new section as is already - done for CERTIFICATES and MODULI GENERATION. Finally we can explain the - trade-offs of resident keys. While here, consistently refer to the FIDO - thingies as "FIDO authenticators", not "FIDO tokens". - - input & OK jmc, naddy + Refuse to use OpenSSL 3.0.4 due to potential RCE. - OpenBSD-Commit-ID: dd98748d7644df048f78dcf793b3b63db9ab1d25 + OpenSSL has a potential RCE in its RSA implementation (CVE-2022-2274) + so refuse to use that specific version. -commit 575771bf79bef7127be6aaccddc46031ea15529e -Author: jmc@openbsd.org -Date: Mon May 2 05:40:37 2022 +0000 +commit fb2f3a61bf3d28fff285524535f7ffcd177c9235 +Author: Darren Tucker +Date: Tue Jul 12 12:54:24 2022 +1000 - upstream: remove an obsolete rsa1 format example from an example; - - from megan batty - ok djm - - OpenBSD-Commit-ID: db2c89879c29bf083df996bd830abfb1e70d62bf + Move unset to before we set anything. -commit 0bc6b4c8f04e292577bdb44d5dc6b630d3448087 -Author: djm@openbsd.org -Date: Sun May 1 23:20:30 2022 +0000 +commit c483a5c0fb8e8b8915fad85c5f6113386a4341ca +Author: Darren Tucker +Date: Wed Jul 6 11:52:54 2022 +1000 - upstream: fix some integer overflows in sieve_large() that show up when - - trying to generate modp groups > 16k bits. Reported via GHPR#306 by Bertram - Felgenhauer, but fixed in a different way. feedback/ok tb@ - - OpenBSD-Commit-ID: 81cbc6dd3a21c57bd6fadea10e44afe37bca558e + Test against openssl-3.0.5. -commit a45615cb172bc827e21ec76750de39dfb30ecc05 -Author: djm@openbsd.org -Date: Fri Apr 29 04:55:07 2022 +0000 +commit 669a56bcfe73f8b985f2bba476ba834d55253acf +Author: Darren Tucker +Date: Tue Jul 5 18:35:53 2022 +1000 - upstream: be stricter in which characters will be accepted in - - specifying a mask length; allow only 0-9. From khaleesicodes via GHPR#278; ok - dtucker@ + Update sanitizer test targets: - OpenBSD-Commit-ID: e267746c047ea86665cdeccef795a8a56082eeb2 + - remove clang-sanitize-memory for now. It takes so long that the test + times out. + - add gcc sanitize-address and sanitize-undefined test targets. -commit 4835544d2dd31de6ffc7dba59f92093aea98155b +commit 48cc68b69118b3ce8d07fd4f82e00d58667d5379 Author: Darren Tucker -Date: Sat Apr 30 10:56:41 2022 +1000 +Date: Tue Jul 5 16:23:28 2022 +1000 - Add Mac OS X 12 test target. + Add GCC address sanitizer build/test. -commit 97a6a8b8c1f2da09712d0e72d0ef800e4edd34cd +commit 55c60bdd39b82457e92efa77da8d16cfa6a49391 Author: Darren Tucker -Date: Fri Apr 29 18:27:34 2022 +1000 +Date: Tue Jul 5 12:02:33 2022 +1000 - Only run tests when source files change. + Move sanitizer logs into regress for collection. + +commit 35ef2b3b6ef198f8574904a45780487ec2f17858 +Author: dtucker@openbsd.org +Date: Mon Jul 4 09:10:31 2022 +0000 + + upstream: Add TEST_REGRESS_CACHE_DIR. - Also run tests on changes to V_9_0 branch. + If set, it is used to cache regress test names that have succeeded and + skip those on a re-run. + + OpenBSD-Regress-ID: a7570dd29a58df59f2cca647c3c2ec989b49f247 -commit 6d0392b9ff4b50a56ac5685d1b9392e2cd432ca3 +commit 7394ed80c4de8b228a43c8956cf2fa1b9c6b2622 Author: Darren Tucker -Date: Fri Apr 29 18:22:34 2022 +1000 +Date: Sun Jul 3 21:46:44 2022 +1000 - Remove now-empty int32_minmax.inc. + Add clang sanitizer tests. -commit af59463553b5ad52d3b42c4455ee3c5600158bb7 -Author: djm@openbsd.org -Date: Fri Apr 29 03:24:30 2022 +0000 +commit bfce0e66b6017a9bfab450b9dc7d4b16f90de817 +Author: Darren Tucker +Date: Sun Jul 3 18:14:09 2022 +1000 - upstream: mention that the helpers are used by ssh(1), ssh-agent(1) + Skip all rlimit tests when sandboxing disabled. - and ssh-keygen(1). Previously only ssh(1) was mentioned. From Pedro - Martelletto + The rlimit tests can hang when being run with some compiler sanitizers + so skip all of them if sandbox=no. + +commit 6208d611520f9ea94d5369f9da404b709930029d +Author: Darren Tucker +Date: Sun Jul 3 17:54:49 2022 +1000 + + Move checks for pollfd.fd and nfds_t. - OpenBSD-Commit-ID: 30f880f989d4b329589c1c404315685960a5f153 + Move the checks for struct pollfd.fd and nfds_t to before the sandboxing + checks. This groups all the sandbox checks together so we can skip them + all when sandboxing is disabled. -commit 3e26b3a6eebcee27be177207cc0846fb844b7a56 +commit 322964f8f2e9c321e77ebae1e4d2cd0ccc5c5a0b Author: dtucker@openbsd.org -Date: Fri Apr 29 03:16:48 2022 +0000 +Date: Fri Jul 1 05:08:23 2022 +0000 - upstream: Don't leak SK device. Patch from Pedro Martelletto via + upstream: Remove leftover line. - github PR#316. ok djm@ + Remove extra line leftover from merge conflict. ok djm@ - OpenBSD-Commit-ID: 17d11327545022e727d95fd08b213171c5a4585d + OpenBSD-Commit-ID: 460e2290875d7ae64971a7e669c244b1d1c0ae2e -commit 247082b5013f0d4fcae8f97453f2a2f01bcda811 +commit 7ec81daad0e03a64e8d91c5590960c48c1a899a3 Author: djm@openbsd.org -Date: Fri Apr 29 03:13:32 2022 +0000 +Date: Fri Jul 1 04:45:50 2022 +0000 - upstream: fix memleak on session-bind path; from Pedro Martelletto, ok + upstream: use consistent field names (s/char/byte) - dtucker@ + in format description - OpenBSD-Commit-ID: e85899a26ba402b4c0717b531317e8fc258f0a7e + OpenBSD-Commit-ID: 3de33572733ee7fcfd7db33d37db23d2280254f0 -commit e05522008092ceb86a87bdd4ad7878424315db89 -Author: djm@openbsd.org -Date: Thu Apr 28 02:53:31 2022 +0000 +commit 32e82a392d9f263485effdd606ff5862d289a4a0 +Author: Darren Tucker +Date: Fri Jul 1 13:55:19 2022 +1000 - upstream: avoid printing hash algorithm twice; from lucas AT sexy.is + Skip select+rlimit check if sandboxing is disabled - OpenBSD-Commit-ID: 9d24671e10a84141b7c504396cabad600e47a941 + It's not needed in that case, and the test can fail when being built + with some compiler memory sanitizer flags. bz#3441 -commit 0979e29356915261d69a9517a1e0aaade7c9fc75 -Author: dtucker@openbsd.org -Date: Wed Apr 27 11:08:55 2022 +0000 +commit 4be7184ebe2a2ccef175983517a35ee06766e1b4 +Author: djm@openbsd.org +Date: Fri Jul 1 03:52:57 2022 +0000 - upstream: Add authfd path to debug output. ok markus@ + upstream: bump up loglevel from debug to info when unable to open - OpenBSD-Commit-ID: f735a17d1a6f2bee63bfc609d76ef8db8c090890 + authorized keys/principals file for errno != ENOENT; bz2042 ok dtucker + + OpenBSD-Commit-ID: e79aa550d91ade6a80f081bda689da24c086d66b -commit 67b7c784769c74fd4d6b147d91e17e1ac1a8a96d +commit 6c31ba10e97b6953c4f325f526f3e846dfea647a Author: dtucker@openbsd.org -Date: Tue Apr 26 07:41:44 2022 +0000 +Date: Fri Jul 1 03:39:44 2022 +0000 - upstream: Check sshauthopt_new() for NULL. bz#3425, from - - tessgauthier at microsoft.com. ok djm@ + upstream: Don't leak the strings allocated by order_hostkeyalgs() - OpenBSD-Commit-ID: af0315bc3e44aa406daa7e0ae7c2d719a974483f - -commit d571314d14b919fbd7c84a61f9bf2065fc0a6841 -Author: millert@openbsd.org -Date: Wed Apr 20 16:00:25 2022 +0000 - - upstream: Remove unnecessary includes: openssl/hmac.h and + and list_hostkey_types() that are passed to compat_pkalg_proposal(). Part of + github PR#324 from ZoltanFridrich, ok djm@ - openssl/evp.h. From Martin Vahlensieck. + This is a roll-forward of the previous rollback now that the required + changes in compat.c have been done. - OpenBSD-Commit-ID: a6debb5fb0c8a44e43e8d5ca7cc70ad2f3ea31c3 + OpenBSD-Commit-ID: c7cd93730b3b9f53cdad3ae32462922834ef73eb -commit da8dddf8cc1f2516ff894b8183e83a7c5ba3ef80 -Author: millert@openbsd.org -Date: Wed Apr 20 15:59:18 2022 +0000 +commit 486c4dc3b83b4b67d663fb0fa62bc24138ec3946 +Author: dtucker@openbsd.org +Date: Fri Jul 1 03:35:45 2022 +0000 - upstream: Add missing includes of stdlib.h and stdint.h. We need + upstream: Always return allocated strings from the kex filtering so - stdlib.h for malloc(3) and stdint.h for SIZE_MAX. Unlike the other xmss - files, ssh-xmss.c does not include xmss_commons.h so ssh-xmss.c must include - those headers itself. From Martin Vahlensieck + that we can free them later. Fix one leak in compat_kex_proposal. Based on + github PR#324 from ZoltanFridrich with some simplications by me. ok djm@ - OpenBSD-Commit-ID: 70e28a9818cee3da1be2ef6503d4b396dd421e6b + OpenBSD-Commit-ID: 9171616da3307612d0ede086fd511142f91246e4 -commit fe9d87a6800a7a33be08f4d5ab662a758055ced2 -Author: millert@openbsd.org -Date: Wed Apr 20 15:56:49 2022 +0000 +commit 96faa0de6c673a2ce84736eba37fc9fb723d9e5c +Author: djm@openbsd.org +Date: Fri Jul 1 00:36:30 2022 +0000 - upstream: Avoid an unnecessary xstrdup in rm_env() when matching + upstream: ignore SIGPIPE earlier in main(), specifically before - patterns. Since match_pattern() doesn't modify its arguments (they are - const), there is no need to make an extra copy of the strings in - options->send_env. From Martin Vahlensieck + muxclient() which performs operations that could cause one; Reported by Noam + Lewis via bz3454, ok dtucker@ - OpenBSD-Commit-ID: 2c9db31e3f4d3403b49642c64ee048b2a0a39351 + OpenBSD-Commit-ID: 63d8e13276869eebac6d7a05d5a96307f9026e47 -commit 7bf2eb958fbb551e7d61e75c176bb3200383285d -Author: Darren Tucker -Date: Tue Apr 26 23:30:59 2022 +1000 +commit 33efac790f6b09d54894ba6c3e17dfb08b6fc7e1 +Author: jmc@openbsd.org +Date: Tue Jun 28 06:09:14 2022 +0000 - Add debian-riscv64 test target. + upstream: reflect the update to -D arg name in usage(); + + OpenBSD-Commit-ID: abdcde4f92b1ef094ae44210ee99d3b0155aad9c -commit 3913c935523902482974c4c503bcff20bd850a6a +commit c71a1442d02f0a3586109dfe2cb366de36dee08e Author: Darren Tucker -Date: Mon Apr 25 17:20:06 2022 +1000 +Date: Wed Jun 29 18:28:47 2022 +1000 - Update OpenSSL and LibreSSL versions in tests. + Update OpenSSL tests to the most recent releases. -commit dcd8dca29bcdb193ff6be35b96fc55e6e30d37d9 -Author: Darren Tucker -Date: Sat Apr 23 20:40:28 2022 +1000 +commit 2a822f29300b2de7335fbff65f0b187a0c582304 +Author: djm@openbsd.org +Date: Mon Jun 27 21:41:55 2022 +0000 - Include stdlib.h for free() prototype. + upstream: allow arguments to sftp -D option, e.g. sftp -D - ... which is used inside the CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG block. + "/usr/libexec/sftp-server -el debug3" + + ok markus@ + + OpenBSD-Commit-ID: 5a002b9f3a7aef2731fc0ffa9c921cf15f38ecce -commit 4cc05de568e1c3edd7834ff3bd9d8214eb34861b -Author: Darren Tucker -Date: Sat Apr 23 20:17:26 2022 +1000 +commit 2369a2810187e08f2af5d58b343956062fb96ee8 +Author: dtucker@openbsd.org +Date: Fri Jun 24 10:45:06 2022 +0000 - Cache timezone data in capsicum sandbox. + upstream: Roll back previous KEX changes as they aren't safe until - From emaste at freebsd.org, originally part of FreeBSD commit r339216 - / fc3c19a9 with autoconf bits added by me. + compat_pkalg_proposal and friends always allocate their returned strings. + Reported by Qualys. + + OpenBSD-Commit-ID: 1c7a88a0d5033f42f88ab9bec58ef1cf72c81ad0 -commit c31404426d212e2964ff9e5e58e1d0fce3d83f27 +commit 646686136c34c2dbf6a01296dfaa9ebee029386d Author: dtucker@openbsd.org -Date: Thu Apr 21 01:36:46 2022 +0000 +Date: Fri Jun 24 04:37:00 2022 +0000 - upstream: It looks like we can't completely avoid + upstream: Don't leak the strings allocated by order_hostkeyalgs() - waiting for processes to exit so retrieve the pid via controlmaster and - use that. + and list_hostkey_types() that are passed to compat_pkalg_proposal(). Part of + github PR#324 from ZoltanFridrich, ok djm@ - OpenBSD-Regress-ID: 8246f00f22b14e49d2ff1744c94897ead33d457b + OpenBSD-Commit-ID: b2f6e5f60f2bba293b831654328a8a0035ef4a1b -commit d19b21afab5c8e2f3df6bd8aee9766bdad3d8c58 -Author: dtucker@openbsd.org -Date: Wed Apr 20 13:25:55 2022 +0000 +commit 193c6d8d905dde836b628fc07a7b9cf2d347e2a3 +Author: Darren Tucker +Date: Sat Jun 25 12:16:15 2022 +1000 + + Zero out LIBFIDO2 when SK support not usable. + + Prevents us from trying to link them into ssh-sk-helper and failing to + build. + +commit 40f5d849d25c60b4ae21261e78484d435f5cfd51 +Author: Darren Tucker +Date: Sat Jun 25 11:47:28 2022 +1000 + + Disable SK support if FIDO libs not found. + +commit 5fd922ade1b25880fe8a8249f5c0385e413108f9 +Author: Damien Miller +Date: Fri Jun 24 14:43:54 2022 +1000 - upstream: Use ssh -f and ControlPersist .. - - to start up test forwards and ssh -O stop to shut them down intead of - sleep loops. This speeds up the test by an order of magnitude. - - OpenBSD-Regress-ID: eb3db5f805100919b092a3b2579c611fba3e83e7 + fix broken case statement in previous -commit 5f76286a126721fa005de6edf3d1c7a265555f19 -Author: dtucker@openbsd.org -Date: Wed Apr 20 05:24:13 2022 +0000 +commit f51423bdaf0008d46b6af082bcfd7a22a87375f0 +Author: Damien Miller +Date: Fri Jun 24 14:40:42 2022 +1000 - upstream: Simplify forward-control test. - - Since we no longer need to support SSH1 we don't need to run shell - commands on the other end of the connection and can use ssh -N instead. - This also makes the test less racy. + request 1.1x API compatibility for OpenSSL >=3.x - OpenBSD-Regress-ID: 32e94ce272820cc398f30b848b2b0f080d10302c + idea/patch from Pedro Martelletto via GHPR#322; ok dtucker@ -commit 687bbf23572d8bdf25cbbcdf8ac583514e1ba710 +commit 455cee8d6c2e4c48c5af9faead3599c49948411e Author: djm@openbsd.org -Date: Thu Mar 31 03:07:33 2022 +0000 +Date: Fri Jun 24 04:27:14 2022 +0000 - upstream: regression test for sftp cp command + upstream: make it clear that RekeyLimit applies to both transmitted - OpenBSD-Regress-ID: c96bea9edde3a384b254785e7f9b2b24a81cdf82 - -commit f1233f19a6a9fe58f52946f50df4772f5b136761 -Author: dtucker@openbsd.org -Date: Wed Apr 20 01:13:47 2022 +0000 - - upstream: Import regenerated moduli + and received data. GHPR#328 from Jan Pazdziora - OpenBSD-Commit-ID: f9a0726d957cf10692a231996a1f34e7f9cdfeb0 + OpenBSD-Commit-ID: d180a905fec9ff418a75c07bb96ea41c9308c3f9 -commit fec014785de198b9a325d1b94e324bb958c5fe7b -Author: djm@openbsd.org -Date: Wed Apr 20 04:19:11 2022 +0000 +commit 17904f05802988d0bb9ed3c8d1d37411e8f459c3 +Author: tobhe@openbsd.org +Date: Tue Jun 21 14:52:13 2022 +0000 - upstream: Try to continue running local I/O for channels in state + upstream: Make sure not to fclose() the same fd twice in case of an - OPEN during SSH transport rekeying. The most visible benefit is that it - should make ~-escapes work in the client (e.g. to exit) if the connection - happened to have stalled during a rekey event. Based work by and ok dtucker@ + error. - OpenBSD-Commit-ID: a66e8f254e92edd4ce09c9f750883ec8f1ea5f45 + ok dtucker@ + + OpenBSD-Commit-ID: e384c4e05d5521e7866b3d53ca59acd2a86eef99 -commit e68154b0d4f0f5085a050ea896955da1b1be6e30 +commit f29d6cf98c25bf044079032d22c1a57c63ab9d8e Author: dtucker@openbsd.org -Date: Wed Apr 20 01:13:47 2022 +0000 +Date: Sat Jun 18 02:17:16 2022 +0000 - upstream: Import regenerated moduli + upstream: Don't attempt to fprintf a null identity comment. From - OpenBSD-Commit-ID: f9a0726d957cf10692a231996a1f34e7f9cdfeb0 + Martin Vahlensieck via tech@. + + OpenBSD-Commit-ID: 4c54d20a8e8e4e9912c38a7b4ef5bfc5ca2e05c2 -commit 69928b106d8f0fa15b88cf3850d992ed81c44ae0 -Author: tj@openbsd.org -Date: Sat Apr 16 00:22:31 2022 +0000 +commit ad1762173bb38716a106e8979806149fd0f2753e +Author: dtucker@openbsd.org +Date: Fri Jun 17 01:00:03 2022 +0000 - upstream: list the correct version number + upstream: Log an error if pipe() fails while accepting a - for when usage of the sftp protocol became default and fix a typo - from ed maste + connection. bz#3447, from vincent-openssh at vinc17 net, ok djm@ - OpenBSD-Commit-ID: 24e1795ed2283fdeacf16413c2f07503bcdebb31 + OpenBSD-Commit-ID: 9d59f19872b94900a5c79da2d57850241ac5df94 -commit 21042a05c0b304c16f655efeec97438249d2e2cc -Author: dtucker@openbsd.org -Date: Tue Apr 12 05:09:49 2022 +0000 +commit 9c59e7486cc8691401228b43b96a3edbb06e0412 +Author: Damien Miller +Date: Fri Jun 24 14:20:43 2022 +1000 - upstream: Correct path for system known hosts file in description + automatically enable built-in FIDO support - of IgnoreUserKnownHosts. Patch from Martin Vahlensieck via tech@ + If libfido2 is found and usable, then enable the built-in + security key support unless --without-security-key-builtin + was requested. - OpenBSD-Commit-ID: 9b7784f054fa5aa4d63cb36bd563889477127215 + ok dtucker@ -commit 53f4aff60a7c1a08a23917bd47496f8901c471f5 -Author: Darren Tucker -Date: Sat Apr 16 14:33:20 2022 +1000 +commit 7d25b37fb2a5ff4dadabcbdac6087a97479434f5 +Author: Damien Miller +Date: Fri Jun 24 13:46:39 2022 +1000 - Resync moduli.5 with upstream. + fix possible NULL deref when built without FIDO - 1.18: remove duplicate publication year; carsten dot kunze at arcor dot de - 1.19: ssh-keygen's -G/-T have been replaced with -M generate/screen. + Analysis/fix from kircher in bz3443; ok dtucker@ -commit d2b888762b9844eb0d8eb59909cdf5af5159f810 -Author: Darren Tucker -Date: Sat Apr 16 14:31:13 2022 +1000 +commit f5ba85daddfc2da6a8dab6038269e02c0695be44 +Author: djm@openbsd.org +Date: Wed Jun 15 16:08:25 2022 +0000 - Retire fbsd6 test VM. + upstream: make sure that UseDNS hostname lookup happens in the monitor - It's long since out of support, relatively slow (it's i686) and the - compiler has trouble with PIE. + and not in the pledge(2)'d unprivileged process; fixes regression caused by + recent refactoring spotted by henning@ + + OpenBSD-Commit-ID: a089870b95101cd8881a2dff65b2f1627d13e88d -commit cd1f70009860a154b51230d367c55ea5f9a4504e +commit acb2059febaddd71ee06c2ebf63dcf211d9ab9f2 Author: djm@openbsd.org -Date: Mon Apr 11 22:52:08 2022 +0000 +Date: Fri Jun 3 04:47:21 2022 +0000 - upstream: clear io_want/io_ready flags at start of poll() cycle; + upstream: move auth_openprincipals() and auth_openkeyfile() over to - avoids plausible spin during rekeying if channel io_want flags are reused - across cycles. ok markus@ deraadt@ + auth2-pubkeyfile.c too; they make more sense there. - OpenBSD-Commit-ID: 91034f855b7c73cd2591657c49ac30f10322b967 + OpenBSD-Commit-ID: 9970d99f900e1117fdaab13e9e910a621b7c60ee -commit aa1920302778273f7f94c2091319aba199068ca0 -Author: dtucker@openbsd.org -Date: Fri Apr 8 05:43:39 2022 +0000 +commit 3d9b0845f34510111cc693bb99a667662ca50cd8 +Author: djm@openbsd.org +Date: Fri Jun 3 04:31:54 2022 +0000 - upstream: Note that curve25519-sha256 was later published in + upstream: test setenv in both client and server, test first-match-wins - RFC8731. ok djm@ + too - OpenBSD-Commit-ID: 2ac2b5d642d4cf5918eaec8653cad9a4460b2743 + OpenBSD-Regress-ID: 4c8804f9db38a02db480b9923317457b377fe34b -commit 4673fa8f2be983f2f88d5afd754adb1a2a39ec9e +commit 22e1a3a71ad6d108ff0c5f07f93c3fcbd30f8b40 Author: djm@openbsd.org -Date: Fri Apr 8 04:40:40 2022 +0000 +Date: Fri Jun 3 04:30:46 2022 +0000 - upstream: two defensive changes from Tobias Stoeckmann via GHPR287 + upstream: Make SetEnv directives first-match-wins in both - enforce stricter invarient for sshbuf_set_parent() - never allow - a buffer to have a previously-set parent changed. + sshd_config and sshd_config; previously if the same name was reused then the + last would win (which is the opposite to how the config is supposed to work). - In sshbuf_reset(), if the reallocation fails, then zero the entire - buffer and not the (potentially smaller) default initial alloc size. + While there, make the ssh_config parsing more like sshd_config. - OpenBSD-Commit-ID: 14583203aa5d50ad38d2e209ae10abaf8955e6a9 + bz3438, ok dtucker + + OpenBSD-Commit-ID: 797909c1e0262c0d00e09280459d7ab00f18273b -commit 26eef015e2d2254375e13afaaf753b78932b1bf5 -Author: Damien Miller -Date: Mon Apr 11 16:07:09 2022 +1000 +commit 38ed6c57e9e592c08e020fa6e82b45b4e1040970 +Author: dtucker@openbsd.org +Date: Fri Jun 3 04:00:15 2022 +0000 - Revert "update build-aux files to match autoconf-2.71" + upstream: Add missing *-sk types to ssh-keyscan manpage. From - This reverts commit 0a8ca39fac6ad19096b6c263436f8b2dd51606f2. + skazi0 via github PR#294. - It turns out that the checked-in copies of these files are actually newer - than autoconf-2.71's copies, so this was effectively a downgrade. - Spotted by Bo Anderson via github + OpenBSD-Commit-ID: fda2c869cdb871f3c90a89fb3f985370bb5d25c0 -commit 0a8ca39fac6ad19096b6c263436f8b2dd51606f2 -Author: Damien Miller -Date: Fri Apr 8 14:48:58 2022 +1000 +commit ea97ec98c41ec2b755dfab459347db674ff9a5de +Author: dtucker@openbsd.org +Date: Fri Jun 3 03:21:09 2022 +0000 - update build-aux files to match autoconf-2.71 + upstream: Add period at end of "not known by any other names" - i.e. config.guess, config.sub and install-sh - -commit 94eb6858efecc1b4f02d8a6bd35e149f55c814c8 -Author: Damien Miller -Date: Wed Apr 6 10:47:48 2022 +1000 - - update version numbers for release - -commit 8e4a8eadf4fe74e65e6492f34250f8cf7d67e8da -Author: djm@openbsd.org -Date: Mon Apr 4 22:45:25 2022 +0000 - - upstream: openssh-9.0 + message. github PR#320 from jschauma, ok djm@ - OpenBSD-Commit-ID: 0dfb461188f4513ec024c1534da8c1ce14c20b64 + OpenBSD-Commit-ID: bd60809803c4bfd3ebb7c5c4d918b10e275266f2 -commit a9f23ea2e3227f406880c2634d066f6f50fa5eaa -Author: naddy@openbsd.org -Date: Thu Mar 31 17:58:44 2022 +0000 +commit 88e376fcd67478ad1660d94bc73ab348ac9f4527 +Author: dtucker@openbsd.org +Date: Fri Jun 3 03:17:42 2022 +0000 - upstream: ssh: document sntrup761x25519-sha512@openssh.com as + upstream: ssh-keygen -A: do not generate DSA keys by default. - default KEX + Based on github PR#303 from jsegitz with man page text from jmc@, ok markus@ + djm@ - OpenBSD-Commit-ID: 12545bfa10bcbf552d04d9d9520d0f4e98b0e171 + OpenBSD-Commit-ID: 5c4c57bdd7063ff03381cfb6696659dd3f9f5b9f -commit 9ec2713d122af79d66ebb9c1d6d9ae8621a8945f +commit 6b3fb624675082a1e5aa615d1b8479873d8b5731 Author: naddy@openbsd.org -Date: Thu Mar 31 17:27:27 2022 +0000 +Date: Tue May 31 14:05:12 2022 +0000 - upstream: man pages: add missing commas between subordinate and - - main clauses + upstream: ssh-keygen: implement "verify-required" certificate option. - jmc@ dislikes a comma before "then" in a conditional, so leave those - untouched. + This was already documented when support for user-verified FIDO + keys was added, but the ssh-keygen(1) code was missing. - ok jmc@ + ok djm@ - OpenBSD-Commit-ID: 9520801729bebcb3c9fe43ad7f9776ab4dd05ea3 - -commit 3741df98ffaaff92b474ee70d8ef276b5882f85a -Author: Darren Tucker -Date: Mon Apr 4 23:52:11 2022 +1000 - - Disable security key on fbsd6 test host. + OpenBSD-Commit-ID: f660f973391b593fea4b7b25913c9a15c3eb8a06 -commit 32c12236f27ae83bfe6d2983b67c9bc67a83a417 -Author: Darren Tucker -Date: Mon Apr 4 15:16:51 2022 +1000 +commit b7f86ffc301be105bba9a3e0618b6fab3ae379bd +Author: jmc@openbsd.org +Date: Sat May 28 05:57:56 2022 +0000 - Specify TEST_SHELL=bash on AIX. + upstream: keywords ref ssh_config.5; - The system shells cause the agent-restrict test to fail due to some - quoting so explicitly specify bash until we can get configure to - autmatically work around that. - -commit 90452c8b69d065b7c7c285ff78b81418a75bcd76 -Author: Darren Tucker -Date: Fri Apr 1 23:38:44 2022 +1100 - - Only return events from ppoll that were requested. + from caspar schutijser - If the underlying system's select() returns bits that were not in the - request set, our ppoll() implementation can return revents for events - not requested, which can apparently cause a hang. Only return revents - for activity in the requested event set. bz#3416, analysis and fix by - yaroslav.kuzmin at vmssoftware com, ok djm@ + OpenBSD-Commit-ID: f146a19d7d5c9374c3b9c520da43b2732d7d1a4e + +commit dc7bc52372f2744fa39191577be5306ee57aacd4 +Author: Damien Miller +Date: Mon May 30 09:29:09 2022 +1000 -commit 6c49eb5fabc56f4865164ed818aa5112d09c31a8 + fix some bugs in the fuzzer + +commit 1781f507c113667613351c19898efaf1e311a865 Author: Darren Tucker -Date: Fri Apr 1 23:21:40 2022 +1100 +Date: Fri May 27 18:19:48 2022 +1000 - Only run regression tests on slow VMs. + Test against OpenSSL 1.1.1o and 3.0.3. -commit f67e47903977b42cb6abcd5565a61bd7293e4dc3 +commit c53906e0c59e569691b4095d3e8db79cf78fa058 Author: Darren Tucker -Date: Fri Apr 1 23:21:06 2022 +1100 +Date: Fri May 27 18:18:31 2022 +1000 - Increase test timeout to allow slow VMs to finish + Test against LibreSSL 3.5.3. -commit 02488c1b54065ddc4f25835dbd2618b2a2fe21f5 -Author: Darren Tucker -Date: Fri Apr 1 16:27:38 2022 +1100 +commit 9b3ad432ad2f19319bcc089370e356c6315d682f +Author: Damien Miller +Date: Fri May 27 17:00:43 2022 +1000 - Use bash or ksh if available for SH in Makefile. + fuzzer for authorized_keys parsing + + mostly redundant to authopt_fuzz, but it's sensitive code so IMO it + makes sense to test this layer too -commit 34c7018c316af4773e432066de28d0ef9d0888cd -Author: Darren Tucker -Date: Fri Apr 1 14:56:54 2022 +1100 +commit c83d8c4d6f3ccceef84d46de107f6b71cda06359 +Author: djm@openbsd.org +Date: Fri May 27 05:02:46 2022 +0000 - Set Makefile SHELL as determined by configure. + upstream: split the low-level file handling functions out from - This should improve compatibility for users with non-POSIX shells. If - using Makefile.in directly (eg make -f Makefile.in distprep) then SHELL - will need to be specified on the command line (along with MANFMT in that - particular case). ok djm@ + auth2-pubkey.c + + Put them in a new auth2-pubkeyfile.c to make it easier to refer to them + (e.g. in unit/fuzz tests) without having to refer to everything else + pubkey auth brings in. + + ok dtucker@ + + OpenBSD-Commit-ID: 3fdca2c61ad97dc1b8d4a7346816f83dc4ce2217 -commit 5b054d76402faab38c48377efd112426469553a0 -Author: Darren Tucker -Date: Fri Apr 1 13:16:47 2022 +1100 +commit 3b0b142d2a0767d8cd838e2f3aefde8a0aaa41e1 +Author: djm@openbsd.org +Date: Fri May 27 05:01:25 2022 +0000 - Skip slow tests on (very) slow test targets. + upstream: refactor authorized_keys/principals handling + + remove "struct ssh *" from arguments - this was only used to pass the + remote host/address. These can be passed in instead and the resulting + code is less tightly coupled to ssh_api.[ch] + + ok dtucker@ + + OpenBSD-Commit-ID: 9d4373d013edc4cc4b5c21a599e1837ac31dda0d -commit b275818065b31a865142c48c2acf6a7c1655c542 -Author: Damien Miller -Date: Thu Mar 31 14:11:36 2022 +1100 +commit 2c334fd36f80cb91cc42e4b978b10aa35e0df236 +Author: dtucker@openbsd.org +Date: Fri May 27 04:29:40 2022 +0000 - depend + upstream: f sshpkt functions fail, then password is not cleared + + with freezero. Unconditionally call freezero to guarantee that password is + removed from RAM. + + From tobias@ and c3h2_ctf via github PR#286, ok djm@ + + OpenBSD-Commit-ID: 6b093619c9515328e25b0f8093779c52402c89cd -commit 3fa539c3ffaabd6211995512d33e29150f88c5c5 -Author: djm@openbsd.org -Date: Thu Mar 31 03:07:03 2022 +0000 +commit 5d3a77f4c5ae774c6796387266503f52c7cdc7c2 +Author: dtucker@openbsd.org +Date: Fri May 27 04:27:49 2022 +0000 - upstream: add a sftp client "cp" command that supports server-side + upstream: Avoid kill with -1 argument. The out_ctx label can be - copying of files. Useful for this task and for testing the copy-data - extension. Patch from Mike Frysinger; ok dtucker@ + reached before fork has been called. If this happens, then kill -1 would be + called, sending SIGTERM to all processes reachable by the current process. - OpenBSD-Commit-ID: 1bb1b950af0d49f0d5425b1f267e197aa1b57444 + From tobias@ and c3h2_ctf via github PR#286, ok djm@ + + OpenBSD-Commit-ID: 6277af1207d81202f5daffdccfeeaed4c763b1a8 -commit 7988bfc4b701c4b3fe9b36c8561a3d1c5d4c9a74 -Author: djm@openbsd.org -Date: Thu Mar 31 03:05:49 2022 +0000 +commit 533b31cd08e4b97f455466f91c36915e2924c15a +Author: dtucker@openbsd.org +Date: Fri May 27 04:13:24 2022 +0000 - upstream: add support for the "corp-data" protocol extension to + upstream: Note that ProxyJump also accepts the same tokens as - allow server-side copies to be performed without having to go via the client. - Patch by Mike Frysinger, ok dtucker@ + ProxyCommand. From pallxk via github PR#305. - OpenBSD-Commit-ID: 00aa510940fedd66dab1843b58682de4eb7156d5 + OpenBSD-Commit-ID: 7115ac351b129205f1f1ffa6bbfd62abd76be7c5 -commit 32dc1c29a4ac9c592ddfef0a4895eb36c1f567ba +commit 9d8c80f8a304babe61ca28f2e3fb5eb6dc9c39bf Author: djm@openbsd.org -Date: Wed Mar 30 21:13:23 2022 +0000 +Date: Wed May 25 06:03:44 2022 +0000 - upstream: select post-quantum KEX - - sntrup761x25519-sha512@openssh.com as the default; ok markus@ + upstream: revert previous; it was broken (spotted by Theo) - OpenBSD-Commit-ID: f02d99cbfce22dffec2e2ab1b60905fbddf48fb9 + OpenBSD-Commit-ID: 457c79afaca2f89ec2606405c1059b98b30d8b0d -commit d6556de1db0822c76ba2745cf5c097d9472adf7c +commit 9e0d02ef7ce88b67643bfb1c2272c9f5f04cc680 Author: djm@openbsd.org -Date: Wed Mar 30 21:10:25 2022 +0000 +Date: Wed May 25 00:31:13 2022 +0000 - upstream: fix poll() spin when a channel's output fd closes without + upstream: make SSHBUF_DBG/SSHBUF_TELL (off by default and only enabled - data in the channel buffer. Introduce more exact packing of channel fds into - the pollfd array. fixes bz3405 and bz3411; ok deraadt@ markus@ + via #define) dump to stderr rather than stdout - OpenBSD-Commit-ID: 06740737849c9047785622ad5d472cb6a3907d10 + OpenBSD-Commit-ID: 10298513ee32db8390aecb0397d782d68cb14318 -commit 8a74a96d25ca4d32fbf298f6c0ac5a148501777d +commit 2487163630f28be28b7e2396b4bd6511b98f1d3e +Author: Tim Rice +Date: Tue May 24 10:21:25 2022 -0700 + + configure.ac: Add missing AC_DEFINE for caph_cache_tzdata test causing + HAVE_CAPH_CACHE_TZDATA to be missing from config.h.in. + Spotted by Bryan Drewery + +commit bedb93415b60db3dfd704a3d525e82adb14a2481 Author: djm@openbsd.org -Date: Wed Mar 30 04:33:09 2022 +0000 +Date: Sun May 15 23:48:07 2022 +0000 - upstream: ssh is almost out of getopt() characters; note the + upstream: regress test for in-place transfers and clobbering larger - remaining remaining available ones in a comment + files with smaller ones; would have caught last regression in scp(1) - OpenBSD-Commit-ID: 48d38cef59d6bc8e84c6c066f6d601875d3253fd + OpenBSD-Regress-ID: 19de4e88dd3a4f7e5c1618c9be3c32415bd93bc2 -commit 6d4fc51adb9d8a42f67b5474f02f877422379de6 +commit b4f0d719c2548cb74da509fb65f384dada4ebd37 +Author: anton@openbsd.org +Date: Fri Apr 22 05:08:43 2022 +0000 + + upstream: Only run agent-ptrace.sh if gdb is available as all + + architectures do not ship with gdb. + + OpenBSD-Regress-ID: ec53e928803e6b87f9ac142d38888ca79a45348d + +commit 9b73345f80255a7f3048026462f2c0c6a241eeac Author: djm@openbsd.org -Date: Wed Mar 30 04:27:51 2022 +0000 +Date: Sun May 15 23:47:21 2022 +0000 - upstream: avoid NULL deref via ssh-keygen -Y find-principals. + upstream: fix in-place copies; r1.163 incorrectly skipped truncation in - bz3409, reported by Mateusz Adamowski + all cases, not just at the start of a transfer. This could cause overwrites + of larger files to leave junk at the end. Spotted by tb@ - OpenBSD-Commit-ID: a3b2c02438052ee858e0ee18e5a288586b5df2c5 + OpenBSD-Commit-ID: b189f19cd68119548c8e24e39c79f61e115bf92c -commit e937514920335b92b543fd9be79cd6481d1eb0b6 -Author: Darren Tucker -Date: Mon Mar 28 17:51:03 2022 +1100 +commit 56a0697fe079ff3e1ba30a2d5c26b5e45f7b71f8 +Author: djm@openbsd.org +Date: Fri May 13 06:31:50 2022 +0000 - Add AIX 5.1 test target. + upstream: arrange for scp, when in sftp mode, to not ftruncate(3) files + + early + + previous behavious of unconditionally truncating the destination file + would cause "scp ~/foo localhost:" and "scp localhost:foo ~/" to + delete all the contents of their destination. + + spotted by solene@ sthen@, also bz3431; ok dtucker@ + + OpenBSD-Commit-ID: ca39fdd39e0ec1466b9666f15cbcfddea6aaa179 -commit 4bbe815ba974b4fd89cc3fc3e3ef1be847a0befe -Author: Darren Tucker -Date: Sat Mar 26 22:01:31 2022 +1100 +commit fbcef70c2832712f027bccea1aa9bc4b4103da93 +Author: dtucker@openbsd.org +Date: Mon May 9 08:25:27 2022 +0000 - Drop leading "v" from release version identifier. + upstream: Remove errant apostrophe. From haruyama at queen-ml org. - It's present in the git tags but not in the release tarball names. - Also drop extra "/" from URL path. + OpenBSD-Commit-ID: dc6b294567cb84b384ad6ced9ca469f2bbf0bd10 -commit f5cdd3b3c275dffaebfca91df782dca29975e9ac -Author: Darren Tucker -Date: Sat Mar 26 16:28:04 2022 +1100 +commit 0086a286ea6bbd11ca9b664ac3bb12b27443d6eb +Author: djm@openbsd.org +Date: Mon May 9 03:09:53 2022 +0000 - Use tarballs when testing LibreSSL releases. + upstream: Allow existing -U (use agent) flag to work with "-Y sign" - This means they'll still work when the combination of -portable and - openbsd github repos no longer match. + operations, where it will be interpreted to require that the private keys is + hosted in an agent; bz3429, suggested by Adam Szkoda; ok dtucker@ + + OpenBSD-Commit-ID: a7bc69873b99c32c42c7628ed9ea91565ba08c2f -commit 24dc37d198f35a7cf71bf4d5384363c7ef4209d4 -Author: Darren Tucker -Date: Sat Mar 26 15:02:45 2022 +1100 +commit cb010744cc98f651b1029bb09efa986eb54e4ccf +Author: djm@openbsd.org +Date: Sun May 8 22:58:35 2022 +0000 - Remove now-unused passwd variable. + upstream: improve error message when 'ssh-keygen -Y sign' is unable to + + load a private key; bz3429, reported by Adam Szkoda ok dtucker@ + + OpenBSD-Commit-ID: bb57b285e67bea536ef81b1055467be2fc380e74 -commit 5b467ceef2c356f0a77f5e8ab4eb0fac367e4d24 -Author: Darren Tucker -Date: Sat Mar 26 13:15:44 2022 +1100 +commit aa61fc82c63d309a90c22ca74fb1da6c6f4372fd +Author: Tobias Heider +Date: Mon May 9 02:00:01 2022 +0200 - Missing semicolon. + Remove duplicate bcrypt_pbkdf.o from Makefile + + bcrypt_pbkdf.o is duplicated in the openbsd-compat Makefile's object + file list. -commit 2923d026e55998133c0f6e5186dca2a3c0fa5ff5 -Author: Darren Tucker -Date: Sat Mar 26 12:49:50 2022 +1100 +commit deb506d00da8d11fb04c1e7b9b1e1cc379c1705c +Author: djm@openbsd.org +Date: Sun May 8 22:32:36 2022 +0000 - Factor out platform-specific locked account check. + upstream: When performing operations that glob(3) a remote path, ensure - Also fixes an incorrect free on platforms with both libiaf and shadow - passwords (probably only Unixware). Prompted by github PR#284, - originally from @c3h2_ctf and stoeckmann@. + that the implicit working directory used to construct that path escapes + glob(3) characters. + + This prevents glob characters from being processed in places they + shouldn't, e.g. "cd /tmp/a*/", "get *.txt" should have the get operation + treat the path "/tmp/a*" literally and not attempt to expand it. + + Reported by Lusia Kundel; ok markus@ + + OpenBSD-Commit-ID: 4f647f58482cbad3d58b1eab7f6a1691433deeef + +commit f38cf74f20b5da113cfa823afd5bfb5c6ba65f3d +Author: Darren Tucker +Date: Fri May 6 14:50:18 2022 +1000 -commit d23efe4b12886ffe416be10bc0a7da6ca8aa72d1 + Also retest OpenBSD upstream on .yml changes. + +commit f87a132800ba3710ab130d703448a31ef1128d77 Author: Darren Tucker -Date: Sat Mar 26 08:13:46 2022 +1100 +Date: Fri May 6 14:46:09 2022 +1000 - Add OpenWRT mips and mipsel test targets. + Note that, for now, we need variadic macros. -commit 16ea8b85838dd7a4dbeba4e51ac4f43fd68b1e5b -Author: djm@openbsd.org -Date: Sun Mar 20 08:52:17 2022 +0000 +commit 217b518e0f7c52c4b909e935141a55344c61e644 +Author: Darren Tucker +Date: Fri May 6 14:39:34 2022 +1000 - upstream: don't leak argument list; bz3404, reported by Balu - - Gajjala ok dtucker@ + Add ubsan minimal testcase on OpenBSD. - OpenBSD-Commit-ID: fddc32d74e5dd5cff1a49ddd6297b0867eae56a6 + As suggested by djm@. -commit a72bde294fe0518c9a44ba63864093a1ef2425e3 +commit 457dce2cfef6a48f5442591cd8b21c7e8cba13f8 Author: djm@openbsd.org -Date: Sun Mar 20 08:51:21 2022 +0000 +Date: Thu May 5 01:04:14 2022 +0000 - upstream: make addargs() and replacearg() a little more robust and - - improve error reporting - - make freeargs(NULL) a noop like the other free functions + upstream: sshkey_unshield_private() contains a exact duplicate of - ok dtucker as part of bz3403 + the code in private2_check_padding(). Pull private2_check_padding() up so the + code can be reused. From Martin Vahlensieck, ok deraadt@ - OpenBSD-Commit-ID: 15f86da83176978b4d1d288caa24c766dfa2983d + OpenBSD-Commit-ID: 876884c3f0e62e8fd8d1594bab06900f971c9c85 -commit 731087d2619fa7f01e675b23f57af10d745e8af2 +commit 0e44db4d9cb313e68a59a44d27884af66c02356e Author: djm@openbsd.org -Date: Fri Mar 18 04:04:11 2022 +0000 +Date: Thu May 5 00:56:58 2022 +0000 - upstream: don't try to resolve ListenAddress directives in the sshd + upstream: channel_new no longer frees remote_name. So update the - re-exec path - we're never going to use the result and if the operation fails - then it can prevent connections from being accepted. Reported by Aaron - Poffenberger; with / ok dtucker@ + comment accordingly. As remote_name is not modified, it can be const as + well. From Martin Vahlensieck - OpenBSD-Commit-ID: 44c53a43909a328e2f5ab26070fdef3594eded60 + OpenBSD-Commit-ID: e4e10dc8dc9f40c166ea5a8e991942bedc75a76a -commit 1c83c082128694ddd11ac05fdf31d70312ff1763 +commit 37b62fd5caf19c85a48241535277cefff65adace Author: djm@openbsd.org -Date: Fri Mar 18 02:50:21 2022 +0000 +Date: Thu May 5 00:55:11 2022 +0000 - upstream: remove blank line + upstream: mux.c: mark argument as const; from Martin Vahlensieck - OpenBSD-Commit-ID: d5e0182965b2fbfb03ad5f256d1a1ce5706bcddf + OpenBSD-Commit-ID: 69a1a93a55986c7c2ad9f733c093b46a47184341 -commit 807be68684da7a1fe969c399ddce2fafb7997dcb -Author: djm@openbsd.org -Date: Fri Mar 18 02:32:22 2022 +0000 +commit f4e67c0ad259b4cf10177277a5827fa5545bac53 +Author: markus@openbsd.org +Date: Wed May 4 07:31:22 2022 +0000 - upstream: helpful comment + upstream: make sure stdout is non-blocking; ok djm@ - OpenBSD-Commit-ID: e3315a45cb04e7feeb614d76ec80a9fe4ca0e8c7 + OpenBSD-Commit-ID: 64940fffbd1b882eda2d7c8c7a43c79368309c0d -commit a0b5816f8f1f645acdf74f7bc11b34455ec30bac -Author: djm@openbsd.org -Date: Fri Mar 18 02:31:25 2022 +0000 +commit e5c036d2092c00bef395e9161dc5ce42d4be9565 +Author: florian@openbsd.org +Date: Tue May 3 07:42:27 2022 +0000 - upstream: ssh-keygen -Y check-novalidate requires namespace or SEGV + upstream: Add FIDO AUTHENTICATOR section and explain a bit how FIDO - will ensue. Patch from Mateusz Adamowski via GHPR#307 + works. The wording came mostly from the 8.2 OpenSSH release notes, addapted + to fit the man page. Then move the -O bits into the new section as is already + done for CERTIFICATES and MODULI GENERATION. Finally we can explain the + trade-offs of resident keys. While here, consistently refer to the FIDO + thingies as "FIDO authenticators", not "FIDO tokens". - OpenBSD-Commit-ID: 99e8ec38f9feb38bce6de240335be34aedeba5fd - -commit 5a252d54a63be30d5ba4be76210942d754a531c0 -Author: djm@openbsd.org -Date: Tue Mar 15 05:27:37 2022 +0000 - - upstream: improve DEBUG_CHANNEL_POLL debugging message + input & OK jmc, naddy - OpenBSD-Commit-ID: 2275eb7bc4707d019b1a0194b9c92c0b78da848f + OpenBSD-Commit-ID: dd98748d7644df048f78dcf793b3b63db9ab1d25 -commit ce324cf58ba2840e31afeb996935800780c8fa4b -Author: cheloha@openbsd.org -Date: Sun Mar 13 23:27:54 2022 +0000 +commit 575771bf79bef7127be6aaccddc46031ea15529e +Author: jmc@openbsd.org +Date: Mon May 2 05:40:37 2022 +0000 - upstream: ssh: xstrdup(): use memcpy(3) + upstream: remove an obsolete rsa1 format example from an example; - Copying the given string into the buffer with strlcpy(3) confers no - benefit in this context because we have already determined the - string's length with strlen(3) in order to allocate that buffer. + from megan batty + ok djm - Thread: https://marc.info/?l=openbsd-tech&m=164687525802691&w=2 + OpenBSD-Commit-ID: db2c89879c29bf083df996bd830abfb1e70d62bf + +commit 0bc6b4c8f04e292577bdb44d5dc6b630d3448087 +Author: djm@openbsd.org +Date: Sun May 1 23:20:30 2022 +0000 + + upstream: fix some integer overflows in sieve_large() that show up when - ok dtucker@ millert@ + trying to generate modp groups > 16k bits. Reported via GHPR#306 by Bertram + Felgenhauer, but fixed in a different way. feedback/ok tb@ - OpenBSD-Commit-ID: f8bfc082e36e2d2dc4e1feece02fe274155ca11a + OpenBSD-Commit-ID: 81cbc6dd3a21c57bd6fadea10e44afe37bca558e -commit 2893c5e764557f48f9d6a929e224ed49c59545db -Author: Darren Tucker -Date: Fri Mar 11 18:43:58 2022 +1100 +commit a45615cb172bc827e21ec76750de39dfb30ecc05 +Author: djm@openbsd.org +Date: Fri Apr 29 04:55:07 2022 +0000 - Resync fmt_scaled. with OpenBSD. + upstream: be stricter in which characters will be accepted in - Fixes underflow reported in bz#3401. + specifying a mask length; allow only 0-9. From khaleesicodes via GHPR#278; ok + dtucker@ + + OpenBSD-Commit-ID: e267746c047ea86665cdeccef795a8a56082eeb2 -commit 5ae31a0fdd27855af29f48ff027491629fff5979 +commit 4835544d2dd31de6ffc7dba59f92093aea98155b Author: Darren Tucker -Date: Wed Mar 9 09:41:56 2022 +1100 +Date: Sat Apr 30 10:56:41 2022 +1000 - Provide killpg implementation. - - Based on github PR#301 for Tandem NonStop. + Add Mac OS X 12 test target. -commit c41c84b439f4cd74d4fe44298a4b4037ddd7d2ae +commit 97a6a8b8c1f2da09712d0e72d0ef800e4edd34cd Author: Darren Tucker -Date: Wed Mar 9 09:29:30 2022 +1100 +Date: Fri Apr 29 18:27:34 2022 +1000 - Check for missing ftruncate prototype. + Only run tests when source files change. - From github PR#301 in conjunction with rsbeckerca. + Also run tests on changes to V_9_0 branch. -commit 8cf5275452a950869cb90eeac7d220b01f77b12e +commit 6d0392b9ff4b50a56ac5685d1b9392e2cd432ca3 Author: Darren Tucker -Date: Tue Mar 8 20:04:06 2022 +1100 +Date: Fri Apr 29 18:22:34 2022 +1000 - Default to not using sandbox when cross compiling. - - On most systems poll(2) does not work when the number of FDs is reduced - with setrlimit, so assume it doesn't when cross compiling and we can't - run the test. bz#3398. + Remove now-empty int32_minmax.inc. -commit 379b30120da53d7c84aa8299c26b18c51c2a0dac +commit af59463553b5ad52d3b42c4455ee3c5600158bb7 Author: djm@openbsd.org -Date: Tue Mar 1 01:59:19 2022 +0000 - - upstream: pack pollfd array before server_accept_loop() ppoll() - - call, and terminate sshd if ppoll() returns errno==EINVAL - - avoids spin in ppoll when MaxStartups > RLIMIT_NOFILE, reported by - Daniel Micay - - feedback/ok deraadt - - OpenBSD-Commit-ID: dbab1c24993ac977ec24d83283b8b7528f7c2c15 - -commit eceafbe0bdbbd9bd2f3cf024ccb350666a9934dd -Author: naddy@openbsd.org -Date: Sun Feb 27 01:33:59 2022 +0000 +Date: Fri Apr 29 03:24:30 2022 +0000 - upstream: include rejected signature algorithm in error message and + upstream: mention that the helpers are used by ssh(1), ssh-agent(1) - not the (useless) key type; ok djm@ + and ssh-keygen(1). Previously only ssh(1) was mentioned. From Pedro + Martelletto - OpenBSD-Commit-ID: d0c0f552a4d9161203e07e95d58a76eb602a76ff + OpenBSD-Commit-ID: 30f880f989d4b329589c1c404315685960a5f153 -commit f2f3269423618a83157e18902385e720f9776007 +commit 3e26b3a6eebcee27be177207cc0846fb844b7a56 Author: dtucker@openbsd.org -Date: Fri Feb 25 09:46:24 2022 +0000 +Date: Fri Apr 29 03:16:48 2022 +0000 - upstream: Remove the char * casts from arguments to do_lstat, + upstream: Don't leak SK device. Patch from Pedro Martelletto via - do_readdir and do_stat paths since the underlying functions now take a const - char *. Patch from vapier at gentoo.org. + github PR#316. ok djm@ - OpenBSD-Commit-ID: 9e4d964dbfb0ed683a2a2900711b88e7f1c0297b + OpenBSD-Commit-ID: 17d11327545022e727d95fd08b213171c5a4585d -commit 4a66dac052c5ff5047161853f36904607649e4f9 +commit 247082b5013f0d4fcae8f97453f2a2f01bcda811 Author: djm@openbsd.org -Date: Fri Feb 25 02:09:27 2022 +0000 +Date: Fri Apr 29 03:13:32 2022 +0000 - upstream: save an unneccessary alloc/free, based on patch from + upstream: fix memleak on session-bind path; from Pedro Martelletto, ok - Martin Vahlensieck; ok dtucker@ + dtucker@ - OpenBSD-Commit-ID: 90ffbf1f837e509742f2c31a1fbf2c0fd376fd5f - -commit 6f117cb151efe138ac57bdd8e26165f350328f5f -Author: Darren Tucker -Date: Tue Mar 1 09:02:06 2022 +1100 - - Remove unused ivbits argument from chacha_keysetup - -commit 15974235dd528aeab0ec67fb92a0a1d733f62be2 -Author: Darren Tucker -Date: Tue Mar 1 09:00:20 2022 +1100 - - Add OPENBSD ORIGINAL marker. + OpenBSD-Commit-ID: e85899a26ba402b4c0717b531317e8fc258f0a7e -commit f2ff669347d320532e7c1b63cdf5c62f46e73150 -Author: Darren Tucker -Date: Mon Feb 28 22:21:36 2022 +1100 +commit e05522008092ceb86a87bdd4ad7878424315db89 +Author: djm@openbsd.org +Date: Thu Apr 28 02:53:31 2022 +0000 - No unused param warnings for clang-12 and gcc-11. + upstream: avoid printing hash algorithm twice; from lucas AT sexy.is - These have too many false positives in -Werror tests on the github CI - since we often provide empty stub functions for functionality not needed - for particular configurations. + OpenBSD-Commit-ID: 9d24671e10a84141b7c504396cabad600e47a941 -commit 96558ecd87adac62efa9a2b5479f686ab86b0be1 -Author: Darren Tucker -Date: Sat Feb 26 14:10:41 2022 +1100 +commit 0979e29356915261d69a9517a1e0aaade7c9fc75 +Author: dtucker@openbsd.org +Date: Wed Apr 27 11:08:55 2022 +0000 - Add debian-i386 test target. + upstream: Add authfd path to debug output. ok markus@ + + OpenBSD-Commit-ID: f735a17d1a6f2bee63bfc609d76ef8db8c090890 -commit 284b6e5394652d519e31782e3b3cdfd7b21d1a81 -Author: Darren Tucker -Date: Sat Feb 26 14:06:14 2022 +1100 +commit 67b7c784769c74fd4d6b147d91e17e1ac1a8a96d +Author: dtucker@openbsd.org +Date: Tue Apr 26 07:41:44 2022 +0000 - Allow ppoll_time64 in seccomp sandbox. + upstream: Check sshauthopt_new() for NULL. bz#3425, from - Should fix sandbox violations on (some? at least i386 and armhf) 32bit - Linux platforms. Patch from chutzpahu at gentoo.org and cjwatson at - debian.org via bz#3396. - -commit 0132056efabc5edb85c3c7105d2fb6dee41843c6 -Author: Darren Tucker -Date: Fri Feb 25 19:47:48 2022 +1100 + tessgauthier at microsoft.com. ok djm@ + + OpenBSD-Commit-ID: af0315bc3e44aa406daa7e0ae7c2d719a974483f - Improve handling of _getshort and _getlong. +commit d571314d14b919fbd7c84a61f9bf2065fc0a6841 +Author: millert@openbsd.org +Date: Wed Apr 20 16:00:25 2022 +0000 + + upstream: Remove unnecessary includes: openssl/hmac.h and - If the system native ones are exactly as required then use them, - otherwise use the local versions mapped to another name to prevent - name collisions. + openssl/evp.h. From Martin Vahlensieck. + + OpenBSD-Commit-ID: a6debb5fb0c8a44e43e8d5ca7cc70ad2f3ea31c3 -commit 8e206e0dd6b9f757b07979e48f53ad5bf9b7b52b -Author: Darren Tucker -Date: Fri Feb 25 15:14:22 2022 +1100 +commit da8dddf8cc1f2516ff894b8183e83a7c5ba3ef80 +Author: millert@openbsd.org +Date: Wed Apr 20 15:59:18 2022 +0000 - Constify utimes in compat library to match specs. + upstream: Add missing includes of stdlib.h and stdint.h. We need - Patch from vapier at chromium.org. + stdlib.h for malloc(3) and stdint.h for SIZE_MAX. Unlike the other xmss + files, ssh-xmss.c does not include xmss_commons.h so ssh-xmss.c must include + those headers itself. From Martin Vahlensieck + + OpenBSD-Commit-ID: 70e28a9818cee3da1be2ef6503d4b396dd421e6b -commit 1b2920e3b63db2eddebeec7330ffe8b723055573 -Author: Darren Tucker -Date: Fri Feb 25 13:50:56 2022 +1100 +commit fe9d87a6800a7a33be08f4d5ab662a758055ced2 +Author: millert@openbsd.org +Date: Wed Apr 20 15:56:49 2022 +0000 - ANSIfy getshort and getlong. + upstream: Avoid an unnecessary xstrdup in rm_env() when matching - These functions appear to have come from OpenBSD's lib/libc/net/res_comp.c - which made this change in 2005. + patterns. Since match_pattern() doesn't modify its arguments (they are + const), there is no need to make an extra copy of the strings in + options->send_env. From Martin Vahlensieck + + OpenBSD-Commit-ID: 2c9db31e3f4d3403b49642c64ee048b2a0a39351 -commit 54a86f4f6e1c43a2ca2be23ef799ab8910d4af70 +commit 7bf2eb958fbb551e7d61e75c176bb3200383285d Author: Darren Tucker -Date: Fri Feb 25 13:23:04 2022 +1100 +Date: Tue Apr 26 23:30:59 2022 +1000 - Use PICFLAG instead of hard coding -fPIC. + Add debian-riscv64 test target. -commit 3016ba47035ac3561aabd48e2be70167fe157d6a +commit 3913c935523902482974c4c503bcff20bd850a6a Author: Darren Tucker -Date: Fri Feb 25 11:37:11 2022 +1100 +Date: Mon Apr 25 17:20:06 2022 +1000 - Add tests for latest releases of {Libre,Open}SSL. + Update OpenSSL and LibreSSL versions in tests. -commit f107467179428a0e3ea9e4aa9738ac12ff02822d -Author: Colin Watson -Date: Thu Feb 24 16:04:18 2022 +0000 +commit dcd8dca29bcdb193ff6be35b96fc55e6e30d37d9 +Author: Darren Tucker +Date: Sat Apr 23 20:40:28 2022 +1000 - Improve detection of -fzero-call-used-regs=all support + Include stdlib.h for free() prototype. - GCC doesn't tell us whether this option is supported unless it runs into - the situation where it would need to emit corresponding code. + ... which is used inside the CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG block. -commit 3383b2cac0e9275bc93c4b4760e6e048f537e1d6 -Author: djm@openbsd.org -Date: Wed Feb 23 21:21:49 2022 +0000 +commit 4cc05de568e1c3edd7834ff3bd9d8214eb34861b +Author: Darren Tucker +Date: Sat Apr 23 20:17:26 2022 +1000 - upstream: free(3) wants stdlib.h + Cache timezone data in capsicum sandbox. - OpenBSD-Commit-ID: 227a8c70a95b4428c49e46863c9ef4bd318a3b8a + From emaste at freebsd.org, originally part of FreeBSD commit r339216 + / fc3c19a9 with autoconf bits added by me. -commit a4537e79ab4ac6db4493c5158744b9ebde5efcb0 -Author: djm@openbsd.org -Date: Wed Feb 23 21:21:16 2022 +0000 +commit c31404426d212e2964ff9e5e58e1d0fce3d83f27 +Author: dtucker@openbsd.org +Date: Thu Apr 21 01:36:46 2022 +0000 - upstream: put back the scp manpage changes for SFTP mode too + upstream: It looks like we can't completely avoid - OpenBSD-Commit-ID: 05dc53921f927e1b5e5694e1f3aa314549f2e768 + waiting for processes to exit so retrieve the pid via controlmaster and + use that. + + OpenBSD-Regress-ID: 8246f00f22b14e49d2ff1744c94897ead33d457b -commit 449bcb8403adfb9724805d02a51aea76046de185 -Author: deraadt@openbsd.org -Date: Wed Feb 23 19:01:00 2022 +0000 +commit d19b21afab5c8e2f3df6bd8aee9766bdad3d8c58 +Author: dtucker@openbsd.org +Date: Wed Apr 20 13:25:55 2022 +0000 - upstream: and we go back to testing sftp-scp after the 8.9 + upstream: Use ssh -f and ControlPersist .. - release... + to start up test forwards and ssh -O stop to shut them down intead of + sleep loops. This speeds up the test by an order of magnitude. - OpenBSD-Commit-ID: a80440168258adca543a4607b871327a279c569c - -commit 166456cedad3962b83b848b1e9caf80794831f0f -Author: Damien Miller -Date: Wed Feb 23 22:31:11 2022 +1100 - - makedepend + OpenBSD-Regress-ID: eb3db5f805100919b092a3b2579c611fba3e83e7 -commit 32ebaa0dbca5d0bb86e384e72bebc153f48413e4 -Author: djm@openbsd.org -Date: Wed Feb 23 11:18:13 2022 +0000 +commit 5f76286a126721fa005de6edf3d1c7a265555f19 +Author: dtucker@openbsd.org +Date: Wed Apr 20 05:24:13 2022 +0000 - upstream: avoid integer overflow of auth attempts (harmless, caught + upstream: Simplify forward-control test. - by monitor) + Since we no longer need to support SSH1 we don't need to run shell + commands on the other end of the connection and can use ssh -N instead. + This also makes the test less racy. - OpenBSD-Commit-ID: 488ad570b003b21e0cd9e7a00349cfc1003b4d86 + OpenBSD-Regress-ID: 32e94ce272820cc398f30b848b2b0f080d10302c -commit 6e0258c64c901753df695e06498b26f9f4812ea6 +commit 687bbf23572d8bdf25cbbcdf8ac583514e1ba710 Author: djm@openbsd.org -Date: Wed Feb 23 11:17:10 2022 +0000 +Date: Thu Mar 31 03:07:33 2022 +0000 - upstream: randomise the password used in fakepw + upstream: regression test for sftp cp command - OpenBSD-Commit-ID: 34e159f73b1fbf0a924a9c042d8d61edde293947 + OpenBSD-Regress-ID: c96bea9edde3a384b254785e7f9b2b24a81cdf82 -commit bf114d6f0a9df0b8369823d9a0daa6c72b0c4cc9 -Author: djm@openbsd.org -Date: Wed Feb 23 11:15:57 2022 +0000 +commit f1233f19a6a9fe58f52946f50df4772f5b136761 +Author: dtucker@openbsd.org +Date: Wed Apr 20 01:13:47 2022 +0000 - upstream: use asprintf to construct .rhosts paths + upstream: Import regenerated moduli - OpenBSD-Commit-ID: 8286e8d3d2c6ff916ff13d041d1713073f738a8b + OpenBSD-Commit-ID: f9a0726d957cf10692a231996a1f34e7f9cdfeb0 -commit c07e154fbdc7285e9ec54e78d8a31f7325d43537 +commit fec014785de198b9a325d1b94e324bb958c5fe7b Author: djm@openbsd.org -Date: Wed Feb 23 11:07:09 2022 +0000 - - upstream: openssh-8.9 - - OpenBSD-Commit-ID: 5c5f791c87c483cdab6d9266b43acdd9ca7bde0e - -commit bc16667b4a1c3cad7029304853c143a32ae04bd4 -Author: Darren Tucker -Date: Tue Feb 22 15:29:22 2022 +1100 +Date: Wed Apr 20 04:19:11 2022 +0000 - Extend select+rlimit sanbox test to include poll. + upstream: Try to continue running local I/O for channels in state - POSIX specifies that poll() shall fail if "nfds argument is greater - than {OPEN_MAX}". The setrlimit sandbox sets this to effectively zero - so this causes poll() to fail in the preauth privsep process. + OPEN during SSH transport rekeying. The most visible benefit is that it + should make ~-escapes work in the client (e.g. to exit) if the connection + happened to have stalled during a rekey event. Based work by and ok dtucker@ - This is likely the underlying cause for the previously observed similar - behaviour of select() on plaforms where it is implement in userspace on - top of poll(). - -commit 6520c488de95366be031d49287ed243620399e23 -Author: Darren Tucker -Date: Tue Feb 22 13:08:59 2022 +1100 - - Add Alpine Linux test VM. + OpenBSD-Commit-ID: a66e8f254e92edd4ce09c9f750883ec8f1ea5f45 -commit a4b325a3fc82d11e0f5d61f62e7fde29415f7afb -Author: Darren Tucker -Date: Tue Feb 22 12:27:07 2022 +1100 +commit e68154b0d4f0f5085a050ea896955da1b1be6e30 +Author: dtucker@openbsd.org +Date: Wed Apr 20 01:13:47 2022 +0000 - Include sys/param.h if present. + upstream: Import regenerated moduli - Needed for howmany() on MUSL systems such as Alpine. + OpenBSD-Commit-ID: f9a0726d957cf10692a231996a1f34e7f9cdfeb0 -commit 5a102e9cb287a43bd7dfe594b775a89a8e94697c -Author: Darren Tucker -Date: Tue Feb 22 12:25:52 2022 +1100 +commit 69928b106d8f0fa15b88cf3850d992ed81c44ae0 +Author: tj@openbsd.org +Date: Sat Apr 16 00:22:31 2022 +0000 - Only include sys/poll.h if we don't have poll.h. + upstream: list the correct version number - Prevents warnings on MUSL based systems such as Alpine. + for when usage of the sftp protocol became default and fix a typo + from ed maste + + OpenBSD-Commit-ID: 24e1795ed2283fdeacf16413c2f07503bcdebb31 -commit 7c0d4ce911d5c58b6166b2db754a4e91f352adf5 -Author: Damien Miller -Date: Tue Feb 22 11:14:51 2022 +1100 +commit 21042a05c0b304c16f655efeec97438249d2e2cc +Author: dtucker@openbsd.org +Date: Tue Apr 12 05:09:49 2022 +0000 - disable agent-restrict test on minix3 - - Minix seems to have a platform-wide limit on the number of - select(2) syscalls that can be concurrently issued. This test - seems to exceed this limit. + upstream: Correct path for system known hosts file in description - Refer to: + of IgnoreUserKnownHosts. Patch from Martin Vahlensieck via tech@ - https://github.com/Stichting-MINIX-Research-Foundation/minix/blob/R3.3.0/minix/servers/vfs/select.c#L114 - https://github.com/Stichting-MINIX-Research-Foundation/minix/blob/R3.3.0/minix/servers/vfs/select.c#L30-L31 + OpenBSD-Commit-ID: 9b7784f054fa5aa4d63cb36bd563889477127215 -commit 81d33d8e3cf7ea5ce3a5653c6102b623e019428a +commit 53f4aff60a7c1a08a23917bd47496f8901c471f5 Author: Darren Tucker -Date: Mon Feb 21 21:27:20 2022 +1100 - - Skip agent-getpeereid when running as root. - -commit fbd772570a25436a33924d91c164d2b24021f010 -Author: dtucker@openbsd.org -Date: Sun Feb 20 03:47:26 2022 +0000 +Date: Sat Apr 16 14:33:20 2022 +1000 - upstream: Aproximate realpath on the expected output by deduping - - leading slashes. Fixes test failure when user's home dir is / which is - possible in some portable configurations. + Resync moduli.5 with upstream. - OpenBSD-Regress-ID: 53b8c53734f8893806961475c7106397f98d9f63 + 1.18: remove duplicate publication year; carsten dot kunze at arcor dot de + 1.19: ssh-keygen's -G/-T have been replaced with -M generate/screen. -commit 336685d223a59f893faeedf0a562e053fd84058e +commit d2b888762b9844eb0d8eb59909cdf5af5159f810 Author: Darren Tucker -Date: Sun Feb 20 13:30:52 2022 +1100 +Date: Sat Apr 16 14:31:13 2022 +1000 - Really move DSA to end of list. + Retire fbsd6 test VM. - In commit ad16a84e syncing from OpenBSD, RSA was accidentally moved to - the end of the list instead of DSA. Spotted by andrew at fyfe.gb.net. + It's long since out of support, relatively slow (it's i686) and the + compiler has trouble with PIE. -commit 63bf4f49ed2fdf2da6f97136c9df0c8168546eb3 -Author: Darren Tucker -Date: Fri Feb 18 12:12:21 2022 +1100 +commit cd1f70009860a154b51230d367c55ea5f9a4504e +Author: djm@openbsd.org +Date: Mon Apr 11 22:52:08 2022 +0000 - Add test configs for MUSL C library. + upstream: clear io_want/io_ready flags at start of poll() cycle; + + avoids plausible spin during rekeying if channel io_want flags are reused + across cycles. ok markus@ deraadt@ + + OpenBSD-Commit-ID: 91034f855b7c73cd2591657c49ac30f10322b967 -commit f7fc6a43f1173e8b2c38770bf6cee485a562d03b -Author: Damien Miller -Date: Thu Feb 17 22:54:19 2022 +1100 +commit aa1920302778273f7f94c2091319aba199068ca0 +Author: dtucker@openbsd.org +Date: Fri Apr 8 05:43:39 2022 +0000 - minix needs BROKEN_POLL too; chokes on /dev/null + upstream: Note that curve25519-sha256 was later published in + + RFC8731. ok djm@ + + OpenBSD-Commit-ID: 2ac2b5d642d4cf5918eaec8653cad9a4460b2743 -commit 667fec5d4fe4406745750a32f69b5d2e1a75e94b +commit 4673fa8f2be983f2f88d5afd754adb1a2a39ec9e Author: djm@openbsd.org -Date: Thu Feb 17 10:58:27 2022 +0000 +Date: Fri Apr 8 04:40:40 2022 +0000 - upstream: check for EINTR/EAGAIN failures in the rfd fast-path; caught + upstream: two defensive changes from Tobias Stoeckmann via GHPR287 - by dtucker's minix3 vm :) ok dtucker@ + enforce stricter invarient for sshbuf_set_parent() - never allow + a buffer to have a previously-set parent changed. - OpenBSD-Commit-ID: 2e2c895a3e82ef347aa6694394a76a438be91361 + In sshbuf_reset(), if the reallocation fails, then zero the entire + buffer and not the (potentially smaller) default initial alloc size. + + OpenBSD-Commit-ID: 14583203aa5d50ad38d2e209ae10abaf8955e6a9 -commit 41417dbda9fb55a0af49a8236e3ef9d50d862644 -Author: Darren Tucker -Date: Thu Feb 17 22:05:29 2022 +1100 +commit 26eef015e2d2254375e13afaaf753b78932b1bf5 +Author: Damien Miller +Date: Mon Apr 11 16:07:09 2022 +1000 - Comment hurd test, the VM is currently broken. + Revert "update build-aux files to match autoconf-2.71" + + This reverts commit 0a8ca39fac6ad19096b6c263436f8b2dd51606f2. + + It turns out that the checked-in copies of these files are actually newer + than autoconf-2.71's copies, so this was effectively a downgrade. + Spotted by Bo Anderson via github -commit b2aee35a1f0dc798339b3fcf96136da71b7e3f6d +commit 0a8ca39fac6ad19096b6c263436f8b2dd51606f2 Author: Damien Miller -Date: Thu Feb 17 21:15:16 2022 +1100 +Date: Fri Apr 8 14:48:58 2022 +1000 - find sk-dummy.so when build_dir != src_dir + update build-aux files to match autoconf-2.71 - spotted by Corinna Vinschen; feedback & ok dtucker@ + i.e. config.guess, config.sub and install-sh -commit 62a2d4e50b2e89f2ef04576931895d5139a5d037 +commit 94eb6858efecc1b4f02d8a6bd35e149f55c814c8 Author: Damien Miller -Date: Wed Feb 16 16:26:17 2022 +1100 +Date: Wed Apr 6 10:47:48 2022 +1000 - update versions in preparation for 8.9 release + update version numbers for release -commit dd6d3dded721ac653ea73c017325e5bfeeec837f +commit 8e4a8eadf4fe74e65e6492f34250f8cf7d67e8da Author: djm@openbsd.org -Date: Tue Feb 15 05:13:36 2022 +0000 +Date: Mon Apr 4 22:45:25 2022 +0000 - upstream: document the unbound/host-bound options to - - PubkeyAuthentication; spotted by HARUYAMA Seigo + upstream: openssh-9.0 - OpenBSD-Commit-ID: 298f681b66a9ecd498f0700082c7a6c46e948981 + OpenBSD-Commit-ID: 0dfb461188f4513ec024c1534da8c1ce14c20b64 -commit df93529dd727fdf2fb290700cd4f1adb0c3c084b -Author: Darren Tucker -Date: Mon Feb 14 14:19:40 2022 +1100 +commit a9f23ea2e3227f406880c2634d066f6f50fa5eaa +Author: naddy@openbsd.org +Date: Thu Mar 31 17:58:44 2022 +0000 - Test if sshd accidentally acquires controlling tty + upstream: ssh: document sntrup761x25519-sha512@openssh.com as - When SSHD_ACQUIRES_CTTY is defined, test for the problematic behaviour - in the STREAMS code before activating the workaround. ok djm@ - -commit 766176cfdbfd7ec38bb6118dde6e4daa0df34888 -Author: Darren Tucker -Date: Sat Feb 12 10:24:56 2022 +1100 - - Add cygwin-release test config. + default KEX - This tests the flags used to build the cygwin release binaries. + OpenBSD-Commit-ID: 12545bfa10bcbf552d04d9d9520d0f4e98b0e171 -commit b30698662b862f5397116d23688aac0764e0886e -Author: Darren Tucker -Date: Fri Feb 11 21:00:35 2022 +1100 +commit 9ec2713d122af79d66ebb9c1d6d9ae8621a8945f +Author: naddy@openbsd.org +Date: Thu Mar 31 17:27:27 2022 +0000 - Move SSHD_ACQUIRES_CTTY workaround into compat. - - On some (most? all?) SysV based systems with STREAMS based ptys, - sshd could acquire a controlling terminal during pty setup when - it pushed the "ptem" module, due to what is probably a bug in - the STREAMS driver that's old enough to vote. Because it was the - privileged sshd's controlling terminal, it was not available for - the user's session, which ended up without one. This is known to - affect at least Solaris <=10, derivatives such as OpenIndiana and - several other SysV systems. See bz#245 for the backstory. - - In the we past worked around that by not calling setsid in the - privileged sshd child, which meant it was not a session or process - group leader. This solved controlling terminal problem because sshd - was not eligble to acquire one, but had other side effects such as - not cleaning up helper subprocesses in the SIGALRM handler since it - was not PG leader. Recent cleanups in the signal handler uncovered - this, resulting in the LoginGraceTime timer not cleaning up privsep - unprivileged processes. - - This change moves the workaround into the STREAMS pty allocation code, - by allocating a sacrificial pty to act as sshd's controlling terminal - before allocating user ptys, so those are still available for users' - sessions. - - On the down side: - - this will waste a pty per ssh connection on affected platforms. - - On the up side: - - it makes the process group behaviour consistent between platforms. + upstream: man pages: add missing commas between subordinate and - - it puts the workaround nearest the code that actually causes the - problem and competely out of the mainline code. + main clauses - - the workaround is only activated if you use the STREAMS code. If, - say, Solaris 11 has the bug but also a working openpty() it doesn't - matter that we defined SSHD_ACQUIRES_CTTY. + jmc@ dislikes a comma before "then" in a conditional, so leave those + untouched. - - the workaround is only activated when the fist pty is allocated, - ie in the post-auth privsep monitor. This means there's no risk - of fd leaks to the unprivileged processes, and there's no effect on - sessions that do not allocate a pty. + ok jmc@ - Based on analysis and work by djm@, ok djm@ + OpenBSD-Commit-ID: 9520801729bebcb3c9fe43ad7f9776ab4dd05ea3 -commit cd00b48cf10f3565936a418c1e6d7e48b5c36140 +commit 3741df98ffaaff92b474ee70d8ef276b5882f85a Author: Darren Tucker -Date: Fri Feb 11 20:09:32 2022 +1100 +Date: Mon Apr 4 23:52:11 2022 +1000 - Simplify handling of --with-ssl-dir. - - ok djm@ + Disable security key on fbsd6 test host. -commit ea13fc830fc0e0dce2459f1fab2ec5099f73bdf0 +commit 32c12236f27ae83bfe6d2983b67c9bc67a83a417 Author: Darren Tucker -Date: Fri Feb 11 13:39:29 2022 +1100 +Date: Mon Apr 4 15:16:51 2022 +1000 - Stop testing OpenBSD HEAD on 6.9 and 7.0. + Specify TEST_SHELL=bash on AIX. - HEAD is not guaranteed to work on previous stable branches, and at the - moment is broken due to libfido API changes. + The system shells cause the agent-restrict test to fail due to some + quoting so explicitly specify bash until we can get configure to + autmatically work around that. -commit 50b9e4a4514697ffb9592200e722de6b427cb9ff -Author: dtucker@openbsd.org -Date: Fri Feb 11 00:43:56 2022 +0000 +commit 90452c8b69d065b7c7c285ff78b81418a75bcd76 +Author: Darren Tucker +Date: Fri Apr 1 23:38:44 2022 +1100 - upstream: Always initialize delim before passing to hpdelim2 which - - might not set it. Found by the Valgrind tests on github, ok deraadt@ + Only return events from ppoll that were requested. - OpenBSD-Commit-ID: c830c0db185ca43beff3f41c19943c724b4f636d + If the underlying system's select() returns bits that were not in the + request set, our ppoll() implementation can return revents for events + not requested, which can apparently cause a hang. Only return revents + for activity in the requested event set. bz#3416, analysis and fix by + yaroslav.kuzmin at vmssoftware com, ok djm@ -commit 6ee53064f476cf163acd5521da45b11b7c57321b +commit 6c49eb5fabc56f4865164ed818aa5112d09c31a8 Author: Darren Tucker -Date: Fri Feb 11 10:03:06 2022 +1100 +Date: Fri Apr 1 23:21:40 2022 +1100 - Fix helper include path and remove excess code. - - Looks like test_hpdelim.c was imported twice into the same file. - Spotted by kevin.brott at gmail com and chris at cataclysmal org. + Only run regression tests on slow VMs. -commit 9fa63a19f68bc87452d3cf5c577cafad2921b7a4 +commit f67e47903977b42cb6abcd5565a61bd7293e4dc3 Author: Darren Tucker -Date: Thu Feb 10 23:27:02 2022 +1100 +Date: Fri Apr 1 23:21:06 2022 +1100 - Put poll.h inside ifdef. + Increase test timeout to allow slow VMs to finish -commit 3ac00dfeb54b252c15dcbf1971582e9e3b946de6 +commit 02488c1b54065ddc4f25835dbd2618b2a2fe21f5 Author: Darren Tucker -Date: Thu Feb 10 22:17:31 2022 +1100 +Date: Fri Apr 1 16:27:38 2022 +1100 - We now support POLLPRI so actually define it. + Use bash or ksh if available for SH in Makefile. -commit 25bd659cc72268f2858c5415740c442ee950049f -Author: dtucker@openbsd.org -Date: Sun Feb 6 22:58:33 2022 +0000 +commit 34c7018c316af4773e432066de28d0ef9d0888cd +Author: Darren Tucker +Date: Fri Apr 1 14:56:54 2022 +1100 - upstream: Add test for empty hostname with port. + Set Makefile SHELL as determined by configure. - OpenBSD-Regress-ID: e19e89d3c432b68997667efea44cf015bbe2a7e3 + This should improve compatibility for users with non-POSIX shells. If + using Makefile.in directly (eg make -f Makefile.in distprep) then SHELL + will need to be specified on the command line (along with MANFMT in that + particular case). ok djm@ -commit a29af853cff41c0635f0378c00fe91bf9c91dea4 -Author: dtucker@openbsd.org -Date: Fri Feb 4 07:53:44 2022 +0000 +commit 5b054d76402faab38c48377efd112426469553a0 +Author: Darren Tucker +Date: Fri Apr 1 13:16:47 2022 +1100 - upstream: Add unit tests for hpdelim. + Skip slow tests on (very) slow test targets. + +commit b275818065b31a865142c48c2acf6a7c1655c542 +Author: Damien Miller +Date: Thu Mar 31 14:11:36 2022 +1100 + + depend + +commit 3fa539c3ffaabd6211995512d33e29150f88c5c5 +Author: djm@openbsd.org +Date: Thu Mar 31 03:07:03 2022 +0000 + + upstream: add a sftp client "cp" command that supports server-side - OpenBSD-Regress-ID: be97b85c19895e6a1ce13c639765a3b48fd95018 + copying of files. Useful for this task and for testing the copy-data + extension. Patch from Mike Frysinger; ok dtucker@ + + OpenBSD-Commit-ID: 1bb1b950af0d49f0d5425b1f267e197aa1b57444 -commit 9699151b039ecc5fad9ac6c6c02e9afdbd26f15f +commit 7988bfc4b701c4b3fe9b36c8561a3d1c5d4c9a74 Author: djm@openbsd.org -Date: Thu Feb 10 04:12:38 2022 +0000 +Date: Thu Mar 31 03:05:49 2022 +0000 - upstream: revert for imminent OpenSSH release, which wil ship with + upstream: add support for the "corp-data" protocol extension to - scp in RCP mode. + allow server-side copies to be performed without having to go via the client. + Patch by Mike Frysinger, ok dtucker@ - > revision 1.106 - > date: 2021/10/15 14:46:46; author: deraadt; state: Exp; lines: +13 -9; commitid: w5n9B2RE38tFfggl; - > openbsd 7.0 release shipped with the (hopefully last) scp that uses RCP - > protocol for copying. Let's get back to testing the SFTP protocol. + OpenBSD-Commit-ID: 00aa510940fedd66dab1843b58682de4eb7156d5 + +commit 32dc1c29a4ac9c592ddfef0a4895eb36c1f567ba +Author: djm@openbsd.org +Date: Wed Mar 30 21:13:23 2022 +0000 + + upstream: select post-quantum KEX - This will be put back once the OpenSSH release is done. + sntrup761x25519-sha512@openssh.com as the default; ok markus@ + + OpenBSD-Commit-ID: f02d99cbfce22dffec2e2ab1b60905fbddf48fb9 + +commit d6556de1db0822c76ba2745cf5c097d9472adf7c +Author: djm@openbsd.org +Date: Wed Mar 30 21:10:25 2022 +0000 + + upstream: fix poll() spin when a channel's output fd closes without + + data in the channel buffer. Introduce more exact packing of channel fds into + the pollfd array. fixes bz3405 and bz3411; ok deraadt@ markus@ - OpenBSD-Commit-ID: 0c725481a78210aceecff1537322c0b2df03e768 + OpenBSD-Commit-ID: 06740737849c9047785622ad5d472cb6a3907d10 -commit 45279abceb37c3cbfac8ba36dde8b2c8cdd63d32 -Author: dtucker@openbsd.org -Date: Tue Feb 8 08:59:12 2022 +0000 +commit 8a74a96d25ca4d32fbf298f6c0ac5a148501777d +Author: djm@openbsd.org +Date: Wed Mar 30 04:33:09 2022 +0000 - upstream: Switch hpdelim interface to accept only ":" as delimiter. + upstream: ssh is almost out of getopt() characters; note the - Historicallly, hpdelim accepted ":" or "/" as a port delimiter between - hosts (or addresses) and ports. These days most of the uses for "/" - are no longer accepted, so there are several places where it checks the - delimiter to disallow it. Make hpdelim accept only ":" and use hpdelim2 - in the other cases. ok djm@ + remaining remaining available ones in a comment - OpenBSD-Commit-ID: 7e6420bd1be87590b6840973f5ad5305804e3102 + OpenBSD-Commit-ID: 48d38cef59d6bc8e84c6c066f6d601875d3253fd -commit a1bcbf04a7c2d81944141db7ecd0ba292d175a66 -Author: pedro martelletto -Date: Mon Feb 7 09:09:59 2022 +0100 +commit 6d4fc51adb9d8a42f67b5474f02f877422379de6 +Author: djm@openbsd.org +Date: Wed Mar 30 04:27:51 2022 +0000 - fix typos in previous + upstream: avoid NULL deref via ssh-keygen -Y find-principals. + + bz3409, reported by Mateusz Adamowski + + OpenBSD-Commit-ID: a3b2c02438052ee858e0ee18e5a288586b5df2c5 -commit 56192518e329b39f063487bc2dc4d796f791eca0 -Author: Damien Miller -Date: Mon Feb 7 12:53:47 2022 +1100 +commit e937514920335b92b543fd9be79cd6481d1eb0b6 +Author: Darren Tucker +Date: Mon Mar 28 17:51:03 2022 +1100 - compat code for fido_assert_set_clientdata() + Add AIX 5.1 test target. -commit d6b5aa08fdcf9b527f8b8f932432941d5b76b7ab -Author: djm@openbsd.org -Date: Mon Feb 7 01:25:12 2022 +0000 +commit 4bbe815ba974b4fd89cc3fc3e3ef1be847a0befe +Author: Darren Tucker +Date: Sat Mar 26 22:01:31 2022 +1100 - upstream: use libfido2 1.8.0+ fido_assert_set_clientdata() instead - - of manually hashing data outselves. Saves a fair bit of code and makes life - easier for some -portable platforms. + Drop leading "v" from release version identifier. - OpenBSD-Commit-ID: 351dfaaa5ab1ee928c0e623041fca28078cff0e0 + It's present in the git tags but not in the release tarball names. + Also drop extra "/" from URL path. -commit 86cc93fd3c26b2e0c7663c6394995fb04ebfbf3b -Author: jsg@openbsd.org -Date: Sun Feb 6 00:29:03 2022 +0000 +commit f5cdd3b3c275dffaebfca91df782dca29975e9ac +Author: Darren Tucker +Date: Sat Mar 26 16:28:04 2022 +1100 - upstream: remove please from manual pages ok jmc@ sthen@ millert@ + Use tarballs when testing LibreSSL releases. - OpenBSD-Commit-ID: 6543acb00f4f38a23472538e1685c013ca1a99aa + This means they'll still work when the combination of -portable and + openbsd github repos no longer match. -commit ad16a84e64a8cf1c69c63de3fb9008320a37009c -Author: dtucker@openbsd.org -Date: Fri Feb 4 02:49:17 2022 +0000 +commit 24dc37d198f35a7cf71bf4d5384363c7ef4209d4 +Author: Darren Tucker +Date: Sat Mar 26 15:02:45 2022 +1100 - upstream: Since they are deprecated, move DSA to the end of the - - default list of public keys so that they will be tried last. From github - PR#295 from "ProBackup-nl", ok djm@ - - OpenBSD-Commit-ID: 7e5d575cf4971d4e2de92e0b6d6efaba53598bf0 + Remove now-unused passwd variable. -commit 253de42753de85dde266e061b6fec12ca6589f7d -Author: Damien Miller -Date: Wed Feb 2 16:52:07 2022 +1100 +commit 5b467ceef2c356f0a77f5e8ab4eb0fac367e4d24 +Author: Darren Tucker +Date: Sat Mar 26 13:15:44 2022 +1100 - portable-specific string array constification - - from Mike Frysinger + Missing semicolon. -commit dfdcc2220cf359c492d5d34eb723370e8bd8a19e -Author: djm@openbsd.org -Date: Tue Feb 1 23:37:15 2022 +0000 +commit 2923d026e55998133c0f6e5186dca2a3c0fa5ff5 +Author: Darren Tucker +Date: Sat Mar 26 12:49:50 2022 +1100 - upstream: test 'ssh-keygen -Y find-principals' with wildcard - - principals; from Fabian Stelzer + Factor out platform-specific locked account check. - OpenBSD-Regress-ID: fbe4da5f0032e7ab496527a5bf0010fd700f8f40 + Also fixes an incorrect free on platforms with both libiaf and shadow + passwords (probably only Unixware). Prompted by github PR#284, + originally from @c3h2_ctf and stoeckmann@. -commit 968e508967ef42480cebad8cf3172465883baa77 -Author: dtucker@openbsd.org -Date: Fri Jan 21 02:54:41 2022 +0000 +commit d23efe4b12886ffe416be10bc0a7da6ca8aa72d1 +Author: Darren Tucker +Date: Sat Mar 26 08:13:46 2022 +1100 - upstream: Enable all supported ciphers and macs in the server - - before trying to benchmark them. Increase the data file size to get more - signal. - - OpenBSD-Regress-ID: dc3697d9f7defdfc51c608782c8e750128e46eb6 + Add OpenWRT mips and mipsel test targets. -commit 15b7199a1fd37eff4c695e09d573f3db9f4274b7 +commit 16ea8b85838dd7a4dbeba4e51ac4f43fd68b1e5b Author: djm@openbsd.org -Date: Tue Feb 1 23:34:47 2022 +0000 +Date: Sun Mar 20 08:52:17 2022 +0000 - upstream: allow 'ssh-keygen -Y find-principals' to match wildcard + upstream: don't leak argument list; bz3404, reported by Balu - principals in allowed_signers files; from Fabian Stelzer + Gajjala ok dtucker@ - OpenBSD-Commit-ID: 1e970b9c025b80717dddff5018fe5e6f470c5098 + OpenBSD-Commit-ID: fddc32d74e5dd5cff1a49ddd6297b0867eae56a6 -commit 541667fe6dc26d7881e55f0bb3a4baa6f3171645 +commit a72bde294fe0518c9a44ba63864093a1ef2425e3 Author: djm@openbsd.org -Date: Tue Feb 1 23:32:51 2022 +0000 +Date: Sun Mar 20 08:51:21 2022 +0000 - upstream: mark const string array contents const too, i.e. static + upstream: make addargs() and replacearg() a little more robust and - const char *array => static const char * const array from Mike Frysinger + improve error reporting - OpenBSD-Commit-ID: a664e31ea6a795d7c81153274a5f47b22bdc9bc1 + make freeargs(NULL) a noop like the other free functions + + ok dtucker as part of bz3403 + + OpenBSD-Commit-ID: 15f86da83176978b4d1d288caa24c766dfa2983d -commit 8cfa73f8a2bde4c98773f33f974c650bdb40dd3c +commit 731087d2619fa7f01e675b23f57af10d745e8af2 Author: djm@openbsd.org -Date: Tue Feb 1 23:11:11 2022 +0000 +Date: Fri Mar 18 04:04:11 2022 +0000 - upstream: better match legacy scp behaviour: show un-expanded paths + upstream: don't try to resolve ListenAddress directives in the sshd - in error messages. Spotted by and ok tb@ + re-exec path - we're never going to use the result and if the operation fails + then it can prevent connections from being accepted. Reported by Aaron + Poffenberger; with / ok dtucker@ - OpenBSD-Commit-ID: 866c8ffac5bd7d38ecbfc3357c8adfa58af637b7 + OpenBSD-Commit-ID: 44c53a43909a328e2f5ab26070fdef3594eded60 -commit 4e62c13ab419b4b224c8bc6a761e91fcf048012d -Author: dtucker@openbsd.org -Date: Tue Feb 1 07:57:32 2022 +0000 +commit 1c83c082128694ddd11ac05fdf31d70312ff1763 +Author: djm@openbsd.org +Date: Fri Mar 18 02:50:21 2022 +0000 - upstream: Remove explicit kill of privsep preauth child's PID in - - SIGALRM handler. It's no longer needed since the child will get terminated by - the SIGTERM to the process group that cleans up any auth helpers, it - simplifies the signal handler and removes the risk of a race when updating - the PID. Based on analysis by HerrSpace in github PR#289, ok djm@ + upstream: remove blank line - OpenBSD-Commit-ID: 2be1ffa28b4051ad9e33bb4371e2ec8a31d6d663 + OpenBSD-Commit-ID: d5e0182965b2fbfb03ad5f256d1a1ce5706bcddf -commit 2a7ccd2ec4022917b745af7186f514f365b7ebe9 -Author: guenther@openbsd.org -Date: Fri Jan 28 06:18:42 2022 +0000 +commit 807be68684da7a1fe969c399ddce2fafb7997dcb +Author: djm@openbsd.org +Date: Fri Mar 18 02:32:22 2022 +0000 - upstream: When it's the possessive of 'it', it's spelled "its", - - without the apostrophe. + upstream: helpful comment - OpenBSD-Commit-ID: fb6ab9c65bd31de831da1eb4631ddac018c5fae7 + OpenBSD-Commit-ID: e3315a45cb04e7feeb614d76ec80a9fe4ca0e8c7 -commit 8a0848cdd3b25c049332cd56034186b7853ae754 -Author: Alex James -Date: Sun Jan 30 16:13:36 2022 -0600 +commit a0b5816f8f1f645acdf74f7bc11b34455ec30bac +Author: djm@openbsd.org +Date: Fri Mar 18 02:31:25 2022 +0000 - sandbox-seccomp-filter: allow gettid + upstream: ssh-keygen -Y check-novalidate requires namespace or SEGV - Some allocators (such as Scudo) use gettid while tracing allocations [1]. - Allow gettid in preauth to prevent sshd from crashing with Scudo. + will ensue. Patch from Mateusz Adamowski via GHPR#307 - [1]: https://github.com/llvm/llvm-project/blob/llvmorg-13.0.0/compiler-rt/lib/gwp_asan/common.cpp#L46 + OpenBSD-Commit-ID: 99e8ec38f9feb38bce6de240335be34aedeba5fd -commit b30d32159dc3c7052f4bfdf36357996c905af739 +commit 5a252d54a63be30d5ba4be76210942d754a531c0 Author: djm@openbsd.org -Date: Sat Jan 22 00:49:34 2022 +0000 +Date: Tue Mar 15 05:27:37 2022 +0000 - upstream: add a ssh_packet_process_read() function that reads from + upstream: improve DEBUG_CHANNEL_POLL debugging message - a fd directly into the transport input buffer. + OpenBSD-Commit-ID: 2275eb7bc4707d019b1a0194b9c92c0b78da848f + +commit ce324cf58ba2840e31afeb996935800780c8fa4b +Author: cheloha@openbsd.org +Date: Sun Mar 13 23:27:54 2022 +0000 + + upstream: ssh: xstrdup(): use memcpy(3) - Use this in the client and server mainloops to avoid unnecessary - copying. It also lets us use a more greedy read size without penalty. + Copying the given string into the buffer with strlcpy(3) confers no + benefit in this context because we have already determined the + string's length with strlen(3) in order to allocate that buffer. - Yields a 2-3% performance gain on cipher-speed.sh (in a fairly - unscientific test tbf) + Thread: https://marc.info/?l=openbsd-tech&m=164687525802691&w=2 - feedback dtucker@ ok markus@ + ok dtucker@ millert@ - OpenBSD-Commit-ID: df4112125bf79d8e38e79a77113e1b373078e632 + OpenBSD-Commit-ID: f8bfc082e36e2d2dc4e1feece02fe274155ca11a -commit a1a8efeaaa9cccb15cdc0a2bd7c347a149a3a7e3 -Author: djm@openbsd.org -Date: Sat Jan 22 00:45:31 2022 +0000 +commit 2893c5e764557f48f9d6a929e224ed49c59545db +Author: Darren Tucker +Date: Fri Mar 11 18:43:58 2022 +1100 - upstream: Use sshbuf_read() to read directly into the channel input - - buffer rather than into a stack buffer that needs to be copied again; - Improves performance by about 1% on cipher-speed.sh feedback dtucker@ ok - markus@ + Resync fmt_scaled. with OpenBSD. - OpenBSD-Commit-ID: bf5e6e3c821ac3546dc8241d8a94e70d47716572 + Fixes underflow reported in bz#3401. -commit 29a76994e21623a1f84d68ebb9dc5a3c909fa3a7 -Author: Damien Miller -Date: Tue Jan 25 11:52:34 2022 +1100 +commit 5ae31a0fdd27855af29f48ff027491629fff5979 +Author: Darren Tucker +Date: Wed Mar 9 09:41:56 2022 +1100 - depend + Provide killpg implementation. + + Based on github PR#301 for Tandem NonStop. -commit 754e0d5c7712296a7a3a83ace863812604c7bc4f -Author: djm@openbsd.org -Date: Sat Jan 22 00:43:43 2022 +0000 +commit c41c84b439f4cd74d4fe44298a4b4037ddd7d2ae +Author: Darren Tucker +Date: Wed Mar 9 09:29:30 2022 +1100 - upstream: Add a sshbuf_read() that attempts to read(2) directly in + Check for missing ftruncate prototype. - to a sshbuf; ok markus@ + From github PR#301 in conjunction with rsbeckerca. + +commit 8cf5275452a950869cb90eeac7d220b01f77b12e +Author: Darren Tucker +Date: Tue Mar 8 20:04:06 2022 +1100 + + Default to not using sandbox when cross compiling. - OpenBSD-Commit-ID: 2d8f249040a4279f3bc23c018947384de8d4a45b + On most systems poll(2) does not work when the number of FDs is reduced + with setrlimit, so assume it doesn't when cross compiling and we can't + run the test. bz#3398. -commit c7964fb9829d9ae2ece8b51a76e4a02e8449338d +commit 379b30120da53d7c84aa8299c26b18c51c2a0dac Author: djm@openbsd.org -Date: Fri Jan 21 07:04:19 2022 +0000 +Date: Tue Mar 1 01:59:19 2022 +0000 - upstream: add a helper for writing an error message to the + upstream: pack pollfd array before server_accept_loop() ppoll() - stderr_buf and setting quit_pending; no functional change but saves a bunch - of boilerplate + call, and terminate sshd if ppoll() returns errno==EINVAL - OpenBSD-Commit-ID: 0747657cad6b9eabd514a6732adad537568e232d - -commit d23b4f7fdb1bd87e2cd7a9ae7c198ae99d347916 -Author: djm@openbsd.org -Date: Fri Jan 21 06:58:06 2022 +0000 - - upstream: correct comment and use local variable instead of long + avoids spin in ppoll when MaxStartups > RLIMIT_NOFILE, reported by + Daniel Micay - indirection; spotted by dtucker@ + feedback/ok deraadt - OpenBSD-Commit-ID: 5f65f5f69db2b7d80a0a81b08f390a63f8845965 + OpenBSD-Commit-ID: dbab1c24993ac977ec24d83283b8b7528f7c2c15 -commit d069b020a02b6e3935080204ee44d233e8158ebb -Author: deraadt@openbsd.org -Date: Fri Jan 21 00:53:40 2022 +0000 +commit eceafbe0bdbbd9bd2f3cf024ccb350666a9934dd +Author: naddy@openbsd.org +Date: Sun Feb 27 01:33:59 2022 +0000 - upstream: When poll(2) returns -1, for some error conditions + upstream: include rejected signature algorithm in error message and - pfd[].revents is not cleared. There are subtle errors in various programs. - In this particular case, the program should error out. ok djm millert + not the (useless) key type; ok djm@ - OpenBSD-Commit-ID: 00f839b16861f7fb2adcf122e95e8a82fa6a375c + OpenBSD-Commit-ID: d0c0f552a4d9161203e07e95d58a76eb602a76ff -commit e204b34337a965feb439826157c191919fd9ecf8 -Author: Damien Miller -Date: Sat Jan 22 11:38:21 2022 +1100 +commit f2f3269423618a83157e18902385e720f9776007 +Author: dtucker@openbsd.org +Date: Fri Feb 25 09:46:24 2022 +0000 - restore tty force-read hack + upstream: Remove the char * casts from arguments to do_lstat, - This portable-specific hack fixes a hang on exit for ttyful sessions - on Linux and some SysVish Unix variants. It was accidentally disabled - in commit 5c79952dfe1a (a precursor to the mainloop poll(2) conversion). + do_readdir and do_stat paths since the underlying functions now take a const + char *. Patch from vapier at gentoo.org. - Spotted by John in bz3383 + OpenBSD-Commit-ID: 9e4d964dbfb0ed683a2a2900711b88e7f1c0297b -commit 68085066b6bad43643b43f5957fcc5fd34782ccd -Author: Corinna Vinschen -Date: Fri Jan 21 03:22:56 2022 +1100 +commit 4a66dac052c5ff5047161853f36904607649e4f9 +Author: djm@openbsd.org +Date: Fri Feb 25 02:09:27 2022 +0000 - Fix signedness bug in Cygwin code + upstream: save an unneccessary alloc/free, based on patch from - The Cygwin-specific pattern match code has a bug. It checks - the size_t value returned by mbstowcs for being < 0. The right - thing to do is to check against (size_t) -1. Fix that. + Martin Vahlensieck; ok dtucker@ - Signed-off-by: Corinna Vinschen + OpenBSD-Commit-ID: 90ffbf1f837e509742f2c31a1fbf2c0fd376fd5f -commit 2e5cfed513e84444483baf1d8b31c40072b05103 +commit 6f117cb151efe138ac57bdd8e26165f350328f5f Author: Darren Tucker -Date: Thu Jan 20 13:26:27 2022 +1100 +Date: Tue Mar 1 09:02:06 2022 +1100 - Improve compatibility of early exit trap handling. - - Dash (as used by the github runners) has some differences in its trap - builtin: - - it doesn't have -p (which is fine, that's not in posix). - - it doesn't work in a subshell (which turns out to be in compliance - with posix, which means bash isn't). - - it doesn't work in a pipeline, ie "trap|cat" produces no output. + Remove unused ivbits argument from chacha_keysetup -commit 3fe6800b6027add478e648934cbb29d684e51943 +commit 15974235dd528aeab0ec67fb92a0a1d733f62be2 Author: Darren Tucker -Date: Thu Jan 20 00:49:57 2022 +1100 +Date: Tue Mar 1 09:00:20 2022 +1100 - Move more tests out of valgrind-1 runner. + Add OPENBSD ORIGINAL marker. -commit 20da6ed136dd76e6a0b229ca3036ef9c7c7ef798 +commit f2ff669347d320532e7c1b63cdf5c62f46e73150 Author: Darren Tucker -Date: Wed Jan 19 15:37:39 2022 +1100 +Date: Mon Feb 28 22:21:36 2022 +1100 - Invoke EXIT handler early when using Valgrind. + No unused param warnings for clang-12 and gcc-11. - When using Valgrind, we need to wait for all invoked programs to - complete before checking their valgrind logs. Some tests, notably - agent-restrict, set an EXIT trap handler to clean up things like - ssh-agent, but those do not get invoked until test-exec.sh exits. - This causes the Valgrind wait to deadlock, so if present invoke - the EXIT handler before checking the Valgrind logs. + These have too many false positives in -Werror tests on the github CI + since we often provide empty stub functions for functionality not needed + for particular configurations. -commit ad2e0580c87b0714cf166bca9d926a95ddeee1c8 +commit 96558ecd87adac62efa9a2b5479f686ab86b0be1 Author: Darren Tucker -Date: Tue Jan 18 12:55:21 2022 +1100 +Date: Sat Feb 26 14:10:41 2022 +1100 - Remove line leftover from upstream sync. + Add debian-i386 test target. -commit d1051c0f11a6b749027e26bbeb61b07df4b67e15 -Author: djm@openbsd.org -Date: Mon Jan 17 22:56:04 2022 +0000 +commit 284b6e5394652d519e31782e3b3cdfd7b21d1a81 +Author: Darren Tucker +Date: Sat Feb 26 14:06:14 2022 +1100 - upstream: when decompressing zlib compressed packets, use - - Z_SYNC_FLUSH instead of Z_PARTIAL_FLUSH as the latter is not actually - specified as a valid mode for inflate(). There should be no practical change - in behaviour as the compression side ensures a flush that should make all - data available to the receiver in all cases. - - repoted by lamm AT ibm.com via bz3372; ok markus + Allow ppoll_time64 in seccomp sandbox. - OpenBSD-Commit-ID: 67cfc1fa8261feae6d2cc0c554711c97867cc81b + Should fix sandbox violations on (some? at least i386 and armhf) 32bit + Linux platforms. Patch from chutzpahu at gentoo.org and cjwatson at + debian.org via bz#3396. -commit d5981b1883746b1ae178a46229c26b53af99e37a -Author: djm@openbsd.org -Date: Mon Jan 17 21:41:04 2022 +0000 +commit 0132056efabc5edb85c3c7105d2fb6dee41843c6 +Author: Darren Tucker +Date: Fri Feb 25 19:47:48 2022 +1100 - upstream: make most of the sftp errors more idiomatic, following - - the general form of "[local/remote] operation path: error message"; ok markus + Improve handling of _getshort and _getlong. - OpenBSD-Commit-ID: 61364cd5f3a9fecaf8d63b4c38a42c0c91f8b571 + If the system native ones are exactly as required then use them, + otherwise use the local versions mapped to another name to prevent + name collisions. -commit ac7c9ec894ed0825d04ef69c55babb49bab1d32e -Author: djm@openbsd.org -Date: Mon Jan 17 21:39:51 2022 +0000 +commit 8e206e0dd6b9f757b07979e48f53ad5bf9b7b52b +Author: Darren Tucker +Date: Fri Feb 25 15:14:22 2022 +1100 - upstream: when transferring multiple files in SFTP mode, create the - - destination directory if it doesn't already exist to match olde-scp(1) - behaviour. noticed by deraadt@ ok markus@ + Constify utimes in compat library to match specs. - OpenBSD-Commit-ID: cf44dfa231d4112f697c24ff39d7ecf2e6311407 + Patch from vapier at chromium.org. -commit 39d17e189f8e72c34c722579d8d4e701fa5132da -Author: djm@openbsd.org -Date: Fri Jan 14 03:43:48 2022 +0000 +commit 1b2920e3b63db2eddebeec7330ffe8b723055573 +Author: Darren Tucker +Date: Fri Feb 25 13:50:56 2022 +1100 - upstream: allow pin-required FIDO keys to be added to ssh-agent(1). - - ssh-askpass will be used to request the PIN at authentication time. - - From Pedro Martelletto, ok djm + ANSIfy getshort and getlong. - OpenBSD-Commit-ID: de8189fcd35b45f632484864523c1655550e2950 + These functions appear to have come from OpenBSD's lib/libc/net/res_comp.c + which made this change in 2005. -commit 52423f64e13db2bdc31a51b32e999cb1bfcf1263 -Author: djm@openbsd.org -Date: Fri Jan 14 03:35:10 2022 +0000 +commit 54a86f4f6e1c43a2ca2be23ef799ab8910d4af70 +Author: Darren Tucker +Date: Fri Feb 25 13:23:04 2022 +1100 - upstream: ssh-sk: free a resident key's user id - - From Pedro Martelletto; ok dtucker & me - - OpenBSD-Commit-ID: 47be40d602b7a6458c4c71114df9b53d149fc2e9 + Use PICFLAG instead of hard coding -fPIC. -commit 014e2f147a2788bfb3cc58d1b170dcf2bf2ee493 -Author: djm@openbsd.org -Date: Fri Jan 14 03:34:00 2022 +0000 +commit 3016ba47035ac3561aabd48e2be70167fe157d6a +Author: Darren Tucker +Date: Fri Feb 25 11:37:11 2022 +1100 - upstream: sshsk_load_resident: don't preallocate resp - - resp is allocated by client_converse(), at which point we lose - the original pointer. - - From Pedro Martelletto; ok dtucker & me + Add tests for latest releases of {Libre,Open}SSL. + +commit f107467179428a0e3ea9e4aa9738ac12ff02822d +Author: Colin Watson +Date: Thu Feb 24 16:04:18 2022 +0000 + + Improve detection of -fzero-call-used-regs=all support - OpenBSD-Commit-ID: 1f1b5ea3282017d6584dfed4f8370dc1db1f44b1 + GCC doesn't tell us whether this option is supported unless it runs into + the situation where it would need to emit corresponding code. -commit c88265f207dfe0e8bdbaf9f0eda63ed6b33781cf +commit 3383b2cac0e9275bc93c4b4760e6e048f537e1d6 Author: djm@openbsd.org -Date: Fri Jan 14 03:32:52 2022 +0000 +Date: Wed Feb 23 21:21:49 2022 +0000 - upstream: sshsk_sign: trim call to sshkey_fingerprint() - - the resulting fingerprint doesn't appear to be used for anything, - and we end up leaking it. - - from Pedro Martelletto; ok dtucker & me + upstream: free(3) wants stdlib.h - OpenBSD-Commit-ID: 5625cf6c68f082bc2cbbd348e69a3ed731d2f9b7 + OpenBSD-Commit-ID: 227a8c70a95b4428c49e46863c9ef4bd318a3b8a -commit 1cd1b2eac39661b849d5a4b4b56363e22bb5f61e +commit a4537e79ab4ac6db4493c5158744b9ebde5efcb0 Author: djm@openbsd.org -Date: Fri Jan 14 03:31:52 2022 +0000 +Date: Wed Feb 23 21:21:16 2022 +0000 - upstream: use status error message to communicate ~user expansion + upstream: put back the scp manpage changes for SFTP mode too - failures; provides better experience for scp in sftp mode, where ~user paths - are more likely to be used; spotted jsg, feedback jsg & deraadt ok jsg & - markus + OpenBSD-Commit-ID: 05dc53921f927e1b5e5694e1f3aa314549f2e768 + +commit 449bcb8403adfb9724805d02a51aea76046de185 +Author: deraadt@openbsd.org +Date: Wed Feb 23 19:01:00 2022 +0000 + + upstream: and we go back to testing sftp-scp after the 8.9 - (forgot to include this file in previous commit) + release... - OpenBSD-Commit-ID: d37cc4c8c861ce48cd6ea9899e96aaac3476847b + OpenBSD-Commit-ID: a80440168258adca543a4607b871327a279c569c -commit a1d42a6ce0398da3833bedf374ef2571af7fea50 +commit 166456cedad3962b83b848b1e9caf80794831f0f Author: Damien Miller -Date: Fri Jan 14 13:49:32 2022 +1100 +Date: Wed Feb 23 22:31:11 2022 +1100 - fix edge case in poll(2) wrapper - - Correct handling of select(2) exceptfds. These should only be consulted - for POLLPRI flagged pfds and not unconditionally converted to POLLERR. - - with and ok dtucker@ + makedepend -commit 976b9588b4b5babcaceec4767a241c11a67a5ccb -Author: Darren Tucker -Date: Fri Jan 14 13:46:35 2022 +1100 +commit 32ebaa0dbca5d0bb86e384e72bebc153f48413e4 +Author: djm@openbsd.org +Date: Wed Feb 23 11:18:13 2022 +0000 - Wrap OpenSSL includes in unit tests in ifdef. + upstream: avoid integer overflow of auth attempts (harmless, caught + + by monitor) - Fixes unit test on systems that do not have OpenSSL headers installed. + OpenBSD-Commit-ID: 488ad570b003b21e0cd9e7a00349cfc1003b4d86 -commit c171879374b2e8b07157503f5639ed0bce59ce89 -Author: Darren Tucker -Date: Thu Jan 13 15:53:33 2022 +1100 +commit 6e0258c64c901753df695e06498b26f9f4812ea6 +Author: djm@openbsd.org +Date: Wed Feb 23 11:17:10 2022 +0000 - Remove sort wrapper. + upstream: randomise the password used in fakepw - agent-restrict now takes care of this itself. + OpenBSD-Commit-ID: 34e159f73b1fbf0a924a9c042d8d61edde293947 -commit 9cc2654403f1a686bb26c07a6ac790edf334cef5 -Author: dtucker@openbsd.org -Date: Thu Jan 13 04:53:16 2022 +0000 +commit bf114d6f0a9df0b8369823d9a0daa6c72b0c4cc9 +Author: djm@openbsd.org +Date: Wed Feb 23 11:15:57 2022 +0000 - upstream: Set LC_ALL in both local and remote shells so that sorted + upstream: use asprintf to construct .rhosts paths - output matches regardless of what the user's shell sets it to. ok djm@ + OpenBSD-Commit-ID: 8286e8d3d2c6ff916ff13d041d1713073f738a8b + +commit c07e154fbdc7285e9ec54e78d8a31f7325d43537 +Author: djm@openbsd.org +Date: Wed Feb 23 11:07:09 2022 +0000 + + upstream: openssh-8.9 - OpenBSD-Regress-ID: 4e97dd69a68b05872033175a4c2315345d01837f + OpenBSD-Commit-ID: 5c5f791c87c483cdab6d9266b43acdd9ca7bde0e -commit 7a75f748cb2dd2f771bf70ea72698aa027996ab1 -Author: dtucker@openbsd.org -Date: Thu Jan 13 04:22:10 2022 +0000 +commit bc16667b4a1c3cad7029304853c143a32ae04bd4 +Author: Darren Tucker +Date: Tue Feb 22 15:29:22 2022 +1100 - upstream: Avoid %'s in commands (not used in OpenBSD, but used in + Extend select+rlimit sanbox test to include poll. - -portable's Valgrind test) being interpretted as printf format strings. + POSIX specifies that poll() shall fail if "nfds argument is greater + than {OPEN_MAX}". The setrlimit sandbox sets this to effectively zero + so this causes poll() to fail in the preauth privsep process. - OpenBSD-Regress-ID: dc8655db27ac4acd2c386c4681bf42a10d80b043 + This is likely the underlying cause for the previously observed similar + behaviour of select() on plaforms where it is implement in userspace on + top of poll(). -commit 6c435bd4994d71442192001483a1cdb846e5ffcd +commit 6520c488de95366be031d49287ed243620399e23 Author: Darren Tucker -Date: Wed Jan 12 16:58:13 2022 +1100 +Date: Tue Feb 22 13:08:59 2022 +1100 - Stop on first test failure to minimize logs. + Add Alpine Linux test VM. -commit 4bc2ba6095620a4484b708ece12842afd8c7685b -Author: dtucker@openbsd.org -Date: Wed Jan 12 07:18:37 2022 +0000 +commit a4b325a3fc82d11e0f5d61f62e7fde29415f7afb +Author: Darren Tucker +Date: Tue Feb 22 12:27:07 2022 +1100 - upstream: Use egrep when searching for an anchored string. + Include sys/param.h if present. - OpenBSD-Regress-ID: dd114a2ac27ac4b06f9e4a586d3f6320c54aeeb4 + Needed for howmany() on MUSL systems such as Alpine. -commit 6bf2efa2679da1e8e60731f41677b2081dedae2c +commit 5a102e9cb287a43bd7dfe594b775a89a8e94697c Author: Darren Tucker -Date: Wed Jan 12 18:25:06 2022 +1100 +Date: Tue Feb 22 12:25:52 2022 +1100 - Add "rev" command replacement if needed. + Only include sys/poll.h if we don't have poll.h. + + Prevents warnings on MUSL based systems such as Alpine. -commit 72bcd7993dadaf967bb3d8564ee31cbf38132b5d -Author: dtucker@openbsd.org -Date: Wed Jan 12 03:30:32 2022 +0000 +commit 7c0d4ce911d5c58b6166b2db754a4e91f352adf5 +Author: Damien Miller +Date: Tue Feb 22 11:14:51 2022 +1100 - upstream: Don't log NULL hostname in restricted agent code, + disable agent-restrict test on minix3 - printf("%s", NULL) is not safe on all platforms. with & ok djm + Minix seems to have a platform-wide limit on the number of + select(2) syscalls that can be concurrently issued. This test + seems to exceed this limit. - OpenBSD-Commit-ID: faf10cdae4adde00cdd668cd1f6e05d0a0e32a02 + Refer to: + + https://github.com/Stichting-MINIX-Research-Foundation/minix/blob/R3.3.0/minix/servers/vfs/select.c#L114 + https://github.com/Stichting-MINIX-Research-Foundation/minix/blob/R3.3.0/minix/servers/vfs/select.c#L30-L31 -commit acabefe3f8fb58c867c99fed9bbf84dfa1771727 -Author: djm@openbsd.org -Date: Tue Jan 11 22:33:16 2022 +0000 +commit 81d33d8e3cf7ea5ce3a5653c6102b623e019428a +Author: Darren Tucker +Date: Mon Feb 21 21:27:20 2022 +1100 - upstream: remove hardcoded domain and use window.location.host, so this - - can be run anywhere - - OpenBSD-Regress-ID: 2ac2ade3b6227d9c547351d3ccdfe671e62b7f92 + Skip agent-getpeereid when running as root. -commit 96da0946e44f34adc0397eb7caa6ec35a3e79891 +commit fbd772570a25436a33924d91c164d2b24021f010 Author: dtucker@openbsd.org -Date: Tue Jan 11 02:56:19 2022 +0000 +Date: Sun Feb 20 03:47:26 2022 +0000 - upstream: "void" functions should not return anything. From Tim Rice + upstream: Aproximate realpath on the expected output by deduping - via -portable. + leading slashes. Fixes test failure when user's home dir is / which is + possible in some portable configurations. - OpenBSD-Commit-ID: ce6616304f4c9881b46413e616b226c306830e2a + OpenBSD-Regress-ID: 53b8c53734f8893806961475c7106397f98d9f63 -commit a882a09722c9f086c9edb65d0c4022fd965ec1ed -Author: djm@openbsd.org -Date: Tue Jan 11 01:26:47 2022 +0000 +commit 336685d223a59f893faeedf0a562e053fd84058e +Author: Darren Tucker +Date: Sun Feb 20 13:30:52 2022 +1100 - upstream: suppress "Connection to xxx closed" messages at LogLevel >= - - error bz3378; ok dtucker@ + Really move DSA to end of list. - OpenBSD-Commit-ID: d5bf457d5d2eb927b81d0663f45248a31028265c + In commit ad16a84e syncing from OpenBSD, RSA was accidentally moved to + the end of the list instead of DSA. Spotted by andrew at fyfe.gb.net. -commit 61a1a6af22e17fc94999a5d1294f27346e6c4668 -Author: Damien Miller -Date: Wed Jan 12 08:57:49 2022 +1100 +commit 63bf4f49ed2fdf2da6f97136c9df0c8168546eb3 +Author: Darren Tucker +Date: Fri Feb 18 12:12:21 2022 +1100 - OS X poll(2) is broken; use compat replacement - - Darwin's poll(2) implementation is broken. For character-special - devices like /dev/null, it returns POLLNVAL when polled with - POLLIN. - - Apparently this is Apple bug 3710161, which is AFAIK not public, - but a websearch will find other OSS projects rediscovering it - periodically since it was first identified in 2005 (!!) + Add test configs for MUSL C library. -commit 613a6545fc5a9542753b503cbe5906538a640b60 -Author: Darren Tucker -Date: Tue Jan 11 20:56:01 2022 +1100 +commit f7fc6a43f1173e8b2c38770bf6cee485a562d03b +Author: Damien Miller +Date: Thu Feb 17 22:54:19 2022 +1100 - libhardended_malloc.so moved into out dir. + minix needs BROKEN_POLL too; chokes on /dev/null -commit 61761340be5e11046556623f8f5412b236cefa95 -Author: Tim Rice -Date: Mon Jan 10 11:07:04 2022 -0800 +commit 667fec5d4fe4406745750a32f69b5d2e1a75e94b +Author: djm@openbsd.org +Date: Thu Feb 17 10:58:27 2022 +0000 - Make USL compilers happy - UX:acomp: ERROR: "sftp-server.c", line 567: void function cannot return value + upstream: check for EINTR/EAGAIN failures in the rfd fast-path; caught + + by dtucker's minix3 vm :) ok dtucker@ + + OpenBSD-Commit-ID: 2e2c895a3e82ef347aa6694394a76a438be91361 -commit 3ef403f351e80a59b6f7e9d43cb82c181855483c +commit 41417dbda9fb55a0af49a8236e3ef9d50d862644 Author: Darren Tucker -Date: Mon Jan 10 21:07:38 2022 +1100 +Date: Thu Feb 17 22:05:29 2022 +1100 - Add wrapper for "sort" to set LC_ALL=C. - - Found by djm, this should make sorts stable and reduce test flakiness. + Comment hurd test, the VM is currently broken. -commit bd69e29f5716090181dbe0b8272eb7eab1a383bb -Author: dtucker@openbsd.org -Date: Sat Jan 8 07:55:26 2022 +0000 +commit b2aee35a1f0dc798339b3fcf96136da71b7e3f6d +Author: Damien Miller +Date: Thu Feb 17 21:15:16 2022 +1100 - upstream: Remove errant "set -x" left over from debugging. + find sk-dummy.so when build_dir != src_dir - OpenBSD-Regress-ID: cd989268e034264cec5df97be7581549032c87dc + spotted by Corinna Vinschen; feedback & ok dtucker@ -commit 1a7c88e26fd673813dc5f61c4ac278564845e004 -Author: dtucker@openbsd.org -Date: Sat Jan 8 07:01:13 2022 +0000 +commit 62a2d4e50b2e89f2ef04576931895d5139a5d037 +Author: Damien Miller +Date: Wed Feb 16 16:26:17 2022 +1100 - upstream: Enable all supported hostkey algorithms (but no others). - - Allows hostbased test to pass when built without OpenSSL. - - OpenBSD-Regress-ID: 5ddd677a68b672517e1e78460dc6ca2ccc0a9562 + update versions in preparation for 8.9 release -commit 12b457c2a42ff271e7967d9bedd068cebb048db9 +commit dd6d3dded721ac653ea73c017325e5bfeeec837f Author: djm@openbsd.org -Date: Sat Jan 8 07:37:32 2022 +0000 +Date: Tue Feb 15 05:13:36 2022 +0000 - upstream: use status error message to communicate ~user expansion + upstream: document the unbound/host-bound options to - failures; provides better experience for scp in sftp mode, where ~user paths - are more likely to be used; spotted jsg, feedback jsg & deraadt ok jsg & - markus + PubkeyAuthentication; spotted by HARUYAMA Seigo - OpenBSD-Commit-ID: fc610ce00ca0cdc2ecdabbd49ce7cb82033f905f + OpenBSD-Commit-ID: 298f681b66a9ecd498f0700082c7a6c46e948981 -commit 63670d4e9030bcee490d5a9cce561373ac5b3b23 -Author: djm@openbsd.org -Date: Sat Jan 8 07:36:11 2022 +0000 +commit df93529dd727fdf2fb290700cd4f1adb0c3c084b +Author: Darren Tucker +Date: Mon Feb 14 14:19:40 2022 +1100 - upstream: fix some corner-case bugs in scp sftp-mode handling of + Test if sshd accidentally acquires controlling tty - ~-prefixed paths; spotted by jsg; feedback jsg & deraadt, ok jsg & markus + When SSHD_ACQUIRES_CTTY is defined, test for the problematic behaviour + in the STREAMS code before activating the workaround. ok djm@ + +commit 766176cfdbfd7ec38bb6118dde6e4daa0df34888 +Author: Darren Tucker +Date: Sat Feb 12 10:24:56 2022 +1100 + + Add cygwin-release test config. - OpenBSD-Commit-ID: d1697dbaaa9f0f5649d69be897eab25c7d37c222 + This tests the flags used to build the cygwin release binaries. -commit e14940bbec57fc7d3ce0644dbefa35f5a8ec97d0 -Author: djm@openbsd.org -Date: Sat Jan 8 07:34:57 2022 +0000 +commit b30698662b862f5397116d23688aac0764e0886e +Author: Darren Tucker +Date: Fri Feb 11 21:00:35 2022 +1100 - upstream: more idiomatic error messages; spotted by jsg & deraadt + Move SSHD_ACQUIRES_CTTY workaround into compat. + + On some (most? all?) SysV based systems with STREAMS based ptys, + sshd could acquire a controlling terminal during pty setup when + it pushed the "ptem" module, due to what is probably a bug in + the STREAMS driver that's old enough to vote. Because it was the + privileged sshd's controlling terminal, it was not available for + the user's session, which ended up without one. This is known to + affect at least Solaris <=10, derivatives such as OpenIndiana and + several other SysV systems. See bz#245 for the backstory. + + In the we past worked around that by not calling setsid in the + privileged sshd child, which meant it was not a session or process + group leader. This solved controlling terminal problem because sshd + was not eligble to acquire one, but had other side effects such as + not cleaning up helper subprocesses in the SIGALRM handler since it + was not PG leader. Recent cleanups in the signal handler uncovered + this, resulting in the LoginGraceTime timer not cleaning up privsep + unprivileged processes. + + This change moves the workaround into the STREAMS pty allocation code, + by allocating a sacrificial pty to act as sshd's controlling terminal + before allocating user ptys, so those are still available for users' + sessions. + + On the down side: + - this will waste a pty per ssh connection on affected platforms. - ok jsg & markus + On the up side: + - it makes the process group behaviour consistent between platforms. - OpenBSD-Commit-ID: 43618c692f3951747b4151c477c7df22afe2bcc8 - -commit 9acddcd5918c623f7ebf454520ffe946a8f15e90 -Author: djm@openbsd.org -Date: Sat Jan 8 07:33:54 2022 +0000 - - upstream: add a variant of send_status() that allows overriding the + - it puts the workaround nearest the code that actually causes the + problem and competely out of the mainline code. - default, generic error message. feedback/ok markus & jsg + - the workaround is only activated if you use the STREAMS code. If, + say, Solaris 11 has the bug but also a working openpty() it doesn't + matter that we defined SSHD_ACQUIRES_CTTY. - OpenBSD-Commit-ID: 81f251e975d759994131b717ee7c0b439659c40f + - the workaround is only activated when the fist pty is allocated, + ie in the post-auth privsep monitor. This means there's no risk + of fd leaks to the unprivileged processes, and there's no effect on + sessions that do not allocate a pty. + + Based on analysis and work by djm@, ok djm@ -commit 961411337719d4cd78f1ab33e4ac549f3fa22f50 -Author: djm@openbsd.org -Date: Sat Jan 8 07:32:45 2022 +0000 +commit cd00b48cf10f3565936a418c1e6d7e48b5c36140 +Author: Darren Tucker +Date: Fri Feb 11 20:09:32 2022 +1100 - upstream: refactor tilde_expand_filename() and make it handle ~user - - paths with no trailing slash; feedback/ok markus and jsg + Simplify handling of --with-ssl-dir. - OpenBSD-Commit-ID: a2ab365598a902f0f14ba6a4f8fb2d07a9b5d51d + ok djm@ -commit dc38236ab6827dec575064cac65c8e7035768773 -Author: dtucker@openbsd.org -Date: Thu Jan 6 22:14:25 2022 +0000 +commit ea13fc830fc0e0dce2459f1fab2ec5099f73bdf0 +Author: Darren Tucker +Date: Fri Feb 11 13:39:29 2022 +1100 - upstream: Don't explicitly set HostbasedAuthentication in - - sshd_config. It defaults to "no", and not explicitly setting it allows us to - enable it for the (optional) hostbased test. + Stop testing OpenBSD HEAD on 6.9 and 7.0. - OpenBSD-Regress-ID: aa8e3548eb5793721641d26e56c29f363b767c0c + HEAD is not guaranteed to work on previous stable branches, and at the + moment is broken due to libfido API changes. -commit e12d912ddf1c873cb72e5de9a197afbe0b6622d2 +commit 50b9e4a4514697ffb9592200e722de6b427cb9ff Author: dtucker@openbsd.org -Date: Thu Jan 6 21:46:56 2022 +0000 +Date: Fri Feb 11 00:43:56 2022 +0000 - upstream: Add test for hostbased auth. It requires some external + upstream: Always initialize delim before passing to hpdelim2 which - setup (see comments at the top) and thus is disabled unless - TEST_SSH_HOSTBASED_AUTH and SUDO are set. + might not set it. Found by the Valgrind tests on github, ok deraadt@ - OpenBSD-Regress-ID: 3ec8ba3750c5b595fc63e7845d13483065a4827a - -commit a48533a8da6a0f4f05ecd055dc8048047e53569e -Author: Damien Miller -Date: Fri Jan 7 09:24:26 2022 +1100 - - depend + OpenBSD-Commit-ID: c830c0db185ca43beff3f41c19943c724b4f636d -commit d9dbb5d9a0326e252d3c7bc13beb9c2434f59409 -Author: djm@openbsd.org -Date: Thu Jan 6 22:06:51 2022 +0000 +commit 6ee53064f476cf163acd5521da45b11b7c57321b +Author: Darren Tucker +Date: Fri Feb 11 10:03:06 2022 +1100 - upstream: allow hostbased auth to select RSA keys when only - - RSA/SHA2 are configured (this is the default case); ok markus@ + Fix helper include path and remove excess code. - OpenBSD-Commit-ID: 411c18c7bde40c60cc6dfb7017968577b4d4a827 + Looks like test_hpdelim.c was imported twice into the same file. + Spotted by kevin.brott at gmail com and chris at cataclysmal org. -commit fdb1d58d0d3888b042e5a500f6ce524486aaf782 -Author: djm@openbsd.org -Date: Thu Jan 6 22:05:42 2022 +0000 +commit 9fa63a19f68bc87452d3cf5c577cafad2921b7a4 +Author: Darren Tucker +Date: Thu Feb 10 23:27:02 2022 +1100 - upstream: add a helper function to match a key type to a list of - - signature algorithms. RSA keys can make signatures with multiple algorithms, - so some special handling is required. ok markus@ - - OpenBSD-Commit-ID: 03b41b2bda06fa4cd9c84cef6095033b9e49b6ff + Put poll.h inside ifdef. -commit 11e8c4309a5086a45fbbbc87d0af5323c6152914 -Author: djm@openbsd.org -Date: Thu Jan 6 22:04:20 2022 +0000 +commit 3ac00dfeb54b252c15dcbf1971582e9e3b946de6 +Author: Darren Tucker +Date: Thu Feb 10 22:17:31 2022 +1100 - upstream: log some details on hostkeys that ssh loads for - - hostbased authn ok markus@ - - OpenBSD-Commit-ID: da17061fa1f0e58cb31b88478a40643e18233e38 + We now support POLLPRI so actually define it. -commit c6706f661739514a34125aa3136532a958929510 -Author: djm@openbsd.org -Date: Thu Jan 6 22:03:59 2022 +0000 +commit 25bd659cc72268f2858c5415740c442ee950049f +Author: dtucker@openbsd.org +Date: Sun Feb 6 22:58:33 2022 +0000 - upstream: log signature algorithm during verification by monitor; - - ok markus + upstream: Add test for empty hostname with port. - OpenBSD-Commit-ID: 02b92bb42c4d4bf05a051702a56eb915151d9ecc + OpenBSD-Regress-ID: e19e89d3c432b68997667efea44cf015bbe2a7e3 -commit 8832402bd500d1661ccc80a476fd563335ef6cdc -Author: djm@openbsd.org -Date: Thu Jan 6 22:02:52 2022 +0000 +commit a29af853cff41c0635f0378c00fe91bf9c91dea4 +Author: dtucker@openbsd.org +Date: Fri Feb 4 07:53:44 2022 +0000 - upstream: piece of UpdateHostkeys client strictification: when - - updating known_hosts with new keys, ignore NULL keys (forgot to include in - prior commit) + upstream: Add unit tests for hpdelim. - OpenBSD-Commit-ID: 49d2eda6379490e1ceec40c3b670b973f63dea08 + OpenBSD-Regress-ID: be97b85c19895e6a1ce13c639765a3b48fd95018 -commit c2d9ced1da0276961d86690b3bd7ebdaca7fdbf7 +commit 9699151b039ecc5fad9ac6c6c02e9afdbd26f15f Author: djm@openbsd.org -Date: Thu Jan 6 22:01:14 2022 +0000 +Date: Thu Feb 10 04:12:38 2022 +0000 - upstream: include rejected signature algorithm in error message + upstream: revert for imminent OpenSSH release, which wil ship with - and not the (useless) key type; ok markus + scp in RCP mode. - OpenBSD-Commit-ID: 4180b5ec7ab347b43f84e00b1972515296dab023 - -commit 7aa7b096cf2bafe2777085abdeed5ce00581f641 -Author: djm@openbsd.org -Date: Thu Jan 6 22:00:18 2022 +0000 - - upstream: make ssh-keysign use the requested signature algorithm + > revision 1.106 + > date: 2021/10/15 14:46:46; author: deraadt; state: Exp; lines: +13 -9; commitid: w5n9B2RE38tFfggl; + > openbsd 7.0 release shipped with the (hopefully last) scp that uses RCP + > protocol for copying. Let's get back to testing the SFTP protocol. - and not the default for the keytype. Part of unbreaking hostbased auth for - RSA/SHA2 keys. ok markus@ + This will be put back once the OpenSSH release is done. - OpenBSD-Commit-ID: b5639a14462948970da3a8020dc06f9a80ecccdc + OpenBSD-Commit-ID: 0c725481a78210aceecff1537322c0b2df03e768 -commit 291721bc7c840d113a49518f3fca70e86248b8e8 -Author: djm@openbsd.org -Date: Thu Jan 6 21:57:28 2022 +0000 +commit 45279abceb37c3cbfac8ba36dde8b2c8cdd63d32 +Author: dtucker@openbsd.org +Date: Tue Feb 8 08:59:12 2022 +0000 - upstream: stricter UpdateHostkey signature verification logic on - - the client- side. Require RSA/SHA2 signatures for RSA hostkeys except when - RSA/SHA1 was explicitly negotiated during initial KEX; bz3375 + upstream: Switch hpdelim interface to accept only ":" as delimiter. - ok markus@ + Historicallly, hpdelim accepted ":" or "/" as a port delimiter between + hosts (or addresses) and ports. These days most of the uses for "/" + are no longer accepted, so there are several places where it checks the + delimiter to disallow it. Make hpdelim accept only ":" and use hpdelim2 + in the other cases. ok djm@ - OpenBSD-Commit-ID: 46e75e8dfa2c813781805b842580dcfbd888cf29 + OpenBSD-Commit-ID: 7e6420bd1be87590b6840973f5ad5305804e3102 -commit 0fa33683223c76289470a954404047bc762be84c -Author: djm@openbsd.org -Date: Thu Jan 6 21:55:23 2022 +0000 +commit a1bcbf04a7c2d81944141db7ecd0ba292d175a66 +Author: pedro martelletto +Date: Mon Feb 7 09:09:59 2022 +0100 - upstream: Fix signature algorithm selection logic for - - UpdateHostkeys on the server side. The previous code tried to prefer RSA/SHA2 - for hostkey proofs of RSA keys, but missed some cases. This will use RSA/SHA2 - signatures for RSA keys if the client proposed these algorithms in initial - KEX. bz3375 - - Mostly by Dmitry Belyavskiy with some tweaks by me. - - ok markus@ - - OpenBSD-Commit-ID: c17ba0c3236340d2c6a248158ebed042ac6a8029 + fix typos in previous -commit 17877bc81db3846e6e7d4cfb124d966bb9c9296b -Author: djm@openbsd.org -Date: Thu Jan 6 21:48:38 2022 +0000 +commit 56192518e329b39f063487bc2dc4d796f791eca0 +Author: Damien Miller +Date: Mon Feb 7 12:53:47 2022 +1100 - upstream: convert ssh, sshd mainloops from select() to poll(); - - feedback & ok deraadt@ and markus@ has been in snaps for a few months - - OpenBSD-Commit-ID: a77e16a667d5b194dcdb3b76308b8bba7fa7239c + compat code for fido_assert_set_clientdata() -commit 5c79952dfe1aa36105c93b3f383ce9be04dee384 +commit d6b5aa08fdcf9b527f8b8f932432941d5b76b7ab Author: djm@openbsd.org -Date: Thu Jan 6 21:46:23 2022 +0000 +Date: Mon Feb 7 01:25:12 2022 +0000 - upstream: prepare for conversion of ssh, sshd mainloop from - - select() to poll() by moving FD_SET construction out of channel handlers into - separate functions. ok markus + upstream: use libfido2 1.8.0+ fido_assert_set_clientdata() instead - OpenBSD-Commit-ID: 937fbf2a4de12b19fb9d5168424e206124807027 - -commit 24c5187edfef4651a625b7d5d692c8c7e794f71f -Author: djm@openbsd.org -Date: Wed Jan 5 21:54:37 2022 +0000 - - upstream: add a comment so I don't make this mistake again + of manually hashing data outselves. Saves a fair bit of code and makes life + easier for some -portable platforms. - OpenBSD-Commit-ID: 69c7f2362f9de913bb29b6318580c5a1b52c921e + OpenBSD-Commit-ID: 351dfaaa5ab1ee928c0e623041fca28078cff0e0 -commit 7369900441929058263a17f56aa67e05ff7ec628 -Author: djm@openbsd.org -Date: Wed Jan 5 21:50:00 2022 +0000 +commit 86cc93fd3c26b2e0c7663c6394995fb04ebfbf3b +Author: jsg@openbsd.org +Date: Sun Feb 6 00:29:03 2022 +0000 - upstream: fix cut-and-pasto in error message + upstream: remove please from manual pages ok jmc@ sthen@ millert@ - OpenBSD-Commit-ID: 4cc5c619e4b456cd2e9bb760d17e3a9c84659198 + OpenBSD-Commit-ID: 6543acb00f4f38a23472538e1685c013ca1a99aa -commit 294c11b1c7d56d3fb61e329603a782315ed70c62 -Author: djm@openbsd.org -Date: Wed Jan 5 08:25:05 2022 +0000 +commit ad16a84e64a8cf1c69c63de3fb9008320a37009c +Author: dtucker@openbsd.org +Date: Fri Feb 4 02:49:17 2022 +0000 - upstream: select all RSA hostkey algorithms for UpdateHostkeys tests, + upstream: Since they are deprecated, move DSA to the end of the - not just RSA-SHA1 + default list of public keys so that they will be tried last. From github + PR#295 from "ProBackup-nl", ok djm@ - OpenBSD-Regress-ID: b40e62b65863f2702a0c10aca583b2fe76772bd8 + OpenBSD-Commit-ID: 7e5d575cf4971d4e2de92e0b6d6efaba53598bf0 -commit 2ea1108c30e3edb6f872dfc1e6da10b041ddf2c0 -Author: djm@openbsd.org -Date: Wed Jan 5 04:56:15 2022 +0000 +commit 253de42753de85dde266e061b6fec12ca6589f7d +Author: Damien Miller +Date: Wed Feb 2 16:52:07 2022 +1100 - upstream: regress test both sshsig message hash algorithms, possible - - now because the algorithm is controllable via the CLI + portable-specific string array constification - OpenBSD-Regress-ID: 0196fa87acc3544b2b4fd98de844a571cb09a39f + from Mike Frysinger -commit 2327c306b5d4a2b7e71178e5a4d139af9902c2b0 +commit dfdcc2220cf359c492d5d34eb723370e8bd8a19e Author: djm@openbsd.org -Date: Wed Jan 5 04:50:11 2022 +0000 +Date: Tue Feb 1 23:37:15 2022 +0000 - upstream: allow selection of hash at sshsig signing time; code + upstream: test 'ssh-keygen -Y find-principals' with wildcard - already supported either sha512 (default) or sha256, but plumbing wasn't - there mostly by Linus Nordberg + principals; from Fabian Stelzer - OpenBSD-Commit-ID: 1b536404b9da74a84b3a1c8d0b05fd564cdc96cd + OpenBSD-Regress-ID: fbe4da5f0032e7ab496527a5bf0010fd700f8f40 -commit 56e941d0a00d6d8bae88317717d5e1b7395c9529 -Author: djm@openbsd.org -Date: Wed Jan 5 04:27:54 2022 +0000 +commit 968e508967ef42480cebad8cf3172465883baa77 +Author: dtucker@openbsd.org +Date: Fri Jan 21 02:54:41 2022 +0000 - upstream: add missing -O option to usage() for ssh-keygen -Y sign; + upstream: Enable all supported ciphers and macs in the server - from Linus Nordberg + before trying to benchmark them. Increase the data file size to get more + signal. - OpenBSD-Commit-ID: 4e78feb4aa830727ab76bb2e3d940440ae1d7af0 + OpenBSD-Regress-ID: dc3697d9f7defdfc51c608782c8e750128e46eb6 -commit 141a14ec9b0924709c98df2dd8013bde5d8d12c7 +commit 15b7199a1fd37eff4c695e09d573f3db9f4274b7 Author: djm@openbsd.org -Date: Wed Jan 5 04:27:01 2022 +0000 +Date: Tue Feb 1 23:34:47 2022 +0000 - upstream: move sig_process_opts() to before sig_sign(); no + upstream: allow 'ssh-keygen -Y find-principals' to match wildcard - functional code change + principals in allowed_signers files; from Fabian Stelzer - OpenBSD-Commit-ID: da02d61f5464f72b4e8b299f83e93c3b657932f9 + OpenBSD-Commit-ID: 1e970b9c025b80717dddff5018fe5e6f470c5098 -commit 37a14249ec993599a9051731e4fb0ac5e976aec1 +commit 541667fe6dc26d7881e55f0bb3a4baa6f3171645 Author: djm@openbsd.org -Date: Wed Jan 5 04:10:39 2022 +0000 +Date: Tue Feb 1 23:32:51 2022 +0000 - upstream: regression test for find-principals NULL deref; from Fabian + upstream: mark const string array contents const too, i.e. static - Stelzer + const char *array => static const char * const array from Mike Frysinger - OpenBSD-Regress-ID: f845a8632a5a7d5ae26978004c93e796270fd3e5 + OpenBSD-Commit-ID: a664e31ea6a795d7c81153274a5f47b22bdc9bc1 -commit eb1f042142fdaba93f6c9560cf6c91ae25f6884a +commit 8cfa73f8a2bde4c98773f33f974c650bdb40dd3c Author: djm@openbsd.org -Date: Wed Jan 5 04:02:42 2022 +0000 +Date: Tue Feb 1 23:11:11 2022 +0000 - upstream: NULL deref when using find-principals when matching an + upstream: better match legacy scp behaviour: show un-expanded paths - allowed_signers line that contains a namespace restriction, but no - restriction specified on the command-line; report and fix from Fabian Stelzer + in error messages. Spotted by and ok tb@ - OpenBSD-Commit-ID: 4a201b86afb668c908d1a559c6af456a61f4b145 + OpenBSD-Commit-ID: 866c8ffac5bd7d38ecbfc3357c8adfa58af637b7 -commit 8f3b18030579f395eca2181da31a5f945af12a59 +commit 4e62c13ab419b4b224c8bc6a761e91fcf048012d Author: dtucker@openbsd.org -Date: Tue Jan 4 08:38:53 2022 +0000 +Date: Tue Feb 1 07:57:32 2022 +0000 - upstream: Log command invocation while debugging. + upstream: Remove explicit kill of privsep preauth child's PID in - This will aid in manually reproducing failing commands. + SIGALRM handler. It's no longer needed since the child will get terminated by + the SIGTERM to the process group that cleans up any auth helpers, it + simplifies the signal handler and removes the risk of a race when updating + the PID. Based on analysis by HerrSpace in github PR#289, ok djm@ - OpenBSD-Regress-ID: b4aba8d5ac5675ceebeeeefa3261ce344e67333a + OpenBSD-Commit-ID: 2be1ffa28b4051ad9e33bb4371e2ec8a31d6d663 -commit bbf285164df535f0d38c36237f007551bbdae27f -Author: Darren Tucker -Date: Sun Dec 26 10:31:15 2021 +1100 +commit 2a7ccd2ec4022917b745af7186f514f365b7ebe9 +Author: guenther@openbsd.org +Date: Fri Jan 28 06:18:42 2022 +0000 - Always save config.h as build artifact. + upstream: When it's the possessive of 'it', it's spelled "its", - Should allow better comparison between failing and succeeding test - platforms. - -commit 03bd4ed0db699687c5cd83405d26f81d2dc28d22 -Author: Darren Tucker -Date: Sat Dec 25 16:42:51 2021 +1100 - - Add OpenBSD 7.0 target. Retire 6.8. + without the apostrophe. + + OpenBSD-Commit-ID: fb6ab9c65bd31de831da1eb4631ddac018c5fae7 -commit c45a752f0de611afd87755c2887c8a24816d08ee -Author: jsg@openbsd.org -Date: Sat Jan 1 05:55:06 2022 +0000 +commit 8a0848cdd3b25c049332cd56034186b7853ae754 +Author: Alex James +Date: Sun Jan 30 16:13:36 2022 -0600 - upstream: spelling + sandbox-seccomp-filter: allow gettid - OpenBSD-Commit-ID: c63e43087a64d0727af13409c708938e05147b62 + Some allocators (such as Scudo) use gettid while tracing allocations [1]. + Allow gettid in preauth to prevent sshd from crashing with Scudo. + + [1]: https://github.com/llvm/llvm-project/blob/llvmorg-13.0.0/compiler-rt/lib/gwp_asan/common.cpp#L46 -commit c672f83a89a756564db0d3af9934ba0e1cf8fa3e +commit b30d32159dc3c7052f4bfdf36357996c905af739 Author: djm@openbsd.org -Date: Tue Jan 4 07:20:33 2022 +0000 +Date: Sat Jan 22 00:49:34 2022 +0000 - upstream: unbreak test: was picking up system ssh-add instead of the + upstream: add a ssh_packet_process_read() function that reads from - one supposedly being tested. Spotted by dtucker and using his VM zoo (which - includes some systems old enough to lack ed25519 key support) + a fd directly into the transport input buffer. - OpenBSD-Regress-ID: 7976eb3df11cc2ca3af91030a6a8c0cef1590bb5 + Use this in the client and server mainloops to avoid unnecessary + copying. It also lets us use a more greedy read size without penalty. + + Yields a 2-3% performance gain on cipher-speed.sh (in a fairly + unscientific test tbf) + + feedback dtucker@ ok markus@ + + OpenBSD-Commit-ID: df4112125bf79d8e38e79a77113e1b373078e632 -commit a23698c3082ffe661abed14b020eac9b0c25eb9f +commit a1a8efeaaa9cccb15cdc0a2bd7c347a149a3a7e3 Author: djm@openbsd.org -Date: Sat Jan 1 04:18:06 2022 +0000 +Date: Sat Jan 22 00:45:31 2022 +0000 - upstream: fix memleak in process_extension(); oss-fuzz issue #42719 + upstream: Use sshbuf_read() to read directly into the channel input - OpenBSD-Commit-ID: d8d49f840162fb7b8949e3a5adb8107444b6de1e + buffer rather than into a stack buffer that needs to be copied again; + Improves performance by about 1% on cipher-speed.sh feedback dtucker@ ok + markus@ + + OpenBSD-Commit-ID: bf5e6e3c821ac3546dc8241d8a94e70d47716572 -commit cb885178f36b83d0f14cfe9f345d2068103feed0 -Author: jsg@openbsd.org -Date: Sat Jan 1 01:55:30 2022 +0000 +commit 29a76994e21623a1f84d68ebb9dc5a3c909fa3a7 +Author: Damien Miller +Date: Tue Jan 25 11:52:34 2022 +1100 - upstream: spelling ok dtucker@ - - OpenBSD-Commit-ID: bfc7ba74c22c928de2e257328b3f1274a3dfdf19 + depend -commit 6b977f8080a32c5b3cbb9edb634b9d5789fb79be +commit 754e0d5c7712296a7a3a83ace863812604c7bc4f Author: djm@openbsd.org -Date: Sun Dec 26 23:34:41 2021 +0000 +Date: Sat Jan 22 00:43:43 2022 +0000 - upstream: split method list search functionality from - - authmethod_lookup() into a separate authmethod_byname(), for cases where we - don't need to check whether a method is enabled, etc. - - use this to fix the "none" authentication method regression reported - by Nam Nguyen via bugs@ + upstream: Add a sshbuf_read() that attempts to read(2) directly in - ok deraadt@ + to a sshbuf; ok markus@ - OpenBSD-Commit-ID: 8cd188dc3a83aa8abe5b7693e762975cd8ea8a17 + OpenBSD-Commit-ID: 2d8f249040a4279f3bc23c018947384de8d4a45b -commit 0074aa2c8d605ee7587279a22cdad4270b4ddd07 -Author: jmc@openbsd.org -Date: Wed Dec 22 06:56:41 2021 +0000 +commit c7964fb9829d9ae2ece8b51a76e4a02e8449338d +Author: djm@openbsd.org +Date: Fri Jan 21 07:04:19 2022 +0000 - upstream: sort -H and -h in SYNOPSIS/usage(); tweak the -H text; + upstream: add a helper for writing an error message to the - ok djm + stderr_buf and setting quit_pending; no functional change but saves a bunch + of boilerplate - OpenBSD-Commit-ID: 90721643e41e9e09deb5b776aaa0443456ab0965 + OpenBSD-Commit-ID: 0747657cad6b9eabd514a6732adad537568e232d -commit 1c9853a68b2319f2e5f929179735e8fbb9988a67 -Author: Darren Tucker -Date: Wed Dec 22 19:33:10 2021 +1100 +commit d23b4f7fdb1bd87e2cd7a9ae7c198ae99d347916 +Author: djm@openbsd.org +Date: Fri Jan 21 06:58:06 2022 +0000 - Use SHA.*_HMAC_BLOCK_SIZE if needed. + upstream: correct comment and use local variable instead of long - If the platform has a native SHA2, does not define SHA.*_BLOCK_LENGTH - but does define SHA.*_HMAC_BLOCK_SIZE (eg Solaris) then use the latter. - Should fix --without-openssl build on Solaris. + indirection; spotted by dtucker@ + + OpenBSD-Commit-ID: 5f65f5f69db2b7d80a0a81b08f390a63f8845965 -commit 715c892f0a5295b391ae92c26ef4d6a86ea96e8e -Author: Damien Miller -Date: Wed Dec 22 09:02:50 2021 +1100 +commit d069b020a02b6e3935080204ee44d233e8158ebb +Author: deraadt@openbsd.org +Date: Fri Jan 21 00:53:40 2022 +0000 - remove sys/param.h in -portable, after upstream + upstream: When poll(2) returns -1, for some error conditions + + pfd[].revents is not cleared. There are subtle errors in various programs. + In this particular case, the program should error out. ok djm millert + + OpenBSD-Commit-ID: 00f839b16861f7fb2adcf122e95e8a82fa6a375c -commit 7a7c69d8b4022b1e5c0afb169c416af8ce70f3e8 +commit e204b34337a965feb439826157c191919fd9ecf8 Author: Damien Miller -Date: Mon Dec 20 13:05:20 2021 +1100 - - add agent-restrict.sh file, missed in last commit - -commit f539136ca51a4976644db5d0be8158cc1914c72a -Author: djm@openbsd.org -Date: Sun Dec 19 22:20:12 2021 +0000 +Date: Sat Jan 22 11:38:21 2022 +1100 - upstream: regression test for destination restrictions in ssh-agent + restore tty force-read hack - OpenBSD-Regress-ID: 3c799d91e736b1753b4a42d80c42fc40de5ad33d - -commit 6e4980eb8ef94c04874a79dd380c3f568e8416d6 -Author: anton@openbsd.org -Date: Sat Dec 18 06:53:59 2021 +0000 - - upstream: Make use of ntests variable, pointed out by clang 13. + This portable-specific hack fixes a hang on exit for ttyful sessions + on Linux and some SysVish Unix variants. It was accidentally disabled + in commit 5c79952dfe1a (a precursor to the mainloop poll(2) conversion). - OpenBSD-Regress-ID: 4241a3d21bdfa1630ed429b6d4fee51038d1be72 + Spotted by John in bz3383 -commit 3eead8158393b697f663ec4301e3c7b6f24580b1 -Author: deraadt@openbsd.org -Date: Tue Dec 14 21:25:27 2021 +0000 +commit 68085066b6bad43643b43f5957fcc5fd34782ccd +Author: Corinna Vinschen +Date: Fri Jan 21 03:22:56 2022 +1100 - upstream: sys/param.h cleanup, mostly using MINIMUM() and + Fix signedness bug in Cygwin code - ok dtucker + The Cygwin-specific pattern match code has a bug. It checks + the size_t value returned by mbstowcs for being < 0. The right + thing to do is to check against (size_t) -1. Fix that. - OpenBSD-Regress-ID: 172a4c45d3bcf92fa6cdf6c4b9db3f1b3abe4db0 + Signed-off-by: Corinna Vinschen -commit 266678e19eb0e86fdf865b431b6e172e7a95bf48 -Author: djm@openbsd.org -Date: Sun Dec 19 22:15:42 2021 +0000 +commit 2e5cfed513e84444483baf1d8b31c40072b05103 +Author: Darren Tucker +Date: Thu Jan 20 13:26:27 2022 +1100 - upstream: document host-bound publickey authentication + Improve compatibility of early exit trap handling. - OpenBSD-Commit-ID: ea6ed91779a81f06d961e30ecc49316b3d71961b + Dash (as used by the github runners) has some differences in its trap + builtin: + - it doesn't have -p (which is fine, that's not in posix). + - it doesn't work in a subshell (which turns out to be in compliance + with posix, which means bash isn't). + - it doesn't work in a pipeline, ie "trap|cat" produces no output. -commit 3d00024b3b156aa9bbd05d105f1deb9cb088f6f7 -Author: djm@openbsd.org -Date: Sun Dec 19 22:15:21 2021 +0000 +commit 3fe6800b6027add478e648934cbb29d684e51943 +Author: Darren Tucker +Date: Thu Jan 20 00:49:57 2022 +1100 - upstream: document agent protocol extensions - - OpenBSD-Commit-ID: 09e8bb391bbaf24c409b75a4af44e0cac65405a7 + Move more tests out of valgrind-1 runner. -commit c385abf76511451bcba78568167b1cd9e90587d5 -Author: djm@openbsd.org -Date: Sun Dec 19 22:14:47 2021 +0000 +commit 20da6ed136dd76e6a0b229ca3036ef9c7c7ef798 +Author: Darren Tucker +Date: Wed Jan 19 15:37:39 2022 +1100 - upstream: PubkeyAuthentication=yes|no|unbound|host-bound - - Allow control over which pubkey methods are used. Added out of - concern that some hardware devices may have difficulty signing - the longer pubkey authentication challenges. This provides a - way for them to disable the extension. It's also handy for - testing. - - feedback / ok markus@ + Invoke EXIT handler early when using Valgrind. - OpenBSD-Commit-ID: ee52580db95c355cf6d563ba89974c210e603b1a + When using Valgrind, we need to wait for all invoked programs to + complete before checking their valgrind logs. Some tests, notably + agent-restrict, set an EXIT trap handler to clean up things like + ssh-agent, but those do not get invoked until test-exec.sh exits. + This causes the Valgrind wait to deadlock, so if present invoke + the EXIT handler before checking the Valgrind logs. -commit 34b1e9cc7654f41cd4c5b1cc290b999dcf6579bb -Author: djm@openbsd.org -Date: Sun Dec 19 22:14:12 2021 +0000 +commit ad2e0580c87b0714cf166bca9d926a95ddeee1c8 +Author: Darren Tucker +Date: Tue Jan 18 12:55:21 2022 +1100 - upstream: document destination-constrained keys - - feedback / ok markus@ - - OpenBSD-Commit-ID: cd8c526c77268f6d91c06adbee66b014d22d672e + Remove line leftover from upstream sync. -commit a6d7677c4abcfba268053e5867f2acabe3aa371b +commit d1051c0f11a6b749027e26bbeb61b07df4b67e15 Author: djm@openbsd.org -Date: Sun Dec 19 22:13:55 2021 +0000 +Date: Mon Jan 17 22:56:04 2022 +0000 - upstream: Use hostkey parsed from hostbound userauth request - - Require host-bound userauth requests for forwarded SSH connections. + upstream: when decompressing zlib compressed packets, use - The hostkey parsed from the host-bound userauth request is now checked - against the most recently bound session ID / hostkey on the agent socket - and the signature refused if they do not match. + Z_SYNC_FLUSH instead of Z_PARTIAL_FLUSH as the latter is not actually + specified as a valid mode for inflate(). There should be no practical change + in behaviour as the compression side ensures a flush that should make all + data available to the receiver in all cases. - ok markus@ + repoted by lamm AT ibm.com via bz3372; ok markus - OpenBSD-Commit-ID: d69877c9a3bd8d1189a5dbdeceefa432044dae02 + OpenBSD-Commit-ID: 67cfc1fa8261feae6d2cc0c554711c97867cc81b -commit baaff0ff4357cc5a079621ba6e2d7e247b765061 +commit d5981b1883746b1ae178a46229c26b53af99e37a Author: djm@openbsd.org -Date: Sun Dec 19 22:13:33 2021 +0000 +Date: Mon Jan 17 21:41:04 2022 +0000 - upstream: agent support for parsing hostkey-bound signatures - - Allow parse_userauth_request() to work with blobs from - publickey-hostbound-v00@openssh.com userauth attempts. - - Extract hostkey from these blobs. + upstream: make most of the sftp errors more idiomatic, following - ok markus@ + the general form of "[local/remote] operation path: error message"; ok markus - OpenBSD-Commit-ID: 81c064255634c1109477dc65c3e983581d336df8 + OpenBSD-Commit-ID: 61364cd5f3a9fecaf8d63b4c38a42c0c91f8b571 -commit 3e16365a79cdeb2d758cf1da6051b1c5266ceed7 +commit ac7c9ec894ed0825d04ef69c55babb49bab1d32e Author: djm@openbsd.org -Date: Sun Dec 19 22:13:12 2021 +0000 +Date: Mon Jan 17 21:39:51 2022 +0000 - upstream: EXT_INFO negotiation of hostbound pubkey auth - - the EXT_INFO packet gets a new publickey-hostbound@openssh.com to - advertise the hostbound public key method. - - Client side support to parse this feature flag and set the kex->flags - indicator if the expected version is offered (currently "0"). + upstream: when transferring multiple files in SFTP mode, create the - ok markus@ + destination directory if it doesn't already exist to match olde-scp(1) + behaviour. noticed by deraadt@ ok markus@ - OpenBSD-Commit-ID: 4cdb2ca5017ec1ed7a9d33bda95c1d6a97b583b0 + OpenBSD-Commit-ID: cf44dfa231d4112f697c24ff39d7ecf2e6311407 -commit 94ae0c6f0e35903b695e033bf4beacea1d376bb1 +commit 39d17e189f8e72c34c722579d8d4e701fa5132da Author: djm@openbsd.org -Date: Sun Dec 19 22:12:54 2021 +0000 +Date: Fri Jan 14 03:43:48 2022 +0000 - upstream: client side of host-bound pubkey authentication - - Add kex->flags member to enable the publickey-hostbound-v00@openssh.com - authentication method. - - Use the new hostbound method in client if the kex->flags flag was set, - and include the inital KEX hostkey in the userauth request. + upstream: allow pin-required FIDO keys to be added to ssh-agent(1). - Note: nothing in kex.c actually sets the new flag yet + ssh-askpass will be used to request the PIN at authentication time. - ok markus@ + From Pedro Martelletto, ok djm - OpenBSD-Commit-ID: 5a6fce8c6c8a77a80ee1526dc467d91036a5910d + OpenBSD-Commit-ID: de8189fcd35b45f632484864523c1655550e2950 -commit 288fd0218dbfdcb05d9fbd1885904bed9b6d42e6 +commit 52423f64e13db2bdc31a51b32e999cb1bfcf1263 Author: djm@openbsd.org -Date: Sun Dec 19 22:12:30 2021 +0000 +Date: Fri Jan 14 03:35:10 2022 +0000 - upstream: sshd side of hostbound public key auth - - This is identical to the standard "publickey" method, but it also includes - the initial server hostkey in the message signed by the client. + upstream: ssh-sk: free a resident key's user id - feedback / ok markus@ + From Pedro Martelletto; ok dtucker & me - OpenBSD-Commit-ID: 7ea01bb7238a560c1bfb426fda0c10a8aac07862 + OpenBSD-Commit-ID: 47be40d602b7a6458c4c71114df9b53d149fc2e9 -commit dbb339f015c33d63484261d140c84ad875a9e548 +commit 014e2f147a2788bfb3cc58d1b170dcf2bf2ee493 Author: djm@openbsd.org -Date: Sun Dec 19 22:12:07 2021 +0000 +Date: Fri Jan 14 03:34:00 2022 +0000 - upstream: prepare for multiple names for authmethods - - allow authentication methods to have one additional name beyond their - primary name. - - allow lookup by this synonym - - Use primary name for authentication decisions, e.g. for - PermitRootLogin=publickey + upstream: sshsk_load_resident: don't preallocate resp - Pass actual invoked name to the authmethods, so they can tell whether they - were requested via the their primary name or synonym. + resp is allocated by client_converse(), at which point we lose + the original pointer. - ok markus@ + From Pedro Martelletto; ok dtucker & me - OpenBSD-Commit-ID: 9e613fcb44b8168823195602ed3d09ffd7994559 + OpenBSD-Commit-ID: 1f1b5ea3282017d6584dfed4f8370dc1db1f44b1 -commit 39f00dcf44915f20684160f0a88d3ef8a3278351 +commit c88265f207dfe0e8bdbaf9f0eda63ed6b33781cf Author: djm@openbsd.org -Date: Sun Dec 19 22:11:39 2021 +0000 +Date: Fri Jan 14 03:32:52 2022 +0000 - upstream: ssh-agent side of destination constraints - - Gives ssh-agent the ability to parse restrict-destination-v00@openssh.com - constraints and to apply them to keys. + upstream: sshsk_sign: trim call to sshkey_fingerprint() - Check constraints against the hostkeys recorded for a SocketEntry when - attempting a signature, adding, listing or deleting keys. Note that - the "delete all keys" request will remove constrained keys regardless of - location. + the resulting fingerprint doesn't appear to be used for anything, + and we end up leaking it. - feedback Jann Horn & markus@ - ok markus@ + from Pedro Martelletto; ok dtucker & me - OpenBSD-Commit-ID: 84a7fb81106c2d609a6ac17469436df16d196319 + OpenBSD-Commit-ID: 5625cf6c68f082bc2cbbd348e69a3ed731d2f9b7 -commit ce943912df812c573a33d00bf9e5435b7fcca3f7 +commit 1cd1b2eac39661b849d5a4b4b56363e22bb5f61e Author: djm@openbsd.org -Date: Sun Dec 19 22:11:06 2021 +0000 +Date: Fri Jan 14 03:31:52 2022 +0000 - upstream: ssh-add side of destination constraints - - Have ssh-add accept a list of "destination constraints" that allow - restricting where keys may be used in conjunction with a ssh-agent/ssh - that supports session ID/hostkey binding. - - Constraints are specified as either "[user@]host-pattern" or - "host-pattern>[user@]host-pattern". - - The first form permits a key to be used to authenticate as the - specified user to the specified host. - - The second form permits a key that has previously been permitted - for use at a host to be available via a forwarded agent to an - additional host. - - For example, constraining a key with "user1@host_a" and - "host_a>host_b". Would permit authentication as "user1" at - "host_a", and allow the key to be available on an agent forwarded - to "host_a" only for authentication to "host_b". The key would not - be visible on agent forwarded to other hosts or usable for - authentication there. - - Internally, destination constraints use host keys to identify hosts. - The host patterns are used to obtain lists of host keys for that - destination that are communicated to the agent. The user/hostkeys are - encoded using a new restrict-destination-v00@openssh.com key - constraint. + upstream: use status error message to communicate ~user expansion - host keys are looked up in the default client user/system known_hosts - files. It is possible to override this set on the command-line. + failures; provides better experience for scp in sftp mode, where ~user paths + are more likely to be used; spotted jsg, feedback jsg & deraadt ok jsg & + markus - feedback Jann Horn & markus@ - ok markus@ + (forgot to include this file in previous commit) - OpenBSD-Commit-ID: 6b52cd2b637f3d29ef543f0ce532a2bce6d86af5 + OpenBSD-Commit-ID: d37cc4c8c861ce48cd6ea9899e96aaac3476847b -commit 5e950d765727ee0b20fc3d2cbb0c790b21ac2425 -Author: djm@openbsd.org -Date: Sun Dec 19 22:10:24 2021 +0000 +commit a1d42a6ce0398da3833bedf374ef2571af7fea50 +Author: Damien Miller +Date: Fri Jan 14 13:49:32 2022 +1100 - upstream: ssh-add side of destination constraints - - Have ssh-add accept a list of "destination constraints" that allow - restricting where keys may be used in conjunction with a ssh-agent/ssh - that supports session ID/hostkey binding. - - Constraints are specified as either "[user@]host-pattern" or - "host-pattern>[user@]host-pattern". - - The first form permits a key to be used to authenticate as the - specified user to the specified host. - - The second form permits a key that has previously been permitted - for use at a host to be available via a forwarded agent to an - additional host. - - For example, constraining a key with "user1@host_a" and - "host_a>host_b". Would permit authentication as "user1" at - "host_a", and allow the key to be available on an agent forwarded - to "host_a" only for authentication to "host_b". The key would not - be visible on agent forwarded to other hosts or usable for - authentication there. - - Internally, destination constraints use host keys to identify hosts. - The host patterns are used to obtain lists of host keys for that - destination that are communicated to the agent. The user/hostkeys are - encoded using a new restrict-destination-v00@openssh.com key - constraint. + fix edge case in poll(2) wrapper - host keys are looked up in the default client user/system known_hosts - files. It is possible to override this set on the command-line. + Correct handling of select(2) exceptfds. These should only be consulted + for POLLPRI flagged pfds and not unconditionally converted to POLLERR. - feedback Jann Horn & markus@ - ok markus@ + with and ok dtucker@ + +commit 976b9588b4b5babcaceec4767a241c11a67a5ccb +Author: Darren Tucker +Date: Fri Jan 14 13:46:35 2022 +1100 + + Wrap OpenSSL includes in unit tests in ifdef. - OpenBSD-Commit-ID: ef47fa9ec0e3c2a82e30d37ef616e245df73163e + Fixes unit test on systems that do not have OpenSSL headers installed. -commit 4c1e3ce85e183a9d0c955c88589fed18e4d6a058 -Author: djm@openbsd.org -Date: Sun Dec 19 22:09:23 2021 +0000 +commit c171879374b2e8b07157503f5639ed0bce59ce89 +Author: Darren Tucker +Date: Thu Jan 13 15:53:33 2022 +1100 - upstream: ssh-agent side of binding + Remove sort wrapper. - record session ID/hostkey/forwarding status for each active socket. + agent-restrict now takes care of this itself. + +commit 9cc2654403f1a686bb26c07a6ac790edf334cef5 +Author: dtucker@openbsd.org +Date: Thu Jan 13 04:53:16 2022 +0000 + + upstream: Set LC_ALL in both local and remote shells so that sorted - Attempt to parse data-to-be-signed at signature request time and extract - session ID from the blob if it is a pubkey userauth request. + output matches regardless of what the user's shell sets it to. ok djm@ - ok markus@ + OpenBSD-Regress-ID: 4e97dd69a68b05872033175a4c2315345d01837f + +commit 7a75f748cb2dd2f771bf70ea72698aa027996ab1 +Author: dtucker@openbsd.org +Date: Thu Jan 13 04:22:10 2022 +0000 + + upstream: Avoid %'s in commands (not used in OpenBSD, but used in - OpenBSD-Commit-ID: a80fd41e292b18b67508362129e9fed549abd318 + -portable's Valgrind test) being interpretted as printf format strings. + + OpenBSD-Regress-ID: dc8655db27ac4acd2c386c4681bf42a10d80b043 -commit e9497ecf73f3c16667288bce48d4e3d7e746fea1 -Author: djm@openbsd.org -Date: Sun Dec 19 22:08:48 2021 +0000 +commit 6c435bd4994d71442192001483a1cdb846e5ffcd +Author: Darren Tucker +Date: Wed Jan 12 16:58:13 2022 +1100 - upstream: ssh client side of binding + Stop on first test failure to minimize logs. + +commit 4bc2ba6095620a4484b708ece12842afd8c7685b +Author: dtucker@openbsd.org +Date: Wed Jan 12 07:18:37 2022 +0000 + + upstream: Use egrep when searching for an anchored string. - send session ID, hostkey, signature and a flag indicating whether the - agent connection is being forwarded to ssh agent each time a connection - is opened via a new "session-bind@openssh.com" agent extension. + OpenBSD-Regress-ID: dd114a2ac27ac4b06f9e4a586d3f6320c54aeeb4 + +commit 6bf2efa2679da1e8e60731f41677b2081dedae2c +Author: Darren Tucker +Date: Wed Jan 12 18:25:06 2022 +1100 + + Add "rev" command replacement if needed. + +commit 72bcd7993dadaf967bb3d8564ee31cbf38132b5d +Author: dtucker@openbsd.org +Date: Wed Jan 12 03:30:32 2022 +0000 + + upstream: Don't log NULL hostname in restricted agent code, - ok markus@ + printf("%s", NULL) is not safe on all platforms. with & ok djm - OpenBSD-Commit-ID: 2f154844fe13167d3ab063f830d7455fcaa99135 + OpenBSD-Commit-ID: faf10cdae4adde00cdd668cd1f6e05d0a0e32a02 -commit b42c61d6840d16ef392ed0f365e8c000734669aa +commit acabefe3f8fb58c867c99fed9bbf84dfa1771727 Author: djm@openbsd.org -Date: Sun Dec 19 22:08:06 2021 +0000 +Date: Tue Jan 11 22:33:16 2022 +0000 - upstream: Record session ID, host key and sig at intital KEX + upstream: remove hardcoded domain and use window.location.host, so this - These will be used later for agent session ID / hostkey binding + can be run anywhere - ok markus@ + OpenBSD-Regress-ID: 2ac2ade3b6227d9c547351d3ccdfe671e62b7f92 + +commit 96da0946e44f34adc0397eb7caa6ec35a3e79891 +Author: dtucker@openbsd.org +Date: Tue Jan 11 02:56:19 2022 +0000 + + upstream: "void" functions should not return anything. From Tim Rice - OpenBSD-Commit-ID: a9af29e33772b18e3e867c6fa8ab35e1694a81fe + via -portable. + + OpenBSD-Commit-ID: ce6616304f4c9881b46413e616b226c306830e2a -commit 26ca33d186473d58a32d812e19273ce078b6ffff +commit a882a09722c9f086c9edb65d0c4022fd965ec1ed Author: djm@openbsd.org -Date: Tue Dec 7 22:06:45 2021 +0000 +Date: Tue Jan 11 01:26:47 2022 +0000 - upstream: better error message for FIDO keys when we can't match + upstream: suppress "Connection to xxx closed" messages at LogLevel >= - them to a token + error bz3378; ok dtucker@ - OpenBSD-Commit-ID: 58255c2a1980088f4ed144db67d879ada2607650 + OpenBSD-Commit-ID: d5bf457d5d2eb927b81d0663f45248a31028265c -commit adb0ea006d7668190f0c42aafe3a2864d352e34a -Author: Darren Tucker -Date: Wed Dec 15 10:50:33 2021 +1100 +commit 61a1a6af22e17fc94999a5d1294f27346e6c4668 +Author: Damien Miller +Date: Wed Jan 12 08:57:49 2022 +1100 - Correct value for IPTOS_DSCP_LE. + OS X poll(2) is broken; use compat replacement + + Darwin's poll(2) implementation is broken. For character-special + devices like /dev/null, it returns POLLNVAL when polled with + POLLIN. - It needs to allow for the preceeding two ECN bits. From daisuke.higashi - at gmail.com via OpenSSH bz#3373, ok claudio@, job@, djm@. + Apparently this is Apple bug 3710161, which is AFAIK not public, + but a websearch will find other OSS projects rediscovering it + periodically since it was first identified in 2005 (!!) -commit 3dafd3fe220bd9046f11fcf5191a79ec8800819f +commit 613a6545fc5a9542753b503cbe5906538a640b60 Author: Darren Tucker -Date: Fri Dec 10 11:57:30 2021 +1100 +Date: Tue Jan 11 20:56:01 2022 +1100 + + libhardended_malloc.so moved into out dir. + +commit 61761340be5e11046556623f8f5412b236cefa95 +Author: Tim Rice +Date: Mon Jan 10 11:07:04 2022 -0800 - Increase timeout for test step. + Make USL compilers happy + UX:acomp: ERROR: "sftp-server.c", line 567: void function cannot return value -commit 5aefb05cd5b843e975b191d6ebb7ddf8de35c112 +commit 3ef403f351e80a59b6f7e9d43cb82c181855483c Author: Darren Tucker -Date: Fri Dec 10 10:27:27 2021 +1100 +Date: Mon Jan 10 21:07:38 2022 +1100 - Update the list of tests that don't work on Minix. + Add wrapper for "sort" to set LC_ALL=C. - While there, remove CC (configure will now find clang) and make the test - list easier to update via cut and paste. + Found by djm, this should make sorts stable and reduce test flakiness. -commit 1c09bb1b2e207d091cec299c49416c23d24a1b31 -Author: Darren Tucker -Date: Fri Dec 10 10:12:57 2021 +1100 +commit bd69e29f5716090181dbe0b8272eb7eab1a383bb +Author: dtucker@openbsd.org +Date: Sat Jan 8 07:55:26 2022 +0000 - Add minix host tuple. + upstream: Remove errant "set -x" left over from debugging. - Define SETEUID_BREAKS_SETUID for it which should make privsep work. + OpenBSD-Regress-ID: cd989268e034264cec5df97be7581549032c87dc -commit a2188579032cf080213a78255373263466cb90cc -Author: jsg@openbsd.org -Date: Sun Dec 5 12:28:27 2021 +0000 +commit 1a7c88e26fd673813dc5f61c4ac278564845e004 +Author: dtucker@openbsd.org +Date: Sat Jan 8 07:01:13 2022 +0000 - upstream: fix unintended sizeof pointer in debug path ok markus@ + upstream: Enable all supported hostkey algorithms (but no others). + + Allows hostbased test to pass when built without OpenSSL. - OpenBSD-Commit-ID: b9c0481ffc0cd801e0840e342e6a282a85aac93c + OpenBSD-Regress-ID: 5ddd677a68b672517e1e78460dc6ca2ccc0a9562 -commit da40355234068c82f1a36196f2d18dd2d81aaafd -Author: naddy@openbsd.org -Date: Sat Dec 4 00:05:39 2021 +0000 +commit 12b457c2a42ff271e7967d9bedd068cebb048db9 +Author: djm@openbsd.org +Date: Sat Jan 8 07:37:32 2022 +0000 - upstream: RSA/SHA-1 is not used by default anymore on the server + upstream: use status error message to communicate ~user expansion + + failures; provides better experience for scp in sftp mode, where ~user paths + are more likely to be used; spotted jsg, feedback jsg & deraadt ok jsg & + markus - OpenBSD-Commit-ID: 64abef6cfc3e53088225f6b8a1dcd86d52dc8353 + OpenBSD-Commit-ID: fc610ce00ca0cdc2ecdabbd49ce7cb82033f905f -commit e9c71498a083a8b502aa831ea931ce294228eda0 +commit 63670d4e9030bcee490d5a9cce561373ac5b3b23 Author: djm@openbsd.org -Date: Thu Dec 2 23:45:36 2021 +0000 +Date: Sat Jan 8 07:36:11 2022 +0000 - upstream: hash full host:port when asked to hash output, fixes hashes + upstream: fix some corner-case bugs in scp sftp-mode handling of - for non- default ports. bz3367 ok dtucker@ + ~-prefixed paths; spotted by jsg; feedback jsg & deraadt, ok jsg & markus - OpenBSD-Commit-ID: 096021cc847da7318ac408742f2d0813ebe9aa73 + OpenBSD-Commit-ID: d1697dbaaa9f0f5649d69be897eab25c7d37c222 -commit b5601202145a03106012c22cb8980bcac2949f0b +commit e14940bbec57fc7d3ce0644dbefa35f5a8ec97d0 Author: djm@openbsd.org -Date: Thu Dec 2 23:23:13 2021 +0000 +Date: Sat Jan 8 07:34:57 2022 +0000 - upstream: improve the testing of credentials against inserted FIDO + upstream: more idiomatic error messages; spotted by jsg & deraadt - keys a little more: ask the token whether a particular key belongs to it in - cases where the token support on-token user- verification (e.g. biometrics) - rather than just assuming that it will accept it. + ok jsg & markus - Will reduce spurious "Confirm user presence" notifications for key - handles that relate to FIDO keys that are not currently inserted in at - least some cases. + OpenBSD-Commit-ID: 43618c692f3951747b4151c477c7df22afe2bcc8 + +commit 9acddcd5918c623f7ebf454520ffe946a8f15e90 +Author: djm@openbsd.org +Date: Sat Jan 8 07:33:54 2022 +0000 + + upstream: add a variant of send_status() that allows overriding the - Motivated by bz3366; by Pedro Martelletto + default, generic error message. feedback/ok markus & jsg - OpenBSD-Commit-ID: ffac7f3215842397800e1ae2e20229671a55a63d + OpenBSD-Commit-ID: 81f251e975d759994131b717ee7c0b439659c40f -commit ca709e27c41c90f4565b17282c48dca7756e083c +commit 961411337719d4cd78f1ab33e4ac549f3fa22f50 Author: djm@openbsd.org -Date: Thu Dec 2 22:40:05 2021 +0000 +Date: Sat Jan 8 07:32:45 2022 +0000 - upstream: move check_sk_options() up so we can use it earlier + upstream: refactor tilde_expand_filename() and make it handle ~user - OpenBSD-Commit-ID: 67fe98ba1c846d22035279782c4664c1865763b4 + paths with no trailing slash; feedback/ok markus and jsg + + OpenBSD-Commit-ID: a2ab365598a902f0f14ba6a4f8fb2d07a9b5d51d -commit b711bc01a7ec76bb6a285730990cbce9b8ca5773 +commit dc38236ab6827dec575064cac65c8e7035768773 Author: dtucker@openbsd.org -Date: Thu Dec 2 22:35:05 2021 +0000 +Date: Thu Jan 6 22:14:25 2022 +0000 - upstream: ssh-rsa is no longer in the default for + upstream: Don't explicitly set HostbasedAuthentication in - PubkeyAcceptedAlgorithms. + sshd_config. It defaults to "no", and not explicitly setting it allows us to + enable it for the (optional) hostbased test. - OpenBSD-Commit-ID: 34a9e1bc30966fdcc922934ae00f09f2596cd73c + OpenBSD-Regress-ID: aa8e3548eb5793721641d26e56c29f363b767c0c -commit dc91ceea33cd4a9f05be953e8d8062f732db5c8a -Author: djm@openbsd.org -Date: Thu Dec 2 02:44:44 2021 +0000 +commit e12d912ddf1c873cb72e5de9a197afbe0b6622d2 +Author: dtucker@openbsd.org +Date: Thu Jan 6 21:46:56 2022 +0000 - upstream: don't put the tty into raw mode when SessionType=none, avoids + upstream: Add test for hostbased auth. It requires some external - ^c being unable to kill such a session. bz3360; ok dtucker@ + setup (see comments at the top) and thus is disabled unless + TEST_SSH_HOSTBASED_AUTH and SUDO are set. - OpenBSD-Commit-ID: 83960c433052303b643b4c380ae2f799ac896f65 + OpenBSD-Regress-ID: 3ec8ba3750c5b595fc63e7845d13483065a4827a -commit e6e7d2654a13ba10141da7b42ea683ea4eeb1f38 +commit a48533a8da6a0f4f05ecd055dc8048047e53569e Author: Damien Miller -Date: Mon Nov 29 14:11:03 2021 +1100 +Date: Fri Jan 7 09:24:26 2022 +1100 + + depend + +commit d9dbb5d9a0326e252d3c7bc13beb9c2434f59409 +Author: djm@openbsd.org +Date: Thu Jan 6 22:06:51 2022 +0000 - previous commit broke bcrypt_pbkdf() + upstream: allow hostbased auth to select RSA keys when only + + RSA/SHA2 are configured (this is the default case); ok markus@ - Accidentally reverted part of the conversion to use SHA512 from SUPERCOP - instead of OpenBSD-style libc SHA512. + OpenBSD-Commit-ID: 411c18c7bde40c60cc6dfb7017968577b4d4a827 -commit c0459588b8d00b73e506c6095958ecfe62a4a7ba -Author: Darren Tucker -Date: Mon Nov 29 14:03:19 2021 +1100 +commit fdb1d58d0d3888b042e5a500f6ce524486aaf782 +Author: djm@openbsd.org +Date: Thu Jan 6 22:05:42 2022 +0000 - Fix typo in Neils' name. + upstream: add a helper function to match a key type to a list of + + signature algorithms. RSA keys can make signatures with multiple algorithms, + so some special handling is required. ok markus@ + + OpenBSD-Commit-ID: 03b41b2bda06fa4cd9c84cef6095033b9e49b6ff -commit 158bf854e2a22cf09064305f4a4e442670562685 -Author: Damien Miller -Date: Mon Nov 29 12:30:22 2021 +1100 +commit 11e8c4309a5086a45fbbbc87d0af5323c6152914 +Author: djm@openbsd.org +Date: Thu Jan 6 22:04:20 2022 +0000 - sync bcrypt-related files with OpenBSD + upstream: log some details on hostkeys that ssh loads for - The main change is that Niels Provos kindly agreed to rescind the - BSD license advertising clause, shifting them to the 3-term BSD - license. + hostbased authn ok markus@ - This was the last thing in OpenSSH that used the advertising clause. + OpenBSD-Commit-ID: da17061fa1f0e58cb31b88478a40643e18233e38 -commit e8976d92a42883ff6b8991438f07df60c2c0d82d -Author: Damien Miller -Date: Mon Nov 29 12:29:29 2021 +1100 +commit c6706f661739514a34125aa3136532a958929510 +Author: djm@openbsd.org +Date: Thu Jan 6 22:03:59 2022 +0000 - depend + upstream: log signature algorithm during verification by monitor; + + ok markus + + OpenBSD-Commit-ID: 02b92bb42c4d4bf05a051702a56eb915151d9ecc + +commit 8832402bd500d1661ccc80a476fd563335ef6cdc +Author: djm@openbsd.org +Date: Thu Jan 6 22:02:52 2022 +0000 + + upstream: piece of UpdateHostkeys client strictification: when + + updating known_hosts with new keys, ignore NULL keys (forgot to include in + prior commit) + + OpenBSD-Commit-ID: 49d2eda6379490e1ceec40c3b670b973f63dea08 + +commit c2d9ced1da0276961d86690b3bd7ebdaca7fdbf7 +Author: djm@openbsd.org +Date: Thu Jan 6 22:01:14 2022 +0000 + + upstream: include rejected signature algorithm in error message + + and not the (useless) key type; ok markus + + OpenBSD-Commit-ID: 4180b5ec7ab347b43f84e00b1972515296dab023 + +commit 7aa7b096cf2bafe2777085abdeed5ce00581f641 +Author: djm@openbsd.org +Date: Thu Jan 6 22:00:18 2022 +0000 + + upstream: make ssh-keysign use the requested signature algorithm + + and not the default for the keytype. Part of unbreaking hostbased auth for + RSA/SHA2 keys. ok markus@ + + OpenBSD-Commit-ID: b5639a14462948970da3a8020dc06f9a80ecccdc -commit 8249afeec013e557fe7491a72ca3285de03e25b1 +commit 291721bc7c840d113a49518f3fca70e86248b8e8 Author: djm@openbsd.org -Date: Sun Nov 28 07:21:26 2021 +0000 +Date: Thu Jan 6 21:57:28 2022 +0000 - upstream: sshsig: return "key not found" when searching empty files + upstream: stricter UpdateHostkey signature verification logic on + + the client- side. Require RSA/SHA2 signatures for RSA hostkeys except when + RSA/SHA1 was explicitly negotiated during initial KEX; bz3375 - rather than "internal error" + ok markus@ - OpenBSD-Commit-ID: e2ccae554c78d7a7cd33fc5d217f35be7e2507ed + OpenBSD-Commit-ID: 46e75e8dfa2c813781805b842580dcfbd888cf29 -commit 9e3227d4dbb5ad9c9091b4c14982cab4bba87b4d +commit 0fa33683223c76289470a954404047bc762be84c Author: djm@openbsd.org -Date: Sun Nov 28 07:15:10 2021 +0000 +Date: Thu Jan 6 21:55:23 2022 +0000 - upstream: ssh-keygen -Y match-principals doesn't accept any -O + upstream: Fix signature algorithm selection logic for + + UpdateHostkeys on the server side. The previous code tried to prefer RSA/SHA2 + for hostkey proofs of RSA keys, but missed some cases. This will use RSA/SHA2 + signatures for RSA keys if the client proposed these algorithms in initial + KEX. bz3375 - options at present, so don't say otherwise in SYNOPSIS; spotted jmc@ + Mostly by Dmitry Belyavskiy with some tweaks by me. + + ok markus@ - OpenBSD-Commit-ID: 9cc43a18f4091010741930b48b3db2f2e4f1d35c + OpenBSD-Commit-ID: c17ba0c3236340d2c6a248158ebed042ac6a8029 -commit 56db1f4a4cf5039fc3b42e84c4b16291fdff32b1 +commit 17877bc81db3846e6e7d4cfb124d966bb9c9296b Author: djm@openbsd.org -Date: Sun Nov 28 07:14:29 2021 +0000 +Date: Thu Jan 6 21:48:38 2022 +0000 - upstream: fix indenting in last commit + upstream: convert ssh, sshd mainloops from select() to poll(); + + feedback & ok deraadt@ and markus@ has been in snaps for a few months - OpenBSD-Commit-ID: 8b9ba989815d0dec1fdf5427a4a4b58eb9cac4d2 + OpenBSD-Commit-ID: a77e16a667d5b194dcdb3b76308b8bba7fa7239c -commit 50bea24a9a9bdebad327c76e700def3261f5694e +commit 5c79952dfe1aa36105c93b3f383ce9be04dee384 Author: djm@openbsd.org -Date: Sun Nov 28 07:10:18 2021 +0000 +Date: Thu Jan 6 21:46:23 2022 +0000 - upstream: missing initialisation for oerrno + upstream: prepare for conversion of ssh, sshd mainloop from - OpenBSD-Commit-ID: 05d646bba238080259bec821c831a6f0b48d2a95 - -commit 5a0f4619041d09cd29f3a08da41db5040372bdd1 -Author: Darren Tucker -Date: Sun Nov 28 15:31:37 2021 +1100 - - Correct ifdef to activate poll() only if needed. + select() to poll() by moving FD_SET construction out of channel handlers into + separate functions. ok markus + + OpenBSD-Commit-ID: 937fbf2a4de12b19fb9d5168424e206124807027 -commit d4035c81a71237f690edd7eda32bef7d63fd9528 +commit 24c5187edfef4651a625b7d5d692c8c7e794f71f Author: djm@openbsd.org -Date: Sat Nov 27 07:23:35 2021 +0000 +Date: Wed Jan 5 21:54:37 2022 +0000 - upstream: whitespac e + upstream: add a comment so I don't make this mistake again - OpenBSD-Regress-ID: b9511d41568056bda489e13524390167889908f8 + OpenBSD-Commit-ID: 69c7f2362f9de913bb29b6318580c5a1b52c921e -commit a443491e6782ef0f5a8bb87a5536c8ee4ff233a1 +commit 7369900441929058263a17f56aa67e05ff7ec628 Author: djm@openbsd.org -Date: Sat Nov 27 07:20:58 2021 +0000 +Date: Wed Jan 5 21:50:00 2022 +0000 - upstream: regression test for match-principals. Mostly by Fabian - - Stelzer + upstream: fix cut-and-pasto in error message - OpenBSD-Regress-ID: ced0bec89af90935103438986bbbc4ad1df9cfa7 + OpenBSD-Commit-ID: 4cc5c619e4b456cd2e9bb760d17e3a9c84659198 -commit 78230b3ec8cbabc1e7de68732dc5cbd4837c6675 +commit 294c11b1c7d56d3fb61e329603a782315ed70c62 Author: djm@openbsd.org -Date: Sat Nov 27 07:14:46 2021 +0000 +Date: Wed Jan 5 08:25:05 2022 +0000 - upstream: Add ssh-keygen -Y match-principals operation to perform - - matching of principals names against an allowed signers file. - - Requested by and mostly written by Fabian Stelzer, towards a TOFU - model for SSH signatures in git. Some tweaks by me. + upstream: select all RSA hostkey algorithms for UpdateHostkeys tests, - "doesn't bother me" deraadt@ + not just RSA-SHA1 - OpenBSD-Commit-ID: 8d1b71f5a4127bc5e10a880c8ea6053394465247 + OpenBSD-Regress-ID: b40e62b65863f2702a0c10aca583b2fe76772bd8 -commit 15db86611baaafb24c40632784dabf82e3ddb1a7 +commit 2ea1108c30e3edb6f872dfc1e6da10b041ddf2c0 Author: djm@openbsd.org -Date: Thu Nov 25 23:02:24 2021 +0000 +Date: Wed Jan 5 04:56:15 2022 +0000 - upstream: debug("func: ...") -> debug_f("...") + upstream: regress test both sshsig message hash algorithms, possible - OpenBSD-Commit-ID: d58494dc05c985326a895adfbe16fbd5bcc54347 - -commit b7ffbb17e37f59249c31f1ff59d6c5d80888f689 -Author: Darren Tucker -Date: Fri Nov 19 18:53:46 2021 +1100 - - Allow for fd = -1 in compat ppoll overflow check. + now because the algorithm is controllable via the CLI - Fixes tests on at least FreeBSD 6, possibly others. + OpenBSD-Regress-ID: 0196fa87acc3544b2b4fd98de844a571cb09a39f -commit 04b172da5b96a51b0d55c905b423ababff9f4e0b -Author: Darren Tucker -Date: Fri Nov 19 16:01:51 2021 +1100 +commit 2327c306b5d4a2b7e71178e5a4d139af9902c2b0 +Author: djm@openbsd.org +Date: Wed Jan 5 04:50:11 2022 +0000 - Don't auto-enable Capsicum sandbox on FreeBSD 9/10. + upstream: allow selection of hash at sshsig signing time; code + + already supported either sha512 (default) or sha256, but plumbing wasn't + there mostly by Linus Nordberg - Since we changed from select() to ppoll() tests have been failing. - This seems to be because FreeBSD 10 (and presumably 9) do not allow - ppoll() in the privsep process and sshd will fail with "Not permitted in - capability mode". Setting CAP_EVENT on the FDs doesn't help, but weirdly, - poll() works without that. Those versions are EOL so this situation is - unlikely to change. + OpenBSD-Commit-ID: 1b536404b9da74a84b3a1c8d0b05fd564cdc96cd -commit a823f39986e7b879f26412e64c15630e1cfa0dc5 +commit 56e941d0a00d6d8bae88317717d5e1b7395c9529 Author: djm@openbsd.org -Date: Thu Nov 18 03:53:48 2021 +0000 +Date: Wed Jan 5 04:27:54 2022 +0000 - upstream: regression test for ssh-keygen -Y find-principals fix; from + upstream: add missing -O option to usage() for ssh-keygen -Y sign; - Fabian Stelzer ok djm markus + from Linus Nordberg - OpenBSD-Regress-ID: 34fe4088854c1a2eb4c0c51cc4676ba24096bac4 + OpenBSD-Commit-ID: 4e78feb4aa830727ab76bb2e3d940440ae1d7af0 -commit 199c4df66c0e39dd5c3333b162af274678c0501d +commit 141a14ec9b0924709c98df2dd8013bde5d8d12c7 Author: djm@openbsd.org -Date: Thu Nov 18 21:32:11 2021 +0000 +Date: Wed Jan 5 04:27:01 2022 +0000 - upstream: less confusing debug message; bz#3365 + upstream: move sig_process_opts() to before sig_sign(); no + + functional code change - OpenBSD-Commit-ID: 836268d3642c2cdc84d39b98d65837f5241e4a50 + OpenBSD-Commit-ID: da02d61f5464f72b4e8b299f83e93c3b657932f9 -commit 97f9b6e61316c97a32dad94b7a37daa9b5f6b836 +commit 37a14249ec993599a9051731e4fb0ac5e976aec1 Author: djm@openbsd.org -Date: Thu Nov 18 21:11:01 2021 +0000 +Date: Wed Jan 5 04:10:39 2022 +0000 - upstream: avoid xmalloc(0) for PKCS#11 keyid for ECDSA keys (we + upstream: regression test for find-principals NULL deref; from Fabian - already did this for RSA keys). Avoids fatal errors for PKCS#11 libraries - that return empty keyid, e.g. Microchip ATECC608B "cryptoauthlib"; bz#3364 + Stelzer - OpenBSD-Commit-ID: 054d4dc1d6a99a2e6f8eebc48207b534057c154d + OpenBSD-Regress-ID: f845a8632a5a7d5ae26978004c93e796270fd3e5 -commit c74aa0eb73bd1edf79947d92d9c618fc3424c4a6 +commit eb1f042142fdaba93f6c9560cf6c91ae25f6884a Author: djm@openbsd.org -Date: Thu Nov 18 03:50:41 2021 +0000 +Date: Wed Jan 5 04:02:42 2022 +0000 - upstream: ssh-keygen -Y find-principals was verifying key validity - - when using ca certs but not with simple key lifetimes within the allowed - signers file. - - Since it returns the first keys principal it finds this could - result in a principal with an expired key even though a valid - one is just below. + upstream: NULL deref when using find-principals when matching an - patch from Fabian Stelzer; feedback/ok djm markus + allowed_signers line that contains a namespace restriction, but no + restriction specified on the command-line; report and fix from Fabian Stelzer - OpenBSD-Commit-ID: b108ed0a76b813226baf683ab468dc1cc79e0905 + OpenBSD-Commit-ID: 4a201b86afb668c908d1a559c6af456a61f4b145 -commit d902d728dfd81622454260e23bc09d5e5a9a795e -Author: Darren Tucker -Date: Thu Nov 18 23:44:07 2021 +1100 +commit 8f3b18030579f395eca2181da31a5f945af12a59 +Author: dtucker@openbsd.org +Date: Tue Jan 4 08:38:53 2022 +0000 - Correct calculation of tv_nsec in poll(). + upstream: Log command invocation while debugging. + + This will aid in manually reproducing failing commands. + + OpenBSD-Regress-ID: b4aba8d5ac5675ceebeeeefa3261ce344e67333a -commit 21dd5a9a3fb35e8299a1fbcf8d506f1f6b752b85 +commit bbf285164df535f0d38c36237f007551bbdae27f Author: Darren Tucker -Date: Thu Nov 18 23:11:37 2021 +1100 +Date: Sun Dec 26 10:31:15 2021 +1100 - Add compat implementation of ppoll using pselect. + Always save config.h as build artifact. + + Should allow better comparison between failing and succeeding test + platforms. -commit b544ce1ad4afb7ee2b09f714aa63efffc73fa93a +commit 03bd4ed0db699687c5cd83405d26f81d2dc28d22 Author: Darren Tucker -Date: Thu Nov 18 23:05:34 2021 +1100 - - Put poll.h inside ifdef HAVE_POLL_H. - -commit 875408270c5a7dd69ed5449e5d85bd7120c88f70 -Author: djm@openbsd.org -Date: Thu Nov 18 03:31:44 2021 +0000 +Date: Sat Dec 25 16:42:51 2021 +1100 - upstream: check for POLLHUP wherever we check for POLLIN - - OpenBSD-Commit-ID: 6aa6f3ec6b17c3bd9bfec672a917f003a76d93e5 + Add OpenBSD 7.0 target. Retire 6.8. -commit 36b5e37030d35bbaa18ba56825b1af55971d18a0 -Author: djm@openbsd.org -Date: Thu Nov 18 03:07:59 2021 +0000 +commit c45a752f0de611afd87755c2887c8a24816d08ee +Author: jsg@openbsd.org +Date: Sat Jan 1 05:55:06 2022 +0000 - upstream: fd leak in sshd listen loop error path; from Gleb - - Smirnoff + upstream: spelling - OpenBSD-Commit-ID: a7a2be27a690a74bf2381bc16cea38e265657412 + OpenBSD-Commit-ID: c63e43087a64d0727af13409c708938e05147b62 -commit b99498d0c93f1edd04857b318308a66b28316bd8 +commit c672f83a89a756564db0d3af9934ba0e1cf8fa3e Author: djm@openbsd.org -Date: Thu Nov 18 03:07:20 2021 +0000 +Date: Tue Jan 4 07:20:33 2022 +0000 - upstream: check for POLLHUP as well as POLLIN in sshd listen loop; + upstream: unbreak test: was picking up system ssh-add instead of the - ok deraadt millert + one supposedly being tested. Spotted by dtucker and using his VM zoo (which + includes some systems old enough to lack ed25519 key support) - OpenBSD-Commit-ID: a4f1244c5a9c2b08dac4f3b1dc22e9d1dc60c587 + OpenBSD-Regress-ID: 7976eb3df11cc2ca3af91030a6a8c0cef1590bb5 -commit 1f3055d788e8cf80851eb1728b535d57eb0dba6a +commit a23698c3082ffe661abed14b020eac9b0c25eb9f Author: djm@openbsd.org -Date: Thu Nov 18 03:06:03 2021 +0000 +Date: Sat Jan 1 04:18:06 2022 +0000 - upstream: check for POLLHUP as well as POLLIN, handle transient IO - - errors as well as half-close on the output side; ok deraadt millert + upstream: fix memleak in process_extension(); oss-fuzz issue #42719 - OpenBSD-Commit-ID: de5c5b9939a37476d256328cbb96305bdecf511e + OpenBSD-Commit-ID: d8d49f840162fb7b8949e3a5adb8107444b6de1e -commit 9778a15fa6dbdac6a95bf15865c2688b4bd6944e -Author: Damien Miller -Date: Thu Nov 18 10:16:55 2021 +1100 +commit cb885178f36b83d0f14cfe9f345d2068103feed0 +Author: jsg@openbsd.org +Date: Sat Jan 1 01:55:30 2022 +0000 - adjust seccomp filter for select->poll conversion + upstream: spelling ok dtucker@ - Needed to add ppoll syscall but also to relax the fallback rlimit - sandbox. Linux poll() fails with EINVAL if npfds > RLIMIT_NOFILE, - so we have to allow a single fd in the rlimit. - -commit fcd8d895bbb849c64f0aed934e3303d37f696f5d -Author: Damien Miller -Date: Thu Nov 18 10:16:44 2021 +1100 - - update depends - -commit 76292787a1e93e668f10e36b4bf59ce0ae28e156 -Author: Damien Miller -Date: Thu Nov 18 09:26:20 2021 +1100 - - compat for timespecsub() and friends + OpenBSD-Commit-ID: bfc7ba74c22c928de2e257328b3f1274a3dfdf19 -commit fd7e7de4ddb4399c7e929b44f2bbfc118eddfcf8 +commit 6b977f8080a32c5b3cbb9edb634b9d5789fb79be Author: djm@openbsd.org -Date: Wed Nov 17 21:06:39 2021 +0000 +Date: Sun Dec 26 23:34:41 2021 +0000 - upstream: set num_listen_socks to 0 on close-all instead of -1, + upstream: split method list search functionality from + + authmethod_lookup() into a separate authmethod_byname(), for cases where we + don't need to check whether a method is enabled, etc. - which interferes with the new poll()-based listen loop; spotted and debugged - by anton@+deraadt@ + use this to fix the "none" authentication method regression reported + by Nam Nguyen via bugs@ + + ok deraadt@ - OpenBSD-Commit-ID: f7ab8ab124f615a2e0c45fee14c38d2f2abbabbd + OpenBSD-Commit-ID: 8cd188dc3a83aa8abe5b7693e762975cd8ea8a17 -commit fd9343579afac30a971f06643a669733d9acb407 -Author: deraadt@openbsd.org -Date: Sun Nov 14 18:47:43 2021 +0000 +commit 0074aa2c8d605ee7587279a22cdad4270b4ddd07 +Author: jmc@openbsd.org +Date: Wed Dec 22 06:56:41 2021 +0000 - upstream: use ppoll() instead of pselect() with djm + upstream: sort -H and -h in SYNOPSIS/usage(); tweak the -H text; + + ok djm - OpenBSD-Commit-ID: 980f87c9564d5d2ad55722b7a6f44f21284cd215 + OpenBSD-Commit-ID: 90721643e41e9e09deb5b776aaa0443456ab0965 -commit 092d29b232ef1a19609a5316ed7e4d896bb2e696 -Author: deraadt@openbsd.org -Date: Sun Nov 14 06:15:36 2021 +0000 +commit 1c9853a68b2319f2e5f929179735e8fbb9988a67 +Author: Darren Tucker +Date: Wed Dec 22 19:33:10 2021 +1100 - upstream: match .events with .fd better + Use SHA.*_HMAC_BLOCK_SIZE if needed. - OpenBSD-Commit-ID: 77eef212ca0add905949532af390164489c5984b + If the platform has a native SHA2, does not define SHA.*_BLOCK_LENGTH + but does define SHA.*_HMAC_BLOCK_SIZE (eg Solaris) then use the latter. + Should fix --without-openssl build on Solaris. -commit 8d642c9a90fa4ed5a3effd785fb3591e14de00cd -Author: deraadt@openbsd.org -Date: Sun Nov 14 03:25:10 2021 +0000 +commit 715c892f0a5295b391ae92c26ef4d6a86ea96e8e +Author: Damien Miller +Date: Wed Dec 22 09:02:50 2021 +1100 - upstream: convert select() to poll() ok djm - - OpenBSD-Commit-ID: b53e4940ff10dd24f8d16e8db8ef1970015d7ead + remove sys/param.h in -portable, after upstream -commit 6582a31c388968f4073af2bd8621880735c3d42b -Author: deraadt@openbsd.org -Date: Sat Nov 13 21:14:13 2021 +0000 +commit 7a7c69d8b4022b1e5c0afb169c416af8ce70f3e8 +Author: Damien Miller +Date: Mon Dec 20 13:05:20 2021 +1100 - upstream: replace select() with ppoll(), including converting - - timeval's to timespec's to make things easier. back and forth and ok; djm - - OpenBSD-Commit-ID: 89d3b23c60875da919e7820f9de6213286ffbec9 + add agent-restrict.sh file, missed in last commit -commit 7c025c005550c86a40200a2bcdd355d09413d61a -Author: deraadt@openbsd.org -Date: Sat Nov 13 17:26:13 2021 +0000 +commit f539136ca51a4976644db5d0be8158cc1914c72a +Author: djm@openbsd.org +Date: Sun Dec 19 22:20:12 2021 +0000 - upstream: It really looks like pledge "stdio dns" is possible - - earlier. Discussed with mestre + upstream: regression test for destination restrictions in ssh-agent - OpenBSD-Commit-ID: 610873de63a593e0ac7bbbcb7a0f2894d36f4c01 + OpenBSD-Regress-ID: 3c799d91e736b1753b4a42d80c42fc40de5ad33d -commit 06acb04c20ee483fe4757bd12aec870cc4bb1076 -Author: deraadt@openbsd.org -Date: Fri Nov 12 05:23:49 2021 +0000 +commit 6e4980eb8ef94c04874a79dd380c3f568e8416d6 +Author: anton@openbsd.org +Date: Sat Dec 18 06:53:59 2021 +0000 - upstream: aggressively pre-fill the pollfd array with fd=-1 + upstream: Make use of ntests variable, pointed out by clang 13. - OpenBSD-Commit-ID: c2a525de8f83c1a04405bd79122c424140552a5b + OpenBSD-Regress-ID: 4241a3d21bdfa1630ed429b6d4fee51038d1be72 -commit 7eec76793dec06e8f06b6cf71f9473141c69d109 +commit 3eead8158393b697f663ec4301e3c7b6f24580b1 Author: deraadt@openbsd.org -Date: Thu Nov 11 15:32:32 2021 +0000 +Date: Tue Dec 14 21:25:27 2021 +0000 - upstream: Convert from select() to ppoll(). Along the way, I - - observed that the select() code was using exceptfds incorrectly.. ok millert + upstream: sys/param.h cleanup, mostly using MINIMUM() and - OpenBSD-Commit-ID: 548e05bfc31b2af02319eb3d051286d4128dec96 - -commit e665ed2d0c24fe11d5470ce72fa1e187377d3fc4 -Author: Darren Tucker -Date: Fri Nov 12 22:55:27 2021 +1100 - - Switch from LibreSSL 3.4.0 to 3.4.1. + ok dtucker - The LibreSSL 3.4.0 release has an OPENBSD_BRANCH that points to - "master" and that branch no longer has the files LibreSSL expects - and thus it will no longer build, breaking the test. + OpenBSD-Regress-ID: 172a4c45d3bcf92fa6cdf6c4b9db3f1b3abe4db0 -commit 21b6b5a06c8c53c548d25e6074c5240e88e2ef34 +commit 266678e19eb0e86fdf865b431b6e172e7a95bf48 Author: djm@openbsd.org -Date: Wed Nov 10 06:29:25 2021 +0000 +Date: Sun Dec 19 22:15:42 2021 +0000 - upstream: add the sntrup761x25519-sha512@openssh.com hybrid - - ECDH/x25519 + Streamlined NTRU Prime post-quantum KEX to the default - KEXAlgorithms list (after the ECDH methods but before the prime-group DH - ones). - - ok markus@ + upstream: document host-bound publickey authentication - OpenBSD-Commit-ID: 22b77e27a04e497a10e22f138107579652854210 + OpenBSD-Commit-ID: ea6ed91779a81f06d961e30ecc49316b3d71961b -commit 239da797cbf07a640d7b1ea02d3f99ace3ef792d +commit 3d00024b3b156aa9bbd05d105f1deb9cb088f6f7 Author: djm@openbsd.org -Date: Wed Nov 10 06:25:08 2021 +0000 +Date: Sun Dec 19 22:15:21 2021 +0000 - upstream: fix ssh-keysign for KEX algorithms that use SHA384/512 - - exchange hashes; feedback/ok markus@ + upstream: document agent protocol extensions - OpenBSD-Commit-ID: 09a8fda1c081f5de1e3128df64f28b7bdadee239 + OpenBSD-Commit-ID: 09e8bb391bbaf24c409b75a4af44e0cac65405a7 -commit 6997a592ecb1013df0c6d7f8df3e6517827aef11 +commit c385abf76511451bcba78568167b1cd9e90587d5 Author: djm@openbsd.org -Date: Mon Nov 8 21:32:49 2021 +0000 +Date: Sun Dec 19 22:14:47 2021 +0000 - upstream: improve error message when trying to expand a ~user path - - for a user that doesn't exist; better matches what the shell does + upstream: PubkeyAuthentication=yes|no|unbound|host-bound - ok deraadt@ + Allow control over which pubkey methods are used. Added out of + concern that some hardware devices may have difficulty signing + the longer pubkey authentication challenges. This provides a + way for them to disable the extension. It's also handy for + testing. - OpenBSD-Commit-ID: 1ddefa3c3a78b69ce13d1b8f67bc9f2cefd23ad6 - -commit 10b899a15c88eb40eb5f73cd0fa84ef0966f79c9 -Author: Darren Tucker -Date: Wed Nov 10 12:34:25 2021 +1100 - - Don't trust closefrom() on Linux. + feedback / ok markus@ - glibc's closefrom implementation does not work in a chroot when the kernel - does not have close_range. It tries to read from /proc/self/fd and when - that fails dies with an assertion of sorts. Instead, call close_range - ourselves from our compat code and fall back if that fails. bz#3349, - with william.wilson at canonical.com and fweimer at redhat.com. + OpenBSD-Commit-ID: ee52580db95c355cf6d563ba89974c210e603b1a -commit eb1f63195a9a38b519536a5b398d9939261ec081 -Author: dtucker@openbsd.org -Date: Sat Nov 6 10:13:39 2021 +0000 +commit 34b1e9cc7654f41cd4c5b1cc290b999dcf6579bb +Author: djm@openbsd.org +Date: Sun Dec 19 22:14:12 2021 +0000 - upstream: Plug a couple of minor mem leaks. From beldmit at + upstream: document destination-constrained keys - gmail.com via github PR#283, ok markus@ + feedback / ok markus@ - OpenBSD-Commit-ID: ec1fa7d305d46226861c3ca6fb9c9beb2ada2892 + OpenBSD-Commit-ID: cd8c526c77268f6d91c06adbee66b014d22d672e -commit e4f501bf1d3b53f1cc23d9521fd7c5163307b760 +commit a6d7677c4abcfba268053e5867f2acabe3aa371b Author: djm@openbsd.org -Date: Fri Nov 5 03:10:58 2021 +0000 +Date: Sun Dec 19 22:13:55 2021 +0000 - upstream: move cert_filter_principals() to earlier in the file for + upstream: Use hostkey parsed from hostbound userauth request - reuse; no code change + Require host-bound userauth requests for forwarded SSH connections. - OpenBSD-Commit-ID: 598fa9528b656b2f38bcc3cf5b6f3869a8c115cf - -commit 59c60f96fee321c7f38f00372826d37f289534af -Author: deraadt@openbsd.org -Date: Wed Nov 3 22:00:56 2021 +0000 - - upstream: Many downstreams expect ssh to compile as non-C99... + The hostkey parsed from the host-bound userauth request is now checked + against the most recently bound session ID / hostkey on the agent socket + and the signature refused if they do not match. - OpenBSD-Commit-ID: e6aa3e08bda68e5fb838fc8a49b1d2dfc38ee783 - -commit 7a78fe63b0b28ef7231913dfefe9d08f9bc41c61 -Author: Darren Tucker -Date: Sat Nov 6 21:07:03 2021 +1100 - - Skip getline() on HP-UX 10.x. + ok markus@ - HP-UX 10.x has a getline() implementation in libc that does not behave - as we expect so don't use it. With correction from Thorsten Glaser and - typo fix from Larkin Nickle. - -commit 343ae252ebb35c6ecae26b447bf1551a7666720e -Author: Damien Miller -Date: Wed Nov 3 12:08:21 2021 +1100 - - basic SECURITY.md (refers people to the website) + OpenBSD-Commit-ID: d69877c9a3bd8d1189a5dbdeceefa432044dae02 -commit ed45a0168638319e0a710633f6085b96b9cec656 +commit baaff0ff4357cc5a079621ba6e2d7e247b765061 Author: djm@openbsd.org -Date: Tue Nov 2 22:57:27 2021 +0000 +Date: Sun Dec 19 22:13:33 2021 +0000 - upstream: crank SSH_SK_VERSION_MAJOR to match recent change in + upstream: agent support for parsing hostkey-bound signatures + + Allow parse_userauth_request() to work with blobs from + publickey-hostbound-v00@openssh.com userauth attempts. + + Extract hostkey from these blobs. - usr/bin/ssh + ok markus@ - OpenBSD-Regress-ID: 113d181c7e3305e138db9b688cdb8b0a0019e552 + OpenBSD-Commit-ID: 81c064255634c1109477dc65c3e983581d336df8 -commit f3c34df860c4c1ebddacb973954e58167d9dbade +commit 3e16365a79cdeb2d758cf1da6051b1c5266ceed7 Author: djm@openbsd.org -Date: Tue Nov 2 22:56:40 2021 +0000 +Date: Sun Dec 19 22:13:12 2021 +0000 - upstream: Better handle FIDO keys on tokens that provide user - - verification (UV) on the device itself, including biometric keys. - - Query the token during key creation to determine whether it supports - on-token UV and, if so, clear the SSH_SK_USER_VERIFICATION_REQD flag - in the key so that ssh(1) doesn't automatically prompty for PIN later. + upstream: EXT_INFO negotiation of hostbound pubkey auth - When making signatures with the key, query the token's capabilities - again and check whether the token is able (right now) to perform user- - verification without a PIN. If it is then the PIN prompt is bypassed - and user verification delegated to the token. If not (e.g. the token - is biometric capable, but no biometric are enrolled), then fall back - to user verification via the usual PIN prompt. + the EXT_INFO packet gets a new publickey-hostbound@openssh.com to + advertise the hostbound public key method. - Work by Pedro Martelletto; ok myself and markus@ + Client side support to parse this feature flag and set the kex->flags + indicator if the expected version is offered (currently "0"). - NB. cranks SSH_SK_VERSION_MAJOR + ok markus@ - OpenBSD-Commit-ID: e318a8c258d9833a0b7eb0236cdb68b5143b2f27 + OpenBSD-Commit-ID: 4cdb2ca5017ec1ed7a9d33bda95c1d6a97b583b0 -commit 0328a081f38c09d2d4d650e94461a47fb5eef536 +commit 94ae0c6f0e35903b695e033bf4beacea1d376bb1 Author: djm@openbsd.org -Date: Fri Oct 29 03:03:06 2021 +0000 +Date: Sun Dec 19 22:12:54 2021 +0000 - upstream: sshsig: add tests for signing key validity and + upstream: client side of host-bound pubkey authentication - find-principals + Add kex->flags member to enable the publickey-hostbound-v00@openssh.com + authentication method. + + Use the new hostbound method in client if the kex->flags flag was set, + and include the inital KEX hostkey in the userauth request. - - adds generic find-principals tests (this command had none before) - - tests certs with a timeboxed validity both with and without a - restriced lifetime for the CA - - test for a revoked CA cert + Note: nothing in kex.c actually sets the new flag yet - by Fabian Stelzer + ok markus@ - OpenBSD-Regress-ID: 9704b2c6df5b8ccfbdf2c06c5431f5f8cad280c9 + OpenBSD-Commit-ID: 5a6fce8c6c8a77a80ee1526dc467d91036a5910d -commit ccd358e1e25e25c13f0825996283cbf7a1647a3b +commit 288fd0218dbfdcb05d9fbd1885904bed9b6d42e6 Author: djm@openbsd.org -Date: Fri Oct 29 02:48:19 2021 +0000 +Date: Sun Dec 19 22:12:30 2021 +0000 - upstream: avoid signedness warning; spotted in -portable + upstream: sshd side of hostbound public key auth + + This is identical to the standard "publickey" method, but it also includes + the initial server hostkey in the message signed by the client. + + feedback / ok markus@ - OpenBSD-Regress-ID: 4cacc126086487c0ea7f3d86b42dec458cf0d0c6 + OpenBSD-Commit-ID: 7ea01bb7238a560c1bfb426fda0c10a8aac07862 -commit 2741f52beb11490d7033a25e56ed0496f0c78006 +commit dbb339f015c33d63484261d140c84ad875a9e548 Author: djm@openbsd.org -Date: Fri Oct 29 03:20:46 2021 +0000 +Date: Sun Dec 19 22:12:07 2021 +0000 - upstream: ssh-keygen: make verify-time argument parsing optional + upstream: prepare for multiple names for authmethods - From Fabian Stelzer + allow authentication methods to have one additional name beyond their + primary name. - OpenBSD-Commit-ID: 1ff35e4c366a45a073663df90381be6a8ef4d370 - -commit a1217d363b88b32cfe54c4f02c6c1cf4bdefdd23 -Author: Damien Miller -Date: Fri Oct 29 13:48:34 2021 +1100 - - unbreak fuzz harness for recent changes - -commit 68e522ed8183587c9367fa3842c5b75f64f3d12b -Author: Darren Tucker -Date: Fri Oct 29 13:32:24 2021 +1100 - - Use -Wbitwise-instead-of-logical if supported. - -commit be28b23012aa3fa323be7ec84863cf238927c078 -Author: Damien Miller -Date: Thu Oct 28 16:24:53 2021 +1100 - - use -Wmisleading-indentation cflag if available + allow lookup by this synonym - ok dtucker@ - -commit 2e6f5f24dd2f9217f4ab8b737ed428d5d5278f91 -Author: Damien Miller -Date: Thu Oct 28 16:24:44 2021 +1100 - - depend - -commit a5ab4882348d26addc9830a44e053238dfa2cb58 -Author: Damien Miller -Date: Thu May 6 10:08:30 2021 +1000 - - remove built-in support for md5crypt() + Use primary name for authentication decisions, e.g. for + PermitRootLogin=publickey + + Pass actual invoked name to the authmethods, so they can tell whether they + were requested via the their primary name or synonym. - Users of MD5-hashed password should arrange for ./configure to link - against libxcrypt or similar. Though it would be better to avoid use - of MD5 password hashing entirely, it's arguably worse than DEScrypt. + ok markus@ - feedback and ok dtucker@ + OpenBSD-Commit-ID: 9e613fcb44b8168823195602ed3d09ffd7994559 -commit c5de1fffa6328b8246b87da28fa9df05813f76a3 +commit 39f00dcf44915f20684160f0a88d3ef8a3278351 Author: djm@openbsd.org -Date: Thu Oct 28 02:55:30 2021 +0000 +Date: Sun Dec 19 22:11:39 2021 +0000 - upstream: increment SSH_SK_VERSION_MAJOR to match last change + upstream: ssh-agent side of destination constraints + + Gives ssh-agent the ability to parse restrict-destination-v00@openssh.com + constraints and to apply them to keys. + + Check constraints against the hostkeys recorded for a SocketEntry when + attempting a signature, adding, listing or deleting keys. Note that + the "delete all keys" request will remove constrained keys regardless of + location. + + feedback Jann Horn & markus@ + ok markus@ - OpenBSD-Regress-ID: 17873814d1cbda97f49c8528d7b5ac9cadf6ddc0 + OpenBSD-Commit-ID: 84a7fb81106c2d609a6ac17469436df16d196319 -commit 0001d04e55802d5bd9d6dece1081a99aa4ba2828 +commit ce943912df812c573a33d00bf9e5435b7fcca3f7 Author: djm@openbsd.org -Date: Thu Oct 28 02:54:18 2021 +0000 +Date: Sun Dec 19 22:11:06 2021 +0000 - upstream: When downloading resident keys from a FIDO token, pass + upstream: ssh-add side of destination constraints - back the user ID that was used when the key was created and append it to the - filename the key is written to (if it is not the default). + Have ssh-add accept a list of "destination constraints" that allow + restricting where keys may be used in conjunction with a ssh-agent/ssh + that supports session ID/hostkey binding. - Avoids keys being clobbered if the user created multiple - resident keys with the same application string but different - user IDs. + Constraints are specified as either "[user@]host-pattern" or + "host-pattern>[user@]host-pattern". - feedback Pedro Martelletto; ok markus + The first form permits a key to be used to authenticate as the + specified user to the specified host. - NB. increments SSH_SK_VERSION_MAJOR + The second form permits a key that has previously been permitted + for use at a host to be available via a forwarded agent to an + additional host. - OpenBSD-Commit-ID: dbd658b5950f583106d945641a634bc6562dd3a3 - -commit d4bed5445646e605c383a4374fa962e23bf9e3a3 -Author: deraadt@openbsd.org -Date: Sun Oct 24 21:24:17 2021 +0000 - - upstream: For open/openat, if the flags parameter does not contain + For example, constraining a key with "user1@host_a" and + "host_a>host_b". Would permit authentication as "user1" at + "host_a", and allow the key to be available on an agent forwarded + to "host_a" only for authentication to "host_b". The key would not + be visible on agent forwarded to other hosts or usable for + authentication there. - O_CREAT, the 3rd (variadic) mode_t parameter is irrelevant. Many developers - in the past have passed mode_t (0, 044, 0644, or such), which might lead - future people to copy this broken idiom, and perhaps even believe this - parameter has some meaning or implication or application. Delete them all. - This comes out of a conversation where tb@ noticed that a strange (but - intentional) pledge behaviour is to always knock-out high-bits from mode_t on - a number of system calls as a safety factor, and his bewilderment that this - appeared to be happening against valid modes (at least visually), but no - sorry, they are all irrelevant junk. They could all be 0xdeafbeef. ok - millert + Internally, destination constraints use host keys to identify hosts. + The host patterns are used to obtain lists of host keys for that + destination that are communicated to the agent. The user/hostkeys are + encoded using a new restrict-destination-v00@openssh.com key + constraint. - OpenBSD-Commit-ID: 503d11633497115688c0c6952686524f01f53121 - -commit d575cf44895104e0fcb0629920fb645207218129 -Author: Darren Tucker -Date: Fri Oct 22 23:27:41 2021 +1100 - - kitchensink test target now needs krb5. - -commit 4ae39cada214e955bcfd3448ff28f0ed18886706 -Author: Darren Tucker -Date: Fri Oct 22 22:54:33 2021 +1100 - - Test both MIT KRB5 and Heimdal. - -commit 22b2681d88619e5247dc53c9f112058a7e248d48 -Author: dtucker@openbsd.org -Date: Fri Oct 22 10:51:57 2021 +0000 - - upstream: Plug mem addrinfo mem leaks. + host keys are looked up in the default client user/system known_hosts + files. It is possible to override this set on the command-line. - Prevent mem leaks in the (unlikely) event that getaddrinfo returns - no addresses. ALso, remove an unneeded NULL check in addr_ntop. From - khaleesicodes via github PR#281, ok deraadt@ + feedback Jann Horn & markus@ + ok markus@ - OpenBSD-Commit-ID: e8a5afc686376637c355c5f7e122dc4b080b9c1a + OpenBSD-Commit-ID: 6b52cd2b637f3d29ef543f0ce532a2bce6d86af5 -commit 27c8c343b610263f83ac2328735feeb881c6c92f -Author: dtucker@openbsd.org -Date: Fri Oct 22 09:22:04 2021 +0000 +commit 5e950d765727ee0b20fc3d2cbb0c790b21ac2425 +Author: djm@openbsd.org +Date: Sun Dec 19 22:10:24 2021 +0000 - upstream: Remove unnecessary semicolons + upstream: ssh-add side of destination constraints - ... in case statements. From khaleesicodes via github PR#280. + Have ssh-add accept a list of "destination constraints" that allow + restricting where keys may be used in conjunction with a ssh-agent/ssh + that supports session ID/hostkey binding. - OpenBSD-Commit-ID: e1e89360b65775cff83e77ce040b342015caf4ed - -commit e7eb73b8d1fe1008d92433ea949491ce654bfaba -Author: dtucker@openbsd.org -Date: Fri Oct 22 09:19:34 2021 +0000 - - upstream: Fix typos in comments. + Constraints are specified as either "[user@]host-pattern" or + "host-pattern>[user@]host-pattern". - From khaleesicodes via github PR#280. + The first form permits a key to be used to authenticate as the + specified user to the specified host. - OpenBSD-Commit-ID: 26fdd83652c40f098bf7c685e8ebb9eb72cc45fc - -commit 052a9d8494175e24312daa6c132665e58c17fe6e -Author: deraadt@openbsd.org -Date: Fri Oct 15 14:46:46 2021 +0000 - - upstream: switch scp(1) back to sftp protocol. + The second form permits a key that has previously been permitted + for use at a host to be available via a forwarded agent to an + additional host. - openbsd 7.0 release shipped with the (hopefully last) scp that uses RCP - protocol for copying. Let's get back to testing the SFTP protocol. + For example, constraining a key with "user1@host_a" and + "host_a>host_b". Would permit authentication as "user1" at + "host_a", and allow the key to be available on an agent forwarded + to "host_a" only for authentication to "host_b". The key would not + be visible on agent forwarded to other hosts or usable for + authentication there. - OpenBSD-Commit-ID: 9eaa35d95fd547b78b0a043b3f518e135f151f30 - -commit a07664646bf6d293f5bbd45a5de54f3c36bb85da -Author: Darren Tucker -Date: Fri Oct 22 14:00:05 2021 +1100 - - Source configs script so setup_ci can use settings - -commit 34df52c201c6b47e5a46b50c215e4d98a8bf6587 -Author: Darren Tucker -Date: Fri Oct 22 09:42:14 2021 +1100 - - Install libedit and pam based on config flags. - -commit 8c626cc563e8d21d844d06f9971a9ee01de6aa2a -Author: Darren Tucker -Date: Thu Oct 21 16:53:39 2021 +1100 - - Don't use 'here string", it's not POSIX. - -commit 086a4b5977472aefa3de918b88efad0faf83b2b1 -Author: Darren Tucker -Date: Thu Oct 21 15:33:27 2021 +1100 - - Remove -Werror from compiler package to install. - -commit 5a7a4687507d057f9b5e7497f3d3f82e64753c02 -Author: Darren Tucker -Date: Thu Oct 21 15:00:53 2021 +1100 - - Build with -Werror on most recent gcc and clang. - -commit 4d2cbdb525d673acf941d48a7044fcf03125611a -Author: Darren Tucker -Date: Fri Oct 15 12:59:06 2021 +1100 - - Include string.h and stdio.h for strerror. - -commit fff13aaa262b7b3ec83ed21e29674cbf331780a7 -Author: Darren Tucker -Date: Fri Oct 15 12:43:36 2021 +1100 - - Include error reason if trace disabling fails. - -commit d4b38144c02f3faa5271e5fb35df93507e06f1b4 -Author: Darren Tucker -Date: Tue Oct 12 22:55:51 2021 +1100 - - Add tcmalloc test target. - -commit 002d65b0a30063c6e49bf8a53e709d8d5a0d45c1 -Author: dtucker@openbsd.org -Date: Sat Oct 9 10:52:42 2021 +0000 - - upstream: Document that CASignatureAlgorithms, ExposeAuthInfo and + Internally, destination constraints use host keys to identify hosts. + The host patterns are used to obtain lists of host keys for that + destination that are communicated to the agent. The user/hostkeys are + encoded using a new restrict-destination-v00@openssh.com key + constraint. + + host keys are looked up in the default client user/system known_hosts + files. It is possible to override this set on the command-line. - PubkeyAuthOptions can be used in a Match block. Patch from eehakkin via - github PR#277. + feedback Jann Horn & markus@ + ok markus@ - OpenBSD-Commit-ID: c0a63f5f52e918645967ac022b28392da4b866aa - -commit 40bd3709dddaae3a1b6113748bec3faa6a607531 -Author: Darren Tucker -Date: Thu Oct 7 15:55:49 2021 +1100 - - Skip SK unit tests when built without security-key + OpenBSD-Commit-ID: ef47fa9ec0e3c2a82e30d37ef616e245df73163e -commit 482f73be10f10b93f818df19fcc8a912c0c371fc -Author: Darren Tucker -Date: Thu Oct 7 15:55:04 2021 +1100 +commit 4c1e3ce85e183a9d0c955c88589fed18e4d6a058 +Author: djm@openbsd.org +Date: Sun Dec 19 22:09:23 2021 +0000 - Include relevant env vars on command line. + upstream: ssh-agent side of binding - Makes it easier to reproduce a build by cut/pasting the configure line. - -commit ef5916b8acd9b1d2f39fad4951dae03b00dbe390 -Author: Darren Tucker -Date: Thu Oct 7 14:28:02 2021 +1100 - - Only enable sk-* key types if ENABLE_SK is defined - -commit 52d4232b493a9858fe616e28a8bbcc89afa2ad4d -Author: Darren Tucker -Date: Wed Oct 6 18:14:37 2021 +1100 - - Disable security key on minix3. + record session ID/hostkey/forwarding status for each active socket. - The test doesn't work so disable. - -commit 7cd062c3a29669b8d7dc2a97e6575f4dcb7d35a2 -Author: Darren Tucker -Date: Wed Oct 6 17:45:28 2021 +1100 - - Add USE_LIBC_SHA2 for (at least) NetBSD 9. - -commit 639c440f6c3c2a8216a5eb9455ef13bf4204089c -Author: Darren Tucker -Date: Wed Oct 6 17:09:31 2021 +1100 - - Define OPENSSL_NO_SHA including OpenSSL from test. + Attempt to parse data-to-be-signed at signature request time and extract + session ID from the blob if it is a pubkey userauth request. - We don't use SHA256 from OpenSSL in the sk-dummy module and the - definitions can conflict with system sha2.h (eg on NetBSD) so define - OPENSSL_NO_SHA so we don't attempt to redefine them. - -commit 8f4be526a338d06624f146fa26007bb9dd3a4f7b -Author: Darren Tucker -Date: Wed Oct 6 15:40:58 2021 +1100 - - Disable security key on NetBSD4 test. + ok markus@ - sk-dummy used for the security key test includes both sha2.h and OpenSSL - causing the definitions conflict so disable security key support on this - platform. - -commit 3b353ae58aa07a1cbbeb1da3ace21fc0dcccd66a -Author: Damien Miller -Date: Wed Oct 6 15:07:01 2021 +1100 - - clean regress/misc/sk-dummy in cleandir target + OpenBSD-Commit-ID: a80fd41e292b18b67508362129e9fed549abd318 -commit 57680a2ab43518c5ccbd8242c40482106cde6ac1 -Author: dtucker@openbsd.org -Date: Sat Oct 2 03:17:01 2021 +0000 +commit e9497ecf73f3c16667288bce48d4e3d7e746fea1 +Author: djm@openbsd.org +Date: Sun Dec 19 22:08:48 2021 +0000 - upstream: Dynamically allocate encoded HashKnownHosts and free as + upstream: ssh client side of binding - appropriate. Saves 1k of static storage and prevents snprintf "possible - truncation" warnings from newer compilers (although in this case it's false - positive since the actual sizes are limited by the output size of the SHA1). - ok djm@ + send session ID, hostkey, signature and a flag indicating whether the + agent connection is being forwarded to ssh agent each time a connection + is opened via a new "session-bind@openssh.com" agent extension. - OpenBSD-Commit-ID: e254ae723f7e3dce352c7d5abc4b6d87faf61bf4 + ok markus@ + + OpenBSD-Commit-ID: 2f154844fe13167d3ab063f830d7455fcaa99135 -commit e3e62deb549fde215b777d95276c304f84bf00c6 +commit b42c61d6840d16ef392ed0f365e8c000734669aa Author: djm@openbsd.org -Date: Wed Oct 6 03:35:13 2021 +0000 +Date: Sun Dec 19 22:08:06 2021 +0000 - upstream: use libc SHA256 functions; make this work when compiled + upstream: Record session ID, host key and sig at intital KEX - !WITH_OPENSSL + These will be used later for agent session ID / hostkey binding - OpenBSD-Regress-ID: fda0764c1097cd42f979ace29b07eb3481259890 - -commit 12937d867019469ebce83c2ff614cdc6688fc2d8 -Author: dtucker@openbsd.org -Date: Fri Oct 1 05:20:20 2021 +0000 - - upstream: Add test for ssh hashed known_hosts handling. + ok markus@ - OpenBSD-Regress-ID: bcef3b3cd5a1ad9899327b4b2183de2541aaf9cf + OpenBSD-Commit-ID: a9af29e33772b18e3e867c6fa8ab35e1694a81fe -commit 5a37cc118f464416d08cd0291a9b1611d8de9943 -Author: Damien Miller -Date: Wed Oct 6 13:16:21 2021 +1100 +commit 26ca33d186473d58a32d812e19273ce078b6ffff +Author: djm@openbsd.org +Date: Tue Dec 7 22:06:45 2021 +0000 - fix broken OPENSSL_HAS_ECC test + upstream: better error message for FIDO keys when we can't match + + them to a token - spotted by dtucker + OpenBSD-Commit-ID: 58255c2a1980088f4ed144db67d879ada2607650 diff --git a/crypto/openssh/Makefile.in b/crypto/openssh/Makefile.in index 70287f51fb81..1efe11f6f27b 100644 --- a/crypto/openssh/Makefile.in +++ b/crypto/openssh/Makefile.in @@ -1,785 +1,789 @@ SHELL=@SH@ AUTORECONF=autoreconf prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ sbindir=@sbindir@ libexecdir=@libexecdir@ datadir=@datadir@ datarootdir=@datarootdir@ mandir=@mandir@ mansubdir=@mansubdir@ sysconfdir=@sysconfdir@ piddir=@piddir@ srcdir=@srcdir@ top_srcdir=@top_srcdir@ abs_top_srcdir=@abs_top_srcdir@ abs_top_builddir=@abs_top_builddir@ DESTDIR= VPATH=@srcdir@ SSH_PROGRAM=@bindir@/ssh ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass SFTP_SERVER=$(libexecdir)/sftp-server SSH_KEYSIGN=$(libexecdir)/ssh-keysign SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper PRIVSEP_PATH=@PRIVSEP_PATH@ SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ STRIP_OPT=@STRIP_OPT@ TEST_SHELL=@TEST_SHELL@ BUILDDIR=@abs_top_builddir@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \ -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ -D_PATH_SSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\" \ -D_PATH_SFTP_SERVER=\"$(SFTP_SERVER)\" \ -D_PATH_SSH_KEY_SIGN=\"$(SSH_KEYSIGN)\" \ -D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \ -D_PATH_SSH_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@ CHANNELLIBS=@CHANNELLIBS@ K5LIBS=@K5LIBS@ GSSLIBS=@GSSLIBS@ SSHDLIBS=@SSHDLIBS@ LIBEDIT=@LIBEDIT@ LIBFIDO2=@LIBFIDO2@ AR=@AR@ AWK=@AWK@ RANLIB=@RANLIB@ INSTALL=@INSTALL@ SED=@SED@ XAUTH_PATH=@XAUTH_PATH@ LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@ LDFLAGS_NOPIE=-L. -Lopenbsd-compat/ @LDFLAGS_NOPIE@ EXEEXT=@EXEEXT@ MANFMT=@MANFMT@ MKDIR_P=@MKDIR_P@ .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 \ sshkey-xmss.o \ xmss_commons.o \ xmss_fast.o \ xmss_hash.o \ xmss_hash_address.o \ xmss_wots.o LIBOPENSSH_OBJS=\ ssh_api.o \ ssherr.o \ sshbuf.o \ sshkey.o \ sshbuf-getput-basic.o \ sshbuf-misc.o \ sshbuf-getput-crypto.o \ krl.o \ bitmap.o \ ${XMSS_OBJS} LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ authfd.o authfile.o \ canohost.o channels.o cipher.o cipher-aes.o cipher-aesctr.o \ cleanup.o \ compat.o fatal.o hostfile.o \ log.o match.o moduli.o nchan.o packet.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-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 cipher-chachapoly-libcrypto.o \ ssh-ed25519.o digest-openssl.o digest-libc.o \ hmac.o ed25519.o hash.o \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ kexgexc.o kexgexs.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 $(SKOBJS) SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ audit.o audit-bsm.o audit-linux.o platform.o \ sshpty.o sshlogin.o servconf.o serverloop.o \ auth.o auth2.o auth-options.o session.o \ auth2-chall.o groupaccess.o \ auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-pubkeyfile.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 \ 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 $(SKOBJS) SFTP_CLIENT_OBJS=sftp-common.o sftp-client.o sftp-glob.o SCP_OBJS= scp.o progressmeter.o $(SFTP_CLIENT_OBJS) 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-usergroup.o progressmeter.o $(SFTP_CLIENT_OBJS) 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 CONFIGFILES_IN=sshd_config ssh_config moduli PATHSUBS = \ -e 's|/etc/ssh/ssh_config|$(sysconfdir)/ssh_config|g' \ -e 's|/etc/ssh/ssh_known_hosts|$(sysconfdir)/ssh_known_hosts|g' \ -e 's|/etc/ssh/sshd_config|$(sysconfdir)/sshd_config|g' \ -e 's|/usr/libexec|$(libexecdir)|g' \ -e 's|/etc/shosts.equiv|$(sysconfdir)/shosts.equiv|g' \ -e 's|/etc/ssh/ssh_host_key|$(sysconfdir)/ssh_host_key|g' \ -e 's|/etc/ssh/ssh_host_ecdsa_key|$(sysconfdir)/ssh_host_ecdsa_key|g' \ -e 's|/etc/ssh/ssh_host_dsa_key|$(sysconfdir)/ssh_host_dsa_key|g' \ -e 's|/etc/ssh/ssh_host_rsa_key|$(sysconfdir)/ssh_host_rsa_key|g' \ -e 's|/etc/ssh/ssh_host_ed25519_key|$(sysconfdir)/ssh_host_ed25519_key|g' \ -e 's|/var/run/sshd.pid|$(piddir)/sshd.pid|g' \ -e 's|/etc/moduli|$(sysconfdir)/moduli|g' \ -e 's|/etc/ssh/moduli|$(sysconfdir)/moduli|g' \ -e 's|/etc/ssh/sshrc|$(sysconfdir)/sshrc|g' \ -e 's|/usr/X11R6/bin/xauth|$(XAUTH_PATH)|g' \ -e 's|/var/empty|$(PRIVSEP_PATH)|g' \ -e 's|/usr/bin:/bin:/usr/sbin:/sbin|@user_path@|g' FIXPATHSCMD = $(SED) $(PATHSUBS) FIXALGORITHMSCMD= $(SHELL) $(srcdir)/fixalgorithms $(SED) \ @UNSUPPORTED_ALGORITHMS@ all: $(CONFIGFILES) $(MANPAGES) $(TARGETS) $(LIBSSH_OBJS): Makefile.in config.h $(SSHOBJS): Makefile.in config.h $(SSHDOBJS): Makefile.in config.h .c.o: $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ LIBCOMPAT=openbsd-compat/libopenbsd-compat.a $(LIBCOMPAT): always (cd openbsd-compat && $(MAKE)) always: libssh.a: $(LIBSSH_OBJS) $(AR) rv $@ $(LIBSSH_OBJS) $(RANLIB) $@ ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(GSSLIBS) $(CHANNELLIBS) sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) $(CHANNELLIBS) scp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SCP_OBJS) $(LD) -o $@ $(SCP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHADD_OBJS) $(LD) -o $@ $(SSHADD_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHAGENT_OBJS) $(LD) -o $@ $(SSHAGENT_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYGEN_OBJS) $(LD) -o $@ $(SSHKEYGEN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSIGN_OBJS) $(LD) -o $@ $(SSHKEYSIGN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(P11HELPER_OBJS) $(LD) -o $@ $(P11HELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS) ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(SKHELPER_OBJS) $(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) $(CHANNELLIBS) ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(CHANNELLIBS) sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTPSERVER_OBJS) $(LD) -o $@ $(SFTPSERVER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(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 $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS) $(MANPAGES): $(MANPAGES_IN) if test "$(MANTYPE)" = "cat"; then \ manpage=$(srcdir)/`echo $@ | sed 's/\.[1-9]\.out$$/\.0/'`; \ else \ manpage=$(srcdir)/`echo $@ | sed 's/\.out$$//'`; \ fi; \ if test "$(MANTYPE)" = "man"; then \ $(FIXPATHSCMD) $${manpage} | $(FIXALGORITHMSCMD) | \ $(AWK) -f $(srcdir)/mdoc2man.awk > $@; \ else \ $(FIXPATHSCMD) $${manpage} | $(FIXALGORITHMSCMD) > $@; \ fi $(CONFIGFILES): $(CONFIGFILES_IN) conffile=`echo $@ | sed 's/.out$$//'`; \ $(FIXPATHSCMD) $(srcdir)/$${conffile} > $@ # fake rule to stop make trying to compile moduli.o into a binary "moduli.o" moduli: echo clean: regressclean rm -f *.o *.lo *.a $(TARGETS) logintest config.cache config.log rm -f *.out core survey rm -f regress/check-perm$(EXEEXT) rm -f regress/mkdtemp$(EXEEXT) rm -f regress/unittests/test_helper/*.a rm -f regress/unittests/test_helper/*.o rm -f regress/unittests/authopt/*.o rm -f regress/unittests/authopt/test_authopt$(EXEEXT) rm -f regress/unittests/bitmap/*.o rm -f regress/unittests/bitmap/test_bitmap$(EXEEXT) rm -f regress/unittests/conversion/*.o rm -f regress/unittests/conversion/test_conversion$(EXEEXT) rm -f regress/unittests/hostkeys/*.o rm -f regress/unittests/hostkeys/test_hostkeys$(EXEEXT) rm -f regress/unittests/kex/*.o rm -f regress/unittests/kex/test_kex$(EXEEXT) rm -f regress/unittests/match/*.o rm -f regress/unittests/match/test_match$(EXEEXT) rm -f regress/unittests/misc/*.o rm -f regress/unittests/misc/test_misc$(EXEEXT) rm -f regress/unittests/sshbuf/*.o rm -f regress/unittests/sshbuf/test_sshbuf$(EXEEXT) rm -f regress/unittests/sshkey/*.o rm -f regress/unittests/sshkey/test_sshkey$(EXEEXT) rm -f regress/unittests/sshsig/*.o rm -f regress/unittests/sshsig/test_sshsig$(EXEEXT) rm -f regress/unittests/utf8/*.o rm -f regress/unittests/utf8/test_utf8$(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 rm -f *.o *.a $(TARGETS) logintest config.cache config.log rm -f *.out core opensshd.init openssh.xml rm -f Makefile buildpkg.sh config.h config.status rm -f survey.sh openbsd-compat/regress/Makefile *~ rm -rf autom4te.cache rm -f regress/check-perm rm -f regress/mkdtemp rm -f regress/unittests/test_helper/*.a rm -f regress/unittests/test_helper/*.o rm -f regress/unittests/authopt/*.o rm -f regress/unittests/authopt/test_authopt rm -f regress/unittests/bitmap/*.o rm -f regress/unittests/bitmap/test_bitmap rm -f regress/unittests/conversion/*.o rm -f regress/unittests/conversion/test_conversion rm -f regress/unittests/hostkeys/*.o rm -f regress/unittests/hostkeys/test_hostkeys rm -f regress/unittests/kex/*.o rm -f regress/unittests/kex/test_kex rm -f regress/unittests/match/*.o rm -f regress/unittests/match/test_match rm -f regress/unittests/misc/*.o rm -f regress/unittests/misc/test_misc rm -f regress/unittests/sshbuf/*.o rm -f regress/unittests/sshbuf/test_sshbuf rm -f regress/unittests/sshkey/*.o rm -f regress/unittests/sshkey/test_sshkey rm -f regress/unittests/sshsig/*.o rm -f regress/unittests/sshsig/test_sshsig rm -f regress/unittests/utf8/*.o rm -f regress/unittests/utf8/test_utf8 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) distclean) if test -d pkg ; then \ rm -fr pkg ; \ fi veryclean: distclean rm -f configure config.h.in *.0 cleandir: veryclean mrproper: veryclean realclean: veryclean catman-do: @for f in $(MANPAGES_IN) ; do \ base=`echo $$f | sed 's/\..*$$//'` ; \ echo "$$f -> $$base.0" ; \ $(MANFMT) $$f | cat -v | sed -e 's/.\^H//g' \ >$$base.0 ; \ done depend: depend-rebuild rm -f .depend.bak depend-rebuild: 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 cmp .depend .depend.bak || (echo .depend stale && exit 1) distprep: catman-do depend-check $(AUTORECONF) -rm -rf autom4te.cache .depend.bak install: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf host-key check-config install-nokeys: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf install-nosysconf: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files check-config: -$(DESTDIR)$(sbindir)/sshd -t -f $(DESTDIR)$(sysconfdir)/sshd_config install-files: $(MKDIR_P) $(DESTDIR)$(bindir) $(MKDIR_P) $(DESTDIR)$(sbindir) $(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)1 $(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)5 $(MKDIR_P) $(DESTDIR)$(mandir)/$(mansubdir)8 $(MKDIR_P) $(DESTDIR)$(libexecdir) $(MKDIR_P) -m 0755 $(DESTDIR)$(PRIVSEP_PATH) $(INSTALL) -m 0755 $(STRIP_OPT) ssh$(EXEEXT) $(DESTDIR)$(bindir)/ssh$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) scp$(EXEEXT) $(DESTDIR)$(bindir)/scp$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-add$(EXEEXT) $(DESTDIR)$(bindir)/ssh-add$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-agent$(EXEEXT) $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT) $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) 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 $(INSTALL) -m 644 scp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 $(INSTALL) -m 644 ssh-add.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 $(INSTALL) -m 644 ssh-agent.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1 $(INSTALL) -m 644 ssh-keygen.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1 $(INSTALL) -m 644 ssh-keyscan.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1 $(INSTALL) -m 644 moduli.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/moduli.5 $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5 $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5 $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1 $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 $(INSTALL) -m 644 ssh-sk-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8 install-sysconf: $(MKDIR_P) $(DESTDIR)$(sysconfdir) @if [ ! -f $(DESTDIR)$(sysconfdir)/ssh_config ]; then \ $(INSTALL) -m 644 ssh_config.out $(DESTDIR)$(sysconfdir)/ssh_config; \ else \ echo "$(DESTDIR)$(sysconfdir)/ssh_config already exists, install will not overwrite"; \ fi @if [ ! -f $(DESTDIR)$(sysconfdir)/sshd_config ]; then \ $(INSTALL) -m 644 sshd_config.out $(DESTDIR)$(sysconfdir)/sshd_config; \ else \ echo "$(DESTDIR)$(sysconfdir)/sshd_config already exists, install will not overwrite"; \ fi @if [ ! -f $(DESTDIR)$(sysconfdir)/moduli ]; then \ if [ -f $(DESTDIR)$(sysconfdir)/primes ]; then \ echo "moving $(DESTDIR)$(sysconfdir)/primes to $(DESTDIR)$(sysconfdir)/moduli"; \ mv "$(DESTDIR)$(sysconfdir)/primes" "$(DESTDIR)$(sysconfdir)/moduli"; \ else \ $(INSTALL) -m 644 moduli.out $(DESTDIR)$(sysconfdir)/moduli; \ fi ; \ else \ echo "$(DESTDIR)$(sysconfdir)/moduli already exists, install will not overwrite"; \ fi host-key: ssh-keygen$(EXEEXT) @if [ -z "$(DESTDIR)" ] ; then \ ./ssh-keygen -A; \ fi host-key-force: ssh-keygen$(EXEEXT) ssh$(EXEEXT) ./ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N "" ./ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N "" ./ssh-keygen -t ed25519 -f $(DESTDIR)$(sysconfdir)/ssh_host_ed25519_key -N "" if ./ssh -Q key | grep ecdsa >/dev/null ; then \ ./ssh-keygen -t ecdsa -f $(DESTDIR)$(sysconfdir)/ssh_host_ecdsa_key -N ""; \ fi uninstallall: uninstall -rm -f $(DESTDIR)$(sysconfdir)/ssh_config -rm -f $(DESTDIR)$(sysconfdir)/sshd_config -rmdir $(DESTDIR)$(sysconfdir) -rmdir $(DESTDIR)$(bindir) -rmdir $(DESTDIR)$(sbindir) -rmdir $(DESTDIR)$(mandir)/$(mansubdir)1 -rmdir $(DESTDIR)$(mandir)/$(mansubdir)8 -rmdir $(DESTDIR)$(mandir) -rmdir $(DESTDIR)$(libexecdir) uninstall: -rm -f $(DESTDIR)$(bindir)/ssh$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/scp$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/ssh-add$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/ssh-agent$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT) -rm -f $(DESTDIR)$(bindir)/sftp$(EXEEXT) -rm -f $(DESTDIR)$(sbindir)/sshd$(EXEEXT) -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) -rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) -rm -f $(DESTDIR)$(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 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-agent.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keygen.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8 regress-prep: $(MKDIR_P) `pwd`/regress/unittests/test_helper $(MKDIR_P) `pwd`/regress/unittests/authopt $(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/misc $(MKDIR_P) `pwd`/regress/unittests/sshbuf $(MKDIR_P) `pwd`/regress/unittests/sshkey $(MKDIR_P) `pwd`/regress/unittests/sshsig $(MKDIR_P) `pwd`/regress/unittests/utf8 $(MKDIR_P) `pwd`/regress/misc/sk-dummy [ -f `pwd`/regress/Makefile ] || \ ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile REGRESSLIBS=libssh.a $(LIBCOMPAT) TESTLIBS=$(LIBS) $(CHANNELLIBS) regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/modpipe.c \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) regress/timestamp$(EXEEXT): $(srcdir)/regress/timestamp.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/timestamp.c \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) regress/setuid-allowed$(EXEEXT): $(srcdir)/regress/setuid-allowed.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/setuid-allowed.c \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) regress/netcat$(EXEEXT): $(srcdir)/regress/netcat.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/netcat.c \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) regress/check-perm$(EXEEXT): $(srcdir)/regress/check-perm.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/check-perm.c \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) regress/mkdtemp$(EXEEXT): $(srcdir)/regress/mkdtemp.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/mkdtemp.c \ $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_HELPER_OBJS=\ regress/unittests/test_helper/test_helper.o \ regress/unittests/test_helper/fuzz.o regress/unittests/test_helper/libtest_helper.a: ${UNITTESTS_TEST_HELPER_OBJS} $(AR) rv $@ $(UNITTESTS_TEST_HELPER_OBJS) $(RANLIB) $@ UNITTESTS_TEST_SSHBUF_OBJS=\ regress/unittests/sshbuf/tests.o \ regress/unittests/sshbuf/test_sshbuf.o \ regress/unittests/sshbuf/test_sshbuf_getput_basic.o \ regress/unittests/sshbuf/test_sshbuf_getput_crypto.o \ regress/unittests/sshbuf/test_sshbuf_misc.o \ regress/unittests/sshbuf/test_sshbuf_fuzz.o \ regress/unittests/sshbuf/test_sshbuf_getput_fuzz.o \ regress/unittests/sshbuf/test_sshbuf_fixed.o regress/unittests/sshbuf/test_sshbuf$(EXEEXT): ${UNITTESTS_TEST_SSHBUF_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHBUF_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_SSHKEY_OBJS=\ regress/unittests/sshkey/test_fuzz.o \ regress/unittests/sshkey/tests.o \ regress/unittests/sshkey/common.o \ regress/unittests/sshkey/test_file.o \ regress/unittests/sshkey/test_sshkey.o \ $(SKOBJS) regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHKEY_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) 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 $(TESTLIBS) UNITTESTS_TEST_BITMAP_OBJS=\ regress/unittests/bitmap/tests.o regress/unittests/bitmap/test_bitmap$(EXEEXT): ${UNITTESTS_TEST_BITMAP_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_BITMAP_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_AUTHOPT_OBJS=\ regress/unittests/authopt/tests.o \ auth-options.o \ $(SKOBJS) regress/unittests/authopt/test_authopt$(EXEEXT): \ ${UNITTESTS_TEST_AUTHOPT_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_AUTHOPT_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_CONVERSION_OBJS=\ regress/unittests/conversion/tests.o regress/unittests/conversion/test_conversion$(EXEEXT): \ ${UNITTESTS_TEST_CONVERSION_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_CONVERSION_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_KEX_OBJS=\ regress/unittests/kex/tests.o \ regress/unittests/kex/test_kex.o \ regress/unittests/kex/test_proposal.o \ $(SKOBJS) regress/unittests/kex/test_kex$(EXEEXT): ${UNITTESTS_TEST_KEX_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_KEX_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_HOSTKEYS_OBJS=\ regress/unittests/hostkeys/tests.o \ regress/unittests/hostkeys/test_iterate.o \ $(SKOBJS) regress/unittests/hostkeys/test_hostkeys$(EXEEXT): \ ${UNITTESTS_TEST_HOSTKEYS_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_HOSTKEYS_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_MATCH_OBJS=\ regress/unittests/match/tests.o regress/unittests/match/test_match$(EXEEXT): \ ${UNITTESTS_TEST_MATCH_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_MATCH_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_MISC_OBJS=\ regress/unittests/misc/tests.o \ regress/unittests/misc/test_parse.o \ regress/unittests/misc/test_expand.o \ regress/unittests/misc/test_convtime.o \ regress/unittests/misc/test_argv.o \ regress/unittests/misc/test_strdelim.o \ regress/unittests/misc/test_hpdelim.o \ regress/unittests/misc/test_ptimeout.o regress/unittests/misc/test_misc$(EXEEXT): \ ${UNITTESTS_TEST_MISC_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_MISC_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) UNITTESTS_TEST_UTF8_OBJS=\ regress/unittests/utf8/tests.o regress/unittests/utf8/test_utf8$(EXEEXT): \ ${UNITTESTS_TEST_UTF8_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_UTF8_OBJS) \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) # 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 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) $(PICFLAG) -shared -o $@ $(SK_DUMMY_OBJS) \ -L. -Lopenbsd-compat -lopenbsd-compat $(LDFLAGS_NOPIE) $(TESTLIBS) regress-binaries: regress-prep $(LIBCOMPAT) \ regress/modpipe$(EXEEXT) \ regress/timestamp$(EXEEXT) \ regress/setuid-allowed$(EXEEXT) \ regress/netcat$(EXEEXT) \ regress/check-perm$(EXEEXT) \ regress/mkdtemp$(EXEEXT) \ $(SK_DUMMY_LIBRARY) regress-unit-binaries: regress-prep $(REGRESSLIBS) \ regress/unittests/authopt/test_authopt$(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/misc/test_misc$(EXEEXT) \ regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \ regress/unittests/sshkey/test_sshkey$(EXEEXT) \ regress/unittests/sshsig/test_sshsig$(EXEEXT) \ regress/unittests/utf8/test_utf8$(EXEEXT) -tests: file-tests t-exec interop-tests unit +tests: file-tests t-exec interop-tests extra-tests unit echo all tests passed unit: regress-unit-binaries cd $(srcdir)/regress || exit $$?; \ $(MAKE) \ .CURDIR="$(abs_top_srcdir)/regress" \ .OBJDIR="$(BUILDDIR)/regress" \ OBJ="$(BUILDDIR)/regress" \ $@ && echo $@ tests passed -interop-tests t-exec file-tests: regress-prep regress-binaries $(TARGETS) +interop-tests t-exec file-tests extra-tests: regress-prep regress-binaries $(TARGETS) cd $(srcdir)/regress || exit $$?; \ EGREP='@EGREP@' \ OPENSSL_BIN='@OPENSSL_BIN@' \ $(MAKE) \ .CURDIR="$(abs_top_srcdir)/regress" \ .OBJDIR="$(BUILDDIR)/regress" \ BUILDDIR="$(BUILDDIR)" \ OBJ="$(BUILDDIR)/regress" \ PATH="$(BUILDDIR):$${PATH}" \ TEST_ENV=MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \ TEST_MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \ 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_MODULI_FILE="$(abs_top_srcdir)/moduli" \ - TEST_SSH_PLINK="plink" \ - TEST_SSH_PUTTYGEN="puttygen" \ - TEST_SSH_CONCH="conch" \ + TEST_SSH_PLINK="@PLINK@" \ + TEST_SSH_PUTTYGEN="@PUTTYGEN@" \ + TEST_SSH_CONCH="@CONCH@" \ + TEST_SSH_DROPBEAR="@DROPBEAR@" \ + TEST_SSH_DROPBEARKEY="@DROPBEARKEY@" \ + TEST_SSH_DROPBEARCONVERT="@DROPBEARCONVERT@" \ + TEST_SSH_DBCLIENT="@DBCLIENT@" \ TEST_SSH_IPV6="@TEST_SSH_IPV6@" \ TEST_SSH_UTF8="@TEST_SSH_UTF8@" \ TEST_SHELL="$(TEST_SHELL)" \ EXEEXT="$(EXEEXT)" \ $@ && echo all $@ passed compat-tests: $(LIBCOMPAT) (cd openbsd-compat/regress && $(MAKE)) regressclean: if [ -f regress/Makefile ] && [ -r regress/Makefile ]; then \ (cd regress && $(MAKE) clean) \ fi survey: survey.sh ssh @$(SHELL) ./survey.sh > survey @echo 'The survey results have been placed in the file "survey" in the' @echo 'current directory. Please review the file then send with' @echo '"make send-survey".' send-survey: survey mail portable-survey@mindrot.org Miscellania - This version of OpenSSH is based upon code retrieved from the OpenBSD CVS repository which in turn was based on the last free sample implementation released by Tatu Ylonen. References - [0] https://www.openssh.com/ [1] https://man.openbsd.org/style.9 diff --git a/crypto/openssh/auth2.c b/crypto/openssh/auth2.c index d2a420d0deec..859dd25c5325 100644 --- a/crypto/openssh/auth2.c +++ b/crypto/openssh/auth2.c @@ -1,854 +1,860 @@ -/* $OpenBSD: auth2.c,v 1.167 2023/08/28 09:48:11 djm Exp $ */ +/* $OpenBSD: auth2.c,v 1.168 2023/12/18 14:45:49 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include "stdlib.h" #include "atomicio.h" #include "xmalloc.h" #include "ssh2.h" #include "packet.h" #include "log.h" #include "sshbuf.h" #include "misc.h" #include "servconf.h" #include "sshkey.h" #include "hostfile.h" #include "auth.h" #include "dispatch.h" #include "pathnames.h" #include "ssherr.h" #include "blacklist_client.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "monitor_wrap.h" #include "digest.h" +#include "kex.h" /* import */ extern ServerOptions options; extern struct sshbuf *loginmsg; /* methods */ extern Authmethod method_none; extern Authmethod method_pubkey; extern Authmethod method_passwd; extern Authmethod method_kbdint; extern Authmethod method_hostbased; #ifdef GSSAPI extern Authmethod method_gssapi; #endif Authmethod *authmethods[] = { &method_none, &method_pubkey, #ifdef GSSAPI &method_gssapi, #endif &method_passwd, &method_kbdint, &method_hostbased, NULL }; /* protocol */ static int input_service_request(int, u_int32_t, struct ssh *); static int input_userauth_request(int, u_int32_t, struct ssh *); /* helper */ static Authmethod *authmethod_byname(const char *); static Authmethod *authmethod_lookup(Authctxt *, const char *); static char *authmethods_get(Authctxt *authctxt); #define MATCH_NONE 0 /* method or submethod mismatch */ #define MATCH_METHOD 1 /* method matches (no submethod specified) */ #define MATCH_BOTH 2 /* method and submethod match */ #define MATCH_PARTIAL 3 /* method matches, submethod can't be checked */ static int list_starts_with(const char *, const char *, const char *); char * auth2_read_banner(void) { struct stat st; char *banner = NULL; size_t len, n; int fd; if ((fd = open(options.banner, O_RDONLY)) == -1) return (NULL); if (fstat(fd, &st) == -1) { close(fd); return (NULL); } if (st.st_size <= 0 || st.st_size > 1*1024*1024) { close(fd); return (NULL); } len = (size_t)st.st_size; /* truncate */ banner = xmalloc(len + 1); n = atomicio(read, fd, banner, len); close(fd); if (n != len) { free(banner); return (NULL); } banner[n] = '\0'; return (banner); } static void userauth_send_banner(struct ssh *ssh, const char *msg) { int r; if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_BANNER)) != 0 || (r = sshpkt_put_cstring(ssh, msg)) != 0 || (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language, unused */ (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); debug("%s: sent", __func__); } static void userauth_banner(struct ssh *ssh) { char *banner = NULL; if (options.banner == NULL) return; if ((banner = PRIVSEP(auth2_read_banner())) == NULL) goto done; userauth_send_banner(ssh, banner); done: free(banner); } /* * loop until authctxt->success == TRUE */ void do_authentication2(struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; ssh_dispatch_init(ssh, &dispatch_protocol_error); + if (ssh->kex->ext_info_c) + ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_input_ext_info); ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_REQUEST, &input_service_request); ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt->success); ssh->authctxt = NULL; } static int input_service_request(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; char *service = NULL; int r, acceptit = 0; if ((r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; if (authctxt == NULL) fatal("input_service_request: no authctxt"); if (strcmp(service, "ssh-userauth") == 0) { if (!authctxt->success) { acceptit = 1; /* now we can handle user-auth requests */ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); } } /* XXX all other service requests are denied */ if (acceptit) { if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_ACCEPT)) != 0 || (r = sshpkt_put_cstring(ssh, service)) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) goto out; } else { debug("bad service request %s", service); ssh_packet_disconnect(ssh, "bad service request %s", service); } + ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &dispatch_protocol_error); r = 0; out: free(service); return r; } #define MIN_FAIL_DELAY_SECONDS 0.005 #define MAX_FAIL_DELAY_SECONDS 5.0 static double user_specific_delay(const char *user) { char b[512]; size_t len = ssh_digest_bytes(SSH_DIGEST_SHA512); u_char *hash = xmalloc(len); double delay; (void)snprintf(b, sizeof b, "%llu%s", (unsigned long long)options.timing_secret, user); if (ssh_digest_memory(SSH_DIGEST_SHA512, b, strlen(b), hash, len) != 0) fatal_f("ssh_digest_memory"); /* 0-4.2 ms of delay */ delay = (double)PEEK_U32(hash) / 1000 / 1000 / 1000 / 1000; freezero(hash, len); debug3_f("user specific delay %0.3lfms", delay/1000); return MIN_FAIL_DELAY_SECONDS + delay; } static void ensure_minimum_time_since(double start, double seconds) { struct timespec ts; double elapsed = monotime_double() - start, req = seconds, remain; if (elapsed > MAX_FAIL_DELAY_SECONDS) { debug3_f("elapsed %0.3lfms exceeded the max delay " "requested %0.3lfms)", elapsed*1000, req*1000); return; } /* if we've already passed the requested time, scale up */ while ((remain = seconds - elapsed) < 0.0) seconds *= 2; ts.tv_sec = remain; ts.tv_nsec = (remain - ts.tv_sec) * 1000000000; debug3_f("elapsed %0.3lfms, delaying %0.3lfms (requested %0.3lfms)", elapsed*1000, remain*1000, req*1000); nanosleep(&ts, NULL); } static int input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; Authmethod *m = NULL; char *user = NULL, *service = NULL, *method = NULL, *style = NULL; int r, authenticated = 0; double tstart = monotime_double(); if (authctxt == NULL) fatal("input_userauth_request: no authctxt"); if ((r = sshpkt_get_cstring(ssh, &user, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &service, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &method, NULL)) != 0) goto out; debug("userauth-request for user %s service %s method %s", user, service, method); debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); if ((style = strchr(user, ':')) != NULL) *style++ = 0; if (authctxt->attempt >= 1024) auth_maxtries_exceeded(ssh); if (authctxt->attempt++ == 0) { /* setup auth context */ authctxt->pw = PRIVSEP(getpwnamallow(ssh, user)); authctxt->user = xstrdup(user); if (authctxt->pw && strcmp(service, "ssh-connection")==0) { authctxt->valid = 1; debug2_f("setting up authctxt for %s", user); } else { authctxt->valid = 0; /* Invalid user, fake password information */ authctxt->pw = fakepw(); #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(ssh, SSH_INVALID_USER)); #endif } #ifdef USE_PAM if (options.use_pam) PRIVSEP(start_pam(ssh)); #endif ssh_packet_set_log_preamble(ssh, "%suser %s", authctxt->valid ? "authenticating " : "invalid ", user); setproctitle("%s%s", authctxt->valid ? user : "unknown", use_privsep ? " [net]" : ""); authctxt->service = xstrdup(service); authctxt->style = style ? xstrdup(style) : NULL; if (use_privsep) mm_inform_authserv(service, style); userauth_banner(ssh); + if ((r = kex_server_update_ext_info(ssh)) != 0) + fatal_fr(r, "kex_server_update_ext_info failed"); if (auth2_setup_methods_lists(authctxt) != 0) ssh_packet_disconnect(ssh, "no authentication methods enabled"); } else if (strcmp(user, authctxt->user) != 0 || strcmp(service, authctxt->service) != 0) { ssh_packet_disconnect(ssh, "Change of username or service " "not allowed: (%s,%s) -> (%s,%s)", authctxt->user, authctxt->service, user, service); } /* reset state */ auth2_challenge_stop(ssh); #ifdef GSSAPI /* XXX move to auth2_gssapi_stop() */ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); #endif auth2_authctxt_reset_info(authctxt); authctxt->postponed = 0; authctxt->server_caused_failure = 0; /* try to authenticate user */ m = authmethod_lookup(authctxt, method); if (m != NULL && authctxt->failures < options.max_authtries) { debug2("input_userauth_request: try method %s", method); authenticated = m->userauth(ssh, method); } if (!authctxt->authenticated && strcmp(method, "none") != 0) ensure_minimum_time_since(tstart, user_specific_delay(authctxt->user)); userauth_finish(ssh, authenticated, method, NULL); r = 0; out: free(service); free(user); free(method); return r; } void userauth_finish(struct ssh *ssh, int authenticated, const char *packet_method, const char *submethod) { Authctxt *authctxt = ssh->authctxt; Authmethod *m = NULL; const char *method = packet_method; char *methods; int r, partial = 0; if (authenticated) { if (!authctxt->valid) { fatal("INTERNAL ERROR: authenticated invalid user %s", authctxt->user); } if (authctxt->postponed) fatal("INTERNAL ERROR: authenticated and postponed"); /* prefer primary authmethod name to possible synonym */ if ((m = authmethod_byname(method)) == NULL) fatal("INTERNAL ERROR: bad method %s", method); method = m->name; } /* Special handling for root */ if (authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed(ssh, method)) { authenticated = 0; #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(ssh, SSH_LOGIN_ROOT_DENIED)); #endif } if (authenticated && options.num_auth_methods != 0) { if (!auth2_update_methods_lists(authctxt, method, submethod)) { authenticated = 0; partial = 1; } } /* Log before sending the reply */ auth_log(ssh, authenticated, partial, method, submethod); /* Update information exposed to session */ if (authenticated || partial) auth2_update_session_info(authctxt, method, submethod); if (authctxt->postponed) return; #ifdef USE_PAM if (options.use_pam && authenticated) { int r, success = 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 (!success) { fatal("Access denied for user %s by PAM account " "configuration", authctxt->user); } } #endif if (authenticated == 1) { /* turn off userauth */ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_SUCCESS)) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "send success packet"); /* now we can break out */ authctxt->success = 1; ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); } else { /* Allow initial try of "none" auth without failure penalty */ if (!partial && !authctxt->server_caused_failure && (authctxt->attempt > 1 || strcmp(method, "none") != 0)) { authctxt->failures++; BLACKLIST_NOTIFY(ssh, BLACKLIST_AUTH_FAIL, "ssh"); } if (authctxt->failures >= options.max_authtries) { #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(ssh, SSH_LOGIN_EXCEED_MAXTRIES)); #endif auth_maxtries_exceeded(ssh); } methods = authmethods_get(authctxt); 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_fr(r, "send failure packet"); free(methods); } } /* * Checks whether method is allowed by at least one AuthenticationMethods * methods list. Returns 1 if allowed, or no methods lists configured. * 0 otherwise. */ int auth2_method_allowed(Authctxt *authctxt, const char *method, const char *submethod) { u_int i; /* * NB. authctxt->num_auth_methods might be zero as a result of * auth2_setup_methods_lists(), so check the configuration. */ if (options.num_auth_methods == 0) return 1; for (i = 0; i < authctxt->num_auth_methods; i++) { if (list_starts_with(authctxt->auth_methods[i], method, submethod) != MATCH_NONE) return 1; } return 0; } static char * authmethods_get(Authctxt *authctxt) { struct sshbuf *b; char *list; int i, r; if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); for (i = 0; authmethods[i] != NULL; i++) { if (strcmp(authmethods[i]->name, "none") == 0) continue; if (authmethods[i]->enabled == NULL || *(authmethods[i]->enabled) == 0) continue; if (!auth2_method_allowed(authctxt, authmethods[i]->name, NULL)) continue; if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) ? "," : "", authmethods[i]->name)) != 0) fatal_fr(r, "buffer error"); } if ((list = sshbuf_dup_string(b)) == NULL) fatal_f("sshbuf_dup_string failed"); sshbuf_free(b); return list; } static Authmethod * authmethod_byname(const char *name) { int i; if (name == NULL) fatal_f("NULL authentication method name"); for (i = 0; authmethods[i] != NULL; i++) { if (strcmp(name, authmethods[i]->name) == 0 || (authmethods[i]->synonym != NULL && strcmp(name, authmethods[i]->synonym) == 0)) return authmethods[i]; } debug_f("unrecognized authentication method name: %s", name); return NULL; } static Authmethod * authmethod_lookup(Authctxt *authctxt, const char *name) { Authmethod *method; if ((method = authmethod_byname(name)) == NULL) return NULL; if (method->enabled == NULL || *(method->enabled) == 0) { debug3_f("method %s not enabled", name); return NULL; } if (!auth2_method_allowed(authctxt, method->name, NULL)) { debug3_f("method %s not allowed " "by AuthenticationMethods", name); return NULL; } return method; } /* * Check a comma-separated list of methods for validity. Is need_enable is * non-zero, then also require that the methods are enabled. * Returns 0 on success or -1 if the methods list is invalid. */ int auth2_methods_valid(const char *_methods, int need_enable) { char *methods, *omethods, *method, *p; u_int i, found; int ret = -1; if (*_methods == '\0') { error("empty authentication method list"); return -1; } omethods = methods = xstrdup(_methods); while ((method = strsep(&methods, ",")) != NULL) { for (found = i = 0; !found && authmethods[i] != NULL; i++) { if ((p = strchr(method, ':')) != NULL) *p = '\0'; if (strcmp(method, authmethods[i]->name) != 0) continue; if (need_enable) { if (authmethods[i]->enabled == NULL || *(authmethods[i]->enabled) == 0) { error("Disabled method \"%s\" in " "AuthenticationMethods list \"%s\"", method, _methods); goto out; } } found = 1; break; } if (!found) { error("Unknown authentication method \"%s\" in list", method); goto out; } } ret = 0; out: free(omethods); return ret; } /* * Prune the AuthenticationMethods supplied in the configuration, removing * any methods lists that include disabled methods. Note that this might * leave authctxt->num_auth_methods == 0, even when multiple required auth * has been requested. For this reason, all tests for whether multiple is * enabled should consult options.num_auth_methods directly. */ int auth2_setup_methods_lists(Authctxt *authctxt) { u_int i; /* First, normalise away the "any" pseudo-method */ if (options.num_auth_methods == 1 && strcmp(options.auth_methods[0], "any") == 0) { free(options.auth_methods[0]); options.auth_methods[0] = NULL; options.num_auth_methods = 0; } if (options.num_auth_methods == 0) return 0; debug3_f("checking methods"); authctxt->auth_methods = xcalloc(options.num_auth_methods, sizeof(*authctxt->auth_methods)); authctxt->num_auth_methods = 0; for (i = 0; i < options.num_auth_methods; i++) { if (auth2_methods_valid(options.auth_methods[i], 1) != 0) { logit("Authentication methods list \"%s\" contains " "disabled method, skipping", options.auth_methods[i]); continue; } debug("authentication methods list %d: %s", authctxt->num_auth_methods, options.auth_methods[i]); authctxt->auth_methods[authctxt->num_auth_methods++] = xstrdup(options.auth_methods[i]); } if (authctxt->num_auth_methods == 0) { error("No AuthenticationMethods left after eliminating " "disabled methods"); return -1; } return 0; } static int list_starts_with(const char *methods, const char *method, const char *submethod) { size_t l = strlen(method); int match; const char *p; if (strncmp(methods, method, l) != 0) return MATCH_NONE; p = methods + l; match = MATCH_METHOD; if (*p == ':') { if (!submethod) return MATCH_PARTIAL; l = strlen(submethod); p += 1; if (strncmp(submethod, p, l)) return MATCH_NONE; p += l; match = MATCH_BOTH; } if (*p != ',' && *p != '\0') return MATCH_NONE; return match; } /* * Remove method from the start of a comma-separated list of methods. * Returns 0 if the list of methods did not start with that method or 1 * if it did. */ static int remove_method(char **methods, const char *method, const char *submethod) { char *omethods = *methods, *p; size_t l = strlen(method); int match; match = list_starts_with(omethods, method, submethod); if (match != MATCH_METHOD && match != MATCH_BOTH) return 0; p = omethods + l; if (submethod && match == MATCH_BOTH) p += 1 + strlen(submethod); /* include colon */ if (*p == ',') p++; *methods = xstrdup(p); free(omethods); return 1; } /* * Called after successful authentication. Will remove the successful method * from the start of each list in which it occurs. If it was the last method * in any list, then authentication is deemed successful. * Returns 1 if the method completed any authentication list or 0 otherwise. */ int auth2_update_methods_lists(Authctxt *authctxt, const char *method, const char *submethod) { u_int i, found = 0; debug3_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)) continue; found = 1; if (*authctxt->auth_methods[i] == '\0') { debug2("authentication methods list %d complete", i); return 1; } debug3("authentication methods list %d remaining: \"%s\"", i, authctxt->auth_methods[i]); } /* This should not happen, but would be bad if it did */ if (!found) fatal_f("method not in AuthenticationMethods"); return 0; } /* Reset method-specific information */ void auth2_authctxt_reset_info(Authctxt *authctxt) { sshkey_free(authctxt->auth_method_key); free(authctxt->auth_method_info); authctxt->auth_method_key = NULL; authctxt->auth_method_info = NULL; } /* Record auth method-specific information for logs */ void auth2_record_info(Authctxt *authctxt, const char *fmt, ...) { va_list ap; int i; free(authctxt->auth_method_info); authctxt->auth_method_info = NULL; va_start(ap, fmt); i = vasprintf(&authctxt->auth_method_info, fmt, ap); va_end(ap); if (i == -1) fatal_f("vasprintf failed"); } /* * Records a public key used in authentication. This is used for logging * and to ensure that the same key is not subsequently accepted again for * multiple authentication. */ void auth2_record_key(Authctxt *authctxt, int authenticated, const struct sshkey *key) { struct sshkey **tmp, *dup; int r; if ((r = sshkey_from_private(key, &dup)) != 0) fatal_fr(r, "copy key"); sshkey_free(authctxt->auth_method_key); authctxt->auth_method_key = dup; if (!authenticated) return; /* If authenticated, make sure we don't accept this key again */ if ((r = sshkey_from_private(key, &dup)) != 0) fatal_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_f("reallocarray failed"); authctxt->prev_keys = tmp; authctxt->prev_keys[authctxt->nprev_keys] = dup; authctxt->nprev_keys++; } /* Checks whether a key has already been previously used for authentication */ int auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key) { u_int i; char *fp; for (i = 0; i < authctxt->nprev_keys; i++) { if (sshkey_equal_public(key, authctxt->prev_keys[i])) { fp = sshkey_fingerprint(authctxt->prev_keys[i], options.fingerprint_hash, SSH_FP_DEFAULT); debug3_f("key already used: %s %s", sshkey_type(authctxt->prev_keys[i]), fp == NULL ? "UNKNOWN" : fp); free(fp); return 1; } } return 0; } /* * Updates authctxt->session_info with details of authentication. Should be * whenever an authentication method succeeds. */ void auth2_update_session_info(Authctxt *authctxt, const char *method, const char *submethod) { int r; if (authctxt->session_info == NULL) { if ((authctxt->session_info = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); } /* Append method[/submethod] */ if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s", method, submethod == NULL ? "" : "/", submethod == NULL ? "" : submethod)) != 0) 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_fr(r, "append key"); } if (authctxt->auth_method_info != NULL) { /* Ensure no ambiguity here */ if (strchr(authctxt->auth_method_info, '\n') != NULL) 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_fr(r, "append method info"); } } if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0) fatal_fr(r, "append"); } diff --git a/crypto/openssh/authfd.c b/crypto/openssh/authfd.c index 25a363664cd2..e04ad0cf2d02 100644 --- a/crypto/openssh/authfd.c +++ b/crypto/openssh/authfd.c @@ -1,754 +1,778 @@ -/* $OpenBSD: authfd.c,v 1.133 2023/03/09 21:06:24 jcs Exp $ */ +/* $OpenBSD: authfd.c,v 1.134 2023/12/18 14:46:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Functions for connecting the local authentication agent. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * SSH2 implementation, * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include "xmalloc.h" #include "ssh.h" #include "sshbuf.h" #include "sshkey.h" #include "authfd.h" #include "cipher.h" #include "log.h" #include "atomicio.h" #include "misc.h" #include "ssherr.h" #define MAX_AGENT_IDENTITIES 2048 /* Max keys in agent reply */ #define MAX_AGENT_REPLY_LEN (256 * 1024) /* Max bytes in agent reply */ /* macro to check for "agent failure" message */ #define agent_failed(x) \ ((x == SSH_AGENT_FAILURE) || \ (x == SSH_COM_AGENT2_FAILURE) || \ (x == SSH2_AGENT_FAILURE)) /* Convert success/failure response from agent to a err.h status */ static int decode_reply(u_char type) { if (agent_failed(type)) return SSH_ERR_AGENT_FAILURE; else if (type == SSH_AGENT_SUCCESS) return 0; else return SSH_ERR_INVALID_FORMAT; } /* * 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_path(const char *authsocket, int *fdp) { int sock, oerrno; struct sockaddr_un sunaddr; debug3_f("path '%s'", authsocket); memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_UNIX; strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) return SSH_ERR_SYSTEM_ERROR; /* close on exec */ if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1 || connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { oerrno = errno; close(sock); errno = oerrno; return SSH_ERR_SYSTEM_ERROR; } if (fdp != NULL) *fdp = sock; else close(sock); 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) { int r; size_t l, len; char buf[1024]; /* Get the length of the message, and format it in the buffer. */ len = sshbuf_len(request); POKE_U32(buf, len); /* Send the length and then the packet to the agent. */ if (atomicio(vwrite, sock, buf, 4) != 4 || atomicio(vwrite, sock, sshbuf_mutable_ptr(request), sshbuf_len(request)) != sshbuf_len(request)) return SSH_ERR_AGENT_COMMUNICATION; /* * Wait for response from the agent. First read the length of the * response packet. */ if (atomicio(read, sock, buf, 4) != 4) return SSH_ERR_AGENT_COMMUNICATION; /* Extract the length, and check it for sanity. */ len = PEEK_U32(buf); if (len > MAX_AGENT_REPLY_LEN) return SSH_ERR_INVALID_FORMAT; /* Read the rest of the response in to the buffer. */ sshbuf_reset(reply); while (len > 0) { l = len; if (l > sizeof(buf)) l = sizeof(buf); if (atomicio(read, sock, buf, l) != l) return SSH_ERR_AGENT_COMMUNICATION; if ((r = sshbuf_put(reply, buf, l)) != 0) return r; len -= l; } return 0; } /* 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 * ssh_get_authentication_socket(). */ void ssh_close_authentication_socket(int sock) { if (getenv(SSH_AUTHSOCKET_ENV_NAME)) close(sock); } /* Lock/unlock agent */ int ssh_lock_agent(int sock, int lock, const char *password) { int r; u_char type = lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK; struct sshbuf *msg; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, type)) != 0 || (r = sshbuf_put_cstring(msg, password)) != 0 || (r = ssh_request_reply_decode(sock, msg)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(msg); return r; } static int deserialise_identity2(struct sshbuf *ids, struct sshkey **keyp, char **commentp) { int r; char *comment = NULL; const u_char *blob; size_t blen; if ((r = sshbuf_get_string_direct(ids, &blob, &blen)) != 0 || (r = sshbuf_get_cstring(ids, &comment, NULL)) != 0) goto out; if ((r = sshkey_from_blob(blob, blen, keyp)) != 0) goto out; if (commentp != NULL) { *commentp = comment; comment = NULL; } r = 0; out: free(comment); return r; } /* * Fetch list of identities held by the agent. */ int ssh_fetch_identitylist(int sock, struct ssh_identitylist **idlp) { u_char type; u_int32_t num, i; struct sshbuf *msg; struct ssh_identitylist *idl = NULL; int r; /* * Send a message to the agent requesting for a list of the * identities it can represent. */ if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_REQUEST_IDENTITIES)) != 0) goto out; if ((r = ssh_request_reply(sock, msg, msg)) != 0) goto out; /* Get message type, and verify that we got a proper answer. */ if ((r = sshbuf_get_u8(msg, &type)) != 0) goto out; if (agent_failed(type)) { r = SSH_ERR_AGENT_FAILURE; goto out; } else if (type != SSH2_AGENT_IDENTITIES_ANSWER) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* Get the number of entries in the response and check it for sanity. */ if ((r = sshbuf_get_u32(msg, &num)) != 0) goto out; if (num > MAX_AGENT_IDENTITIES) { r = SSH_ERR_INVALID_FORMAT; goto out; } if (num == 0) { r = SSH_ERR_AGENT_NO_IDENTITIES; goto out; } /* Deserialise the response into a list of keys/comments */ if ((idl = calloc(1, sizeof(*idl))) == NULL || (idl->keys = calloc(num, sizeof(*idl->keys))) == NULL || (idl->comments = calloc(num, sizeof(*idl->comments))) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } for (i = 0; i < num;) { if ((r = deserialise_identity2(msg, &(idl->keys[i]), &(idl->comments[i]))) != 0) { if (r == SSH_ERR_KEY_TYPE_UNKNOWN) { /* Gracefully skip unknown key types */ num--; continue; } else goto out; } i++; } idl->nkeys = num; *idlp = idl; idl = NULL; r = 0; out: sshbuf_free(msg); if (idl != NULL) ssh_free_identitylist(idl); return r; } void ssh_free_identitylist(struct ssh_identitylist *idl) { size_t i; if (idl == NULL) return; for (i = 0; i < idl->nkeys; i++) { if (idl->keys != NULL) sshkey_free(idl->keys[i]); if (idl->comments != NULL) free(idl->comments[i]); } free(idl->keys); free(idl->comments); free(idl); } /* * Check if the ssh agent has a given key. * Returns 0 if found, or a negative SSH_ERR_* error code on failure. */ int 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) { return r; } for (i = 0; i < idlist->nkeys; i++) { if (sshkey_equal_public(idlist->keys[i], key)) { ret = 0; break; } } ssh_free_identitylist(idlist); return ret; } /* * Sends a challenge (typically from a server via ssh(1)) to the agent, * and waits for a response from the agent. * Returns true (non-zero) if the agent gave the correct answer, zero * otherwise. */ /* encode signature algorithm in flag bits, so we can keep the msg format */ static u_int agent_encode_alg(const struct sshkey *key, const char *alg) { if (alg != NULL && sshkey_type_plain(key->type) == KEY_RSA) { if (strcmp(alg, "rsa-sha2-256") == 0 || strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0) return SSH_AGENT_RSA_SHA2_256; if (strcmp(alg, "rsa-sha2-512") == 0 || strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0) return SSH_AGENT_RSA_SHA2_512; } return 0; } /* ask agent to sign data, returns err.h code on error, 0 on success */ int ssh_agent_sign(int sock, const struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg, u_int compat) { struct sshbuf *msg; u_char *sig = NULL, type = 0; size_t len = 0; u_int flags = 0; int r = SSH_ERR_INTERNAL_ERROR; *sigp = NULL; *lenp = 0; if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; flags |= agent_encode_alg(key, alg); if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || (r = sshkey_puts(key, msg)) != 0 || (r = sshbuf_put_string(msg, data, datalen)) != 0 || (r = sshbuf_put_u32(msg, flags)) != 0) goto out; if ((r = ssh_request_reply(sock, msg, msg)) != 0) goto out; if ((r = sshbuf_get_u8(msg, &type)) != 0) goto out; if (agent_failed(type)) { r = SSH_ERR_AGENT_FAILURE; goto out; } else if (type != SSH2_AGENT_SIGN_RESPONSE) { r = SSH_ERR_INVALID_FORMAT; goto out; } if ((r = sshbuf_get_string(msg, &sig, &len)) != 0) goto out; /* Check what we actually got back from the agent. */ if ((r = sshkey_check_sigtype(sig, len, alg)) != 0) goto out; /* success */ *sigp = sig; *lenp = len; sig = NULL; len = 0; r = 0; out: freezero(sig, len); sshbuf_free(msg); return r; } /* Encode key for a message to the agent. */ static int encode_dest_constraint_hop(struct sshbuf *m, const struct dest_constraint_hop *dch) { struct sshbuf *b; u_int i; int r; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_cstring(b, dch->user)) != 0 || (r = sshbuf_put_cstring(b, dch->hostname)) != 0 || (r = sshbuf_put_string(b, NULL, 0)) != 0) /* reserved */ goto out; for (i = 0; i < dch->nkeys; i++) { if ((r = sshkey_puts(dch->keys[i], b)) != 0 || (r = sshbuf_put_u8(b, dch->key_is_ca[i] != 0)) != 0) goto out; } if ((r = sshbuf_put_stringb(m, b)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(b); return r; } static int encode_dest_constraint(struct sshbuf *m, const struct dest_constraint *dc) { struct sshbuf *b; int r; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = encode_dest_constraint_hop(b, &dc->from)) != 0 || (r = encode_dest_constraint_hop(b, &dc->to)) != 0 || (r = sshbuf_put_string(b, NULL, 0)) != 0) /* reserved */ goto out; if ((r = sshbuf_put_stringb(m, b)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(b); return r; } static int -encode_constraints(struct sshbuf *m, u_int life, u_int confirm, u_int maxsign, - const char *provider, struct dest_constraint **dest_constraints, - size_t ndest_constraints) +encode_constraints(struct sshbuf *m, u_int life, u_int confirm, + u_int maxsign, const char *provider, + struct dest_constraint **dest_constraints, size_t ndest_constraints, + int cert_only, struct sshkey **certs, size_t ncerts) { int r; struct sshbuf *b = NULL; size_t i; if (life != 0) { if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_LIFETIME)) != 0 || (r = sshbuf_put_u32(m, life)) != 0) goto out; } if (confirm != 0) { if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_CONFIRM)) != 0) goto out; } if (maxsign != 0) { if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_MAXSIGN)) != 0 || (r = sshbuf_put_u32(m, maxsign)) != 0) goto out; } 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; } if (dest_constraints != NULL && ndest_constraints > 0) { if ((b = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } for (i = 0; i < ndest_constraints; i++) { if ((r = encode_dest_constraint(b, dest_constraints[i])) != 0) goto out; } if ((r = sshbuf_put_u8(m, SSH_AGENT_CONSTRAIN_EXTENSION)) != 0 || (r = sshbuf_put_cstring(m, "restrict-destination-v00@openssh.com")) != 0 || (r = sshbuf_put_stringb(m, b)) != 0) goto out; + sshbuf_free(b); + b = NULL; + } + if (ncerts != 0) { + if ((b = sshbuf_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + for (i = 0; i < ncerts; i++) { + if ((r = sshkey_puts(certs[i], b)) != 0) + goto out; + } + if ((r = sshbuf_put_u8(m, + SSH_AGENT_CONSTRAIN_EXTENSION)) != 0 || + (r = sshbuf_put_cstring(m, + "associated-certs-v00@openssh.com")) != 0 || + (r = sshbuf_put_u8(m, cert_only != 0)) != 0 || + (r = sshbuf_put_stringb(m, b)) != 0) + goto out; + sshbuf_free(b); + b = NULL; } r = 0; out: sshbuf_free(b); return r; } /* * Adds an identity to the authentication server. * This call is intended only for use by ssh-add(1) and like applications. */ int ssh_add_identity_constrained(int sock, struct sshkey *key, const char *comment, u_int life, u_int confirm, u_int maxsign, const char *provider, struct dest_constraint **dest_constraints, size_t ndest_constraints) { struct sshbuf *msg; int r, constrained = (life || confirm || maxsign || provider || dest_constraints); u_char type; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; switch (key->type) { #ifdef WITH_OPENSSL case KEY_RSA: case KEY_RSA_CERT: case KEY_DSA: case KEY_DSA_CERT: case KEY_ECDSA: case KEY_ECDSA_CERT: 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 ? SSH2_AGENTC_ADD_ID_CONSTRAINED : SSH2_AGENTC_ADD_IDENTITY; if ((r = sshbuf_put_u8(msg, type)) != 0 || (r = sshkey_private_serialize_maxsign(key, msg, maxsign, 0)) != 0 || (r = sshbuf_put_cstring(msg, comment)) != 0) goto out; break; default: r = SSH_ERR_INVALID_ARGUMENT; goto out; } if (constrained && (r = encode_constraints(msg, life, confirm, maxsign, - provider, dest_constraints, ndest_constraints)) != 0) + provider, dest_constraints, ndest_constraints, 0, NULL, 0)) != 0) goto out; if ((r = ssh_request_reply_decode(sock, msg)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(msg); return r; } /* * Removes an identity from the authentication server. * This call is intended only for use by ssh-add(1) and like applications. */ int ssh_remove_identity(int sock, const struct sshkey *key) { struct sshbuf *msg; int r; u_char *blob = NULL; size_t blen; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if (key->type != KEY_UNSPEC) { if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) goto out; if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_REMOVE_IDENTITY)) != 0 || (r = sshbuf_put_string(msg, blob, blen)) != 0) goto out; } else { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if ((r = ssh_request_reply_decode(sock, msg)) != 0) goto out; /* success */ r = 0; out: if (blob != NULL) freezero(blob, blen); sshbuf_free(msg); return r; } /* * Add/remove an token-based identity from the authentication server. * This call is intended only for use by ssh-add(1) and like applications. */ int ssh_update_card(int sock, int add, const char *reader_id, const char *pin, u_int life, u_int confirm, - struct dest_constraint **dest_constraints, size_t ndest_constraints) + struct dest_constraint **dest_constraints, size_t ndest_constraints, + int cert_only, struct sshkey **certs, size_t ncerts) { struct sshbuf *msg; - int r, constrained = (life || confirm || dest_constraints); + int r, constrained = (life || confirm || dest_constraints || certs); u_char type; if (add) { type = constrained ? SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED : SSH_AGENTC_ADD_SMARTCARD_KEY; } else type = SSH_AGENTC_REMOVE_SMARTCARD_KEY; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, type)) != 0 || (r = sshbuf_put_cstring(msg, reader_id)) != 0 || (r = sshbuf_put_cstring(msg, pin)) != 0) goto out; if (constrained && (r = encode_constraints(msg, life, confirm, 0, NULL, - dest_constraints, ndest_constraints)) != 0) + dest_constraints, ndest_constraints, + cert_only, certs, ncerts)) != 0) goto out; if ((r = ssh_request_reply_decode(sock, msg)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(msg); return r; } /* * Removes all identities from the agent. * This call is intended only for use by ssh-add(1) and like applications. * * This supports the SSH protocol 1 message to because, when clearing all * keys from an agent, we generally want to clear both protocol v1 and v2 * keys. */ int ssh_remove_all_identities(int sock, int version) { struct sshbuf *msg; u_char type = (version == 1) ? SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES : SSH2_AGENTC_REMOVE_ALL_IDENTITIES; int r; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, type)) != 0) goto out; if ((r = ssh_request_reply_decode(sock, msg)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(msg); return r; } /* Binds a session ID to a hostkey via the initial KEX signature. */ int ssh_agent_bind_hostkey(int sock, const struct sshkey *key, const struct sshbuf *session_id, const struct sshbuf *signature, int forwarding) { struct sshbuf *msg; int r; if (key == NULL || session_id == NULL || signature == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((msg = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_u8(msg, SSH_AGENTC_EXTENSION)) != 0 || (r = sshbuf_put_cstring(msg, "session-bind@openssh.com")) != 0 || (r = sshkey_puts(key, msg)) != 0 || (r = sshbuf_put_stringb(msg, session_id)) != 0 || (r = sshbuf_put_stringb(msg, signature)) != 0 || (r = sshbuf_put_u8(msg, forwarding ? 1 : 0)) != 0) goto out; if ((r = ssh_request_reply_decode(sock, msg)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(msg); return r; } diff --git a/crypto/openssh/authfd.h b/crypto/openssh/authfd.h index 7a1c0ddff980..c1e4b405ce29 100644 --- a/crypto/openssh/authfd.h +++ b/crypto/openssh/authfd.h @@ -1,121 +1,122 @@ -/* $OpenBSD: authfd.h,v 1.51 2021/12/19 22:10:24 djm Exp $ */ +/* $OpenBSD: authfd.h,v 1.52 2023/12/18 14:46:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Functions to interface with the SSH_AUTHENTICATION_FD socket. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #ifndef AUTHFD_H #define AUTHFD_H struct sshbuf; struct sshkey; /* List of identities returned by ssh_fetch_identitylist() */ struct ssh_identitylist { size_t nkeys; struct sshkey **keys; char **comments; }; /* Key destination restrictions */ struct dest_constraint_hop { char *user; /* wildcards allowed */ char *hostname; /* used to matching cert principals and for display */ int is_ca; u_int nkeys; /* number of entries in *both* 'keys' and 'key_is_ca' */ struct sshkey **keys; int *key_is_ca; }; struct dest_constraint { struct dest_constraint_hop from; struct dest_constraint_hop to; }; 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, const char *provider, struct dest_constraint **dest_constraints, size_t ndest_constraints); 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, struct dest_constraint **dest_constraints, - size_t ndest_constraints); + size_t ndest_constraints, + int cert_only, struct sshkey **certs, size_t ncerts); int ssh_remove_all_identities(int sock, int version); int ssh_agent_sign(int sock, const struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, const char *alg, u_int compat); int ssh_agent_bind_hostkey(int sock, const struct sshkey *key, const struct sshbuf *session_id, const struct sshbuf *signature, int forwarding); /* Messages for the authentication agent connection. */ #define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1 #define SSH_AGENT_RSA_IDENTITIES_ANSWER 2 #define SSH_AGENTC_RSA_CHALLENGE 3 #define SSH_AGENT_RSA_RESPONSE 4 #define SSH_AGENT_FAILURE 5 #define SSH_AGENT_SUCCESS 6 #define SSH_AGENTC_ADD_RSA_IDENTITY 7 #define SSH_AGENTC_REMOVE_RSA_IDENTITY 8 #define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 /* private OpenSSH extensions for SSH2 */ #define SSH2_AGENTC_REQUEST_IDENTITIES 11 #define SSH2_AGENT_IDENTITIES_ANSWER 12 #define SSH2_AGENTC_SIGN_REQUEST 13 #define SSH2_AGENT_SIGN_RESPONSE 14 #define SSH2_AGENTC_ADD_IDENTITY 17 #define SSH2_AGENTC_REMOVE_IDENTITY 18 #define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19 /* smartcard */ #define SSH_AGENTC_ADD_SMARTCARD_KEY 20 #define SSH_AGENTC_REMOVE_SMARTCARD_KEY 21 /* lock/unlock the agent */ #define SSH_AGENTC_LOCK 22 #define SSH_AGENTC_UNLOCK 23 /* add key with constraints */ #define SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24 #define SSH2_AGENTC_ADD_ID_CONSTRAINED 25 #define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26 /* generic extension mechanism */ #define SSH_AGENTC_EXTENSION 27 #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 /* additional error code for ssh.com's ssh-agent2 */ #define SSH_COM_AGENT2_FAILURE 102 #define SSH_AGENT_OLD_SIGNATURE 0x01 #define SSH_AGENT_RSA_SHA2_256 0x02 #define SSH_AGENT_RSA_SHA2_512 0x04 #endif /* AUTHFD_H */ diff --git a/crypto/openssh/channels.c b/crypto/openssh/channels.c index 598ff322a175..20f31dadd782 100644 --- a/crypto/openssh/channels.c +++ b/crypto/openssh/channels.c @@ -1,5291 +1,5317 @@ -/* $OpenBSD: channels.c,v 1.433 2023/09/04 00:01:46 djm Exp $ */ +/* $OpenBSD: channels.c,v 1.435 2023/12/18 14:47:20 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * This file contains functions for generic socket connection forwarding. * There is also code for initiating connection forwarding for X11 connections, * arbitrary tcp/ip connections, and the authentication agent connection. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * SSH2 support added by Markus Friedl. * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 1999 Dug Song. All rights reserved. * Copyright (c) 1999 Theo de Raadt. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #include #include #include #ifdef HAVE_POLL_H #include #endif #include #ifdef HAVE_STDINT_H # include #endif #include #include #include #include #include #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "ssherr.h" #include "sshbuf.h" #include "packet.h" #include "log.h" #include "misc.h" #include "channels.h" #include "compat.h" #include "canohost.h" #include "sshkey.h" #include "authfd.h" #include "pathnames.h" #include "match.h" /* XXX remove once we're satisfied there's no lurking bugs */ /* #define DEBUG_CHANNEL_POLL 1 */ /* -- agent forwarding */ #define NUM_SOCKS 10 /* -- tcp forwarding */ /* special-case port number meaning allow any port */ #define FWD_PERMIT_ANY_PORT 0 /* special-case wildcard meaning allow any host */ #define FWD_PERMIT_ANY_HOST "*" /* -- X11 forwarding */ /* Maximum number of fake X11 displays to try. */ #define MAX_DISPLAYS 1000 /* Per-channel callback for pre/post IO actions */ typedef void chan_fn(struct ssh *, Channel *c); /* * Data structure for storing which hosts are permitted for forward requests. * The local sides of any remote forwards are stored in this array to prevent * a corrupt remote server from accessing arbitrary TCP/IP ports on our local * network (which might be behind a firewall). */ /* XXX: streamlocal wants a path instead of host:port */ /* Overload host_to_connect; we could just make this match Forward */ /* XXX - can we use listen_host instead of listen_path? */ struct permission { char *host_to_connect; /* Connect to 'host'. */ int port_to_connect; /* Connect to 'port'. */ char *listen_host; /* Remote side should listen address. */ char *listen_path; /* Remote side should listen path. */ int listen_port; /* Remote side should listen port. */ Channel *downstream; /* Downstream mux*/ }; /* * Stores the forwarding permission state for a single direction (local or * remote). */ struct permission_set { /* * List of all local permitted host/port pairs to allow for the * user. */ u_int num_permitted_user; struct permission *permitted_user; /* * List of all permitted host/port pairs to allow for the admin. */ u_int num_permitted_admin; struct permission *permitted_admin; /* * If this is true, all opens/listens are permitted. This is the * case on the server on which we have to trust the client anyway, * and the user could do anything after logging in. */ int all_permitted; }; /* Used to record timeouts per channel type */ struct ssh_channel_timeout { char *type_pattern; int timeout_secs; }; /* Master structure for channels state */ struct ssh_channels { /* * Pointer to an array containing all allocated channels. The array * is dynamically extended as needed. */ Channel **channels; /* * Size of the channel array. All slots of the array must always be * initialized (at least the type field); unused slots set to NULL */ u_int channels_alloc; /* * 'channel_pre*' are called just before IO to add any bits * relevant to channels in the c->io_want bitmasks. * * 'channel_post*': perform any appropriate operations for * channels which have c->io_ready events pending. */ chan_fn **channel_pre; chan_fn **channel_post; /* -- tcp forwarding */ struct permission_set local_perms; struct permission_set remote_perms; /* -- X11 forwarding */ /* Saved X11 local (client) display. */ char *x11_saved_display; /* Saved X11 authentication protocol name. */ char *x11_saved_proto; /* Saved X11 authentication data. This is the real data. */ char *x11_saved_data; u_int x11_saved_data_len; /* Deadline after which all X11 connections are refused */ time_t x11_refuse_time; /* * Fake X11 authentication data. This is what the server will be * sending us; we should replace any occurrences of this by the * real data. */ u_char *x11_fake_data; u_int x11_fake_data_len; /* AF_UNSPEC or AF_INET or AF_INET6 */ int IPv4or6; /* Channel timeouts by type */ struct ssh_channel_timeout *timeouts; size_t ntimeouts; }; /* helper */ static void port_open_helper(struct ssh *ssh, Channel *c, char *rtype); static const char *channel_rfwd_bind_host(const char *listen_host); /* non-blocking connect helpers */ static int connect_next(struct channel_connect *); static void channel_connect_ctx_free(struct channel_connect *); static Channel *rdynamic_connect_prepare(struct ssh *, char *, char *); static int rdynamic_connect_finish(struct ssh *, Channel *); /* Setup helper */ static void channel_handler_init(struct ssh_channels *sc); /* -- channel core */ void channel_init_channels(struct ssh *ssh) { struct ssh_channels *sc; if ((sc = calloc(1, sizeof(*sc))) == NULL) fatal_f("allocation failed"); sc->channels_alloc = 10; sc->channels = xcalloc(sc->channels_alloc, sizeof(*sc->channels)); sc->IPv4or6 = AF_UNSPEC; channel_handler_init(sc); ssh->chanctxt = sc; } Channel * channel_by_id(struct ssh *ssh, int id) { Channel *c; if (id < 0 || (u_int)id >= ssh->chanctxt->channels_alloc) { logit_f("%d: bad id", id); return NULL; } c = ssh->chanctxt->channels[id]; if (c == NULL) { logit_f("%d: bad id: channel free", id); return NULL; } return c; } Channel * channel_by_remote_id(struct ssh *ssh, u_int remote_id) { Channel *c; u_int i; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { c = ssh->chanctxt->channels[i]; if (c != NULL && c->have_remote_id && c->remote_id == remote_id) return c; } return NULL; } /* * Returns the channel if it is allowed to receive protocol messages. * Private channels, like listening sockets, may not receive messages. */ Channel * channel_lookup(struct ssh *ssh, int id) { Channel *c; if ((c = channel_by_id(ssh, id)) == NULL) return NULL; switch (c->type) { case SSH_CHANNEL_X11_OPEN: case SSH_CHANNEL_LARVAL: case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_DYNAMIC: case SSH_CHANNEL_RDYNAMIC_OPEN: case SSH_CHANNEL_RDYNAMIC_FINISH: case SSH_CHANNEL_OPENING: case SSH_CHANNEL_OPEN: case SSH_CHANNEL_ABANDONED: case SSH_CHANNEL_MUX_PROXY: return c; } logit("Non-public channel %d, type %d.", id, c->type); return NULL; } /* * Add a timeout for open channels whose c->ctype (or c->xctype if it is set) * match type_pattern. */ void channel_add_timeout(struct ssh *ssh, const char *type_pattern, int timeout_secs) { struct ssh_channels *sc = ssh->chanctxt; debug2_f("channel type \"%s\" timeout %d seconds", type_pattern, timeout_secs); sc->timeouts = xrecallocarray(sc->timeouts, sc->ntimeouts, sc->ntimeouts + 1, sizeof(*sc->timeouts)); sc->timeouts[sc->ntimeouts].type_pattern = xstrdup(type_pattern); sc->timeouts[sc->ntimeouts].timeout_secs = timeout_secs; sc->ntimeouts++; } /* Clears all previously-added channel timeouts */ void channel_clear_timeouts(struct ssh *ssh) { struct ssh_channels *sc = ssh->chanctxt; size_t i; debug3_f("clearing"); for (i = 0; i < sc->ntimeouts; i++) free(sc->timeouts[i].type_pattern); free(sc->timeouts); sc->timeouts = NULL; sc->ntimeouts = 0; } static int lookup_timeout(struct ssh *ssh, const char *type) { struct ssh_channels *sc = ssh->chanctxt; size_t i; for (i = 0; i < sc->ntimeouts; i++) { if (match_pattern(type, sc->timeouts[i].type_pattern)) return sc->timeouts[i].timeout_secs; } return 0; } /* * Sets "extended type" of a channel; used by session layer to add additional * information about channel types (e.g. shell, login, subsystem) that can then * be used to select timeouts. * Will reset c->inactive_deadline as a side-effect. */ void channel_set_xtype(struct ssh *ssh, int id, const char *xctype) { Channel *c; if ((c = channel_by_id(ssh, id)) == NULL) fatal_f("missing channel %d", id); if (c->xctype != NULL) free(c->xctype); c->xctype = xstrdup(xctype); /* Type has changed, so look up inactivity deadline again */ c->inactive_deadline = lookup_timeout(ssh, c->xctype); debug2_f("labeled channel %d as %s (inactive timeout %u)", id, xctype, c->inactive_deadline); } /* * Register filedescriptors for a channel, used when allocating a channel or * when the channel consumer/producer is ready, e.g. shell exec'd */ static void channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd, int extusage, int nonblock, int is_tty) { int val; if (rfd != -1) (void)fcntl(rfd, F_SETFD, FD_CLOEXEC); if (wfd != -1 && wfd != rfd) (void)fcntl(wfd, F_SETFD, FD_CLOEXEC); if (efd != -1 && efd != rfd && efd != wfd) (void)fcntl(efd, F_SETFD, FD_CLOEXEC); c->rfd = rfd; c->wfd = wfd; c->sock = (rfd == wfd) ? rfd : -1; c->efd = efd; c->extended_usage = extusage; if ((c->isatty = is_tty) != 0) debug2("channel %d: rfd %d isatty", c->self, c->rfd); #ifdef _AIX /* XXX: Later AIX versions can't push as much data to tty */ c->wfd_isatty = is_tty || isatty(c->wfd); #endif /* enable nonblocking mode */ c->restore_block = 0; if (nonblock == CHANNEL_NONBLOCK_STDIO) { /* * Special handling for stdio file descriptors: do not set * non-blocking mode if they are TTYs. Otherwise prepare to * restore their blocking state on exit to avoid interfering * with other programs that follow. */ if (rfd != -1 && !isatty(rfd) && (val = fcntl(rfd, F_GETFL)) != -1 && !(val & O_NONBLOCK)) { c->restore_flags[0] = val; c->restore_block |= CHANNEL_RESTORE_RFD; set_nonblock(rfd); } if (wfd != -1 && !isatty(wfd) && (val = fcntl(wfd, F_GETFL)) != -1 && !(val & O_NONBLOCK)) { c->restore_flags[1] = val; c->restore_block |= CHANNEL_RESTORE_WFD; set_nonblock(wfd); } if (efd != -1 && !isatty(efd) && (val = fcntl(efd, F_GETFL)) != -1 && !(val & O_NONBLOCK)) { c->restore_flags[2] = val; c->restore_block |= CHANNEL_RESTORE_EFD; set_nonblock(efd); } } else if (nonblock) { if (rfd != -1) set_nonblock(rfd); if (wfd != -1) set_nonblock(wfd); if (efd != -1) set_nonblock(efd); } } /* * Allocate a new channel object and set its type and socket. */ Channel * channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd, u_int window, u_int maxpack, int extusage, const char *remote_name, int nonblock) { struct ssh_channels *sc = ssh->chanctxt; u_int i, found = 0; Channel *c; int r; /* Try to find a free slot where to put the new channel. */ for (i = 0; i < sc->channels_alloc; i++) { if (sc->channels[i] == NULL) { /* Found a free slot. */ found = i; break; } } if (i >= sc->channels_alloc) { /* * There are no free slots. Take last+1 slot and expand * the array. */ found = sc->channels_alloc; if (sc->channels_alloc > CHANNELS_MAX_CHANNELS) fatal_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; debug2("channel: expanding %d", sc->channels_alloc); } /* Initialize and return new channel. */ c = sc->channels[found] = xcalloc(1, sizeof(Channel)); if ((c->input = sshbuf_new()) == NULL || (c->output = sshbuf_new()) == NULL || (c->extended = sshbuf_new()) == NULL) fatal_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); c->self = found; c->type = type; c->ctype = ctype; c->local_window = window; c->local_window_max = window; c->local_maxpacket = maxpack; c->remote_name = xstrdup(remote_name); c->ctl_chan = -1; c->delayed = 1; /* prevent call to channel_post handler */ c->inactive_deadline = lookup_timeout(ssh, c->ctype); TAILQ_INIT(&c->status_confirms); debug("channel %d: new %s [%s] (inactive timeout: %u)", found, c->ctype, remote_name, c->inactive_deadline); return c; } int channel_close_fd(struct ssh *ssh, Channel *c, int *fdp) { int ret, fd = *fdp; if (fd == -1) return 0; /* restore blocking */ if (*fdp == c->rfd && (c->restore_block & CHANNEL_RESTORE_RFD) != 0) (void)fcntl(*fdp, F_SETFL, c->restore_flags[0]); else if (*fdp == c->wfd && (c->restore_block & CHANNEL_RESTORE_WFD) != 0) (void)fcntl(*fdp, F_SETFL, c->restore_flags[1]); else if (*fdp == c->efd && (c->restore_block & CHANNEL_RESTORE_EFD) != 0) (void)fcntl(*fdp, F_SETFL, c->restore_flags[2]); if (*fdp == c->rfd) { c->io_want &= ~SSH_CHAN_IO_RFD; c->io_ready &= ~SSH_CHAN_IO_RFD; c->rfd = -1; c->pfds[0] = -1; } if (*fdp == c->wfd) { c->io_want &= ~SSH_CHAN_IO_WFD; c->io_ready &= ~SSH_CHAN_IO_WFD; c->wfd = -1; c->pfds[1] = -1; } if (*fdp == c->efd) { c->io_want &= ~SSH_CHAN_IO_EFD; c->io_ready &= ~SSH_CHAN_IO_EFD; c->efd = -1; c->pfds[2] = -1; } if (*fdp == c->sock) { c->io_want &= ~SSH_CHAN_IO_SOCK; c->io_ready &= ~SSH_CHAN_IO_SOCK; c->sock = -1; c->pfds[3] = -1; } ret = close(fd); *fdp = -1; /* probably redundant */ return ret; } /* Close all channel fd/socket. */ static void channel_close_fds(struct ssh *ssh, Channel *c) { int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd; channel_close_fd(ssh, c, &c->sock); if (rfd != sock) channel_close_fd(ssh, c, &c->rfd); if (wfd != sock && wfd != rfd) channel_close_fd(ssh, c, &c->wfd); if (efd != sock && efd != rfd && efd != wfd) channel_close_fd(ssh, c, &c->efd); } static void fwd_perm_clear(struct permission *perm) { free(perm->host_to_connect); free(perm->listen_host); free(perm->listen_path); memset(perm, 0, sizeof(*perm)); } /* Returns an printable name for the specified forwarding permission list */ static const char * fwd_ident(int who, int where) { if (who == FORWARD_ADM) { if (where == FORWARD_LOCAL) return "admin local"; else if (where == FORWARD_REMOTE) return "admin remote"; } else if (who == FORWARD_USER) { if (where == FORWARD_LOCAL) return "user local"; else if (where == FORWARD_REMOTE) return "user remote"; } fatal("Unknown forward permission list %d/%d", who, where); } /* Returns the forwarding permission list for the specified direction */ static struct permission_set * permission_set_get(struct ssh *ssh, int where) { struct ssh_channels *sc = ssh->chanctxt; switch (where) { case FORWARD_LOCAL: return &sc->local_perms; break; case FORWARD_REMOTE: return &sc->remote_perms; break; default: fatal_f("invalid forwarding direction %d", where); } } /* Returns pointers to the specified forwarding list and its element count */ static void permission_set_get_array(struct ssh *ssh, int who, int where, struct permission ***permpp, u_int **npermpp) { struct permission_set *pset = permission_set_get(ssh, where); switch (who) { case FORWARD_USER: *permpp = &pset->permitted_user; *npermpp = &pset->num_permitted_user; break; case FORWARD_ADM: *permpp = &pset->permitted_admin; *npermpp = &pset->num_permitted_admin; break; default: fatal_f("invalid forwarding client %d", who); } } /* Adds an entry to the specified forwarding list */ static int permission_set_add(struct ssh *ssh, int who, int where, const char *host_to_connect, int port_to_connect, const char *listen_host, const char *listen_path, int listen_port, Channel *downstream) { struct permission **permp; u_int n, *npermp; permission_set_get_array(ssh, who, where, &permp, &npermp); if (*npermp >= INT_MAX) fatal_f("%s overflow", fwd_ident(who, where)); *permp = xrecallocarray(*permp, *npermp, *npermp + 1, sizeof(**permp)); n = (*npermp)++; #define MAYBE_DUP(s) ((s == NULL) ? NULL : xstrdup(s)) (*permp)[n].host_to_connect = MAYBE_DUP(host_to_connect); (*permp)[n].port_to_connect = port_to_connect; (*permp)[n].listen_host = MAYBE_DUP(listen_host); (*permp)[n].listen_path = MAYBE_DUP(listen_path); (*permp)[n].listen_port = listen_port; (*permp)[n].downstream = downstream; #undef MAYBE_DUP return (int)n; } static void mux_remove_remote_forwardings(struct ssh *ssh, Channel *c) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->local_perms; struct permission *perm; int r; u_int i; for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (perm->downstream != c) continue; /* cancel on the server, since mux client is gone */ debug("channel %d: cleanup remote forward for %s:%u", c->self, perm->listen_host, perm->listen_port); if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "cancel-tcpip-forward")) != 0 || (r = sshpkt_put_u8(ssh, 0)) != 0 || (r = sshpkt_put_cstring(ssh, channel_rfwd_bind_host(perm->listen_host))) != 0 || (r = sshpkt_put_u32(ssh, perm->listen_port)) != 0 || (r = sshpkt_send(ssh)) != 0) { fatal_fr(r, "channel %i", c->self); } fwd_perm_clear(perm); /* unregister */ } } /* Free the channel and close its fd/socket. */ void channel_free(struct ssh *ssh, Channel *c) { struct ssh_channels *sc = ssh->chanctxt; char *s; u_int i, n; Channel *other; struct channel_confirm *cc; for (n = 0, i = 0; i < sc->channels_alloc; i++) { if ((other = sc->channels[i]) == NULL) continue; n++; /* detach from mux client and prepare for closing */ if (c->type == SSH_CHANNEL_MUX_CLIENT && other->type == SSH_CHANNEL_MUX_PROXY && other->mux_ctx == c) { other->mux_ctx = NULL; other->type = SSH_CHANNEL_OPEN; other->istate = CHAN_INPUT_CLOSED; other->ostate = CHAN_OUTPUT_CLOSED; } } debug("channel %d: free: %s, nchannels %u", c->self, c->remote_name ? c->remote_name : "???", n); if (c->type == SSH_CHANNEL_MUX_CLIENT) { mux_remove_remote_forwardings(ssh, c); free(c->mux_ctx); c->mux_ctx = NULL; } 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); debug3("channel %d: status: %s", c->self, s); free(s); } channel_close_fds(ssh, c); sshbuf_free(c->input); sshbuf_free(c->output); sshbuf_free(c->extended); c->input = c->output = c->extended = NULL; free(c->remote_name); c->remote_name = NULL; free(c->path); c->path = NULL; free(c->listening_addr); c->listening_addr = NULL; free(c->xctype); c->xctype = NULL; while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) { if (cc->abandon_cb != NULL) cc->abandon_cb(ssh, c, cc->ctx); TAILQ_REMOVE(&c->status_confirms, cc, entry); 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; freezero(c, sizeof(*c)); } void channel_free_all(struct ssh *ssh) { u_int i; struct ssh_channels *sc = ssh->chanctxt; for (i = 0; i < sc->channels_alloc; i++) if (sc->channels[i] != NULL) channel_free(ssh, sc->channels[i]); free(sc->channels); sc->channels = NULL; sc->channels_alloc = 0; free(sc->x11_saved_display); sc->x11_saved_display = NULL; free(sc->x11_saved_proto); sc->x11_saved_proto = NULL; free(sc->x11_saved_data); sc->x11_saved_data = NULL; sc->x11_saved_data_len = 0; free(sc->x11_fake_data); sc->x11_fake_data = NULL; sc->x11_fake_data_len = 0; } /* * Closes the sockets/fds of all channels. This is used to close extra file * descriptors after a fork. */ void channel_close_all(struct ssh *ssh) { u_int i; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) if (ssh->chanctxt->channels[i] != NULL) channel_close_fds(ssh, ssh->chanctxt->channels[i]); } /* * Stop listening to channels. */ void channel_stop_listening(struct ssh *ssh) { u_int i; Channel *c; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { c = ssh->chanctxt->channels[i]; if (c != NULL) { switch (c->type) { case SSH_CHANNEL_AUTH_SOCKET: case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_RPORT_LISTENER: case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_UNIX_LISTENER: case SSH_CHANNEL_RUNIX_LISTENER: channel_close_fd(ssh, c, &c->sock); channel_free(ssh, c); break; } } } } /* * Returns true if no channel has too much buffered data, and false if one or * more channel is overfull. */ int channel_not_very_much_buffered_data(struct ssh *ssh) { u_int i; u_int maxsize = ssh_packet_get_maxsize(ssh); Channel *c; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { c = ssh->chanctxt->channels[i]; if (c == NULL || c->type != SSH_CHANNEL_OPEN) continue; if (sshbuf_len(c->output) > maxsize) { debug2("channel %d: big output buffer %zu > %u", c->self, sshbuf_len(c->output), maxsize); return 0; } } return 1; } /* Returns true if any channel is still open. */ int channel_still_open(struct ssh *ssh) { u_int i; Channel *c; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { c = ssh->chanctxt->channels[i]; if (c == NULL) continue; switch (c->type) { case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_RPORT_LISTENER: case SSH_CHANNEL_MUX_LISTENER: case SSH_CHANNEL_CLOSED: case SSH_CHANNEL_AUTH_SOCKET: case SSH_CHANNEL_DYNAMIC: case SSH_CHANNEL_RDYNAMIC_OPEN: case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_ZOMBIE: case SSH_CHANNEL_ABANDONED: case SSH_CHANNEL_UNIX_LISTENER: case SSH_CHANNEL_RUNIX_LISTENER: continue; case SSH_CHANNEL_LARVAL: continue; case SSH_CHANNEL_OPENING: case SSH_CHANNEL_OPEN: case SSH_CHANNEL_RDYNAMIC_FINISH: case SSH_CHANNEL_X11_OPEN: case SSH_CHANNEL_MUX_CLIENT: case SSH_CHANNEL_MUX_PROXY: return 1; default: fatal_f("bad channel type %d", c->type); /* NOTREACHED */ } } return 0; } +/* Returns true if a channel with a TTY is open. */ +int +channel_tty_open(struct ssh *ssh) +{ + u_int i; + Channel *c; + + for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { + c = ssh->chanctxt->channels[i]; + if (c == NULL || c->type != SSH_CHANNEL_OPEN) + continue; + if (c->client_tty) + return 1; + } + return 0; +} + /* Returns the id of an open channel suitable for keepaliving */ int channel_find_open(struct ssh *ssh) { u_int i; Channel *c; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { c = ssh->chanctxt->channels[i]; if (c == NULL || !c->have_remote_id) continue; switch (c->type) { case SSH_CHANNEL_CLOSED: case SSH_CHANNEL_DYNAMIC: case SSH_CHANNEL_RDYNAMIC_OPEN: case SSH_CHANNEL_RDYNAMIC_FINISH: case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_RPORT_LISTENER: case SSH_CHANNEL_MUX_LISTENER: case SSH_CHANNEL_MUX_CLIENT: case SSH_CHANNEL_MUX_PROXY: case SSH_CHANNEL_OPENING: case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_ZOMBIE: case SSH_CHANNEL_ABANDONED: case SSH_CHANNEL_UNIX_LISTENER: case SSH_CHANNEL_RUNIX_LISTENER: continue; case SSH_CHANNEL_LARVAL: case SSH_CHANNEL_AUTH_SOCKET: case SSH_CHANNEL_OPEN: case SSH_CHANNEL_X11_OPEN: return i; default: fatal_f("bad channel type %d", c->type); /* NOTREACHED */ } } return -1; } /* Returns the state of the channel's extended usage flag */ const char * channel_format_extended_usage(const Channel *c) { if (c->efd == -1) return "closed"; switch (c->extended_usage) { case CHAN_EXTENDED_WRITE: return "write"; case CHAN_EXTENDED_READ: return "read"; case CHAN_EXTENDED_IGNORE: return "ignore"; default: return "UNKNOWN"; } } static char * channel_format_status(const Channel *c) { char *ret = NULL; xasprintf(&ret, "t%d [%s] %s%u i%u/%zu o%u/%zu e[%s]/%zu " "fd %d/%d/%d sock %d cc %d io 0x%02x/0x%02x", c->type, c->xctype != NULL ? c->xctype : c->ctype, c->have_remote_id ? "r" : "nr", c->remote_id, c->istate, sshbuf_len(c->input), c->ostate, sshbuf_len(c->output), channel_format_extended_usage(c), sshbuf_len(c->extended), c->rfd, c->wfd, c->efd, c->sock, c->ctl_chan, c->io_want, c->io_ready); return ret; } /* * Returns a message describing the currently open forwarded connections, * suitable for sending to the client. The message contains crlf pairs for * newlines. */ char * channel_open_message(struct ssh *ssh) { struct sshbuf *buf; Channel *c; u_int i; int r; char *cp, *ret; if ((buf = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_putf(buf, "The following connections are open:\r\n")) != 0) fatal_fr(r, "sshbuf_putf"); for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { c = ssh->chanctxt->channels[i]; if (c == NULL) continue; switch (c->type) { case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_RPORT_LISTENER: case SSH_CHANNEL_CLOSED: case SSH_CHANNEL_AUTH_SOCKET: case SSH_CHANNEL_ZOMBIE: case SSH_CHANNEL_ABANDONED: case SSH_CHANNEL_MUX_LISTENER: case SSH_CHANNEL_UNIX_LISTENER: case SSH_CHANNEL_RUNIX_LISTENER: continue; case SSH_CHANNEL_LARVAL: case SSH_CHANNEL_OPENING: case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_DYNAMIC: case SSH_CHANNEL_RDYNAMIC_OPEN: case SSH_CHANNEL_RDYNAMIC_FINISH: case SSH_CHANNEL_OPEN: case SSH_CHANNEL_X11_OPEN: case SSH_CHANNEL_MUX_PROXY: case SSH_CHANNEL_MUX_CLIENT: cp = channel_format_status(c); if ((r = sshbuf_putf(buf, " #%d %.300s (%s)\r\n", c->self, c->remote_name, cp)) != 0) { free(cp); fatal_fr(r, "sshbuf_putf"); } free(cp); continue; default: fatal_f("bad channel type %d", c->type); /* NOTREACHED */ } } if ((ret = sshbuf_dup_string(buf)) == NULL) fatal_f("sshbuf_dup_string"); sshbuf_free(buf); return ret; } static void open_preamble(struct ssh *ssh, const char *where, Channel *c, const char *type) { int r; if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN)) != 0 || (r = sshpkt_put_cstring(ssh, type)) != 0 || (r = sshpkt_put_u32(ssh, c->self)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) { fatal_r(r, "%s: channel %i: open", where, c->self); } } void channel_send_open(struct ssh *ssh, int id) { Channel *c = channel_lookup(ssh, id); int r; if (c == NULL) { logit("channel_send_open: %d: bad id", id); return; } debug2("channel %d: send open", id); open_preamble(ssh, __func__, c, c->ctype); if ((r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i", c->self); } void channel_request_start(struct ssh *ssh, int id, char *service, int wantconfirm) { Channel *c = channel_lookup(ssh, id); int r; if (c == NULL) { logit_f("%d: unknown channel id", id); return; } if (!c->have_remote_id) 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_fr(r, "channel %i", c->self); } } void channel_register_status_confirm(struct ssh *ssh, int id, channel_confirm_cb *cb, channel_confirm_abandon_cb *abandon_cb, void *ctx) { struct channel_confirm *cc; Channel *c; if ((c = channel_lookup(ssh, id)) == NULL) fatal_f("%d: bad id", id); cc = xcalloc(1, sizeof(*cc)); cc->cb = cb; cc->abandon_cb = abandon_cb; cc->ctx = ctx; TAILQ_INSERT_TAIL(&c->status_confirms, cc, entry); } void channel_register_open_confirm(struct ssh *ssh, int id, channel_open_fn *fn, void *ctx) { Channel *c = channel_lookup(ssh, id); if (c == NULL) { logit_f("%d: bad id", id); return; } c->open_confirm = fn; c->open_confirm_ctx = ctx; } void channel_register_cleanup(struct ssh *ssh, int id, channel_callback_fn *fn, int do_close) { Channel *c = channel_by_id(ssh, id); if (c == NULL) { logit_f("%d: bad id", id); return; } c->detach_user = fn; c->detach_close = do_close; } void channel_cancel_cleanup(struct ssh *ssh, int id) { Channel *c = channel_by_id(ssh, id); if (c == NULL) { logit_f("%d: bad id", id); return; } c->detach_user = NULL; c->detach_close = 0; } void channel_register_filter(struct ssh *ssh, int id, channel_infilter_fn *ifn, channel_outfilter_fn *ofn, channel_filter_cleanup_fn *cfn, void *ctx) { Channel *c = channel_lookup(ssh, id); if (c == NULL) { logit_f("%d: bad id", id); return; } c->input_filter = ifn; c->output_filter = ofn; c->filter_ctx = ctx; c->filter_cleanup = cfn; } void channel_set_fds(struct ssh *ssh, int id, int rfd, int wfd, int efd, int extusage, int nonblock, int is_tty, u_int window_max) { Channel *c = channel_lookup(ssh, id); int r; if (c == NULL || c->type != SSH_CHANNEL_LARVAL) fatal("channel_activate for non-larval channel %d.", id); if (!c->have_remote_id) fatal_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; c->lastused = monotime(); c->local_window = c->local_window_max = window_max; if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i", c->self); } static void channel_pre_listener(struct ssh *ssh, Channel *c) { c->io_want = SSH_CHAN_IO_SOCK_R; } static void channel_pre_connecting(struct ssh *ssh, Channel *c) { debug3("channel %d: waiting for connection", c->self); c->io_want = SSH_CHAN_IO_SOCK_W; } static void channel_pre_open(struct ssh *ssh, Channel *c) { c->io_want = 0; if (c->istate == CHAN_INPUT_OPEN && c->remote_window > 0 && sshbuf_len(c->input) < c->remote_window && sshbuf_check_reserve(c->input, CHAN_RBUF) == 0) c->io_want |= SSH_CHAN_IO_RFD; if (c->ostate == CHAN_OUTPUT_OPEN || c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { if (sshbuf_len(c->output) > 0) { c->io_want |= SSH_CHAN_IO_WFD; } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { if (CHANNEL_EFD_OUTPUT_ACTIVE(c)) debug2("channel %d: " "obuf_empty delayed efd %d/(%zu)", c->self, c->efd, sshbuf_len(c->extended)); else chan_obuf_empty(ssh, c); } } /** XXX check close conditions, too */ if (c->efd != -1 && !(c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED)) { if (c->extended_usage == CHAN_EXTENDED_WRITE && sshbuf_len(c->extended) > 0) c->io_want |= SSH_CHAN_IO_EFD_W; else if (c->efd != -1 && !(c->flags & CHAN_EOF_SENT) && (c->extended_usage == CHAN_EXTENDED_READ || c->extended_usage == CHAN_EXTENDED_IGNORE) && sshbuf_len(c->extended) < c->remote_window) c->io_want |= SSH_CHAN_IO_EFD_R; } /* XXX: What about efd? races? */ } /* * This is a special state for X11 authentication spoofing. An opened X11 * connection (when authentication spoofing is being done) remains in this * state until the first packet has been completely read. The authentication * data in that packet is then substituted by the real data if it matches the * fake data, and the channel is put into normal mode. * XXX All this happens at the client side. * Returns: 0 = need more data, -1 = wrong cookie, 1 = ok */ static int x11_open_helper(struct ssh *ssh, struct sshbuf *b) { struct ssh_channels *sc = ssh->chanctxt; u_char *ucp; u_int proto_len, data_len; /* Is this being called after the refusal deadline? */ if (sc->x11_refuse_time != 0 && monotime() >= sc->x11_refuse_time) { verbose("Rejected X11 connection after ForwardX11Timeout " "expired"); return -1; } /* Check if the fixed size part of the packet is in buffer. */ if (sshbuf_len(b) < 12) return 0; /* Parse the lengths of variable-length fields. */ ucp = sshbuf_mutable_ptr(b); if (ucp[0] == 0x42) { /* Byte order MSB first. */ proto_len = 256 * ucp[6] + ucp[7]; data_len = 256 * ucp[8] + ucp[9]; } else if (ucp[0] == 0x6c) { /* Byte order LSB first. */ proto_len = ucp[6] + 256 * ucp[7]; data_len = ucp[8] + 256 * ucp[9]; } else { debug2("Initial X11 packet contains bad byte order byte: 0x%x", ucp[0]); return -1; } /* Check if the whole packet is in buffer. */ if (sshbuf_len(b) < 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3)) return 0; /* Check if authentication protocol matches. */ if (proto_len != strlen(sc->x11_saved_proto) || memcmp(ucp + 12, sc->x11_saved_proto, proto_len) != 0) { debug2("X11 connection uses different authentication protocol."); return -1; } /* Check if authentication data matches our fake data. */ if (data_len != sc->x11_fake_data_len || timingsafe_bcmp(ucp + 12 + ((proto_len + 3) & ~3), sc->x11_fake_data, sc->x11_fake_data_len) != 0) { debug2("X11 auth data does not match fake data."); return -1; } /* Check fake data length */ if (sc->x11_fake_data_len != sc->x11_saved_data_len) { error("X11 fake_data_len %d != saved_data_len %d", sc->x11_fake_data_len, sc->x11_saved_data_len); return -1; } /* * Received authentication protocol and data match * our fake data. Substitute the fake data with real * data. */ memcpy(ucp + 12 + ((proto_len + 3) & ~3), sc->x11_saved_data, sc->x11_saved_data_len); return 1; } void channel_force_close(struct ssh *ssh, Channel *c, int abandon) { debug3_f("channel %d: forcibly closing", c->self); if (c->istate == CHAN_INPUT_OPEN) chan_read_failed(ssh, c); if (c->istate == CHAN_INPUT_WAIT_DRAIN) { sshbuf_reset(c->input); chan_ibuf_empty(ssh, c); } if (c->ostate == CHAN_OUTPUT_OPEN || c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { sshbuf_reset(c->output); chan_write_failed(ssh, c); } if (c->detach_user) c->detach_user(ssh, c->self, 1, NULL); if (c->efd != -1) channel_close_fd(ssh, c, &c->efd); if (abandon) c->type = SSH_CHANNEL_ABANDONED; /* exempt from inactivity timeouts */ c->inactive_deadline = 0; c->lastused = 0; } static void channel_pre_x11_open(struct ssh *ssh, Channel *c) { int ret = x11_open_helper(ssh, c->output); /* c->force_drain = 1; */ if (ret == 1) { c->type = SSH_CHANNEL_OPEN; c->lastused = monotime(); channel_pre_open(ssh, c); } else if (ret == -1) { logit("X11 connection rejected because of wrong " "authentication."); debug2("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate); channel_force_close(ssh, c, 0); } } static void channel_pre_mux_client(struct ssh *ssh, Channel *c) { c->io_want = 0; if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause && sshbuf_check_reserve(c->input, CHAN_RBUF) == 0) c->io_want |= SSH_CHAN_IO_RFD; if (c->istate == CHAN_INPUT_WAIT_DRAIN) { /* clear buffer immediately (discard any partial packet) */ sshbuf_reset(c->input); chan_ibuf_empty(ssh, c); /* Start output drain. XXX just kill chan? */ chan_rcvd_oclose(ssh, c); } if (c->ostate == CHAN_OUTPUT_OPEN || c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { if (sshbuf_len(c->output) > 0) c->io_want |= SSH_CHAN_IO_WFD; else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) chan_obuf_empty(ssh, c); } } /* try to decode a socks4 header */ static int channel_decode_socks4(Channel *c, struct sshbuf *input, struct sshbuf *output) { const u_char *p; char *host; u_int len, have, i, found, need; char username[256]; struct { u_int8_t version; u_int8_t command; u_int16_t dest_port; struct in_addr dest_addr; } s4_req, s4_rsp; int r; debug2("channel %d: decode socks4", c->self); have = sshbuf_len(input); len = sizeof(s4_req); if (have < len) return 0; p = sshbuf_ptr(input); need = 1; /* SOCKS4A uses an invalid IP address 0.0.0.x */ if (p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] != 0) { debug2("channel %d: socks4a request", c->self); /* ... and needs an extra string (the hostname) */ need = 2; } /* Check for terminating NUL on the string(s) */ for (found = 0, i = len; i < have; i++) { if (p[i] == '\0') { found++; if (found == need) break; } if (i > 1024) { /* the peer is probably sending garbage */ debug("channel %d: decode socks4: too long", c->self); return -1; } } if (found < need) return 0; if ((r = sshbuf_get(input, &s4_req.version, 1)) != 0 || (r = sshbuf_get(input, &s4_req.command, 1)) != 0 || (r = sshbuf_get(input, &s4_req.dest_port, 2)) != 0 || (r = sshbuf_get(input, &s4_req.dest_addr, 4)) != 0) { debug_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: 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_fr(r, "channel %d: consume", c->self); free(c->path); c->path = NULL; if (need == 1) { /* SOCKS4: one string */ host = inet_ntoa(s4_req.dest_addr); c->path = xstrdup(host); } else { /* SOCKS4A: two strings */ have = sshbuf_len(input); p = sshbuf_ptr(input); if (memchr(p, '\0', have) == NULL) { error("channel %d: decode socks4a: host not nul " "terminated", c->self); return -1; } len = strlen(p); debug2("channel %d: decode socks4a: host %s/%d", c->self, p, len); len++; /* trailing '\0' */ if (len > NI_MAXHOST) { error("channel %d: hostname \"%.100s\" too long", c->self, p); return -1; } c->path = xstrdup(p); if ((r = sshbuf_consume(input, len)) != 0) fatal_fr(r, "channel %d: consume", c->self); } c->host_port = ntohs(s4_req.dest_port); debug2("channel %d: dynamic request: socks4 host %s port %u command %u", c->self, c->path, c->host_port, s4_req.command); if (s4_req.command != 1) { debug("channel %d: cannot handle: %s cn %d", c->self, need == 1 ? "SOCKS4" : "SOCKS4A", s4_req.command); return -1; } s4_rsp.version = 0; /* vn: 0 for reply */ s4_rsp.command = 90; /* cd: req granted */ s4_rsp.dest_port = 0; /* ignored */ s4_rsp.dest_addr.s_addr = INADDR_ANY; /* ignored */ if ((r = sshbuf_put(output, &s4_rsp, sizeof(s4_rsp))) != 0) fatal_fr(r, "channel %d: append reply", c->self); return 1; } /* try to decode a socks5 header */ #define SSH_SOCKS5_AUTHDONE 0x1000 #define SSH_SOCKS5_NOAUTH 0x00 #define SSH_SOCKS5_IPV4 0x01 #define SSH_SOCKS5_DOMAIN 0x03 #define SSH_SOCKS5_IPV6 0x04 #define SSH_SOCKS5_CONNECT 0x01 #define SSH_SOCKS5_SUCCESS 0x00 static int channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output) { /* XXX use get/put_u8 instead of trusting struct padding */ struct { u_int8_t version; u_int8_t command; u_int8_t reserved; u_int8_t atyp; } s5_req, s5_rsp; u_int16_t dest_port; char dest_addr[255+1], ntop[INET6_ADDRSTRLEN]; const u_char *p; u_int have, need, i, found, nmethods, addrlen, af; int r; debug2("channel %d: decode socks5", c->self); p = sshbuf_ptr(input); if (p[0] != 0x05) return -1; have = sshbuf_len(input); if (!(c->flags & SSH_SOCKS5_AUTHDONE)) { /* format: ver | nmethods | methods */ if (have < 2) return 0; nmethods = p[1]; if (have < nmethods + 2) return 0; /* look for method: "NO AUTHENTICATION REQUIRED" */ for (found = 0, i = 2; i < nmethods + 2; i++) { if (p[i] == SSH_SOCKS5_NOAUTH) { found = 1; break; } } if (!found) { debug("channel %d: method SSH_SOCKS5_NOAUTH not found", c->self); return -1; } if ((r = sshbuf_consume(input, nmethods + 2)) != 0) fatal_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_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 */ } debug2("channel %d: socks5 post auth", c->self); if (have < sizeof(s5_req)+1) return 0; /* need more */ memcpy(&s5_req, p, sizeof(s5_req)); if (s5_req.version != 0x05 || s5_req.command != SSH_SOCKS5_CONNECT || s5_req.reserved != 0x00) { debug2("channel %d: only socks5 connect supported", c->self); return -1; } switch (s5_req.atyp){ case SSH_SOCKS5_IPV4: addrlen = 4; af = AF_INET; break; case SSH_SOCKS5_DOMAIN: addrlen = p[sizeof(s5_req)]; af = -1; break; case SSH_SOCKS5_IPV6: addrlen = 16; af = AF_INET6; break; default: debug2("channel %d: bad socks5 atyp %d", c->self, s5_req.atyp); return -1; } need = sizeof(s5_req) + addrlen + 2; if (s5_req.atyp == SSH_SOCKS5_DOMAIN) need++; if (have < need) return 0; if ((r = sshbuf_consume(input, sizeof(s5_req))) != 0) fatal_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_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_r(r, "channel %d: parse addr/port", c->self); return -1; } dest_addr[addrlen] = '\0'; free(c->path); c->path = NULL; if (s5_req.atyp == SSH_SOCKS5_DOMAIN) { if (addrlen >= NI_MAXHOST) { error("channel %d: dynamic request: socks5 hostname " "\"%.100s\" too long", c->self, dest_addr); return -1; } c->path = xstrdup(dest_addr); } else { if (inet_ntop(af, dest_addr, ntop, sizeof(ntop)) == NULL) return -1; c->path = xstrdup(ntop); } c->host_port = ntohs(dest_port); debug2("channel %d: dynamic request: socks5 host %s port %u command %u", c->self, c->path, c->host_port, s5_req.command); s5_rsp.version = 0x05; s5_rsp.command = SSH_SOCKS5_SUCCESS; s5_rsp.reserved = 0; /* ignored */ s5_rsp.atyp = SSH_SOCKS5_IPV4; dest_port = 0; /* ignored */ if ((r = sshbuf_put(output, &s5_rsp, sizeof(s5_rsp))) != 0 || (r = sshbuf_put_u32(output, ntohl(INADDR_ANY))) != 0 || (r = sshbuf_put(output, &dest_port, sizeof(dest_port))) != 0) fatal_fr(r, "channel %d: append reply", c->self); return 1; } Channel * channel_connect_stdio_fwd(struct ssh *ssh, const char *host_to_connect, int port_to_connect, int in, int out, int nonblock) { Channel *c; 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, 0, "stdio-forward", nonblock); c->path = xstrdup(host_to_connect); c->host_port = port_to_connect; c->listening_port = 0; c->force_drain = 1; channel_register_fds(ssh, c, in, out, -1, 0, 1, 0); port_open_helper(ssh, c, port_to_connect == PORT_STREAMLOCAL ? "direct-streamlocal@openssh.com" : "direct-tcpip"); return c; } /* dynamic port forwarding */ static void channel_pre_dynamic(struct ssh *ssh, Channel *c) { const u_char *p; u_int have; int ret; c->io_want = 0; have = sshbuf_len(c->input); debug2("channel %d: pre_dynamic: have %d", c->self, have); /* sshbuf_dump(c->input, stderr); */ /* check if the fixed size part of the packet is in buffer. */ if (have < 3) { /* need more */ c->io_want |= SSH_CHAN_IO_RFD; return; } /* try to guess the protocol */ p = sshbuf_ptr(c->input); /* XXX sshbuf_peek_u8? */ switch (p[0]) { case 0x04: ret = channel_decode_socks4(c, c->input, c->output); break; case 0x05: ret = channel_decode_socks5(c, c->input, c->output); break; default: ret = -1; break; } if (ret < 0) { chan_mark_dead(ssh, c); } else if (ret == 0) { debug2("channel %d: pre_dynamic: need more", c->self); /* need more */ c->io_want |= SSH_CHAN_IO_RFD; if (sshbuf_len(c->output)) c->io_want |= SSH_CHAN_IO_WFD; } else { /* switch to the next state */ c->type = SSH_CHANNEL_OPENING; port_open_helper(ssh, c, "direct-tcpip"); } } /* simulate read-error */ static void rdynamic_close(struct ssh *ssh, Channel *c) { c->type = SSH_CHANNEL_OPEN; channel_force_close(ssh, c, 0); } /* reverse dynamic port forwarding */ static void channel_before_prepare_io_rdynamic(struct ssh *ssh, Channel *c) { const u_char *p; u_int have, len; int r, ret; have = sshbuf_len(c->output); debug2("channel %d: pre_rdynamic: have %d", c->self, have); /* sshbuf_dump(c->output, stderr); */ /* EOF received */ if (c->flags & CHAN_EOF_RCVD) { if ((r = sshbuf_consume(c->output, have)) != 0) fatal_fr(r, "channel %d: consume", c->self); rdynamic_close(ssh, c); return; } /* check if the fixed size part of the packet is in buffer. */ if (have < 3) return; /* try to guess the protocol */ p = sshbuf_ptr(c->output); switch (p[0]) { case 0x04: /* switch input/output for reverse forwarding */ ret = channel_decode_socks4(c, c->output, c->input); break; case 0x05: ret = channel_decode_socks5(c, c->output, c->input); break; default: ret = -1; break; } if (ret < 0) { rdynamic_close(ssh, c); } else if (ret == 0) { debug2("channel %d: pre_rdynamic: need more", c->self); /* send socks request to peer */ len = sshbuf_len(c->input); if (len > 0 && len < c->remote_window) { if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_stringb(ssh, c->input)) != 0 || (r = sshpkt_send(ssh)) != 0) { fatal_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) { /* the connect failed */ rdynamic_close(ssh, c); } } /* This is our fake X11 server socket. */ static void channel_post_x11_listener(struct ssh *ssh, Channel *c) { Channel *nc; struct sockaddr_storage addr; int r, newsock, oerrno, remote_port; socklen_t addrlen; char buf[16384], *remote_ipaddr; if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0) return; debug("X11 connection requested."); addrlen = sizeof(addr); newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); if (c->single_connection) { oerrno = errno; debug2("single_connection: closing X11 listener."); channel_close_fd(ssh, c, &c->sock); chan_mark_dead(ssh, c); errno = oerrno; } if (newsock == -1) { if (errno != EINTR && errno != EWOULDBLOCK && errno != ECONNABORTED) error("accept: %.100s", strerror(errno)); if (errno == EMFILE || errno == ENFILE) c->notbefore = monotime() + 1; return; } set_nodelay(newsock); remote_ipaddr = get_peer_ipaddr(newsock); remote_port = get_peer_port(newsock); snprintf(buf, sizeof buf, "X11 connection from %.200s port %d", remote_ipaddr, remote_port); nc = channel_new(ssh, "x11-connection", SSH_CHANNEL_OPENING, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, buf, 1); open_preamble(ssh, __func__, nc, "x11"); if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 || (r = sshpkt_put_u32(ssh, remote_port)) != 0) { fatal_fr(r, "channel %i: reply", c->self); } if ((r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i: send", c->self); free(remote_ipaddr); } static void port_open_helper(struct ssh *ssh, Channel *c, char *rtype) { char *local_ipaddr = get_local_ipaddr(c->sock); int local_port = c->sock == -1 ? 65536 : get_local_port(c->sock); char *remote_ipaddr = get_peer_ipaddr(c->sock); int remote_port = get_peer_port(c->sock); int r; if (remote_port == -1) { /* Fake addr/port to appease peers that validate it (Tectia) */ free(remote_ipaddr); remote_ipaddr = xstrdup("127.0.0.1"); remote_port = 65535; } free(c->remote_name); xasprintf(&c->remote_name, "%s: listening port %d for %.100s port %d, " "connect from %.200s port %d to %.100s port %d", rtype, c->listening_port, c->path, c->host_port, remote_ipaddr, remote_port, local_ipaddr, local_port); open_preamble(ssh, __func__, c, rtype); if (strcmp(rtype, "direct-tcpip") == 0) { /* target host, port */ if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 || (r = sshpkt_put_u32(ssh, c->host_port)) != 0) fatal_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_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_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_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_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_fr(r, "channel %i: reply", c->self); } if ((r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i: send", c->self); free(remote_ipaddr); free(local_ipaddr); } void channel_set_x11_refuse_time(struct ssh *ssh, time_t refuse_time) { ssh->chanctxt->x11_refuse_time = refuse_time; } /* * This socket is listening for connections to a forwarded TCP/IP port. */ static void channel_post_port_listener(struct ssh *ssh, Channel *c) { Channel *nc; struct sockaddr_storage addr; int newsock, nextstate; socklen_t addrlen; char *rtype; if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0) return; debug("Connection to port %d forwarding to %.100s port %d requested.", c->listening_port, c->path, c->host_port); if (c->type == SSH_CHANNEL_RPORT_LISTENER) { nextstate = SSH_CHANNEL_OPENING; rtype = "forwarded-tcpip"; } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) { nextstate = SSH_CHANNEL_OPENING; rtype = "forwarded-streamlocal@openssh.com"; } else if (c->host_port == PORT_STREAMLOCAL) { nextstate = SSH_CHANNEL_OPENING; rtype = "direct-streamlocal@openssh.com"; } else if (c->host_port == 0) { nextstate = SSH_CHANNEL_DYNAMIC; rtype = "dynamic-tcpip"; } else { nextstate = SSH_CHANNEL_OPENING; rtype = "direct-tcpip"; } addrlen = sizeof(addr); newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); if (newsock == -1) { if (errno != EINTR && errno != EWOULDBLOCK && errno != ECONNABORTED) error("accept: %.100s", strerror(errno)); if (errno == EMFILE || errno == ENFILE) c->notbefore = monotime() + 1; return; } if (c->host_port != PORT_STREAMLOCAL) set_nodelay(newsock); nc = channel_new(ssh, rtype, nextstate, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, rtype, 1); nc->listening_port = c->listening_port; nc->host_port = c->host_port; if (c->path != NULL) nc->path = xstrdup(c->path); if (nextstate != SSH_CHANNEL_DYNAMIC) port_open_helper(ssh, nc, rtype); } /* * This is the authentication agent socket listening for connections from * clients. */ static void channel_post_auth_listener(struct ssh *ssh, Channel *c) { Channel *nc; int r, newsock; struct sockaddr_storage addr; socklen_t addrlen; if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0) return; addrlen = sizeof(addr); newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); if (newsock == -1) { error("accept from auth socket: %.100s", strerror(errno)); if (errno == EMFILE || errno == ENFILE) c->notbefore = monotime() + 1; return; } nc = channel_new(ssh, "agent-connection", SSH_CHANNEL_OPENING, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, "accepted auth socket", 1); open_preamble(ssh, __func__, nc, "auth-agent@openssh.com"); if ((r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i", c->self); } static void channel_post_connecting(struct ssh *ssh, Channel *c) { int err = 0, sock, isopen, r; socklen_t sz = sizeof(err); if ((c->io_ready & SSH_CHAN_IO_SOCK_W) == 0) return; if (!c->have_remote_id) 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) { err = errno; error("getsockopt SO_ERROR failed"); } if (err == 0) { /* Non-blocking connection completed */ debug("channel %d: connected to %s port %d", c->self, c->connect_ctx.host, c->connect_ctx.port); channel_connect_ctx_free(&c->connect_ctx); c->type = SSH_CHANNEL_OPEN; c->lastused = monotime(); if (isopen) { /* no message necessary */ } else { if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, c->self)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i open confirm", c->self); } return; } if (err == EINTR || err == EAGAIN || err == EINPROGRESS) return; /* Non-blocking connection failed */ debug("channel %d: connection failed: %s", c->self, strerror(err)); /* Try next address, if any */ if ((sock = connect_next(&c->connect_ctx)) == -1) { /* Exhausted all addresses for this destination */ error("connect_to %.100s port %d: failed.", c->connect_ctx.host, c->connect_ctx.port); channel_connect_ctx_free(&c->connect_ctx); if (isopen) { rdynamic_close(ssh, c); } else { if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, SSH2_OPEN_CONNECT_FAILED)) != 0 || (r = sshpkt_put_cstring(ssh, strerror(err))) != 0 || (r = sshpkt_put_cstring(ssh, "")) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i: failure", c->self); chan_mark_dead(ssh, c); } } /* New non-blocking connection in progress */ close(c->sock); c->sock = c->rfd = c->wfd = sock; } static int channel_handle_rfd(struct ssh *ssh, Channel *c) { char buf[CHAN_RBUF]; ssize_t len; int r, force; size_t nr = 0, have, avail, maxlen = CHANNEL_MAX_READ; int pty_zeroread = 0; #ifdef PTY_ZEROREAD /* Bug on AIX: read(1) can return 0 for a non-closed fd */ pty_zeroread = c->isatty; #endif force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED; if (!force && (c->io_ready & SSH_CHAN_IO_RFD) == 0) return 1; if ((avail = sshbuf_avail(c->input)) == 0) return 1; /* Shouldn't happen */ /* * For "simple" channels (i.e. not datagram or filtered), we can * read directly to the channel buffer. */ if (!pty_zeroread && c->input_filter == NULL && !c->datagram) { /* Only OPEN channels have valid rwin */ if (c->type == SSH_CHANNEL_OPEN) { if ((have = sshbuf_len(c->input)) >= c->remote_window) return 1; /* shouldn't happen */ if (maxlen > c->remote_window - have) maxlen = c->remote_window - have; } if (maxlen > avail) maxlen = avail; if ((r = sshbuf_read(c->rfd, c->input, maxlen, &nr)) != 0) { if (errno == EINTR || (!force && (errno == EAGAIN || errno == EWOULDBLOCK))) return 1; debug2("channel %d: read failed rfd %d maxlen %zu: %s", c->self, c->rfd, maxlen, ssh_err(r)); goto rfail; } if (nr != 0) c->lastused = monotime(); return 1; } errno = 0; len = read(c->rfd, buf, sizeof(buf)); /* fixup AIX zero-length read with errno set to look more like errors */ if (pty_zeroread && len == 0 && errno != 0) len = -1; if (len == -1 && (errno == EINTR || ((errno == EAGAIN || errno == EWOULDBLOCK) && !force))) return 1; if (len < 0 || (!pty_zeroread && len == 0)) { debug2("channel %d: read<=0 rfd %d len %zd: %s", c->self, c->rfd, len, len == 0 ? "closed" : strerror(errno)); rfail: if (c->type != SSH_CHANNEL_OPEN) { debug2("channel %d: not open", c->self); chan_mark_dead(ssh, c); return -1; } else { chan_read_failed(ssh, c); } return -1; } c->lastused = monotime(); if (c->input_filter != NULL) { if (c->input_filter(ssh, c, buf, len) == -1) { debug2("channel %d: filter stops", c->self); chan_read_failed(ssh, c); } } else if (c->datagram) { if ((r = sshbuf_put_string(c->input, buf, len)) != 0) fatal_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; } static int channel_handle_wfd(struct ssh *ssh, Channel *c) { struct termios tio; u_char *data = NULL, *buf; /* XXX const; need filter API change */ size_t dlen, olen = 0; int r, len; if ((c->io_ready & SSH_CHAN_IO_WFD) == 0) return 1; if (sshbuf_len(c->output) == 0) return 1; /* Send buffered output data to the socket. */ olen = sshbuf_len(c->output); if (c->output_filter != NULL) { if ((buf = c->output_filter(ssh, c, &data, &dlen)) == NULL) { debug2("channel %d: filter stops", c->self); if (c->type != SSH_CHANNEL_OPEN) chan_mark_dead(ssh, c); else chan_write_failed(ssh, c); return -1; } } else if (c->datagram) { if ((r = sshbuf_get_string(c->output, &data, &dlen)) != 0) fatal_fr(r, "channel %i: get datagram", c->self); buf = data; } else { buf = data = sshbuf_mutable_ptr(c->output); dlen = sshbuf_len(c->output); } if (c->datagram) { /* ignore truncated writes, datagrams might get lost */ len = write(c->wfd, buf, dlen); free(data); if (len == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) return 1; if (len <= 0) goto write_fail; goto out; } #ifdef _AIX /* XXX: Later AIX versions can't push as much data to tty */ if (c->wfd_isatty) dlen = MINIMUM(dlen, 8*1024); #endif len = write(c->wfd, buf, dlen); if (len == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) return 1; if (len <= 0) { write_fail: if (c->type != SSH_CHANNEL_OPEN) { debug2("channel %d: not open", c->self); chan_mark_dead(ssh, c); return -1; } else { chan_write_failed(ssh, c); } return -1; } c->lastused = monotime(); #ifndef BROKEN_TCGETATTR_ICANON if (c->isatty && dlen >= 1 && buf[0] != '\r') { if (tcgetattr(c->wfd, &tio) == 0 && !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { /* * Simulate echo to reduce the impact of * traffic analysis. We need to match the * size of a SSH2_MSG_CHANNEL_DATA message * (4 byte channel id + buf) */ if ((r = sshpkt_msg_ignore(ssh, 4+len)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i: ignore", c->self); } } #endif /* BROKEN_TCGETATTR_ICANON */ 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); return 1; } static int channel_handle_efd_write(struct ssh *ssh, Channel *c) { int r; ssize_t len; if ((c->io_ready & SSH_CHAN_IO_EFD_W) == 0) return 1; if (sshbuf_len(c->extended) == 0) return 1; len = write(c->efd, sshbuf_ptr(c->extended), sshbuf_len(c->extended)); debug2("channel %d: written %zd to efd %d", c->self, len, c->efd); if (len == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) return 1; if (len <= 0) { debug2("channel %d: closing write-efd %d", c->self, c->efd); channel_close_fd(ssh, c, &c->efd); } else { if ((r = sshbuf_consume(c->extended, len)) != 0) fatal_fr(r, "channel %i: consume", c->self); c->local_consumed += len; c->lastused = monotime(); } return 1; } static int channel_handle_efd_read(struct ssh *ssh, Channel *c) { char buf[CHAN_RBUF]; ssize_t len; int r, force; force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED; if (!force && (c->io_ready & SSH_CHAN_IO_EFD_R) == 0) return 1; len = read(c->efd, buf, sizeof(buf)); debug2("channel %d: read %zd from efd %d", c->self, len, c->efd); if (len == -1 && (errno == EINTR || ((errno == EAGAIN || errno == EWOULDBLOCK) && !force))) return 1; if (len <= 0) { debug2("channel %d: closing read-efd %d", c->self, c->efd); channel_close_fd(ssh, c, &c->efd); return 1; } c->lastused = monotime(); 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; } static int channel_handle_efd(struct ssh *ssh, Channel *c) { if (c->efd == -1) return 1; /** XXX handle drain efd, too */ if (c->extended_usage == CHAN_EXTENDED_WRITE) return channel_handle_efd_write(ssh, c); else if (c->extended_usage == CHAN_EXTENDED_READ || c->extended_usage == CHAN_EXTENDED_IGNORE) return channel_handle_efd_read(ssh, c); return 1; } static int channel_check_window(struct ssh *ssh, Channel *c) { int r; if (c->type == SSH_CHANNEL_OPEN && !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) && ((c->local_window_max - c->local_window > c->local_maxpacket*3) || c->local_window < c->local_window_max/2) && c->local_consumed > 0) { if (!c->have_remote_id) fatal_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_fr(r, "channel %i", c->self); } debug2("channel %d: window %d sent adjust %d", c->self, c->local_window, c->local_consumed); c->local_window += c->local_consumed; c->local_consumed = 0; } return 1; } static void channel_post_open(struct ssh *ssh, Channel *c) { channel_handle_rfd(ssh, c); channel_handle_wfd(ssh, c); channel_handle_efd(ssh, c); channel_check_window(ssh, c); } static u_int read_mux(struct ssh *ssh, Channel *c, u_int need) { char buf[CHAN_RBUF]; ssize_t len; u_int rlen; int r; if (sshbuf_len(c->input) < need) { rlen = need - sshbuf_len(c->input); len = read(c->rfd, buf, MINIMUM(rlen, CHAN_RBUF)); if (len == -1 && (errno == EINTR || errno == EAGAIN)) return sshbuf_len(c->input); if (len <= 0) { debug2("channel %d: ctl read<=0 rfd %d len %zd", c->self, c->rfd, len); chan_read_failed(ssh, c); return 0; } else if ((r = sshbuf_put(c->input, buf, len)) != 0) fatal_fr(r, "channel %i: append", c->self); } return sshbuf_len(c->input); } static void channel_post_mux_client_read(struct ssh *ssh, Channel *c) { u_int need; if ((c->io_ready & SSH_CHAN_IO_RFD) == 0) return; if (c->istate != CHAN_INPUT_OPEN && c->istate != CHAN_INPUT_WAIT_DRAIN) return; if (c->mux_pause) return; /* * Don't not read past the precise end of packets to * avoid disrupting fd passing. */ if (read_mux(ssh, c, 4) < 4) /* read header */ return; /* XXX sshbuf_peek_u32 */ need = PEEK_U32(sshbuf_ptr(c->input)); #define CHANNEL_MUX_MAX_PACKET (256 * 1024) if (need > CHANNEL_MUX_MAX_PACKET) { debug2("channel %d: packet too big %u > %u", c->self, CHANNEL_MUX_MAX_PACKET, need); chan_rcvd_oclose(ssh, c); return; } if (read_mux(ssh, c, need + 4) < need + 4) /* read body */ return; if (c->mux_rcb(ssh, c) != 0) { debug("channel %d: mux_rcb failed", c->self); chan_mark_dead(ssh, c); return; } } static void channel_post_mux_client_write(struct ssh *ssh, Channel *c) { ssize_t len; int r; if ((c->io_ready & SSH_CHAN_IO_WFD) == 0) return; if (sshbuf_len(c->output) == 0) return; len = write(c->wfd, sshbuf_ptr(c->output), sshbuf_len(c->output)); if (len == -1 && (errno == EINTR || errno == EAGAIN)) return; if (len <= 0) { chan_mark_dead(ssh, c); return; } if ((r = sshbuf_consume(c->output, len)) != 0) fatal_fr(r, "channel %i: consume", c->self); } static void channel_post_mux_client(struct ssh *ssh, Channel *c) { channel_post_mux_client_read(ssh, c); channel_post_mux_client_write(ssh, c); } static void channel_post_mux_listener(struct ssh *ssh, Channel *c) { Channel *nc; struct sockaddr_storage addr; socklen_t addrlen; int newsock; uid_t euid; gid_t egid; if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0) return; debug("multiplexing control connection"); /* * Accept connection on control socket */ memset(&addr, 0, sizeof(addr)); addrlen = sizeof(addr); if ((newsock = accept(c->sock, (struct sockaddr*)&addr, &addrlen)) == -1) { error_f("accept: %s", strerror(errno)); if (errno == EMFILE || errno == ENFILE) c->notbefore = monotime() + 1; return; } if (getpeereid(newsock, &euid, &egid) == -1) { error_f("getpeereid failed: %s", strerror(errno)); close(newsock); return; } if ((euid != 0) && (getuid() != euid)) { error("multiplex uid mismatch: peer euid %u != uid %u", (u_int)euid, (u_int)getuid()); close(newsock); return; } nc = channel_new(ssh, "mux-control", SSH_CHANNEL_MUX_CLIENT, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, "mux-control", 1); nc->mux_rcb = c->mux_rcb; debug3_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 */ nc->flags |= CHAN_LOCAL; } static void channel_handler_init(struct ssh_channels *sc) { chan_fn **pre, **post; if ((pre = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*pre))) == NULL || (post = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*post))) == NULL) fatal_f("allocation failed"); pre[SSH_CHANNEL_OPEN] = &channel_pre_open; pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener; pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener; pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; pre[SSH_CHANNEL_RDYNAMIC_FINISH] = &channel_pre_connecting; pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener; pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client; post[SSH_CHANNEL_OPEN] = &channel_post_open; post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener; post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener; post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; post[SSH_CHANNEL_RDYNAMIC_FINISH] = &channel_post_connecting; post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener; post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client; sc->channel_pre = pre; sc->channel_post = post; } /* gc dead channels */ static void channel_garbage_collect(struct ssh *ssh, Channel *c) { if (c == NULL) return; if (c->detach_user != NULL) { if (!chan_is_dead(ssh, c, c->detach_close)) return; debug2("channel %d: gc: notify user", c->self); c->detach_user(ssh, c->self, 0, NULL); /* if we still have a callback */ if (c->detach_user != NULL) return; debug2("channel %d: gc: user detached", c->self); } if (!chan_is_dead(ssh, c, 1)) return; debug2("channel %d: garbage collecting", c->self); channel_free(ssh, c); } enum channel_table { CHAN_PRE, CHAN_POST }; static void channel_handler(struct ssh *ssh, int table, struct timespec *timeout) { struct ssh_channels *sc = ssh->chanctxt; chan_fn **ftab = table == CHAN_PRE ? sc->channel_pre : sc->channel_post; u_int i, oalloc; Channel *c; time_t now; now = monotime(); for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) { c = sc->channels[i]; if (c == NULL) continue; /* Try to keep IO going while rekeying */ if (ssh_packet_is_rekeying(ssh) && c->type != SSH_CHANNEL_OPEN) continue; if (c->delayed) { if (table == CHAN_PRE) c->delayed = 0; else continue; } if (ftab[c->type] != NULL) { if (table == CHAN_PRE && c->type == SSH_CHANNEL_OPEN && c->inactive_deadline != 0 && c->lastused != 0 && now >= c->lastused + c->inactive_deadline) { /* channel closed for inactivity */ verbose("channel %d: closing after %u seconds " "of inactivity", c->self, c->inactive_deadline); channel_force_close(ssh, c, 1); } else if (c->notbefore <= now) { /* Run handlers that are not paused. */ (*ftab[c->type])(ssh, c); /* inactivity timeouts must interrupt poll() */ if (timeout != NULL && c->type == SSH_CHANNEL_OPEN && c->lastused != 0 && c->inactive_deadline != 0) { ptimeout_deadline_monotime(timeout, c->lastused + c->inactive_deadline); } } else if (timeout != NULL) { /* * Arrange for poll() wakeup when channel pause * timer expires. */ ptimeout_deadline_monotime(timeout, c->notbefore); } } channel_garbage_collect(ssh, c); } } /* * Create sockets before preparing IO. * This is necessary for things that need to happen after reading * the network-input but need to be completed before IO event setup, e.g. * because they may create new channels. */ static void channel_before_prepare_io(struct ssh *ssh) { struct ssh_channels *sc = ssh->chanctxt; Channel *c; u_int i, oalloc; for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) { c = sc->channels[i]; if (c == NULL) continue; if (c->type == SSH_CHANNEL_RDYNAMIC_OPEN) channel_before_prepare_io_rdynamic(ssh, c); } } static void dump_channel_poll(const char *func, const char *what, Channel *c, u_int pollfd_offset, struct pollfd *pfd) { #ifdef DEBUG_CHANNEL_POLL debug3("%s: channel %d: %s r%d w%d e%d s%d c->pfds [ %d %d %d %d ] " "io_want 0x%02x io_ready 0x%02x pfd[%u].fd=%d " "pfd.ev 0x%02x pfd.rev 0x%02x", func, c->self, what, c->rfd, c->wfd, c->efd, c->sock, c->pfds[0], c->pfds[1], c->pfds[2], c->pfds[3], c->io_want, c->io_ready, pollfd_offset, pfd->fd, pfd->events, pfd->revents); #endif } /* Prepare pollfd entries for a single channel */ static void channel_prepare_pollfd(Channel *c, u_int *next_pollfd, struct pollfd *pfd, u_int npfd) { u_int ev, p = *next_pollfd; if (c == NULL) return; if (p + 4 > npfd) { /* Shouldn't happen */ fatal_f("channel %d: bad pfd offset %u (max %u)", c->self, p, npfd); } c->pfds[0] = c->pfds[1] = c->pfds[2] = c->pfds[3] = -1; /* * prepare c->rfd * * This is a special case, since c->rfd might be the same as * c->wfd, c->efd and/or c->sock. Handle those here if they want * IO too. */ if (c->rfd != -1) { ev = 0; if ((c->io_want & SSH_CHAN_IO_RFD) != 0) ev |= POLLIN; /* rfd == wfd */ if (c->wfd == c->rfd) { if ((c->io_want & SSH_CHAN_IO_WFD) != 0) ev |= POLLOUT; } /* rfd == efd */ if (c->efd == c->rfd) { if ((c->io_want & SSH_CHAN_IO_EFD_R) != 0) ev |= POLLIN; if ((c->io_want & SSH_CHAN_IO_EFD_W) != 0) ev |= POLLOUT; } /* rfd == sock */ if (c->sock == c->rfd) { if ((c->io_want & SSH_CHAN_IO_SOCK_R) != 0) ev |= POLLIN; if ((c->io_want & SSH_CHAN_IO_SOCK_W) != 0) ev |= POLLOUT; } /* Pack a pfd entry if any event armed for this fd */ if (ev != 0) { c->pfds[0] = p; pfd[p].fd = c->rfd; pfd[p].events = ev; dump_channel_poll(__func__, "rfd", c, p, &pfd[p]); p++; } } /* prepare c->wfd if wanting IO and not already handled above */ if (c->wfd != -1 && c->rfd != c->wfd) { ev = 0; if ((c->io_want & SSH_CHAN_IO_WFD)) ev |= POLLOUT; /* Pack a pfd entry if any event armed for this fd */ if (ev != 0) { c->pfds[1] = p; pfd[p].fd = c->wfd; pfd[p].events = ev; dump_channel_poll(__func__, "wfd", c, p, &pfd[p]); p++; } } /* prepare c->efd if wanting IO and not already handled above */ if (c->efd != -1 && c->rfd != c->efd) { ev = 0; if ((c->io_want & SSH_CHAN_IO_EFD_R) != 0) ev |= POLLIN; if ((c->io_want & SSH_CHAN_IO_EFD_W) != 0) ev |= POLLOUT; /* Pack a pfd entry if any event armed for this fd */ if (ev != 0) { c->pfds[2] = p; pfd[p].fd = c->efd; pfd[p].events = ev; dump_channel_poll(__func__, "efd", c, p, &pfd[p]); p++; } } /* prepare c->sock if wanting IO and not already handled above */ if (c->sock != -1 && c->rfd != c->sock) { ev = 0; if ((c->io_want & SSH_CHAN_IO_SOCK_R) != 0) ev |= POLLIN; if ((c->io_want & SSH_CHAN_IO_SOCK_W) != 0) ev |= POLLOUT; /* Pack a pfd entry if any event armed for this fd */ if (ev != 0) { c->pfds[3] = p; pfd[p].fd = c->sock; pfd[p].events = 0; dump_channel_poll(__func__, "sock", c, p, &pfd[p]); p++; } } *next_pollfd = p; } /* * Allocate/prepare poll structure */ void channel_prepare_poll(struct ssh *ssh, struct pollfd **pfdp, u_int *npfd_allocp, u_int *npfd_activep, u_int npfd_reserved, struct timespec *timeout) { struct ssh_channels *sc = ssh->chanctxt; u_int i, oalloc, p, npfd = npfd_reserved; channel_before_prepare_io(ssh); /* might create a new channel */ /* clear out I/O flags from last poll */ for (i = 0; i < sc->channels_alloc; i++) { if (sc->channels[i] == NULL) continue; sc->channels[i]->io_want = sc->channels[i]->io_ready = 0; } /* Allocate 4x pollfd for each channel (rfd, wfd, efd, sock) */ if (sc->channels_alloc >= (INT_MAX / 4) - npfd_reserved) fatal_f("too many channels"); /* shouldn't happen */ npfd += sc->channels_alloc * 4; if (npfd > *npfd_allocp) { *pfdp = xrecallocarray(*pfdp, *npfd_allocp, npfd, sizeof(**pfdp)); *npfd_allocp = npfd; } *npfd_activep = npfd_reserved; oalloc = sc->channels_alloc; channel_handler(ssh, CHAN_PRE, timeout); if (oalloc != sc->channels_alloc) { /* shouldn't happen */ fatal_f("channels_alloc changed during CHAN_PRE " "(was %u, now %u)", oalloc, sc->channels_alloc); } /* Prepare pollfd */ p = npfd_reserved; for (i = 0; i < sc->channels_alloc; i++) channel_prepare_pollfd(sc->channels[i], &p, *pfdp, npfd); *npfd_activep = p; } static void fd_ready(Channel *c, int p, struct pollfd *pfds, u_int npfd, int fd, const char *what, u_int revents_mask, u_int ready) { struct pollfd *pfd = &pfds[p]; if (fd == -1) return; if (p == -1 || (u_int)p >= npfd) fatal_f("channel %d: bad pfd %d (max %u)", c->self, p, npfd); dump_channel_poll(__func__, what, c, p, pfd); if (pfd->fd != fd) { fatal("channel %d: inconsistent %s fd=%d pollfd[%u].fd %d " "r%d w%d e%d s%d", c->self, what, fd, p, pfd->fd, c->rfd, c->wfd, c->efd, c->sock); } if ((pfd->revents & POLLNVAL) != 0) { fatal("channel %d: invalid %s pollfd[%u].fd %d r%d w%d e%d s%d", c->self, what, p, pfd->fd, c->rfd, c->wfd, c->efd, c->sock); } if ((pfd->revents & (revents_mask|POLLHUP|POLLERR)) != 0) c->io_ready |= ready & c->io_want; } /* * After poll, perform any appropriate operations for channels which have * events pending. */ void channel_after_poll(struct ssh *ssh, struct pollfd *pfd, u_int npfd) { struct ssh_channels *sc = ssh->chanctxt; u_int i; int p; Channel *c; #ifdef DEBUG_CHANNEL_POLL for (p = 0; p < (int)npfd; p++) { if (pfd[p].revents == 0) continue; debug_f("pfd[%u].fd %d rev 0x%04x", p, pfd[p].fd, pfd[p].revents); } #endif /* Convert pollfd into c->io_ready */ for (i = 0; i < sc->channels_alloc; i++) { c = sc->channels[i]; if (c == NULL) continue; /* if rfd is shared with efd/sock then wfd should be too */ if (c->rfd != -1 && c->wfd != -1 && c->rfd != c->wfd && (c->rfd == c->efd || c->rfd == c->sock)) { /* Shouldn't happen */ fatal_f("channel %d: unexpected fds r%d w%d e%d s%d", c->self, c->rfd, c->wfd, c->efd, c->sock); } c->io_ready = 0; /* rfd, potentially shared with wfd, efd and sock */ if (c->rfd != -1 && (p = c->pfds[0]) != -1) { fd_ready(c, p, pfd, npfd, c->rfd, "rfd", POLLIN, SSH_CHAN_IO_RFD); if (c->rfd == c->wfd) { fd_ready(c, p, pfd, npfd, c->wfd, "wfd/r", POLLOUT, SSH_CHAN_IO_WFD); } if (c->rfd == c->efd) { fd_ready(c, p, pfd, npfd, c->efd, "efdr/r", POLLIN, SSH_CHAN_IO_EFD_R); fd_ready(c, p, pfd, npfd, c->efd, "efdw/r", POLLOUT, SSH_CHAN_IO_EFD_W); } if (c->rfd == c->sock) { fd_ready(c, p, pfd, npfd, c->sock, "sockr/r", POLLIN, SSH_CHAN_IO_SOCK_R); fd_ready(c, p, pfd, npfd, c->sock, "sockw/r", POLLOUT, SSH_CHAN_IO_SOCK_W); } dump_channel_poll(__func__, "rfd", c, p, pfd); } /* wfd */ if (c->wfd != -1 && c->wfd != c->rfd && (p = c->pfds[1]) != -1) { fd_ready(c, p, pfd, npfd, c->wfd, "wfd", POLLOUT, SSH_CHAN_IO_WFD); dump_channel_poll(__func__, "wfd", c, p, pfd); } /* efd */ if (c->efd != -1 && c->efd != c->rfd && (p = c->pfds[2]) != -1) { fd_ready(c, p, pfd, npfd, c->efd, "efdr", POLLIN, SSH_CHAN_IO_EFD_R); fd_ready(c, p, pfd, npfd, c->efd, "efdw", POLLOUT, SSH_CHAN_IO_EFD_W); dump_channel_poll(__func__, "efd", c, p, pfd); } /* sock */ if (c->sock != -1 && c->sock != c->rfd && (p = c->pfds[3]) != -1) { fd_ready(c, p, pfd, npfd, c->sock, "sockr", POLLIN, SSH_CHAN_IO_SOCK_R); fd_ready(c, p, pfd, npfd, c->sock, "sockw", POLLOUT, SSH_CHAN_IO_SOCK_W); dump_channel_poll(__func__, "sock", c, p, pfd); } } channel_handler(ssh, CHAN_POST, NULL); } /* * Enqueue data for channels with open or draining c->input. * Returns non-zero if a packet was enqueued. */ static int channel_output_poll_input_open(struct ssh *ssh, Channel *c) { size_t len, plen; const u_char *pkt; int r; if ((len = sshbuf_len(c->input)) == 0) { if (c->istate == CHAN_INPUT_WAIT_DRAIN) { /* * input-buffer is empty and read-socket shutdown: * tell peer, that we will not send more data: * send IEOF. * hack for extended data: delay EOF if EFD still * in use. */ if (CHANNEL_EFD_INPUT_ACTIVE(c)) debug2("channel %d: " "ibuf_empty delayed efd %d/(%zu)", c->self, c->efd, sshbuf_len(c->extended)); else chan_ibuf_empty(ssh, c); } return 0; } if (!c->have_remote_id) 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_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 * backpressure at read time? (i.e. read + discard) */ if (plen > c->remote_window || plen > c->remote_maxpacket) { debug("channel %d: datagram too big", c->self); return 0; } /* Enqueue it */ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_string(ssh, pkt, plen)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %i: send datagram", c->self); c->remote_window -= plen; return 1; } /* Enqueue packet for buffered data. */ if (len > c->remote_window) len = c->remote_window; if (len > c->remote_maxpacket) len = c->remote_maxpacket; if (len == 0) return 0; 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_fr(r, "channel %i: send data", c->self); if ((r = sshbuf_consume(c->input, len)) != 0) fatal_fr(r, "channel %i: consume", c->self); c->remote_window -= len; return 1; } /* * Enqueue data for channels with open c->extended in read mode. * Returns non-zero if a packet was enqueued. */ static int channel_output_poll_extended_read(struct ssh *ssh, Channel *c) { size_t len; int r; if ((len = sshbuf_len(c->extended)) == 0) return 0; debug2("channel %d: rwin %u elen %zu euse %d", c->self, c->remote_window, sshbuf_len(c->extended), c->extended_usage); if (len > c->remote_window) len = c->remote_window; if (len > c->remote_maxpacket) len = c->remote_maxpacket; if (len == 0) return 0; if (!c->have_remote_id) 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_fr(r, "channel %i: data", c->self); if ((r = sshbuf_consume(c->extended, len)) != 0) fatal_fr(r, "channel %i: consume", c->self); c->remote_window -= len; debug2("channel %d: sent ext data %zu", c->self, len); return 1; } /* * If there is data to send to the connection, enqueue some of it now. * Returns non-zero if data was enqueued. */ int channel_output_poll(struct ssh *ssh) { struct ssh_channels *sc = ssh->chanctxt; Channel *c; u_int i; int ret = 0; for (i = 0; i < sc->channels_alloc; i++) { c = sc->channels[i]; if (c == NULL) continue; /* * We are only interested in channels that can have buffered * incoming data. */ if (c->type != SSH_CHANNEL_OPEN) continue; if ((c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { /* XXX is this true? */ debug3("channel %d: will not send data after close", c->self); continue; } /* Get the amount of buffered data for this channel. */ if (c->istate == CHAN_INPUT_OPEN || c->istate == CHAN_INPUT_WAIT_DRAIN) ret |= channel_output_poll_input_open(ssh, c); /* Send extended data, i.e. stderr */ if (!(c->flags & CHAN_EOF_SENT) && c->extended_usage == CHAN_EXTENDED_READ) ret |= channel_output_poll_extended_read(ssh, c); } return ret; } /* -- mux proxy support */ /* * When multiplexing channel messages for mux clients we have to deal * with downstream messages from the mux client and upstream messages * from the ssh server: * 1) Handling downstream messages is straightforward and happens * in channel_proxy_downstream(): * - We forward all messages (mostly) unmodified to the server. * - However, in order to route messages from upstream to the correct * downstream client, we have to replace the channel IDs used by the * mux clients with a unique channel ID because the mux clients might * use conflicting channel IDs. * - so we inspect and change both SSH2_MSG_CHANNEL_OPEN and * SSH2_MSG_CHANNEL_OPEN_CONFIRMATION messages, create a local * SSH_CHANNEL_MUX_PROXY channel and replace the mux clients ID * with the newly allocated channel ID. * 2) Upstream messages are received by matching SSH_CHANNEL_MUX_PROXY * channels and processed by channel_proxy_upstream(). The local channel ID * is then translated back to the original mux client ID. * 3) In both cases we need to keep track of matching SSH2_MSG_CHANNEL_CLOSE * messages so we can clean up SSH_CHANNEL_MUX_PROXY channels. * 4) The SSH_CHANNEL_MUX_PROXY channels also need to closed when the * downstream mux client are removed. * 5) Handling SSH2_MSG_CHANNEL_OPEN messages from the upstream server * requires more work, because they are not addressed to a specific * channel. E.g. client_request_forwarded_tcpip() needs to figure * out whether the request is addressed to the local client or a * specific downstream client based on the listen-address/port. * 6) Agent and X11-Forwarding have a similar problem and are currently * not supported as the matching session/channel cannot be identified * easily. */ /* * receive packets from downstream mux clients: * channel callback fired on read from mux client, creates * SSH_CHANNEL_MUX_PROXY channels and translates channel IDs * on channel creation. */ int channel_proxy_downstream(struct ssh *ssh, Channel *downstream) { Channel *c = NULL; struct sshbuf *original = NULL, *modified = NULL; const u_char *cp; char *ctype = NULL, *listen_host = NULL; u_char type; size_t have; int ret = -1, r; u_int id, remote_id, listen_port; /* sshbuf_dump(downstream->input, stderr); */ if ((r = sshbuf_get_string_direct(downstream->input, &cp, &have)) != 0) { error_fr(r, "parse"); return -1; } if (have < 2) { error_f("short message"); return -1; } type = cp[1]; /* skip padlen + type */ cp += 2; have -= 2; if (ssh_packet_log_type(type)) 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_f("alloc"); goto out; } if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0 || (r = sshbuf_get_u32(original, &id)) != 0) { error_fr(r, "parse"); goto out; } c = channel_new(ssh, "mux-proxy", SSH_CHANNEL_MUX_PROXY, -1, -1, -1, 0, 0, 0, ctype, 1); c->mux_ctx = downstream; /* point to mux client */ c->mux_downstream_id = id; /* original downstream id */ if ((r = sshbuf_put_cstring(modified, ctype)) != 0 || (r = sshbuf_put_u32(modified, c->self)) != 0 || (r = sshbuf_putb(modified, original)) != 0) { error_fr(r, "compose"); channel_free(ssh, c); goto out; } break; case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: /* * Almost the same as SSH2_MSG_CHANNEL_OPEN, except then we * need to parse 'remote_id' instead of 'ctype'. */ if ((original = sshbuf_from(cp, have)) == NULL || (modified = sshbuf_new()) == NULL) { error_f("alloc"); goto out; } if ((r = sshbuf_get_u32(original, &remote_id)) != 0 || (r = sshbuf_get_u32(original, &id)) != 0) { error_fr(r, "parse"); goto out; } c = channel_new(ssh, "mux-proxy", SSH_CHANNEL_MUX_PROXY, -1, -1, -1, 0, 0, 0, "mux-down-connect", 1); c->mux_ctx = downstream; /* point to mux client */ c->mux_downstream_id = id; c->remote_id = remote_id; c->have_remote_id = 1; if ((r = sshbuf_put_u32(modified, remote_id)) != 0 || (r = sshbuf_put_u32(modified, c->self)) != 0 || (r = sshbuf_putb(modified, original)) != 0) { error_fr(r, "compose"); channel_free(ssh, c); goto out; } break; case SSH2_MSG_GLOBAL_REQUEST: if ((original = sshbuf_from(cp, have)) == NULL) { error_f("alloc"); goto out; } if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0) { error_fr(r, "parse"); goto out; } if (strcmp(ctype, "tcpip-forward") != 0) { 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_fr(r, "parse"); goto out; } if (listen_port > 65535) { error_f("tcpip-forward for %s: bad port %u", listen_host, listen_port); goto out; } /* Record that connection to this host/port is permitted. */ permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL, "", -1, listen_host, NULL, (int)listen_port, downstream); listen_host = NULL; break; case SSH2_MSG_CHANNEL_CLOSE: if (have < 4) break; remote_id = PEEK_U32(cp); if ((c = channel_by_remote_id(ssh, remote_id)) != NULL) { if (c->flags & CHAN_CLOSE_RCVD) channel_free(ssh, c); else c->flags |= CHAN_CLOSE_SENT; } break; } if (modified) { if ((r = sshpkt_start(ssh, type)) != 0 || (r = sshpkt_putb(ssh, modified)) != 0 || (r = sshpkt_send(ssh)) != 0) { error_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_fr(r, "send"); goto out; } } ret = 0; out: free(ctype); free(listen_host); sshbuf_free(original); sshbuf_free(modified); return ret; } /* * receive packets from upstream server and de-multiplex packets * to correct downstream: * implemented as a helper for channel input handlers, * replaces local (proxy) channel ID with downstream channel ID. */ int channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh) { struct sshbuf *b = NULL; Channel *downstream; const u_char *cp = NULL; size_t len; int r; /* * When receiving packets from the peer we need to check whether we * need to forward the packets to the mux client. In this case we * restore the original channel id and keep track of CLOSE messages, * so we can cleanup the channel. */ if (c == NULL || c->type != SSH_CHANNEL_MUX_PROXY) return 0; if ((downstream = c->mux_ctx) == NULL) return 0; switch (type) { case SSH2_MSG_CHANNEL_CLOSE: case SSH2_MSG_CHANNEL_DATA: case SSH2_MSG_CHANNEL_EOF: case SSH2_MSG_CHANNEL_EXTENDED_DATA: case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: case SSH2_MSG_CHANNEL_OPEN_FAILURE: case SSH2_MSG_CHANNEL_WINDOW_ADJUST: case SSH2_MSG_CHANNEL_SUCCESS: case SSH2_MSG_CHANNEL_FAILURE: case SSH2_MSG_CHANNEL_REQUEST: break; default: debug2_f("channel %u: unsupported type %u", c->self, type); return 0; } if ((b = sshbuf_new()) == NULL) { error_f("alloc reply"); goto out; } /* get remaining payload (after id) */ cp = sshpkt_ptr(ssh, &len); if (cp == NULL) { error_f("no packet"); goto out; } /* translate id and send to muxclient */ if ((r = sshbuf_put_u8(b, 0)) != 0 || /* padlen */ (r = sshbuf_put_u8(b, type)) != 0 || (r = sshbuf_put_u32(b, c->mux_downstream_id)) != 0 || (r = sshbuf_put(b, cp, len)) != 0 || (r = sshbuf_put_stringb(downstream->output, b)) != 0) { error_fr(r, "compose muxclient"); goto out; } /* sshbuf_dump(b, stderr); */ if (ssh_packet_log_type(type)) debug3_f("channel %u: up->down: type %u", c->self, type); out: /* update state */ switch (type) { case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: /* record remote_id for SSH2_MSG_CHANNEL_CLOSE */ if (cp && len > 4) { c->remote_id = PEEK_U32(cp); c->have_remote_id = 1; } break; case SSH2_MSG_CHANNEL_CLOSE: if (c->flags & CHAN_CLOSE_SENT) channel_free(ssh, c); else c->flags |= CHAN_CLOSE_RCVD; break; } sshbuf_free(b); return 1; } /* -- protocol input */ /* Parse a channel ID from the current packet */ static int channel_parse_id(struct ssh *ssh, const char *where, const char *what) { u_int32_t id; int r; if ((r = sshpkt_get_u32(ssh, &id)) != 0) { error_r(r, "%s: parse id", where); ssh_packet_disconnect(ssh, "Invalid %s message", what); } if (id > INT_MAX) { error_r(r, "%s: bad channel id %u", where, id); ssh_packet_disconnect(ssh, "Invalid %s channel id", what); } return (int)id; } /* Lookup a channel from an ID in the current packet */ static Channel * channel_from_packet_id(struct ssh *ssh, const char *where, const char *what) { int id = channel_parse_id(ssh, where, what); Channel *c; if ((c = channel_lookup(ssh, id)) == NULL) { ssh_packet_disconnect(ssh, "%s packet referred to nonexistent channel %d", what, id); } return c; } int channel_input_data(int type, u_int32_t seq, struct ssh *ssh) { const u_char *data; size_t data_len, win_len; Channel *c = channel_from_packet_id(ssh, __func__, "data"); int r; if (channel_proxy_upstream(c, type, seq, ssh)) return 0; /* Ignore any data for non-open channels (might happen on close) */ if (c->type != SSH_CHANNEL_OPEN && c->type != SSH_CHANNEL_RDYNAMIC_OPEN && c->type != SSH_CHANNEL_RDYNAMIC_FINISH && c->type != SSH_CHANNEL_X11_OPEN) return 0; /* Get the data. */ if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 || (r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "channel %i: get data", c->self); win_len = data_len; if (c->datagram) win_len += 4; /* string length header */ /* * The sending side reduces its window as it sends data, so we * must 'fake' consumption of the data in order to ensure that window * updates are sent back. Otherwise the connection might deadlock. */ if (c->ostate != CHAN_OUTPUT_OPEN) { c->local_window -= win_len; c->local_consumed += win_len; return 0; } if (win_len > c->local_maxpacket) { logit("channel %d: rcvd big packet %zu, maxpack %u", c->self, win_len, c->local_maxpacket); return 0; } if (win_len > c->local_window) { - logit("channel %d: rcvd too much data %zu, win %u", - c->self, win_len, c->local_window); - return 0; + c->local_window_exceeded += win_len - c->local_window; + logit("channel %d: rcvd too much data %zu, win %u/%u " + "(excess %u)", c->self, win_len, c->local_window, + c->local_window_max, c->local_window_exceeded); + c->local_window = 0; + /* Allow 10% grace before bringing the hammer down */ + if (c->local_window_exceeded > (c->local_window_max / 10)) { + ssh_packet_disconnect(ssh, "channel %d: peer ignored " + "channel window", c->self); + } + } else { + c->local_window -= win_len; + c->local_window_exceeded = 0; } - c->local_window -= win_len; if (c->datagram) { if ((r = sshbuf_put_string(c->output, data, data_len)) != 0) fatal_fr(r, "channel %i: append datagram", c->self); } else if ((r = sshbuf_put(c->output, data, data_len)) != 0) fatal_fr(r, "channel %i: append data", c->self); return 0; } int channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh) { const u_char *data; size_t data_len; u_int32_t tcode; Channel *c = channel_from_packet_id(ssh, __func__, "extended data"); int r; if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if (c->type != SSH_CHANNEL_OPEN) { logit("channel %d: ext data for non open", c->self); return 0; } if (c->flags & CHAN_EOF_RCVD) { if (ssh->compat & SSH_BUG_EXTEOF) debug("channel %d: accepting ext data after eof", c->self); else ssh_packet_disconnect(ssh, "Received extended_data " "after EOF on channel %d.", c->self); } if ((r = sshpkt_get_u32(ssh, &tcode)) != 0) { error_fr(r, "parse tcode"); ssh_packet_disconnect(ssh, "Invalid extended_data message"); } if (c->efd == -1 || c->extended_usage != CHAN_EXTENDED_WRITE || tcode != SSH2_EXTENDED_DATA_STDERR) { logit("channel %d: bad ext data", c->self); return 0; } if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 || (r = sshpkt_get_end(ssh)) != 0) { error_fr(r, "parse data"); ssh_packet_disconnect(ssh, "Invalid extended_data message"); } if (data_len > c->local_window) { logit("channel %d: rcvd too much extended_data %zu, win %u", c->self, data_len, c->local_window); return 0; } debug2("channel %d: rcvd ext data %zu", c->self, data_len); /* XXX sshpkt_getb? */ if ((r = sshbuf_put(c->extended, data, data_len)) != 0) error_fr(r, "append"); c->local_window -= data_len; return 0; } int channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = channel_from_packet_id(ssh, __func__, "ieof"); int r; if ((r = sshpkt_get_end(ssh)) != 0) { error_fr(r, "parse data"); ssh_packet_disconnect(ssh, "Invalid ieof message"); } if (channel_proxy_upstream(c, type, seq, ssh)) return 0; chan_rcvd_ieof(ssh, c); /* XXX force input close */ if (c->force_drain && c->istate == CHAN_INPUT_OPEN) { debug("channel %d: FORCE input drain", c->self); c->istate = CHAN_INPUT_WAIT_DRAIN; if (sshbuf_len(c->input) == 0) chan_ibuf_empty(ssh, c); } return 0; } int channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = channel_from_packet_id(ssh, __func__, "oclose"); int r; if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if ((r = sshpkt_get_end(ssh)) != 0) { error_fr(r, "parse data"); ssh_packet_disconnect(ssh, "Invalid oclose message"); } chan_rcvd_oclose(ssh, c); return 0; } int channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = channel_from_packet_id(ssh, __func__, "open confirmation"); u_int32_t remote_window, remote_maxpacket; int r; if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if (c->type != SSH_CHANNEL_OPENING) ssh_packet_disconnect(ssh, "Received open confirmation for " "non-opening channel %d.", c->self); /* * Record the remote channel number and mark that the channel * is now open. */ if ((r = sshpkt_get_u32(ssh, &c->remote_id)) != 0 || (r = sshpkt_get_u32(ssh, &remote_window)) != 0 || (r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0 || (r = sshpkt_get_end(ssh)) != 0) { error_fr(r, "window/maxpacket"); ssh_packet_disconnect(ssh, "Invalid open confirmation message"); } c->have_remote_id = 1; c->remote_window = remote_window; c->remote_maxpacket = remote_maxpacket; c->type = SSH_CHANNEL_OPEN; if (c->open_confirm) { debug2_f("channel %d: callback start", c->self); c->open_confirm(ssh, c->self, 1, c->open_confirm_ctx); debug2_f("channel %d: callback done", c->self); } c->lastused = monotime(); debug2("channel %d: open confirm rwindow %u rmax %u", c->self, c->remote_window, c->remote_maxpacket); return 0; } static char * reason2txt(int reason) { switch (reason) { case SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED: return "administratively prohibited"; case SSH2_OPEN_CONNECT_FAILED: return "connect failed"; case SSH2_OPEN_UNKNOWN_CHANNEL_TYPE: return "unknown channel type"; case SSH2_OPEN_RESOURCE_SHORTAGE: return "resource shortage"; } return "unknown reason"; } int channel_input_open_failure(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = channel_from_packet_id(ssh, __func__, "open failure"); u_int32_t reason; char *msg = NULL; int r; if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if (c->type != SSH_CHANNEL_OPENING) ssh_packet_disconnect(ssh, "Received open failure for " "non-opening channel %d.", c->self); if ((r = sshpkt_get_u32(ssh, &reason)) != 0) { 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_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_f("channel %d: callback start", c->self); c->open_confirm(ssh, c->self, 0, c->open_confirm_ctx); debug2_f("channel %d: callback done", c->self); } /* Schedule the channel for cleanup/deletion. */ chan_mark_dead(ssh, c); return 0; } int channel_input_window_adjust(int type, u_int32_t seq, struct ssh *ssh) { int id = channel_parse_id(ssh, __func__, "window adjust"); Channel *c; u_int32_t adjust; u_int new_rwin; int r; if ((c = channel_lookup(ssh, id)) == NULL) { logit("Received window adjust for non-open channel %d.", id); return 0; } if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if ((r = sshpkt_get_u32(ssh, &adjust)) != 0 || (r = sshpkt_get_end(ssh)) != 0) { error_fr(r, "parse adjust"); ssh_packet_disconnect(ssh, "Invalid window adjust message"); } debug2("channel %d: rcvd adjust %u", c->self, adjust); if ((new_rwin = c->remote_window + adjust) < c->remote_window) { fatal("channel %d: adjust %u overflows remote window %u", c->self, adjust, c->remote_window); } c->remote_window = new_rwin; return 0; } int channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh) { int id = channel_parse_id(ssh, __func__, "status confirm"); Channel *c; struct channel_confirm *cc; /* Reset keepalive timeout */ ssh_packet_set_alive_timeouts(ssh, 0); debug2_f("type %d id %d", type, id); if ((c = channel_lookup(ssh, id)) == NULL) { logit_f("%d: unknown", id); return 0; } if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if (sshpkt_get_end(ssh) != 0) ssh_packet_disconnect(ssh, "Invalid status confirm message"); if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL) return 0; cc->cb(ssh, type, c, cc->ctx); TAILQ_REMOVE(&c->status_confirms, cc, entry); freezero(cc, sizeof(*cc)); return 0; } /* -- tcp forwarding */ void channel_set_af(struct ssh *ssh, int af) { ssh->chanctxt->IPv4or6 = af; } /* * Determine whether or not a port forward listens to loopback, the * specified address or wildcard. On the client, a specified bind * address will always override gateway_ports. On the server, a * gateway_ports of 1 (``yes'') will override the client's specification * and force a wildcard bind, whereas a value of 2 (``clientspecified'') * will bind to whatever address the client asked for. * * Special-case listen_addrs are: * * "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR * "" (empty string), "*" -> wildcard v4/v6 * "localhost" -> loopback v4/v6 * "127.0.0.1" / "::1" -> accepted even if gateway_ports isn't set */ static const char * channel_fwd_bind_addr(struct ssh *ssh, const char *listen_addr, int *wildcardp, int is_client, struct ForwardOptions *fwd_opts) { const char *addr = NULL; int wildcard = 0; if (listen_addr == NULL) { /* No address specified: default to gateway_ports setting */ if (fwd_opts->gateway_ports) wildcard = 1; } else if (fwd_opts->gateway_ports || is_client) { if (((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)) { wildcard = 1; /* * Notify client if they requested a specific listen * address and it was overridden. */ if (*listen_addr != '\0' && strcmp(listen_addr, "0.0.0.0") != 0 && strcmp(listen_addr, "*") != 0) { ssh_packet_send_debug(ssh, "Forwarding listen address " "\"%s\" overridden by server " "GatewayPorts", listen_addr); } } else if (strcmp(listen_addr, "localhost") != 0 || strcmp(listen_addr, "127.0.0.1") == 0 || strcmp(listen_addr, "::1") == 0) { /* * Accept 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 || strcmp(listen_addr, "::1") == 0) { /* * If a specific IPv4/IPv6 localhost address has been * requested then accept it even if gateway_ports is in * effect. This allows the client to prefer IPv4 or IPv6. */ addr = listen_addr; } if (wildcardp != NULL) *wildcardp = wildcard; return addr; } static int channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type, struct Forward *fwd, int *allocated_listen_port, struct ForwardOptions *fwd_opts) { Channel *c; int sock, r, success = 0, wildcard = 0, is_client; struct addrinfo hints, *ai, *aitop; const char *host, *addr; char ntop[NI_MAXHOST], strport[NI_MAXSERV]; in_port_t *lport_p; is_client = (type == SSH_CHANNEL_PORT_LISTENER); if (is_client && fwd->connect_path != NULL) { host = fwd->connect_path; } else { host = (type == SSH_CHANNEL_RPORT_LISTENER) ? fwd->listen_host : fwd->connect_host; if (host == NULL) { error("No forward host name."); return 0; } if (strlen(host) >= NI_MAXHOST) { error("Forward host name too long."); return 0; } } /* Determine the bind address, cf. channel_fwd_bind_addr() comment */ addr = channel_fwd_bind_addr(ssh, fwd->listen_host, &wildcard, is_client, fwd_opts); debug3_f("type %d wildcard %d addr %s", type, wildcard, (addr == NULL) ? "NULL" : addr); /* * getaddrinfo returns a loopback address if the hostname is * set to NULL and hints.ai_flags is not AI_PASSIVE */ memset(&hints, 0, sizeof(hints)); hints.ai_family = ssh->chanctxt->IPv4or6; hints.ai_flags = wildcard ? AI_PASSIVE : 0; hints.ai_socktype = SOCK_STREAM; snprintf(strport, sizeof strport, "%d", fwd->listen_port); if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) { if (addr == NULL) { /* This really shouldn't happen */ ssh_packet_disconnect(ssh, "getaddrinfo: fatal error: %s", ssh_gai_strerror(r)); } else { error_f("getaddrinfo(%.64s): %s", addr, ssh_gai_strerror(r)); } return 0; } if (allocated_listen_port != NULL) *allocated_listen_port = 0; for (ai = aitop; ai; ai = ai->ai_next) { switch (ai->ai_family) { case AF_INET: lport_p = &((struct sockaddr_in *)ai->ai_addr)-> sin_port; break; case AF_INET6: lport_p = &((struct sockaddr_in6 *)ai->ai_addr)-> sin6_port; break; default: continue; } /* * If allocating a port for -R forwards, then use the * same port for all address families. */ if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 && allocated_listen_port != NULL && *allocated_listen_port > 0) *lport_p = htons(*allocated_listen_port); if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { error_f("getnameinfo failed"); continue; } /* Create a port to listen for the host. */ sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock == -1) { /* this is no error since kernel may not support ipv6 */ verbose("socket [%s]:%s: %.100s", ntop, strport, strerror(errno)); continue; } set_reuseaddr(sock); if (ai->ai_family == AF_INET6) sock_set_v6only(sock); debug("Local forwarding listening on %s port %s.", ntop, strport); /* Bind the socket to the address. */ if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) { /* * address can be in if use ipv6 address is * already bound */ if (!ai->ai_next) error("bind [%s]:%s: %.100s", ntop, strport, strerror(errno)); else verbose("bind [%s]:%s: %.100s", ntop, strport, strerror(errno)); close(sock); continue; } /* Start listening for connections on the socket. */ if (listen(sock, SSH_LISTEN_BACKLOG) == -1) { error("listen [%s]:%s: %.100s", ntop, strport, strerror(errno)); close(sock); continue; } /* * fwd->listen_port == 0 requests a dynamically allocated port - * record what we got. */ if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 && allocated_listen_port != NULL && *allocated_listen_port == 0) { *allocated_listen_port = get_local_port(sock); debug("Allocated listen port %d", *allocated_listen_port); } /* Allocate a channel number for the socket. */ c = channel_new(ssh, "port-listener", type, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "port listener", 1); c->path = xstrdup(host); c->host_port = fwd->connect_port; c->listening_addr = addr == NULL ? NULL : xstrdup(addr); if (fwd->listen_port == 0 && allocated_listen_port != NULL && !(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_f("cannot listen to port: %d", fwd->listen_port); freeaddrinfo(aitop); return success; } static int channel_setup_fwd_listener_streamlocal(struct ssh *ssh, int type, struct Forward *fwd, struct ForwardOptions *fwd_opts) { struct sockaddr_un sunaddr; const char *path; Channel *c; int port, sock; mode_t omask; switch (type) { case SSH_CHANNEL_UNIX_LISTENER: if (fwd->connect_path != NULL) { if (strlen(fwd->connect_path) > sizeof(sunaddr.sun_path)) { error("Local connecting path too long: %s", fwd->connect_path); return 0; } path = fwd->connect_path; port = PORT_STREAMLOCAL; } else { if (fwd->connect_host == NULL) { error("No forward host name."); return 0; } if (strlen(fwd->connect_host) >= NI_MAXHOST) { error("Forward host name too long."); return 0; } path = fwd->connect_host; port = fwd->connect_port; } break; case SSH_CHANNEL_RUNIX_LISTENER: path = fwd->listen_path; port = PORT_STREAMLOCAL; break; default: error_f("unexpected channel type %d", type); return 0; } if (fwd->listen_path == NULL) { error("No forward path name."); return 0; } if (strlen(fwd->listen_path) > sizeof(sunaddr.sun_path)) { error("Local listening path too long: %s", fwd->listen_path); return 0; } debug3_f("type %d path %s", type, fwd->listen_path); /* Start a Unix domain listener. */ omask = umask(fwd_opts->streamlocal_bind_mask); sock = unix_listener(fwd->listen_path, SSH_LISTEN_BACKLOG, fwd_opts->streamlocal_bind_unlink); umask(omask); if (sock < 0) return 0; debug("Local forwarding listening on path %s.", fwd->listen_path); /* Allocate a channel number for the socket. */ c = channel_new(ssh, "unix-listener", type, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "unix listener", 1); c->path = xstrdup(path); c->host_port = port; c->listening_port = PORT_STREAMLOCAL; c->listening_addr = xstrdup(fwd->listen_path); return 1; } static int channel_cancel_rport_listener_tcpip(struct ssh *ssh, const char *host, u_short port) { u_int i; int found = 0; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { Channel *c = ssh->chanctxt->channels[i]; if (c == NULL || c->type != SSH_CHANNEL_RPORT_LISTENER) continue; if (strcmp(c->path, host) == 0 && c->listening_port == port) { debug2_f("close channel %d", i); channel_free(ssh, c); found = 1; } } return found; } static int channel_cancel_rport_listener_streamlocal(struct ssh *ssh, const char *path) { u_int i; int found = 0; for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { Channel *c = ssh->chanctxt->channels[i]; if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER) continue; if (c->path == NULL) continue; if (strcmp(c->path, path) == 0) { debug2_f("close channel %d", i); channel_free(ssh, c); found = 1; } } return found; } int channel_cancel_rport_listener(struct ssh *ssh, struct Forward *fwd) { if (fwd->listen_path != NULL) { return channel_cancel_rport_listener_streamlocal(ssh, fwd->listen_path); } else { return channel_cancel_rport_listener_tcpip(ssh, fwd->listen_host, fwd->listen_port); } } static int channel_cancel_lport_listener_tcpip(struct ssh *ssh, const char *lhost, u_short lport, int cport, struct ForwardOptions *fwd_opts) { u_int i; int found = 0; const char *addr = channel_fwd_bind_addr(ssh, lhost, NULL, 1, fwd_opts); for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { Channel *c = ssh->chanctxt->channels[i]; if (c == NULL || c->type != SSH_CHANNEL_PORT_LISTENER) continue; if (c->listening_port != lport) continue; if (cport == CHANNEL_CANCEL_PORT_STATIC) { /* skip dynamic forwardings */ if (c->host_port == 0) continue; } else { if (c->host_port != cport) continue; } if ((c->listening_addr == NULL && addr != NULL) || (c->listening_addr != NULL && addr == NULL)) continue; if (addr == NULL || strcmp(c->listening_addr, addr) == 0) { debug2_f("close channel %d", i); channel_free(ssh, c); found = 1; } } return found; } static int channel_cancel_lport_listener_streamlocal(struct ssh *ssh, const char *path) { u_int i; int found = 0; if (path == NULL) { error_f("no path specified."); return 0; } for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { Channel *c = ssh->chanctxt->channels[i]; if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER) continue; if (c->listening_addr == NULL) continue; if (strcmp(c->listening_addr, path) == 0) { debug2_f("close channel %d", i); channel_free(ssh, c); found = 1; } } return found; } int channel_cancel_lport_listener(struct ssh *ssh, struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts) { if (fwd->listen_path != NULL) { return channel_cancel_lport_listener_streamlocal(ssh, fwd->listen_path); } else { return channel_cancel_lport_listener_tcpip(ssh, fwd->listen_host, fwd->listen_port, cport, fwd_opts); } } /* protocol local port fwd, used by ssh */ int channel_setup_local_fwd_listener(struct ssh *ssh, struct Forward *fwd, struct ForwardOptions *fwd_opts) { if (fwd->listen_path != NULL) { return channel_setup_fwd_listener_streamlocal(ssh, SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts); } else { return channel_setup_fwd_listener_tcpip(ssh, SSH_CHANNEL_PORT_LISTENER, fwd, NULL, fwd_opts); } } /* Matches a remote forwarding permission against a requested forwarding */ static int remote_open_match(struct permission *allowed_open, struct Forward *fwd) { int ret; char *lhost; /* XXX add ACLs for streamlocal */ if (fwd->listen_path != NULL) return 1; if (fwd->listen_host == NULL || allowed_open->listen_host == NULL) return 0; if (allowed_open->listen_port != FWD_PERMIT_ANY_PORT && allowed_open->listen_port != fwd->listen_port) return 0; /* Match hostnames case-insensitively */ lhost = xstrdup(fwd->listen_host); lowercase(lhost); ret = match_pattern(lhost, allowed_open->listen_host); free(lhost); return ret; } /* Checks whether a requested remote forwarding is permitted */ static int check_rfwd_permission(struct ssh *ssh, struct Forward *fwd) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->remote_perms; u_int i, permit, permit_adm = 1; struct permission *perm; /* XXX apply GatewayPorts override before checking? */ permit = pset->all_permitted; if (!permit) { for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (remote_open_match(perm, fwd)) { permit = 1; break; } } } if (pset->num_permitted_admin > 0) { permit_adm = 0; for (i = 0; i < pset->num_permitted_admin; i++) { perm = &pset->permitted_admin[i]; if (remote_open_match(perm, fwd)) { permit_adm = 1; break; } } } return permit && permit_adm; } /* protocol v2 remote port fwd, used by sshd */ int channel_setup_remote_fwd_listener(struct ssh *ssh, struct Forward *fwd, int *allocated_listen_port, struct ForwardOptions *fwd_opts) { if (!check_rfwd_permission(ssh, fwd)) { ssh_packet_send_debug(ssh, "port forwarding refused"); if (fwd->listen_path != NULL) /* XXX always allowed, see remote_open_match() */ logit("Received request from %.100s port %d to " "remote forward to path \"%.100s\", " "but the request was denied.", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), fwd->listen_path); else if(fwd->listen_host != NULL) logit("Received request from %.100s port %d to " "remote forward to host %.100s port %d, " "but the request was denied.", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), fwd->listen_host, fwd->listen_port ); else logit("Received request from %.100s port %d to remote " "forward, but the request was denied.", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh)); return 0; } if (fwd->listen_path != NULL) { return channel_setup_fwd_listener_streamlocal(ssh, SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts); } else { return channel_setup_fwd_listener_tcpip(ssh, SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port, fwd_opts); } } /* * Translate the requested rfwd listen host to something usable for * this server. */ static const char * channel_rfwd_bind_host(const char *listen_host) { if (listen_host == NULL) { return "localhost"; } else if (*listen_host == '\0' || strcmp(listen_host, "*") == 0) { return ""; } else return listen_host; } /* * Initiate forwarding of connections to port "port" on remote host through * the secure channel to host:port from local side. * Returns handle (index) for updating the dynamic listen port with * channel_update_permission(). */ int channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd) { int r, success = 0, idx = -1; const char *host_to_connect, *listen_host, *listen_path; int port_to_connect, listen_port; /* Send the forward request to the remote side. */ if (fwd->listen_path != NULL) { if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "streamlocal-forward@openssh.com")) != 0 || (r = sshpkt_put_u8(ssh, 1)) != 0 || /* want reply */ (r = sshpkt_put_cstring(ssh, fwd->listen_path)) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "request streamlocal"); } else { if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "tcpip-forward")) != 0 || (r = sshpkt_put_u8(ssh, 1)) != 0 || /* want reply */ (r = sshpkt_put_cstring(ssh, channel_rfwd_bind_host(fwd->listen_host))) != 0 || (r = sshpkt_put_u32(ssh, fwd->listen_port)) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "request tcpip-forward"); } /* Assume that server accepts the request */ success = 1; if (success) { /* Record that connection to this host/port is permitted. */ host_to_connect = listen_host = listen_path = NULL; port_to_connect = listen_port = 0; if (fwd->connect_path != NULL) { host_to_connect = fwd->connect_path; port_to_connect = PORT_STREAMLOCAL; } else { host_to_connect = fwd->connect_host; port_to_connect = fwd->connect_port; } if (fwd->listen_path != NULL) { listen_path = fwd->listen_path; listen_port = PORT_STREAMLOCAL; } else { listen_host = fwd->listen_host; listen_port = fwd->listen_port; } idx = permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL, host_to_connect, port_to_connect, listen_host, listen_path, listen_port, NULL); } return idx; } static int open_match(struct permission *allowed_open, const char *requestedhost, int requestedport) { if (allowed_open->host_to_connect == NULL) return 0; if (allowed_open->port_to_connect != FWD_PERMIT_ANY_PORT && allowed_open->port_to_connect != requestedport) return 0; if (strcmp(allowed_open->host_to_connect, FWD_PERMIT_ANY_HOST) != 0 && strcmp(allowed_open->host_to_connect, requestedhost) != 0) return 0; return 1; } /* * Note that in the listen host/port case * we don't support FWD_PERMIT_ANY_PORT and * need to translate between the configured-host (listen_host) * and what we've sent to the remote server (channel_rfwd_bind_host) */ static int open_listen_match_tcpip(struct permission *allowed_open, const char *requestedhost, u_short requestedport, int translate) { const char *allowed_host; if (allowed_open->host_to_connect == NULL) return 0; if (allowed_open->listen_port != requestedport) return 0; if (!translate && allowed_open->listen_host == NULL && requestedhost == NULL) return 1; allowed_host = translate ? channel_rfwd_bind_host(allowed_open->listen_host) : allowed_open->listen_host; if (allowed_host == NULL || requestedhost == NULL || strcmp(allowed_host, requestedhost) != 0) return 0; return 1; } static int open_listen_match_streamlocal(struct permission *allowed_open, const char *requestedpath) { if (allowed_open->host_to_connect == NULL) return 0; if (allowed_open->listen_port != PORT_STREAMLOCAL) return 0; if (allowed_open->listen_path == NULL || strcmp(allowed_open->listen_path, requestedpath) != 0) return 0; return 1; } /* * Request cancellation of remote forwarding of connection host:port from * local side. */ static int channel_request_rforward_cancel_tcpip(struct ssh *ssh, const char *host, u_short port) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->local_perms; int r; u_int i; struct permission *perm = NULL; for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (open_listen_match_tcpip(perm, host, port, 0)) break; perm = NULL; } if (perm == NULL) { debug_f("requested forward not found"); return -1; } if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "cancel-tcpip-forward")) != 0 || (r = sshpkt_put_u8(ssh, 0)) != 0 || /* want reply */ (r = sshpkt_put_cstring(ssh, channel_rfwd_bind_host(host))) != 0 || (r = sshpkt_put_u32(ssh, port)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send cancel"); fwd_perm_clear(perm); /* unregister */ return 0; } /* * Request cancellation of remote forwarding of Unix domain socket * path from local side. */ static int channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->local_perms; int r; u_int i; struct permission *perm = NULL; for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (open_listen_match_streamlocal(perm, path)) break; perm = NULL; } if (perm == NULL) { debug_f("requested forward not found"); return -1; } if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "cancel-streamlocal-forward@openssh.com")) != 0 || (r = sshpkt_put_u8(ssh, 0)) != 0 || /* want reply */ (r = sshpkt_put_cstring(ssh, path)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send cancel"); fwd_perm_clear(perm); /* unregister */ return 0; } /* * Request cancellation of remote forwarding of a connection from local side. */ int channel_request_rforward_cancel(struct ssh *ssh, struct Forward *fwd) { if (fwd->listen_path != NULL) { return channel_request_rforward_cancel_streamlocal(ssh, fwd->listen_path); } else { return channel_request_rforward_cancel_tcpip(ssh, fwd->listen_host, fwd->listen_port ? fwd->listen_port : fwd->allocated_port); } } /* * Permits opening to any host/port if permitted_user[] is empty. This is * usually called by the server, because the user could connect to any port * anyway, and the server has no way to know but to trust the client anyway. */ void channel_permit_all(struct ssh *ssh, int where) { struct permission_set *pset = permission_set_get(ssh, where); if (pset->num_permitted_user == 0) pset->all_permitted = 1; } /* * Permit the specified host/port for forwarding. */ void channel_add_permission(struct ssh *ssh, int who, int where, char *host, int port) { int local = where == FORWARD_LOCAL; struct permission_set *pset = permission_set_get(ssh, where); debug("allow %s forwarding to host %s port %d", fwd_ident(who, where), host, port); /* * Remote forwards set listen_host/port, local forwards set * host/port_to_connect. */ permission_set_add(ssh, who, where, local ? host : 0, local ? port : 0, local ? NULL : host, NULL, local ? 0 : port, NULL); pset->all_permitted = 0; } /* * Administratively disable forwarding. */ void channel_disable_admin(struct ssh *ssh, int where) { channel_clear_permission(ssh, FORWARD_ADM, where); permission_set_add(ssh, FORWARD_ADM, where, NULL, 0, NULL, NULL, 0, NULL); } /* * Clear a list of permitted opens. */ void channel_clear_permission(struct ssh *ssh, int who, int where) { struct permission **permp; u_int *npermp; permission_set_get_array(ssh, who, where, &permp, &npermp); *permp = xrecallocarray(*permp, *npermp, 0, sizeof(**permp)); *npermp = 0; } /* * Update the listen port for a dynamic remote forward, after * the actual 'newport' has been allocated. If 'newport' < 0 is * passed then they entry will be invalidated. */ void channel_update_permission(struct ssh *ssh, int idx, int newport) { struct permission_set *pset = &ssh->chanctxt->local_perms; if (idx < 0 || (u_int)idx >= pset->num_permitted_user) { debug_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", newport > 0 ? "Updating" : "Removing", newport, pset->permitted_user[idx].host_to_connect, pset->permitted_user[idx].port_to_connect); if (newport <= 0) fwd_perm_clear(&pset->permitted_user[idx]); else { pset->permitted_user[idx].listen_port = (ssh->compat & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport; } } /* returns port number, FWD_PERMIT_ANY_PORT or -1 on error */ int permitopen_port(const char *p) { int port; if (strcmp(p, "*") == 0) return FWD_PERMIT_ANY_PORT; if ((port = a2port(p)) > 0) return port; return -1; } /* Try to start non-blocking connect to next host in cctx list */ static int connect_next(struct channel_connect *cctx) { int sock, saved_errno; struct sockaddr_un *sunaddr; char ntop[NI_MAXHOST]; char strport[MAXIMUM(NI_MAXSERV, sizeof(sunaddr->sun_path))]; for (; cctx->ai; cctx->ai = cctx->ai->ai_next) { switch (cctx->ai->ai_family) { case AF_UNIX: /* unix:pathname instead of host:port */ sunaddr = (struct sockaddr_un *)cctx->ai->ai_addr; strlcpy(ntop, "unix", sizeof(ntop)); strlcpy(strport, sunaddr->sun_path, sizeof(strport)); break; case AF_INET: case AF_INET6: if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { error_f("getnameinfo failed"); continue; } break; default: continue; } debug_f("start for host %.100s ([%.100s]:%s)", cctx->host, ntop, strport); if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype, cctx->ai->ai_protocol)) == -1) { if (cctx->ai->ai_next == NULL) error("socket: %.100s", strerror(errno)); else verbose("socket: %.100s", strerror(errno)); continue; } if (set_nonblock(sock) == -1) fatal_f("set_nonblock(%d)", sock); if (connect(sock, cctx->ai->ai_addr, cctx->ai->ai_addrlen) == -1 && errno != EINPROGRESS) { debug_f("host %.100s ([%.100s]:%s): %.100s", cctx->host, ntop, strport, strerror(errno)); saved_errno = errno; close(sock); errno = saved_errno; continue; /* fail -- try next */ } if (cctx->ai->ai_family != AF_UNIX) set_nodelay(sock); debug_f("connect host %.100s ([%.100s]:%s) in progress, fd=%d", cctx->host, ntop, strport, sock); cctx->ai = cctx->ai->ai_next; return sock; } return -1; } static void channel_connect_ctx_free(struct channel_connect *cctx) { free(cctx->host); if (cctx->aitop) { if (cctx->aitop->ai_family == AF_UNIX) free(cctx->aitop); else freeaddrinfo(cctx->aitop); } memset(cctx, 0, sizeof(*cctx)); } /* * Return connecting socket to remote host:port or local socket path, * passing back the failure reason if appropriate. */ static int connect_to_helper(struct ssh *ssh, const char *name, int port, int socktype, char *ctype, char *rname, struct channel_connect *cctx, int *reason, const char **errmsg) { struct addrinfo hints; int gaierr; int sock = -1; char strport[NI_MAXSERV]; if (port == PORT_STREAMLOCAL) { struct sockaddr_un *sunaddr; struct addrinfo *ai; if (strlen(name) > sizeof(sunaddr->sun_path)) { error("%.100s: %.100s", name, strerror(ENAMETOOLONG)); return -1; } /* * Fake up a struct addrinfo for AF_UNIX connections. * channel_connect_ctx_free() must check ai_family * and use free() not freeaddirinfo() for AF_UNIX. */ ai = xmalloc(sizeof(*ai) + sizeof(*sunaddr)); memset(ai, 0, sizeof(*ai) + sizeof(*sunaddr)); ai->ai_addr = (struct sockaddr *)(ai + 1); ai->ai_addrlen = sizeof(*sunaddr); ai->ai_family = AF_UNIX; ai->ai_socktype = socktype; ai->ai_protocol = PF_UNSPEC; sunaddr = (struct sockaddr_un *)ai->ai_addr; sunaddr->sun_family = AF_UNIX; strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path)); cctx->aitop = ai; } else { memset(&hints, 0, sizeof(hints)); hints.ai_family = ssh->chanctxt->IPv4or6; hints.ai_socktype = socktype; snprintf(strport, sizeof strport, "%d", port); if ((gaierr = getaddrinfo(name, strport, &hints, &cctx->aitop)) != 0) { if (errmsg != NULL) *errmsg = ssh_gai_strerror(gaierr); if (reason != NULL) *reason = SSH2_OPEN_CONNECT_FAILED; error("connect_to %.100s: unknown host (%s)", name, ssh_gai_strerror(gaierr)); return -1; } } cctx->host = xstrdup(name); cctx->port = port; cctx->ai = cctx->aitop; if ((sock = connect_next(cctx)) == -1) { error("connect to %.100s port %d failed: %s", name, port, strerror(errno)); return -1; } return sock; } /* Return CONNECTING channel to remote host:port or local socket path */ static Channel * connect_to(struct ssh *ssh, const char *host, int port, char *ctype, char *rname) { struct channel_connect cctx; Channel *c; int sock; memset(&cctx, 0, sizeof(cctx)); sock = connect_to_helper(ssh, host, port, SOCK_STREAM, ctype, rname, &cctx, NULL, NULL); if (sock == -1) { channel_connect_ctx_free(&cctx); return NULL; } c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); c->host_port = port; c->path = xstrdup(host); c->connect_ctx = cctx; return c; } /* * returns either the newly connected channel or the downstream channel * that needs to deal with this connection. */ Channel * channel_connect_by_listen_address(struct ssh *ssh, const char *listen_host, u_short listen_port, char *ctype, char *rname) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->local_perms; u_int i; struct permission *perm; for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (open_listen_match_tcpip(perm, listen_host, listen_port, 1)) { if (perm->downstream) return perm->downstream; if (perm->port_to_connect == 0) return rdynamic_connect_prepare(ssh, ctype, rname); return connect_to(ssh, perm->host_to_connect, perm->port_to_connect, ctype, rname); } } error("WARNING: Server requests forwarding for unknown listen_port %d", listen_port); return NULL; } Channel * channel_connect_by_listen_path(struct ssh *ssh, const char *path, char *ctype, char *rname) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->local_perms; u_int i; struct permission *perm; for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (open_listen_match_streamlocal(perm, path)) { return connect_to(ssh, perm->host_to_connect, perm->port_to_connect, ctype, rname); } } error("WARNING: Server requests forwarding for unknown path %.100s", path); return NULL; } /* Check if connecting to that port is permitted and connect. */ Channel * channel_connect_to_port(struct ssh *ssh, const char *host, u_short port, char *ctype, char *rname, int *reason, const char **errmsg) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->local_perms; struct channel_connect cctx; Channel *c; u_int i, permit, permit_adm = 1; int sock; struct permission *perm; permit = pset->all_permitted; if (!permit) { for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (open_match(perm, host, port)) { permit = 1; break; } } } if (pset->num_permitted_admin > 0) { permit_adm = 0; for (i = 0; i < pset->num_permitted_admin; i++) { perm = &pset->permitted_admin[i]; if (open_match(perm, host, port)) { permit_adm = 1; break; } } } if (!permit || !permit_adm) { logit("Received request from %.100s port %d to connect to " "host %.100s port %d, but the request was denied.", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), host, port); if (reason != NULL) *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; return NULL; } memset(&cctx, 0, sizeof(cctx)); sock = connect_to_helper(ssh, host, port, SOCK_STREAM, ctype, rname, &cctx, reason, errmsg); if (sock == -1) { channel_connect_ctx_free(&cctx); return NULL; } c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); c->host_port = port; c->path = xstrdup(host); c->connect_ctx = cctx; return c; } /* Check if connecting to that path is permitted and connect. */ Channel * channel_connect_to_path(struct ssh *ssh, const char *path, char *ctype, char *rname) { struct ssh_channels *sc = ssh->chanctxt; struct permission_set *pset = &sc->local_perms; u_int i, permit, permit_adm = 1; struct permission *perm; permit = pset->all_permitted; if (!permit) { for (i = 0; i < pset->num_permitted_user; i++) { perm = &pset->permitted_user[i]; if (open_match(perm, path, PORT_STREAMLOCAL)) { permit = 1; break; } } } if (pset->num_permitted_admin > 0) { permit_adm = 0; for (i = 0; i < pset->num_permitted_admin; i++) { perm = &pset->permitted_admin[i]; if (open_match(perm, path, PORT_STREAMLOCAL)) { permit_adm = 1; break; } } } if (!permit || !permit_adm) { logit("Received request to connect to path %.100s, " "but the request was denied.", path); return NULL; } return connect_to(ssh, path, PORT_STREAMLOCAL, ctype, rname); } void channel_send_window_changes(struct ssh *ssh) { struct ssh_channels *sc = ssh->chanctxt; struct winsize ws; int r; u_int i; for (i = 0; i < sc->channels_alloc; i++) { if (sc->channels[i] == NULL || !sc->channels[i]->client_tty || sc->channels[i]->type != SSH_CHANNEL_OPEN) continue; if (ioctl(sc->channels[i]->rfd, TIOCGWINSZ, &ws) == -1) continue; channel_request_start(ssh, i, "window-change", 0); if ((r = sshpkt_put_u32(ssh, (u_int)ws.ws_col)) != 0 || (r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 || (r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 || (r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "channel %u; send window-change", i); } } /* Return RDYNAMIC_OPEN channel: channel allows SOCKS, but is not connected */ static Channel * rdynamic_connect_prepare(struct ssh *ssh, char *ctype, char *rname) { Channel *c; int r; c = channel_new(ssh, ctype, SSH_CHANNEL_RDYNAMIC_OPEN, -1, -1, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); c->host_port = 0; c->path = NULL; /* * We need to open the channel before we have a FD, * so that we can get SOCKS header from peer. */ if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, c->self)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) fatal_fr(r, "channel %i; confirm", c->self); return c; } /* Return CONNECTING socket to remote host:port or local socket path */ 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); if (sock == -1) channel_connect_ctx_free(&cctx); else { /* similar to SSH_CHANNEL_CONNECTING but we've already sent the open */ c->type = SSH_CHANNEL_RDYNAMIC_FINISH; c->connect_ctx = cctx; channel_register_fds(ssh, c, sock, sock, -1, 0, 1, 0); } return sock; } /* -- X11 forwarding */ /* * Creates an internet domain socket for listening for X11 connections. * Returns 0 and a suitable display number for the DISPLAY variable * stored in display_numberp , or -1 if an error occurs. */ int x11_create_display_inet(struct ssh *ssh, int x11_display_offset, int x11_use_localhost, int single_connection, u_int *display_numberp, int **chanids) { Channel *nc = NULL; int display_number, sock; u_short port; struct addrinfo hints, *ai, *aitop; char strport[NI_MAXSERV]; int gaierr, n, num_socks = 0, socks[NUM_SOCKS]; if (chanids == NULL) return -1; for (display_number = x11_display_offset; display_number < MAX_DISPLAYS; display_number++) { port = 6000 + display_number; memset(&hints, 0, sizeof(hints)); hints.ai_family = ssh->chanctxt->IPv4or6; hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; snprintf(strport, sizeof strport, "%d", port); if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) { error("getaddrinfo: %.100s", ssh_gai_strerror(gaierr)); return -1; } for (ai = aitop; ai; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue; sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock == -1) { if ((errno != EINVAL) && (errno != EAFNOSUPPORT) #ifdef EPFNOSUPPORT && (errno != EPFNOSUPPORT) #endif ) { error("socket: %.100s", strerror(errno)); freeaddrinfo(aitop); return -1; } else { debug("x11_create_display_inet: Socket family %d not supported", ai->ai_family); continue; } } if (ai->ai_family == AF_INET6) sock_set_v6only(sock); if (x11_use_localhost) set_reuseaddr(sock); if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) { debug2_f("bind port %d: %.100s", port, strerror(errno)); close(sock); for (n = 0; n < num_socks; n++) close(socks[n]); num_socks = 0; break; } socks[num_socks++] = sock; if (num_socks == NUM_SOCKS) break; } freeaddrinfo(aitop); if (num_socks > 0) break; } if (display_number >= MAX_DISPLAYS) { error("Failed to allocate internet-domain X11 display socket."); return -1; } /* Start listening for connections on the socket. */ for (n = 0; n < num_socks; n++) { sock = socks[n]; if (listen(sock, SSH_LISTEN_BACKLOG) == -1) { error("listen: %.100s", strerror(errno)); close(sock); return -1; } } /* Allocate a channel for each socket. */ *chanids = xcalloc(num_socks + 1, sizeof(**chanids)); for (n = 0; n < num_socks; n++) { sock = socks[n]; nc = channel_new(ssh, "x11-listener", SSH_CHANNEL_X11_LISTENER, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "X11 inet listener", 1); nc->single_connection = single_connection; (*chanids)[n] = nc->self; } (*chanids)[n] = -1; /* Return the display number for the DISPLAY environment variable. */ *display_numberp = display_number; return 0; } static int connect_local_xsocket_path(const char *pathname) { int sock; struct sockaddr_un addr; sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock == -1) { error("socket: %.100s", strerror(errno)); return -1; } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strlcpy(addr.sun_path, pathname, sizeof addr.sun_path); if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) return sock; close(sock); error("connect %.100s: %.100s", addr.sun_path, strerror(errno)); return -1; } static int connect_local_xsocket(u_int dnr) { char buf[1024]; snprintf(buf, sizeof buf, _PATH_UNIX_X, dnr); return connect_local_xsocket_path(buf); } #ifdef __APPLE__ static int is_path_to_xsocket(const char *display, char *path, size_t pathlen) { struct stat sbuf; if (strlcpy(path, display, pathlen) >= pathlen) { error("%s: display path too long", __func__); return 0; } if (display[0] != '/') return 0; if (stat(path, &sbuf) == 0) { return 1; } else { char *dot = strrchr(path, '.'); if (dot != NULL) { *dot = '\0'; if (stat(path, &sbuf) == 0) { return 1; } } } return 0; } #endif int x11_connect_display(struct ssh *ssh) { u_int display_number; const char *display; char buf[1024], *cp; struct addrinfo hints, *ai, *aitop; char strport[NI_MAXSERV]; int gaierr, sock = 0; /* Try to open a socket for the local X server. */ display = getenv("DISPLAY"); if (!display) { error("DISPLAY not set."); return -1; } /* * Now we decode the value of the DISPLAY variable and make a * connection to the real X server. */ #ifdef __APPLE__ /* Check if display is a path to a socket (as set by launchd). */ { char path[PATH_MAX]; if (is_path_to_xsocket(display, path, sizeof(path))) { debug("x11_connect_display: $DISPLAY is launchd"); /* Create a socket. */ sock = connect_local_xsocket_path(path); if (sock < 0) return -1; /* OK, we now have a connection to the display. */ return sock; } } #endif /* * Check if it is a unix domain socket. Unix domain displays are in * one of the following formats: unix:d[.s], :d[.s], ::d[.s] */ if (strncmp(display, "unix:", 5) == 0 || display[0] == ':') { /* Connect to the unix domain socket. */ if (sscanf(strrchr(display, ':') + 1, "%u", &display_number) != 1) { error("Could not parse display number from DISPLAY: " "%.100s", display); return -1; } /* Create a socket. */ sock = connect_local_xsocket(display_number); if (sock < 0) return -1; /* OK, we now have a connection to the display. */ return sock; } /* * Connect to an inet socket. The DISPLAY value is supposedly * hostname:d[.s], where hostname may also be numeric IP address. */ strlcpy(buf, display, sizeof(buf)); cp = strchr(buf, ':'); if (!cp) { error("Could not find ':' in DISPLAY: %.100s", display); return -1; } *cp = 0; /* * buf now contains the host name. But first we parse the * display number. */ if (sscanf(cp + 1, "%u", &display_number) != 1) { error("Could not parse display number from DISPLAY: %.100s", display); return -1; } /* Look up the host address */ memset(&hints, 0, sizeof(hints)); hints.ai_family = ssh->chanctxt->IPv4or6; hints.ai_socktype = SOCK_STREAM; snprintf(strport, sizeof strport, "%u", 6000 + display_number); if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) { error("%.100s: unknown host. (%s)", buf, ssh_gai_strerror(gaierr)); return -1; } for (ai = aitop; ai; ai = ai->ai_next) { /* Create a socket. */ sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock == -1) { debug2("socket: %.100s", strerror(errno)); continue; } /* Connect it to the display. */ if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) { debug2("connect %.100s port %u: %.100s", buf, 6000 + display_number, strerror(errno)); close(sock); continue; } /* Success */ break; } freeaddrinfo(aitop); if (!ai) { error("connect %.100s port %u: %.100s", buf, 6000 + display_number, strerror(errno)); return -1; } set_nodelay(sock); return sock; } /* * Requests forwarding of X11 connections, generates fake authentication * data, and enables authentication spoofing. * This should be called in the client only. */ void x11_request_forwarding_with_spoofing(struct ssh *ssh, int client_session_id, const char *disp, const char *proto, const char *data, int want_reply) { struct ssh_channels *sc = ssh->chanctxt; u_int data_len = (u_int) strlen(data) / 2; u_int i, value; const char *cp; char *new_data; int r, screen_number; if (sc->x11_saved_display == NULL) sc->x11_saved_display = xstrdup(disp); else if (strcmp(disp, sc->x11_saved_display) != 0) { error("x11_request_forwarding_with_spoofing: different " "$DISPLAY already forwarded"); return; } cp = strchr(disp, ':'); if (cp) cp = strchr(cp, '.'); if (cp) screen_number = (u_int)strtonum(cp + 1, 0, 400, NULL); else screen_number = 0; if (sc->x11_saved_proto == NULL) { /* Save protocol name. */ sc->x11_saved_proto = xstrdup(proto); /* Extract real authentication data. */ sc->x11_saved_data = xmalloc(data_len); for (i = 0; i < data_len; i++) { if (sscanf(data + 2 * i, "%2x", &value) != 1) { fatal("x11_request_forwarding: bad " "authentication data: %.100s", data); } sc->x11_saved_data[i] = value; } sc->x11_saved_data_len = data_len; /* Generate fake data of the same length. */ sc->x11_fake_data = xmalloc(data_len); arc4random_buf(sc->x11_fake_data, data_len); sc->x11_fake_data_len = data_len; } /* Convert the fake data into hex. */ new_data = tohex(sc->x11_fake_data, data_len); /* Send the request packet. */ channel_request_start(ssh, client_session_id, "x11-req", want_reply); if ((r = sshpkt_put_u8(ssh, 0)) != 0 || /* bool: single connection */ (r = sshpkt_put_cstring(ssh, proto)) != 0 || (r = sshpkt_put_cstring(ssh, new_data)) != 0 || (r = sshpkt_put_u32(ssh, screen_number)) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "send x11-req"); free(new_data); } diff --git a/crypto/openssh/channels.h b/crypto/openssh/channels.h index 58019a84e71c..bb2650f6b877 100644 --- a/crypto/openssh/channels.h +++ b/crypto/openssh/channels.h @@ -1,399 +1,401 @@ -/* $OpenBSD: channels.h,v 1.152 2023/09/04 00:01:46 djm Exp $ */ +/* $OpenBSD: channels.h,v 1.154 2023/12/18 14:47:20 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CHANNEL_H #define CHANNEL_H /* Definitions for channel types. */ #define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */ #define SSH_CHANNEL_PORT_LISTENER 2 /* Listening on a port. */ #define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */ #define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */ #define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */ #define SSH_CHANNEL_AUTH_SOCKET 6 /* authentication socket */ #define SSH_CHANNEL_X11_OPEN 7 /* reading first X11 packet */ #define SSH_CHANNEL_LARVAL 10 /* larval session */ #define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */ #define SSH_CHANNEL_CONNECTING 12 #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 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-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 #define CHANNEL_CANCEL_PORT_STATIC -1 /* nonblocking flags for channel_new */ #define CHANNEL_NONBLOCK_LEAVE 0 /* don't modify non-blocking state */ #define CHANNEL_NONBLOCK_SET 1 /* set non-blocking state */ #define CHANNEL_NONBLOCK_STDIO 2 /* set non-blocking and restore on close */ /* c->restore_block mask flags */ #define CHANNEL_RESTORE_RFD 0x01 #define CHANNEL_RESTORE_WFD 0x02 #define CHANNEL_RESTORE_EFD 0x04 /* TCP forwarding */ #define FORWARD_DENY 0 #define FORWARD_REMOTE (1) #define FORWARD_LOCAL (1<<1) #define FORWARD_ALLOW (FORWARD_REMOTE|FORWARD_LOCAL) #define FORWARD_ADM 0x100 #define FORWARD_USER 0x101 struct ssh; struct Channel; typedef struct Channel Channel; struct fwd_perm_list; typedef void channel_open_fn(struct ssh *, int, int, void *); typedef void channel_callback_fn(struct ssh *, int, int, void *); typedef int channel_infilter_fn(struct ssh *, struct Channel *, char *, int); typedef void channel_filter_cleanup_fn(struct ssh *, int, void *); typedef u_char *channel_outfilter_fn(struct ssh *, struct Channel *, u_char **, size_t *); /* Channel success/failure callbacks */ typedef void channel_confirm_cb(struct ssh *, int, struct Channel *, void *); typedef void channel_confirm_abandon_cb(struct ssh *, struct Channel *, void *); struct channel_confirm { TAILQ_ENTRY(channel_confirm) entry; channel_confirm_cb *cb; channel_confirm_abandon_cb *abandon_cb; void *ctx; }; TAILQ_HEAD(channel_confirms, channel_confirm); /* Context for non-blocking connects */ struct channel_connect { char *host; int port; struct addrinfo *ai, *aitop; }; /* 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 */ u_int istate; /* input from channel (state of receive half) */ u_int ostate; /* output to channel (state of transmit half) */ int flags; /* close sent/rcvd */ int rfd; /* read fd */ int wfd; /* write fd */ int efd; /* extended fd */ int sock; /* sock fd */ u_int io_want; /* bitmask of SSH_CHAN_IO_* */ u_int io_ready; /* bitmask of SSH_CHAN_IO_* */ int pfds[4]; /* pollfd entries for rfd/wfd/efd/sock */ int ctl_chan; /* control channel (multiplexed connections) */ int isatty; /* rfd is a tty */ #ifdef _AIX int wfd_isatty; /* wfd is a tty */ #endif int client_tty; /* (client) TTY has been requested */ int force_drain; /* force close on iEOF */ time_t notbefore; /* Pause IO until deadline (time_t) */ int delayed; /* post-IO handlers for newly created * channels are delayed until the first call * to a matching pre-IO handler. * this way post-IO handlers are not * accidentally called if a FD gets reused */ int restore_block; /* fd mask to restore blocking status */ int restore_flags[3];/* flags to restore */ struct sshbuf *input; /* data read from socket, to be sent over * encrypted connection */ struct sshbuf *output; /* data received over encrypted connection for * send on socket */ struct sshbuf *extended; char *path; /* path for unix domain sockets, or host name for forwards */ int listening_port; /* port being listened for forwards */ char *listening_addr; /* addr being listened for forwards */ int host_port; /* remote port to connect for forwards */ char *remote_name; /* remote hostname */ u_int remote_window; u_int remote_maxpacket; u_int local_window; + u_int local_window_exceeded; u_int local_window_max; u_int local_consumed; u_int local_maxpacket; int extended_usage; int single_connection; char *ctype; /* const type - NB. not freed on channel_free */ char *xctype; /* extended type */ /* callback */ channel_open_fn *open_confirm; void *open_confirm_ctx; channel_callback_fn *detach_user; int detach_close; struct channel_confirms status_confirms; /* filter */ channel_infilter_fn *input_filter; channel_outfilter_fn *output_filter; void *filter_ctx; channel_filter_cleanup_fn *filter_cleanup; /* keep boundaries */ int datagram; /* non-blocking connect */ /* XXX make this a pointer so the structure can be opaque */ struct channel_connect connect_ctx; /* multiplexing protocol hook, called for each packet received */ mux_callback_fn *mux_rcb; void *mux_ctx; int mux_pause; int mux_downstream_id; /* Inactivity timeouts */ /* Last traffic seen for OPEN channels */ time_t lastused; /* Inactivity timeout deadline in seconds (0 = no timeout) */ int inactive_deadline; }; #define CHAN_EXTENDED_IGNORE 0 #define CHAN_EXTENDED_READ 1 #define CHAN_EXTENDED_WRITE 2 /* default window/packet sizes for tcp/x11-fwd-channel */ #define CHAN_SES_PACKET_DEFAULT (32*1024) #define CHAN_SES_WINDOW_DEFAULT (64*CHAN_SES_PACKET_DEFAULT) #define CHAN_TCP_PACKET_DEFAULT (32*1024) #define CHAN_TCP_WINDOW_DEFAULT (64*CHAN_TCP_PACKET_DEFAULT) #define CHAN_X11_PACKET_DEFAULT (16*1024) #define CHAN_X11_WINDOW_DEFAULT (4*CHAN_X11_PACKET_DEFAULT) /* possible input states */ #define CHAN_INPUT_OPEN 0 #define CHAN_INPUT_WAIT_DRAIN 1 #define CHAN_INPUT_WAIT_OCLOSE 2 #define CHAN_INPUT_CLOSED 3 /* possible output states */ #define CHAN_OUTPUT_OPEN 0 #define CHAN_OUTPUT_WAIT_DRAIN 1 #define CHAN_OUTPUT_WAIT_IEOF 2 #define CHAN_OUTPUT_CLOSED 3 #define CHAN_CLOSE_SENT 0x01 #define CHAN_CLOSE_RCVD 0x02 #define CHAN_EOF_SENT 0x04 #define CHAN_EOF_RCVD 0x08 #define CHAN_LOCAL 0x10 /* file descriptor events */ #define SSH_CHAN_IO_RFD 0x01 #define SSH_CHAN_IO_WFD 0x02 #define SSH_CHAN_IO_EFD_R 0x04 #define SSH_CHAN_IO_EFD_W 0x08 #define SSH_CHAN_IO_EFD (SSH_CHAN_IO_EFD_R|SSH_CHAN_IO_EFD_W) #define SSH_CHAN_IO_SOCK_R 0x10 #define SSH_CHAN_IO_SOCK_W 0x20 #define SSH_CHAN_IO_SOCK (SSH_CHAN_IO_SOCK_R|SSH_CHAN_IO_SOCK_W) /* Read buffer size */ #define CHAN_RBUF (16*1024) /* Maximum size for direct reads to buffers */ #define CHANNEL_MAX_READ CHAN_SES_PACKET_DEFAULT /* Maximum channel input buffer size */ #define CHAN_INPUT_MAX (16*1024*1024) /* Hard limit on number of channels */ #define CHANNELS_MAX_CHANNELS (16*1024) /* check whether 'efd' is still in use */ #define CHANNEL_EFD_INPUT_ACTIVE(c) \ (c->extended_usage == CHAN_EXTENDED_READ && \ (c->efd != -1 || \ sshbuf_len(c->extended) > 0)) #define CHANNEL_EFD_OUTPUT_ACTIVE(c) \ (c->extended_usage == CHAN_EXTENDED_WRITE && \ c->efd != -1 && (!(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD)) || \ sshbuf_len(c->extended) > 0)) /* Add channel management structures to SSH transport instance */ void channel_init_channels(struct ssh *ssh); /* channel management */ Channel *channel_by_id(struct ssh *, int); Channel *channel_by_remote_id(struct ssh *, u_int); Channel *channel_lookup(struct ssh *, int); Channel *channel_new(struct ssh *, char *, int, int, int, int, u_int, u_int, int, const char *, int); void channel_set_fds(struct ssh *, int, int, int, int, int, int, int, u_int); void channel_free(struct ssh *, Channel *); void channel_free_all(struct ssh *); void channel_stop_listening(struct ssh *); void channel_force_close(struct ssh *, Channel *, int); void channel_set_xtype(struct ssh *, int, const char *); void channel_send_open(struct ssh *, int); void channel_request_start(struct ssh *, int, char *, int); void channel_register_cleanup(struct ssh *, int, channel_callback_fn *, int); void channel_register_open_confirm(struct ssh *, int, channel_open_fn *, void *); void channel_register_filter(struct ssh *, int, channel_infilter_fn *, channel_outfilter_fn *, channel_filter_cleanup_fn *, void *); void channel_register_status_confirm(struct ssh *, int, channel_confirm_cb *, channel_confirm_abandon_cb *, void *); void channel_cancel_cleanup(struct ssh *, int); int channel_close_fd(struct ssh *, Channel *, int *); void channel_send_window_changes(struct ssh *); /* channel inactivity timeouts */ void channel_add_timeout(struct ssh *, const char *, int); void channel_clear_timeouts(struct ssh *); /* mux proxy support */ int channel_proxy_downstream(struct ssh *, Channel *mc); int channel_proxy_upstream(Channel *, int, u_int32_t, struct ssh *); /* protocol handler */ int channel_input_data(int, u_int32_t, struct ssh *); int channel_input_extended_data(int, u_int32_t, struct ssh *); int channel_input_ieof(int, u_int32_t, struct ssh *); int channel_input_oclose(int, u_int32_t, struct ssh *); int channel_input_open_confirmation(int, u_int32_t, struct ssh *); int channel_input_open_failure(int, u_int32_t, struct ssh *); int channel_input_port_open(int, u_int32_t, struct ssh *); int channel_input_window_adjust(int, u_int32_t, struct ssh *); int channel_input_status_confirm(int, u_int32_t, struct ssh *); /* file descriptor handling (read/write) */ struct pollfd; struct timespec; void channel_prepare_poll(struct ssh *, struct pollfd **, u_int *, u_int *, u_int, struct timespec *); void channel_after_poll(struct ssh *, struct pollfd *, u_int); int channel_output_poll(struct ssh *); int channel_not_very_much_buffered_data(struct ssh *); void channel_close_all(struct ssh *); int channel_still_open(struct ssh *); +int channel_tty_open(struct ssh *); const char *channel_format_extended_usage(const Channel *); char *channel_open_message(struct ssh *); int channel_find_open(struct ssh *); /* tcp forwarding */ struct Forward; struct ForwardOptions; void channel_set_af(struct ssh *, int af); void channel_permit_all(struct ssh *, int); void channel_add_permission(struct ssh *, int, int, char *, int); void channel_clear_permission(struct ssh *, int, int); void channel_disable_admin(struct ssh *, int); void channel_update_permission(struct ssh *, int, int); Channel *channel_connect_to_port(struct ssh *, const char *, u_short, char *, char *, int *, const char **); Channel *channel_connect_to_path(struct ssh *, const char *, char *, char *); Channel *channel_connect_stdio_fwd(struct ssh *, const char*, int, int, int, int); Channel *channel_connect_by_listen_address(struct ssh *, const char *, u_short, char *, char *); Channel *channel_connect_by_listen_path(struct ssh *, const char *, char *, char *); int channel_request_remote_forwarding(struct ssh *, struct Forward *); int channel_setup_local_fwd_listener(struct ssh *, struct Forward *, struct ForwardOptions *); int channel_request_rforward_cancel(struct ssh *, struct Forward *); int channel_setup_remote_fwd_listener(struct ssh *, struct Forward *, int *, struct ForwardOptions *); int channel_cancel_rport_listener(struct ssh *, struct Forward *); int channel_cancel_lport_listener(struct ssh *, struct Forward *, int, struct ForwardOptions *); int permitopen_port(const char *); /* x11 forwarding */ void channel_set_x11_refuse_time(struct ssh *, time_t); int x11_connect_display(struct ssh *); int x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **); void x11_request_forwarding_with_spoofing(struct ssh *, int, const char *, const char *, const char *, int); /* channel close */ int chan_is_dead(struct ssh *, Channel *, int); void chan_mark_dead(struct ssh *, Channel *); /* channel events */ void chan_rcvd_oclose(struct ssh *, Channel *); void chan_rcvd_eow(struct ssh *, Channel *); void chan_read_failed(struct ssh *, Channel *); void chan_ibuf_empty(struct ssh *, Channel *); void chan_rcvd_ieof(struct ssh *, Channel *); void chan_write_failed(struct ssh *, Channel *); void chan_obuf_empty(struct ssh *, Channel *); #endif diff --git a/crypto/openssh/cipher.c b/crypto/openssh/cipher.c index 02aea4089ff9..90b139c89985 100644 --- a/crypto/openssh/cipher.c +++ b/crypto/openssh/cipher.c @@ -1,526 +1,505 @@ -/* $OpenBSD: cipher.c,v 1.119 2021/04/03 06:18:40 djm Exp $ */ +/* $OpenBSD: cipher.c,v 1.120 2023/10/10 06:49:54 tb Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * * Copyright (c) 1999 Niels Provos. All rights reserved. * Copyright (c) 1999, 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include "cipher.h" #include "misc.h" #include "sshbuf.h" #include "ssherr.h" #include "digest.h" #include "openbsd-compat/openssl-compat.h" #ifndef WITH_OPENSSL #define EVP_CIPHER_CTX void #endif struct sshcipher_ctx { int plaintext; int encrypt; EVP_CIPHER_CTX *evp; struct chachapoly_ctx *cp_ctx; struct aesctr_ctx ac_ctx; /* XXX union with evp? */ const struct sshcipher *cipher; }; struct sshcipher { char *name; u_int block_size; u_int key_len; u_int iv_len; /* defaults to block_size */ u_int auth_len; u_int flags; #define CFLAG_CBC (1<<0) #define CFLAG_CHACHAPOLY (1<<1) #define CFLAG_AESCTR (1<<2) #define CFLAG_NONE (1<<3) #define CFLAG_INTERNAL CFLAG_NONE /* Don't use "none" for packets */ #ifdef WITH_OPENSSL const EVP_CIPHER *(*evptype)(void); #else void *ignored; #endif }; static const struct sshcipher ciphers[] = { #ifdef WITH_OPENSSL #ifndef OPENSSL_NO_DES { "3des-cbc", 8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc }, #endif { "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 }, { "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 }, { "aes128-gcm@openssh.com", 16, 16, 12, 16, 0, EVP_aes_128_gcm }, { "aes256-gcm@openssh.com", 16, 32, 12, 16, 0, EVP_aes_256_gcm }, #else { "aes128-ctr", 16, 16, 0, 0, CFLAG_AESCTR, NULL }, { "aes192-ctr", 16, 24, 0, 0, CFLAG_AESCTR, NULL }, { "aes256-ctr", 16, 32, 0, 0, CFLAG_AESCTR, NULL }, #endif { "chacha20-poly1305@openssh.com", 8, 64, 0, 16, CFLAG_CHACHAPOLY, NULL }, { "none", 8, 0, 0, 0, CFLAG_NONE, NULL }, { NULL, 0, 0, 0, 0, 0, NULL } }; /*--*/ /* Returns a comma-separated list of supported ciphers. */ char * cipher_alg_list(char sep, int auth_only) { char *tmp, *ret = NULL; size_t nlen, rlen = 0; const struct sshcipher *c; for (c = ciphers; c->name != NULL; c++) { if ((c->flags & CFLAG_INTERNAL) != 0) continue; if (auth_only && c->auth_len == 0) continue; if (ret != NULL) ret[rlen++] = sep; nlen = strlen(c->name); if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { free(ret); return NULL; } ret = tmp; memcpy(ret + rlen, c->name, nlen + 1); rlen += nlen; } 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) { return (c->block_size); } u_int cipher_keylen(const struct sshcipher *c) { return (c->key_len); } u_int cipher_seclen(const struct sshcipher *c) { if (strcmp("3des-cbc", c->name) == 0) return 14; return cipher_keylen(c); } u_int cipher_authlen(const struct sshcipher *c) { return (c->auth_len); } u_int cipher_ivlen(const struct sshcipher *c) { /* * Default is cipher block size, except for chacha20+poly1305 that * needs no IV. XXX make iv_len == -1 default? */ return (c->iv_len != 0 || (c->flags & CFLAG_CHACHAPOLY) != 0) ? c->iv_len : c->block_size; } u_int cipher_is_cbc(const struct sshcipher *c) { return (c->flags & CFLAG_CBC) != 0; } u_int cipher_ctx_is_plaintext(struct sshcipher_ctx *cc) { return cc->plaintext; } const struct sshcipher * cipher_by_name(const char *name) { const struct sshcipher *c; for (c = ciphers; c->name != NULL; c++) if (strcmp(c->name, name) == 0) return c; return NULL; } #define CIPHER_SEP "," int ciphers_valid(const char *names) { const struct sshcipher *c; char *cipher_list, *cp; char *p; if (names == NULL || strcmp(names, "") == 0) return 0; if ((cipher_list = cp = strdup(names)) == NULL) return 0; for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; (p = strsep(&cp, CIPHER_SEP))) { c = cipher_by_name(p); if (c == NULL || (c->flags & CFLAG_INTERNAL) != 0) { free(cipher_list); return 0; } } free(cipher_list); return 1; } const char * cipher_warning_message(const struct sshcipher_ctx *cc) { if (cc == NULL || cc->cipher == NULL) return NULL; /* XXX repurpose for CBC warning */ return NULL; } int cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher, const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, int do_encrypt) { struct sshcipher_ctx *cc = NULL; int ret = SSH_ERR_INTERNAL_ERROR; #ifdef WITH_OPENSSL const EVP_CIPHER *type; int klen; #endif *ccp = NULL; if ((cc = calloc(sizeof(*cc), 1)) == NULL) return SSH_ERR_ALLOC_FAIL; cc->plaintext = (cipher->flags & CFLAG_NONE) != 0; cc->encrypt = do_encrypt; if (keylen < cipher->key_len || (iv != NULL && ivlen < cipher_ivlen(cipher))) { ret = SSH_ERR_INVALID_ARGUMENT; goto out; } cc->cipher = cipher; if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { 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) { ret = 0; goto out; } #ifndef WITH_OPENSSL if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen); aesctr_ivsetup(&cc->ac_ctx, iv); ret = 0; goto out; } ret = SSH_ERR_INVALID_ARGUMENT; goto out; #else /* WITH_OPENSSL */ type = (*cipher->evptype)(); if ((cc->evp = EVP_CIPHER_CTX_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (EVP_CipherInit(cc->evp, type, NULL, (u_char *)iv, (do_encrypt == CIPHER_ENCRYPT)) == 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (cipher_authlen(cipher) && !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, -1, (u_char *)iv)) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } klen = EVP_CIPHER_CTX_key_length(cc->evp); if (klen > 0 && keylen != (u_int)klen) { if (EVP_CIPHER_CTX_set_key_length(cc->evp, keylen) == 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } } if (EVP_CipherInit(cc->evp, NULL, (u_char *)key, NULL, -1) == 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } ret = 0; #endif /* WITH_OPENSSL */ out: if (ret == 0) { /* success */ *ccp = cc; } else { if (cc != NULL) { #ifdef WITH_OPENSSL EVP_CIPHER_CTX_free(cc->evp); #endif /* WITH_OPENSSL */ freezero(cc, sizeof(*cc)); } } return ret; } /* * cipher_crypt() operates as following: * Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'. * 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. * This tag is written on encryption and verified on decryption. * Both 'aadlen' and 'authlen' can be set to 0. */ int 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, len, aadlen, authlen, cc->encrypt); } if ((cc->cipher->flags & CFLAG_NONE) != 0) { memcpy(dest, src, aadlen + len); return 0; } #ifndef WITH_OPENSSL if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { if (aadlen) memcpy(dest, src, aadlen); aesctr_encrypt_bytes(&cc->ac_ctx, src + aadlen, dest + aadlen, len); return 0; } return SSH_ERR_INVALID_ARGUMENT; #else if (authlen) { u_char lastiv[1]; if (authlen != cipher_authlen(cc->cipher)) return SSH_ERR_INVALID_ARGUMENT; /* increment IV */ if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN, 1, lastiv)) return SSH_ERR_LIBCRYPTO_ERROR; /* set tag on decyption */ if (!cc->encrypt && !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_TAG, authlen, (u_char *)src + aadlen + len)) return SSH_ERR_LIBCRYPTO_ERROR; } if (aadlen) { if (authlen && EVP_Cipher(cc->evp, NULL, (u_char *)src, aadlen) < 0) return SSH_ERR_LIBCRYPTO_ERROR; memcpy(dest, src, aadlen); } if (len % cc->cipher->block_size) return SSH_ERR_INVALID_ARGUMENT; if (EVP_Cipher(cc->evp, dest + aadlen, (u_char *)src + aadlen, len) < 0) return SSH_ERR_LIBCRYPTO_ERROR; if (authlen) { /* compute tag (on encrypt) or verify tag (on decrypt) */ if (EVP_Cipher(cc->evp, NULL, NULL, 0) < 0) return cc->encrypt ? SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID; if (cc->encrypt && !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_GET_TAG, authlen, dest + aadlen + len)) return SSH_ERR_LIBCRYPTO_ERROR; } return 0; #endif } /* Extract the packet length, including any decryption necessary beforehand */ int 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, cp, len); if (len < 4) return SSH_ERR_MESSAGE_INCOMPLETE; *plenp = PEEK_U32(cp); return 0; } void cipher_free(struct sshcipher_ctx *cc) { if (cc == NULL) return; 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 freezero(cc, sizeof(*cc)); } -/* - * Exports an IV from the sshcipher_ctx required to export the key - * state back from the unprivileged child to the privileged parent - * process. - */ -int -cipher_get_keyiv_len(const struct sshcipher_ctx *cc) -{ - const struct sshcipher *c = cc->cipher; - - if ((c->flags & CFLAG_CHACHAPOLY) != 0) - return 0; - else if ((c->flags & CFLAG_AESCTR) != 0) - return sizeof(cc->ac_ctx.ctr); -#ifdef WITH_OPENSSL - return EVP_CIPHER_CTX_iv_length(cc->evp); -#else - return 0; -#endif -} - int cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, size_t len) { #ifdef WITH_OPENSSL const struct sshcipher *c = cc->cipher; int evplen; #endif if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { if (len != 0) return SSH_ERR_INVALID_ARGUMENT; return 0; } if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { if (len != sizeof(cc->ac_ctx.ctr)) return SSH_ERR_INVALID_ARGUMENT; memcpy(iv, cc->ac_ctx.ctr, len); return 0; } if ((cc->cipher->flags & CFLAG_NONE) != 0) return 0; #ifdef WITH_OPENSSL evplen = EVP_CIPHER_CTX_iv_length(cc->evp); if (evplen == 0) return 0; else if (evplen < 0) return SSH_ERR_LIBCRYPTO_ERROR; if ((size_t)evplen != len) return SSH_ERR_INVALID_ARGUMENT; if (cipher_authlen(c)) { if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN, len, iv)) return SSH_ERR_LIBCRYPTO_ERROR; } else if (!EVP_CIPHER_CTX_get_iv(cc->evp, iv, len)) return SSH_ERR_LIBCRYPTO_ERROR; #endif return 0; } int cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv, size_t len) { #ifdef WITH_OPENSSL const struct sshcipher *c = cc->cipher; int evplen = 0; #endif if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) return 0; if ((cc->cipher->flags & CFLAG_NONE) != 0) return 0; #ifdef WITH_OPENSSL evplen = EVP_CIPHER_CTX_iv_length(cc->evp); if (evplen <= 0) return SSH_ERR_LIBCRYPTO_ERROR; if ((size_t)evplen != len) return SSH_ERR_INVALID_ARGUMENT; if (cipher_authlen(c)) { /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */ if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv)) return SSH_ERR_LIBCRYPTO_ERROR; } else if (!EVP_CIPHER_CTX_set_iv(cc->evp, iv, evplen)) return SSH_ERR_LIBCRYPTO_ERROR; #endif return 0; } diff --git a/crypto/openssh/cipher.h b/crypto/openssh/cipher.h index 1a591cd7fd46..6533ff2bbdec 100644 --- a/crypto/openssh/cipher.h +++ b/crypto/openssh/cipher.h @@ -1,78 +1,77 @@ -/* $OpenBSD: cipher.h,v 1.55 2020/01/23 10:24:29 dtucker Exp $ */ +/* $OpenBSD: cipher.h,v 1.56 2023/10/10 06:49:54 tb Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef CIPHER_H #define CIPHER_H #include #ifdef WITH_OPENSSL #include #endif #include "cipher-chachapoly.h" #include "cipher-aesctr.h" #define CIPHER_ENCRYPT 1 #define CIPHER_DECRYPT 0 struct sshcipher; struct sshcipher_ctx; 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 *, u_int, u_int, u_int); int cipher_get_length(struct sshcipher_ctx *, u_int *, u_int, const u_char *, u_int); void cipher_free(struct sshcipher_ctx *); u_int cipher_blocksize(const struct sshcipher *); u_int cipher_keylen(const struct sshcipher *); u_int cipher_seclen(const struct sshcipher *); u_int cipher_authlen(const struct sshcipher *); u_int cipher_ivlen(const struct sshcipher *); u_int cipher_is_cbc(const struct sshcipher *); u_int cipher_ctx_is_plaintext(struct sshcipher_ctx *); int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, size_t); int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *, size_t); -int cipher_get_keyiv_len(const struct sshcipher_ctx *); #endif /* CIPHER_H */ diff --git a/crypto/openssh/clientloop.c b/crypto/openssh/clientloop.c index 3e9fa3220b7d..eb4902905fb1 100644 --- a/crypto/openssh/clientloop.c +++ b/crypto/openssh/clientloop.c @@ -1,2865 +1,2877 @@ -/* $OpenBSD: clientloop.c,v 1.398 2023/09/10 03:51:55 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.402 2023/11/24 00:31:30 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * The main loop for the interactive session (client side). * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * * Copyright (c) 1999 Theo de Raadt. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * SSH2 support added by Markus Friedl. * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #ifdef HAVE_PATHS_H #include #endif #ifdef HAVE_POLL_H #include #endif #include #include #include #include #include #include #include #include #include #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "packet.h" #include "sshbuf.h" #include "compat.h" #include "channels.h" #include "dispatch.h" #include "sshkey.h" #include "cipher.h" #include "kex.h" #include "myproposal.h" #include "log.h" #include "misc.h" #include "readconf.h" #include "clientloop.h" #include "sshconnect.h" #include "authfd.h" #include "atomicio.h" #include "sshpty.h" #include "match.h" #include "msg.h" #include "ssherr.h" #include "hostfile.h" /* Permitted RSA signature algorithms for UpdateHostkeys proofs */ #define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256" /* Uncertainty (in percent) of keystroke timing intervals */ #define SSH_KEYSTROKE_TIMING_FUZZ 10 /* import options */ extern Options options; /* Control socket */ extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */ /* * Name of the host we are connecting to. This is the name given on the * command line, or the Hostname specified for the user-supplied name in a * configuration file. */ extern char *host; /* * 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 * window size to be sent to the server a little later. This is volatile * because this is updated in a signal handler. */ static volatile sig_atomic_t received_window_change_signal = 0; static volatile sig_atomic_t received_signal = 0; /* Time when backgrounded control master using ControlPersist should exit */ static time_t control_persist_exit_time = 0; /* Common data for the client loop code. */ volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ static int last_was_cr; /* Last character was a newline. */ static int exit_status; /* Used to store the command exit status. */ static struct sshbuf *stderr_buffer; /* Used for final exit message. */ static int connection_in; /* Connection to server (input). */ static int connection_out; /* Connection to server (output). */ static int need_rekeying; /* Set to non-zero if rekeying is requested. */ static int session_closed; /* In SSH2: login session closed. */ static time_t x11_refuse_time; /* If >0, refuse x11 opens after this time. */ static time_t server_alive_time; /* Time to do server_alive_check */ static int hostkeys_update_complete; static int session_setup_complete; static void client_init_dispatch(struct ssh *ssh); int session_ident = -1; /* Track escape per proto2 channel */ struct escape_filter_ctx { int escape_pending; int escape_char; }; /* Context for channel confirmation replies */ struct channel_reply_ctx { const char *request_type; int id; enum confirm_action action; }; /* Global request success/failure callbacks */ /* XXX move to struct ssh? */ struct global_confirm { TAILQ_ENTRY(global_confirm) entry; global_confirm_cb *cb; void *ctx; int ref_count; }; TAILQ_HEAD(global_confirms, global_confirm); static struct global_confirms global_confirms = TAILQ_HEAD_INITIALIZER(global_confirms); void ssh_process_session2_setup(int, int, int, struct sshbuf *); static void quit_message(const char *fmt, ...) __attribute__((__format__ (printf, 1, 2))); static void quit_message(const char *fmt, ...) { char *msg; va_list args; int r; va_start(args, fmt); xvasprintf(&msg, fmt, args); va_end(args); if ((r = sshbuf_putf(stderr_buffer, "%s\r\n", msg)) != 0) fatal_fr(r, "sshbuf_putf"); + free(msg); quit_pending = 1; } /* * Signal handler for the window change signal (SIGWINCH). This just sets a * flag indicating that the window has changed. */ static void window_change_handler(int sig) { received_window_change_signal = 1; } /* * Signal handler for signals that cause the program to terminate. These * signals must be trapped to restore terminal modes. */ static void signal_handler(int sig) { received_signal = sig; quit_pending = 1; } /* * Sets control_persist_exit_time to the absolute time when the * backgrounded control master should exit due to expiry of the * ControlPersist timeout. Sets it to 0 if we are not a backgrounded * control master process, or if there is no ControlPersist timeout. */ static void set_control_persist_exit_time(struct ssh *ssh) { if (muxserver_sock == -1 || !options.control_persist || options.control_persist_timeout == 0) { /* not using a ControlPersist timeout */ control_persist_exit_time = 0; } else if (channel_still_open(ssh)) { /* some client connections are still open */ if (control_persist_exit_time > 0) debug2_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_f("schedule exit in %d seconds", options.control_persist_timeout); } /* else we are already counting down to the timeout */ } #define SSH_X11_VALID_DISPLAY_CHARS ":/.-_" static int client_x11_display_valid(const char *display) { size_t i, dlen; if (display == NULL) return 0; dlen = strlen(display); for (i = 0; i < dlen; i++) { if (!isalnum((u_char)display[i]) && strchr(SSH_X11_VALID_DISPLAY_CHARS, display[i]) == NULL) { debug("Invalid character '%c' in DISPLAY", display[i]); return 0; } } return 1; } #define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" #define X11_TIMEOUT_SLACK 60 int client_x11_get_proto(struct ssh *ssh, const char *display, const char *xauth_path, u_int trusted, u_int timeout, char **_proto, char **_data) { char *cmd, line[512], xdisplay[512]; char xauthfile[PATH_MAX], xauthdir[PATH_MAX]; static char proto[512], data[512]; FILE *f; int got_data = 0, generated = 0, do_unlink = 0, r; struct stat st; u_int now, x11_timeout_real; *_proto = proto; *_data = data; proto[0] = data[0] = xauthfile[0] = xauthdir[0] = '\0'; if (!client_x11_display_valid(display)) { if (display != NULL) logit("DISPLAY \"%s\" invalid; disabling X11 forwarding", display); return -1; } if (xauth_path != NULL && stat(xauth_path, &st) == -1) { debug("No xauth program."); xauth_path = NULL; } if (xauth_path != NULL) { /* * Handle FamilyLocal case where $DISPLAY does * not match an authorization entry. For this we * just try "xauth list unix:displaynum.screennum". * XXX: "localhost" match to determine FamilyLocal * is not perfect. */ if (strncmp(display, "localhost:", 10) == 0) { if ((r = snprintf(xdisplay, sizeof(xdisplay), "unix:%s", display + 10)) < 0 || (size_t)r >= sizeof(xdisplay)) { error_f("display name too long"); return -1; } display = xdisplay; } if (trusted == 0) { /* * Generate an untrusted X11 auth cookie. * * The authentication cookie should briefly outlive * ssh's willingness to forward X11 connections to * avoid nasty fail-open behaviour in the X server. */ mktemp_proto(xauthdir, sizeof(xauthdir)); if (mkdtemp(xauthdir) == NULL) { error_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_f("xauthfile path too long"); rmdir(xauthdir); return -1; } if (timeout == 0) { /* auth doesn't time out */ xasprintf(&cmd, "%s -f %s generate %s %s " "untrusted 2>%s", xauth_path, xauthfile, display, SSH_X11_PROTO, _PATH_DEVNULL); } else { /* Add some slack to requested expiry */ if (timeout < UINT_MAX - X11_TIMEOUT_SLACK) x11_timeout_real = timeout + X11_TIMEOUT_SLACK; else { /* Don't overflow on long timeouts */ x11_timeout_real = UINT_MAX; } xasprintf(&cmd, "%s -f %s generate %s %s " "untrusted timeout %u 2>%s", xauth_path, xauthfile, display, SSH_X11_PROTO, x11_timeout_real, _PATH_DEVNULL); } debug2_f("xauth command: %s", cmd); if (timeout != 0 && x11_refuse_time == 0) { now = monotime() + 1; if (SSH_TIME_T_MAX - timeout < now) x11_refuse_time = SSH_TIME_T_MAX; else x11_refuse_time = now + timeout; channel_set_x11_refuse_time(ssh, x11_refuse_time); } if (system(cmd) == 0) generated = 1; free(cmd); } /* * When in untrusted mode, we read the cookie only if it was * successfully generated as an untrusted one in the step * above. */ if (trusted || generated) { xasprintf(&cmd, "%s %s%s list %s 2>" _PATH_DEVNULL, xauth_path, generated ? "-f " : "" , generated ? xauthfile : "", display); debug2("x11_get_proto: %s", cmd); f = popen(cmd, "r"); if (f && fgets(line, sizeof(line), f) && sscanf(line, "%*s %511s %511s", proto, data) == 2) got_data = 1; if (f) pclose(f); free(cmd); } } if (do_unlink) { unlink(xauthfile); rmdir(xauthdir); } /* Don't fall back to fake X11 data for untrusted forwarding */ if (!trusted && !got_data) { error("Warning: untrusted X11 forwarding setup failed: " "xauth key data not generated"); return -1; } /* * If we didn't get authentication data, just make up some * data. The forwarding code will check the validity of the * response anyway, and substitute this data. The X11 * server, however, will ignore this fake data and use * whatever authentication mechanisms it was using otherwise * for the local connection. */ if (!got_data) { u_int8_t rnd[16]; u_int i; logit("Warning: No xauth data; " "using fake authentication data for X11 forwarding."); strlcpy(proto, SSH_X11_PROTO, sizeof proto); arc4random_buf(rnd, sizeof(rnd)); for (i = 0; i < sizeof(rnd); i++) { snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", rnd[i]); } } return 0; } /* * Checks if the client window has changed, and sends a packet about it to * the server if so. The actual change is detected elsewhere (by a software * interrupt on Unix); this just checks the flag and sends a message if * appropriate. */ static void client_check_window_change(struct ssh *ssh) { if (!received_window_change_signal) return; received_window_change_signal = 0; debug2_f("changed"); channel_send_window_changes(ssh); } static int client_global_request_reply(int type, u_int32_t seq, struct ssh *ssh) { struct global_confirm *gc; if ((gc = TAILQ_FIRST(&global_confirms)) == NULL) return 0; if (gc->cb != NULL) gc->cb(ssh, type, seq, gc->ctx); if (--gc->ref_count <= 0) { TAILQ_REMOVE(&global_confirms, gc, entry); 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) { int r; if (ssh_packet_inc_alive_timeouts(ssh) > options.server_alive_count_max) { logit("Timeout, server %s not responding.", host); cleanup_exit(255); } if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "keepalive@openssh.com")) != 0 || (r = sshpkt_put_u8(ssh, 1)) != 0 || /* boolean: want reply */ (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); /* Insert an empty placeholder to maintain ordering */ client_register_global_confirm(NULL, NULL); schedule_server_alive_check(); } /* Try to send a dummy keystroke */ static int send_chaff(struct ssh *ssh) { int r; if ((ssh->kex->flags & KEX_HAS_PING) == 0) return 0; /* XXX probabilistically send chaff? */ /* * a SSH2_MSG_CHANNEL_DATA payload is 9 bytes: * 4 bytes channel ID + 4 bytes string length + 1 byte string data * simulate that here. */ if ((r = sshpkt_start(ssh, SSH2_MSG_PING)) != 0 || (r = sshpkt_put_cstring(ssh, "PING!")) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); return 1; } /* Sets the next interval to send a keystroke or chaff packet */ static void set_next_interval(const struct timespec *now, struct timespec *next_interval, u_int interval_ms, int starting) { struct timespec tmp; long long interval_ns, fuzz_ns; static long long rate_fuzz; interval_ns = interval_ms * (1000LL * 1000); fuzz_ns = (interval_ns * SSH_KEYSTROKE_TIMING_FUZZ) / 100; /* Center fuzz around requested interval */ if (fuzz_ns > INT_MAX) fuzz_ns = INT_MAX; if (fuzz_ns > interval_ns) { /* Shouldn't happen */ fatal_f("internal error: fuzz %u%% %lldns > interval %lldns", SSH_KEYSTROKE_TIMING_FUZZ, fuzz_ns, interval_ns); } /* * Randomise the keystroke/chaff intervals in two ways: * 1. Each interval has some random jitter applied to make the * interval-to-interval time unpredictable. * 2. The overall interval rate is also randomly perturbed for each * chaffing session to make the average rate unpredictable. */ if (starting) rate_fuzz = arc4random_uniform(fuzz_ns); interval_ns -= fuzz_ns; interval_ns += arc4random_uniform(fuzz_ns) + rate_fuzz; tmp.tv_sec = interval_ns / (1000 * 1000 * 1000); tmp.tv_nsec = interval_ns % (1000 * 1000 * 1000); timespecadd(now, &tmp, next_interval); } /* * Performs keystroke timing obfuscation. Returns non-zero if the * output fd should be polled. */ static int obfuscate_keystroke_timing(struct ssh *ssh, struct timespec *timeout, int channel_did_enqueue) { static int active; static struct timespec next_interval, chaff_until; struct timespec now, tmp; int just_started = 0, had_keystroke = 0; static unsigned long long nchaff; char *stop_reason = NULL; long long n; monotime_ts(&now); if (options.obscure_keystroke_timing_interval <= 0) return 1; /* disabled in config */ - if (!channel_still_open(ssh) || quit_pending) { + if (!channel_tty_open(ssh) || quit_pending) { /* Stop if no channels left of we're waiting for one to close */ stop_reason = "no active channels"; } else if (ssh_packet_is_rekeying(ssh)) { /* Stop if we're rekeying */ stop_reason = "rekeying started"; } else if (!ssh_packet_interactive_data_to_write(ssh) && ssh_packet_have_data_to_write(ssh)) { /* Stop if the output buffer has more than a few keystrokes */ stop_reason = "output buffer filling"; } else if (active && channel_did_enqueue && ssh_packet_have_data_to_write(ssh)) { /* Still in active mode and have a keystroke queued. */ had_keystroke = 1; } else if (active) { if (timespeccmp(&now, &chaff_until, >=)) { /* Stop if there have been no keystrokes for a while */ stop_reason = "chaff time expired"; } else if (timespeccmp(&now, &next_interval, >=)) { /* Otherwise if we were due to send, then send chaff */ if (send_chaff(ssh)) nchaff++; } } if (stop_reason != NULL) { if (active) { debug3_f("stopping: %s (%llu chaff packets sent)", stop_reason, nchaff); active = 0; } return 1; } /* * If we're in interactive mode, and only have a small amount * of outbound data, then we assume that the user is typing * interactively. In this case, start quantising outbound packets to * fixed time intervals to hide inter-keystroke timing. */ if (!active && ssh_packet_interactive_data_to_write(ssh) && channel_did_enqueue && ssh_packet_have_data_to_write(ssh)) { debug3_f("starting: interval ~%dms", options.obscure_keystroke_timing_interval); just_started = had_keystroke = active = 1; nchaff = 0; set_next_interval(&now, &next_interval, options.obscure_keystroke_timing_interval, 1); } /* Don't hold off if obfuscation inactive */ if (!active) return 1; if (had_keystroke) { /* * Arrange to send chaff packets for a random interval after * the last keystroke was sent. */ ms_to_timespec(&tmp, SSH_KEYSTROKE_CHAFF_MIN_MS + arc4random_uniform(SSH_KEYSTROKE_CHAFF_RNG_MS)); timespecadd(&now, &tmp, &chaff_until); } ptimeout_deadline_monotime_tsp(timeout, &next_interval); if (just_started) return 1; /* Don't arm output fd for poll until the timing interval has elapsed */ if (timespeccmp(&now, &next_interval, <)) return 0; /* Calculate number of intervals missed since the last check */ n = (now.tv_sec - next_interval.tv_sec) * 1000LL * 1000 * 1000; n += now.tv_nsec - next_interval.tv_nsec; n /= options.obscure_keystroke_timing_interval * 1000LL * 1000; n = (n < 0) ? 1 : n + 1; /* Advance to the next interval */ set_next_interval(&now, &next_interval, options.obscure_keystroke_timing_interval * n, 0); return 1; } /* * Waits until the client can do something (some data becomes available on * one of the file descriptors). */ static void client_wait_until_can_do_something(struct ssh *ssh, struct pollfd **pfdp, u_int *npfd_allocp, u_int *npfd_activep, int channel_did_enqueue, - int *conn_in_readyp, int *conn_out_readyp) + sigset_t *sigsetp, int *conn_in_readyp, int *conn_out_readyp) { struct timespec timeout; int ret, oready; u_int p; *conn_in_readyp = *conn_out_readyp = 0; /* Prepare channel poll. First two pollfd entries are reserved */ ptimeout_init(&timeout); channel_prepare_poll(ssh, pfdp, npfd_allocp, npfd_activep, 2, &timeout); if (*npfd_activep < 2) fatal_f("bad npfd %u", *npfd_activep); /* shouldn't happen */ /* channel_prepare_poll could have closed the last channel */ if (session_closed && !channel_still_open(ssh) && !ssh_packet_have_data_to_write(ssh)) { /* clear events since we did not call poll() */ for (p = 0; p < *npfd_activep; p++) (*pfdp)[p].revents = 0; return; } oready = obfuscate_keystroke_timing(ssh, &timeout, channel_did_enqueue); /* Monitor server connection on reserved pollfd entries */ (*pfdp)[0].fd = connection_in; (*pfdp)[0].events = POLLIN; (*pfdp)[1].fd = connection_out; (*pfdp)[1].events = (oready && ssh_packet_have_data_to_write(ssh)) ? POLLOUT : 0; /* * Wait for something to happen. This will suspend the process until * some polled descriptor can be read, written, or has some other * event pending, or a timeout expires. */ set_control_persist_exit_time(ssh); if (control_persist_exit_time > 0) ptimeout_deadline_monotime(&timeout, control_persist_exit_time); if (options.server_alive_interval > 0) ptimeout_deadline_monotime(&timeout, server_alive_time); if (options.rekey_interval > 0 && !ssh_packet_is_rekeying(ssh)) { ptimeout_deadline_sec(&timeout, ssh_packet_get_rekey_timeout(ssh)); } - ret = ppoll(*pfdp, *npfd_activep, ptimeout_get_tsp(&timeout), NULL); + ret = ppoll(*pfdp, *npfd_activep, ptimeout_get_tsp(&timeout), sigsetp); if (ret == -1) { /* * We have to clear the events because we return. * We have to return, because the mainloop checks for the flags * set by the signal handlers. */ for (p = 0; p < *npfd_activep; p++) (*pfdp)[p].revents = 0; if (errno == EINTR) return; /* Note: we might still have data in the buffers. */ quit_message("poll: %s", strerror(errno)); return; } *conn_in_readyp = (*pfdp)[0].revents != 0; *conn_out_readyp = (*pfdp)[1].revents != 0; if (options.server_alive_interval > 0 && !*conn_in_readyp && monotime() >= server_alive_time) { /* * ServerAlive check is needed. We can't rely on the poll * timing out since traffic on the client side such as port * forwards can keep waking it up. */ server_alive_check(ssh); } } static void client_suspend_self(struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr) { /* Flush stdout and stderr buffers. */ if (sshbuf_len(bout) > 0) atomicio(vwrite, fileno(stdout), sshbuf_mutable_ptr(bout), sshbuf_len(bout)); if (sshbuf_len(berr) > 0) atomicio(vwrite, fileno(stderr), sshbuf_mutable_ptr(berr), sshbuf_len(berr)); leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); sshbuf_reset(bin); sshbuf_reset(bout); sshbuf_reset(berr); /* Send the suspend signal to the program itself. */ kill(getpid(), SIGTSTP); /* Reset window sizes in case they have changed */ received_window_change_signal = 1; enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); } static void client_process_net_input(struct ssh *ssh) { int r; /* * Read input from the server, and add any such data to the buffer of * the packet subsystem. */ schedule_server_alive_check(); if ((r = ssh_packet_process_read(ssh, connection_in)) == 0) return; /* success */ if (r == SSH_ERR_SYSTEM_ERROR) { if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) return; if (errno == EPIPE) { quit_message("Connection to %s closed by remote host.", host); return; } } quit_message("Read from remote host %s: %s", host, ssh_err(r)); } static void client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx) { struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx; char errmsg[256]; int r, tochan; /* * If a TTY was explicitly requested, then a failure to allocate * one is fatal. */ if (cr->action == CONFIRM_TTY && (options.request_tty == REQUEST_TTY_FORCE || options.request_tty == REQUEST_TTY_YES)) cr->action = CONFIRM_CLOSE; /* XXX suppress on mux _client_ quietmode */ tochan = options.log_level >= SYSLOG_LEVEL_ERROR && c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; if (type == SSH2_MSG_CHANNEL_SUCCESS) { debug2("%s request accepted on channel %d", cr->request_type, c->self); } else if (type == SSH2_MSG_CHANNEL_FAILURE) { if (tochan) { snprintf(errmsg, sizeof(errmsg), "%s request failed\r\n", cr->request_type); } else { snprintf(errmsg, sizeof(errmsg), "%s request failed on channel %d", cr->request_type, c->self); } /* If error occurred on primary session channel, then exit */ if (cr->action == CONFIRM_CLOSE && c->self == session_ident) fatal("%s", errmsg); /* * If error occurred on mux client, append to * their stderr. */ if (tochan) { debug3_f("channel %d: mux request: %s", c->self, cr->request_type); if ((r = sshbuf_put(c->extended, errmsg, strlen(errmsg))) != 0) fatal_fr(r, "sshbuf_put"); } else error("%s", errmsg); if (cr->action == CONFIRM_TTY) { /* * If a TTY allocation error occurred, then arrange * for the correct TTY to leave raw mode. */ if (c->self == session_ident) leave_raw_mode(0); else mux_tty_alloc_failed(ssh, c); } else if (cr->action == CONFIRM_CLOSE) { chan_read_failed(ssh, c); chan_write_failed(ssh, c); } } free(cr); } static void client_abandon_status_confirm(struct ssh *ssh, Channel *c, void *ctx) { free(ctx); } void client_expect_confirm(struct ssh *ssh, int id, const char *request, enum confirm_action action) { struct channel_reply_ctx *cr = xcalloc(1, sizeof(*cr)); cr->request_type = request; cr->action = action; channel_register_status_confirm(ssh, id, client_status_confirm, client_abandon_status_confirm, cr); } void client_register_global_confirm(global_confirm_cb *cb, void *ctx) { struct global_confirm *gc, *last_gc; /* Coalesce identical callbacks */ last_gc = TAILQ_LAST(&global_confirms, global_confirms); if (last_gc && last_gc->cb == cb && last_gc->ctx == ctx) { if (++last_gc->ref_count >= INT_MAX) fatal_f("last_gc->ref_count = %d", last_gc->ref_count); return; } gc = xcalloc(1, sizeof(*gc)); gc->cb = cb; gc->ctx = ctx; gc->ref_count = 1; TAILQ_INSERT_TAIL(&global_confirms, gc, entry); } /* * Returns non-zero if the client is able to handle a hostkeys-00@openssh.com * hostkey update request. */ static int can_update_hostkeys(void) { if (hostkeys_update_complete) return 0; if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK && options.batch_mode) return 0; /* won't ask in batchmode, so don't even try */ if (!options.update_hostkeys || options.num_user_hostfiles <= 0) return 0; return 1; } static void client_repledge(void) { debug3_f("enter"); /* Might be able to tighten pledge now that session is established */ if (options.control_master || options.control_path != NULL || options.forward_x11 || options.fork_after_authentication || can_update_hostkeys() || (session_ident != -1 && !session_setup_complete)) { /* Can't tighten */ return; } /* * LocalCommand and UpdateHostkeys have finished, so can get rid of * filesystem. * * XXX protocol allows a server can to change hostkeys during the * connection at rekey time that could trigger a hostkeys update * but AFAIK no implementations support this. Could improve by * forcing known_hosts to be read-only or via unveil(2). */ if (options.num_local_forwards != 0 || options.num_remote_forwards != 0 || options.num_permitted_remote_opens != 0 || options.enable_escape_commandline != 0) { /* rfwd needs inet */ debug("pledge: network"); if (pledge("stdio unix inet dns proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } else if (options.forward_agent != 0) { /* agent forwarding needs to open $SSH_AUTH_SOCK at will */ debug("pledge: agent"); if (pledge("stdio unix proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } else { debug("pledge: fork"); if (pledge("stdio proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } /* XXX further things to do: * * - might be able to get rid of proc if we kill ~^Z * - ssh -N (no session) * - stdio forwarding * - sessions without tty */ } static void process_cmdline(struct ssh *ssh) { void (*handler)(int); char *s, *cmd; int ok, delete = 0, local = 0, remote = 0, dynamic = 0; struct Forward fwd; memset(&fwd, 0, sizeof(fwd)); leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); handler = ssh_signal(SIGINT, SIG_IGN); cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); if (s == NULL) goto out; while (isspace((u_char)*s)) s++; if (*s == '-') s++; /* Skip cmdline '-', if any */ if (*s == '\0') goto out; if (*s == 'h' || *s == 'H' || *s == '?') { logit("Commands:"); logit(" -L[bind_address:]port:host:hostport " "Request local forward"); logit(" -R[bind_address:]port:host:hostport " "Request remote forward"); logit(" -D[bind_address:]port " "Request dynamic forward"); logit(" -KL[bind_address:]port " "Cancel local forward"); logit(" -KR[bind_address:]port " "Cancel remote forward"); logit(" -KD[bind_address:]port " "Cancel dynamic forward"); if (!options.permit_local_command) goto out; logit(" !args " "Execute local command"); goto out; } if (*s == '!' && options.permit_local_command) { s++; ssh_local_cmd(s); goto out; } if (*s == 'K') { delete = 1; s++; } if (*s == 'L') local = 1; else if (*s == 'R') remote = 1; else if (*s == 'D') dynamic = 1; else { logit("Invalid command."); goto out; } while (isspace((u_char)*++s)) ; /* XXX update list of forwards in options */ if (delete) { /* We pass 1 for dynamicfwd to restrict to 1 or 2 fields. */ if (!parse_forward(&fwd, s, 1, 0)) { logit("Bad forwarding close specification."); goto out; } if (remote) ok = channel_request_rforward_cancel(ssh, &fwd) == 0; else if (dynamic) ok = channel_cancel_lport_listener(ssh, &fwd, 0, &options.fwd_opts) > 0; else ok = channel_cancel_lport_listener(ssh, &fwd, CHANNEL_CANCEL_PORT_STATIC, &options.fwd_opts) > 0; if (!ok) { logit("Unknown port forwarding."); goto out; } logit("Canceled forwarding."); } else { /* -R specs can be both dynamic or not, so check both. */ if (remote) { if (!parse_forward(&fwd, s, 0, remote) && !parse_forward(&fwd, s, 1, remote)) { logit("Bad remote forwarding specification."); goto out; } } else if (!parse_forward(&fwd, s, dynamic, remote)) { logit("Bad local forwarding specification."); goto out; } if (local || dynamic) { if (!channel_setup_local_fwd_listener(ssh, &fwd, &options.fwd_opts)) { logit("Port forwarding failed."); goto out; } } else { if (channel_request_remote_forwarding(ssh, &fwd) < 0) { logit("Port forwarding failed."); goto out; } } logit("Forwarding port."); } out: ssh_signal(SIGINT, handler); enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); free(cmd); free(fwd.listen_host); free(fwd.listen_path); free(fwd.connect_host); free(fwd.connect_path); } /* reasons to suppress output of an escape command in help output */ #define SUPPRESS_NEVER 0 /* never suppress, always show */ #define SUPPRESS_MUXCLIENT 1 /* don't show in mux client sessions */ #define SUPPRESS_MUXMASTER 2 /* don't show in mux master sessions */ #define SUPPRESS_SYSLOG 4 /* don't show when logging to syslog */ #define SUPPRESS_NOCMDLINE 8 /* don't show when cmdline disabled*/ struct escape_help_text { const char *cmd; const char *text; unsigned int flags; }; static struct escape_help_text esc_txt[] = { {".", "terminate session", SUPPRESS_MUXMASTER}, {".", "terminate connection (and any multiplexed sessions)", SUPPRESS_MUXCLIENT}, {"B", "send a BREAK to the remote system", SUPPRESS_NEVER}, {"C", "open a command line", SUPPRESS_MUXCLIENT|SUPPRESS_NOCMDLINE}, {"R", "request rekey", SUPPRESS_NEVER}, {"V/v", "decrease/increase verbosity (LogLevel)", SUPPRESS_MUXCLIENT}, {"^Z", "suspend ssh", SUPPRESS_MUXCLIENT}, {"#", "list forwarded connections", SUPPRESS_NEVER}, {"&", "background ssh (when waiting for connections to terminate)", SUPPRESS_MUXCLIENT}, {"?", "this message", SUPPRESS_NEVER}, }; static void print_escape_help(struct sshbuf *b, int escape_char, int mux_client, int using_stderr) { unsigned int i, suppress_flags; int r; if ((r = sshbuf_putf(b, "%c?\r\nSupported escape sequences:\r\n", escape_char)) != 0) fatal_fr(r, "sshbuf_putf"); suppress_flags = (mux_client ? SUPPRESS_MUXCLIENT : 0) | (mux_client ? 0 : SUPPRESS_MUXMASTER) | (using_stderr ? 0 : SUPPRESS_SYSLOG) | (options.enable_escape_commandline == 0 ? SUPPRESS_NOCMDLINE : 0); for (i = 0; i < sizeof(esc_txt)/sizeof(esc_txt[0]); i++) { if (esc_txt[i].flags & suppress_flags) continue; if ((r = sshbuf_putf(b, " %c%-3s - %s\r\n", escape_char, esc_txt[i].cmd, esc_txt[i].text)) != 0) fatal_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_fr(r, "sshbuf_putf"); } /* * Process the characters one by one. */ static int process_escapes(struct ssh *ssh, Channel *c, struct sshbuf *bin, struct sshbuf *bout, struct sshbuf *berr, char *buf, int len) { pid_t pid; int r, bytes = 0; u_int i; u_char ch; char *s; struct escape_filter_ctx *efc; if (c == NULL || c->filter_ctx == NULL || len <= 0) return 0; efc = (struct escape_filter_ctx *)c->filter_ctx; for (i = 0; i < (u_int)len; i++) { /* Get one character at a time. */ ch = buf[i]; if (efc->escape_pending) { /* We have previously seen an escape character. */ /* Clear the flag now. */ efc->escape_pending = 0; /* Process the escaped character. */ switch (ch) { case '.': /* Terminate the connection. */ if ((r = sshbuf_putf(berr, "%c.\r\n", efc->escape_char)) != 0) fatal_fr(r, "sshbuf_putf"); if (c && c->ctl_chan != -1) { channel_force_close(ssh, c, 1); return 0; } else quit_pending = 1; return -1; case 'Z' - 64: /* XXX support this for mux clients */ if (c && c->ctl_chan != -1) { char b[16]; noescape: if (ch == 'Z' - 64) snprintf(b, sizeof b, "^Z"); else snprintf(b, sizeof b, "%c", ch); if ((r = sshbuf_putf(berr, "%c%s escape not available to " "multiplexed sessions\r\n", efc->escape_char, b)) != 0) fatal_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_fr(r, "sshbuf_putf"); /* Restore terminal modes and suspend. */ client_suspend_self(bin, bout, berr); /* We have been continued. */ continue; case 'B': if ((r = sshbuf_putf(berr, "%cB\r\n", efc->escape_char)) != 0) fatal_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_fr(r, "send packet"); continue; case 'R': if (ssh->compat & SSH_BUG_NOREKEY) logit("Server does not " "support re-keying"); else need_rekeying = 1; continue; case 'V': /* FALLTHROUGH */ case 'v': if (c && c->ctl_chan != -1) goto noescape; if (!log_is_on_stderr()) { if ((r = sshbuf_putf(berr, "%c%c [Logging to syslog]\r\n", efc->escape_char, ch)) != 0) fatal_fr(r, "sshbuf_putf"); continue; } if (ch == 'V' && options.log_level > SYSLOG_LEVEL_QUIET) log_change_level(--options.log_level); if (ch == 'v' && options.log_level < SYSLOG_LEVEL_DEBUG3) log_change_level(++options.log_level); if ((r = sshbuf_putf(berr, "%c%c [LogLevel %s]\r\n", efc->escape_char, ch, log_level_name(options.log_level))) != 0) fatal_fr(r, "sshbuf_putf"); continue; case '&': if (c->ctl_chan != -1) goto noescape; /* * Detach the program (continue to serve * connections, but put in background and no * more new connections). */ /* Restore tty modes. */ leave_raw_mode( options.request_tty == REQUEST_TTY_FORCE); /* Stop listening for new connections. */ channel_stop_listening(ssh); if ((r = sshbuf_putf(berr, "%c& " "[backgrounded]\n", efc->escape_char)) != 0) fatal_fr(r, "sshbuf_putf"); /* Fork into background. */ pid = fork(); if (pid == -1) { error("fork: %.100s", strerror(errno)); continue; } if (pid != 0) { /* This is the parent. */ /* The parent just exits. */ exit(0); } /* The child continues serving connections. */ /* fake EOF on stdin */ if ((r = sshbuf_put_u8(bin, 4)) != 0) fatal_fr(r, "sshbuf_put_u8"); return -1; case '?': print_escape_help(berr, efc->escape_char, (c && c->ctl_chan != -1), log_is_on_stderr()); continue; case '#': if ((r = sshbuf_putf(berr, "%c#\r\n", efc->escape_char)) != 0) fatal_fr(r, "sshbuf_putf"); s = channel_open_message(ssh); if ((r = sshbuf_put(berr, s, strlen(s))) != 0) fatal_fr(r, "sshbuf_put"); free(s); continue; case 'C': if (c && c->ctl_chan != -1) goto noescape; if (options.enable_escape_commandline == 0) { if ((r = sshbuf_putf(berr, "commandline disabled\r\n")) != 0) fatal_fr(r, "sshbuf_putf"); continue; } process_cmdline(ssh); continue; default: if (ch != efc->escape_char) { if ((r = sshbuf_put_u8(bin, efc->escape_char)) != 0) fatal_fr(r, "sshbuf_put_u8"); bytes++; } /* Escaped characters fall through here */ break; } } else { /* * The previous character was not an escape char. * Check if this is an escape. */ if (last_was_cr && ch == efc->escape_char) { /* * It is. Set the flag and continue to * next character. */ efc->escape_pending = 1; continue; } } /* * Normal character. Record whether it was a newline, * and append it to the buffer. */ last_was_cr = (ch == '\r' || ch == '\n'); if ((r = sshbuf_put_u8(bin, ch)) != 0) fatal_fr(r, "sshbuf_put_u8"); bytes++; } return bytes; } /* * Get packets from the connection input buffer, and process them as long as * there are packets available. * * Any unknown packets received during the actual * session cause the session to terminate. This is * intended to make debugging easier since no * confirmations are sent. Any compatible protocol * extensions must be negotiated during the * preparatory phase. */ static void client_process_buffered_input_packets(struct ssh *ssh) { ssh_dispatch_run_fatal(ssh, DISPATCH_NONBLOCK, &quit_pending); } /* scan buf[] for '~' before sending data to the peer */ /* Helper: allocate a new escape_filter_ctx and fill in its escape char */ void * client_new_escape_filter_ctx(int escape_char) { struct escape_filter_ctx *ret; ret = xcalloc(1, sizeof(*ret)); ret->escape_pending = 0; ret->escape_char = escape_char; return (void *)ret; } /* Free the escape filter context on channel free */ void client_filter_cleanup(struct ssh *ssh, int cid, void *ctx) { free(ctx); } int client_simple_escape_filter(struct ssh *ssh, Channel *c, char *buf, int len) { if (c->extended_usage != CHAN_EXTENDED_WRITE) return 0; return process_escapes(ssh, c, c->input, c->output, c->extended, buf, len); } static void client_channel_closed(struct ssh *ssh, int id, int force, void *arg) { channel_cancel_cleanup(ssh, id); session_closed = 1; leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); } /* * Implements the interactive session with the server. This is called after * the user has been authenticated, and a command has been started on the * remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character * used as an escape character for terminating or suspending the session. */ int client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, int ssh2_chan_id) { struct pollfd *pfd = NULL; u_int npfd_alloc = 0, npfd_active = 0; double start_time, total_time; int channel_did_enqueue = 0, r, len; u_int64_t ibytes, obytes; int conn_in_ready, conn_out_ready; + sigset_t bsigset, osigset; debug("Entering interactive session."); session_ident = ssh2_chan_id; if (options.control_master && !option_clear_or_none(options.control_path)) { debug("pledge: id"); if (pledge("stdio rpath wpath cpath unix inet dns recvfd sendfd proc exec id tty", NULL) == -1) 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_f("pledge(): %s", strerror(errno)); } else if (options.update_hostkeys) { debug("pledge: filesystem"); if (pledge("stdio rpath wpath cpath unix inet dns proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } else if (!option_clear_or_none(options.proxy_command) || options.fork_after_authentication) { debug("pledge: proc"); if (pledge("stdio cpath unix inet dns proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } else { debug("pledge: network"); if (pledge("stdio unix inet dns proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } /* might be able to tighten now */ client_repledge(); start_time = monotime_double(); /* Initialize variables. */ last_was_cr = 1; exit_status = -1; connection_in = ssh_packet_get_connection_in(ssh); connection_out = ssh_packet_get_connection_out(ssh); quit_pending = 0; /* Initialize buffer. */ if ((stderr_buffer = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); client_init_dispatch(ssh); /* * Set signal handlers, (e.g. to restore non-blocking mode) * but don't overwrite SIG_IGN, matches behaviour from rsh(1) */ if (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); if (session_ident != -1) { if (escape_char_arg != SSH_ESCAPECHAR_NONE) { channel_register_filter(ssh, session_ident, client_simple_escape_filter, NULL, client_filter_cleanup, client_new_escape_filter_ctx( escape_char_arg)); } channel_register_cleanup(ssh, session_ident, client_channel_closed, 0); } schedule_server_alive_check(); + if (sigemptyset(&bsigset) == -1 || + sigaddset(&bsigset, SIGHUP) == -1 || + sigaddset(&bsigset, SIGINT) == -1 || + sigaddset(&bsigset, SIGQUIT) == -1 || + sigaddset(&bsigset, SIGTERM) == -1) + error_f("bsigset setup: %s", strerror(errno)); + /* Main loop of the client for the interactive session mode. */ while (!quit_pending) { channel_did_enqueue = 0; /* Process buffered packets sent by the server. */ client_process_buffered_input_packets(ssh); if (session_closed && !channel_still_open(ssh)) break; if (ssh_packet_is_rekeying(ssh)) { debug("rekeying in progress"); } else if (need_rekeying) { /* manual rekey request */ debug("need rekeying"); if ((r = kex_start_rekex(ssh)) != 0) fatal_fr(r, "kex_start_rekex"); need_rekeying = 0; } else { /* * Make packets from buffered channel data, and * enqueue them for sending to the server. */ if (ssh_packet_not_very_much_data_to_write(ssh)) channel_did_enqueue = channel_output_poll(ssh); /* * Check if the window size has changed, and buffer a * message about it to the server if so. */ client_check_window_change(ssh); - - if (quit_pending) - break; } /* * Wait until we have something to do (something becomes * available on one of the descriptors). */ + if (sigprocmask(SIG_BLOCK, &bsigset, &osigset) == -1) + error_f("bsigset sigprocmask: %s", strerror(errno)); + if (quit_pending) + break; client_wait_until_can_do_something(ssh, &pfd, &npfd_alloc, - &npfd_active, channel_did_enqueue, + &npfd_active, channel_did_enqueue, &osigset, &conn_in_ready, &conn_out_ready); + if (sigprocmask(SIG_UNBLOCK, &bsigset, &osigset) == -1) + error_f("osigset sigprocmask: %s", strerror(errno)); if (quit_pending) break; /* Do channel operations. */ channel_after_poll(ssh, pfd, npfd_active); /* Buffer input from the connection. */ if (conn_in_ready) client_process_net_input(ssh); if (quit_pending) break; /* A timeout may have triggered rekeying */ if ((r = ssh_packet_check_rekey(ssh)) != 0) fatal_fr(r, "cannot start rekeying"); /* * Send as much buffered packet data as possible to the * sender. */ if (conn_out_ready) { 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 * timeout has expired without any active client * connections, then quit. */ if (control_persist_exit_time > 0) { if (monotime() >= control_persist_exit_time) { debug("ControlPersist timeout expired"); break; } } } free(pfd); /* Terminate the session. */ /* Stop watching for window change. */ ssh_signal(SIGWINCH, SIG_DFL); if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 || (r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_BY_APPLICATION)) != 0 || (r = sshpkt_put_cstring(ssh, "disconnected by user")) != 0 || (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language tag */ (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "send disconnect"); channel_free_all(ssh); if (have_pty) leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); /* * If there was no shell or command requested, there will be no remote * exit status to be returned. In that case, clear error code if the * connection was deliberately terminated at this end. */ if (options.session_type == SESSION_TYPE_NONE && received_signal == SIGTERM) { received_signal = 0; exit_status = 0; } if (received_signal) { verbose("Killed by signal %d.", (int) received_signal); cleanup_exit(255); } /* * In interactive mode (with pseudo tty) display a message indicating * that the connection has been closed. */ if (have_pty && options.log_level >= SYSLOG_LEVEL_INFO) quit_message("Connection to %s closed.", host); /* Output any buffered data for stderr. */ if (sshbuf_len(stderr_buffer) > 0) { len = atomicio(vwrite, fileno(stderr), (u_char *)sshbuf_ptr(stderr_buffer), sshbuf_len(stderr_buffer)); if (len < 0 || (u_int)len != sshbuf_len(stderr_buffer)) error("Write failed flushing stderr buffer."); else if ((r = sshbuf_consume(stderr_buffer, len)) != 0) fatal_fr(r, "sshbuf_consume"); } /* Clear and free any buffers. */ sshbuf_free(stderr_buffer); /* Report bytes transferred, and transfer rates. */ total_time = monotime_double() - start_time; ssh_packet_get_bytes(ssh, &ibytes, &obytes); verbose("Transferred: sent %llu, received %llu bytes, in %.1f seconds", (unsigned long long)obytes, (unsigned long long)ibytes, total_time); if (total_time > 0) verbose("Bytes per second: sent %.1f, received %.1f", obytes / total_time, ibytes / total_time); /* Return the exit status of the program. */ debug("Exit status %d", exit_status); return exit_status; } /*********/ static Channel * client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type, int rchan, u_int rwindow, u_int rmaxpack) { Channel *c = NULL; struct sshbuf *b = NULL; char *listen_address, *originator_address; u_int listen_port, originator_port; int r; /* Get rest of the packet */ if ((r = sshpkt_get_cstring(ssh, &listen_address, NULL)) != 0 || (r = sshpkt_get_u32(ssh, &listen_port)) != 0 || (r = sshpkt_get_cstring(ssh, &originator_address, NULL)) != 0 || (r = sshpkt_get_u32(ssh, &originator_port)) != 0 || (r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); debug_f("listen %s port %d, originator %s port %d", listen_address, listen_port, originator_address, originator_port); if (listen_port > 0xffff) error_f("invalid listen port"); else if (originator_port > 0xffff) error_f("invalid originator port"); else { c = channel_connect_by_listen_address(ssh, listen_address, listen_port, "forwarded-tcpip", originator_address); } if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { if ((b = sshbuf_new()) == NULL) { error_f("alloc reply"); goto out; } /* reconstruct and send to muxclient */ if ((r = sshbuf_put_u8(b, 0)) != 0 || /* padlen */ (r = sshbuf_put_u8(b, SSH2_MSG_CHANNEL_OPEN)) != 0 || (r = sshbuf_put_cstring(b, request_type)) != 0 || (r = sshbuf_put_u32(b, rchan)) != 0 || (r = sshbuf_put_u32(b, rwindow)) != 0 || (r = sshbuf_put_u32(b, rmaxpack)) != 0 || (r = sshbuf_put_cstring(b, listen_address)) != 0 || (r = sshbuf_put_u32(b, listen_port)) != 0 || (r = sshbuf_put_cstring(b, originator_address)) != 0 || (r = sshbuf_put_u32(b, originator_port)) != 0 || (r = sshbuf_put_stringb(c->output, b)) != 0) { error_fr(r, "compose for muxclient"); goto out; } } out: sshbuf_free(b); free(originator_address); free(listen_address); return c; } static Channel * client_request_forwarded_streamlocal(struct ssh *ssh, const char *request_type, int rchan) { Channel *c = NULL; char *listen_path; int r; /* Get the remote path. */ 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_fr(r, "parse packet"); debug_f("request: %s", listen_path); c = channel_connect_by_listen_path(ssh, listen_path, "forwarded-streamlocal@openssh.com", "forwarded-streamlocal"); free(listen_path); return c; } static Channel * client_request_x11(struct ssh *ssh, const char *request_type, int rchan) { Channel *c = NULL; char *originator; u_int originator_port; int r, sock; if (!options.forward_x11) { error("Warning: ssh server tried X11 forwarding."); error("Warning: this is probably a break-in attempt by a " "malicious server."); return NULL; } if (x11_refuse_time != 0 && monotime() >= x11_refuse_time) { verbose("Rejected X11 connection after ForwardX11Timeout " "expired"); return NULL; } if ((r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 || (r = sshpkt_get_u32(ssh, &originator_port)) != 0 || (r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); /* XXX check permission */ /* XXX range check originator port? */ debug("client_request_x11: request from %s %u", originator, originator_port); free(originator); sock = x11_connect_display(ssh); if (sock < 0) return NULL; - c = channel_new(ssh, "x11", + c = channel_new(ssh, "x11-connection", SSH_CHANNEL_X11_OPEN, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); c->force_drain = 1; return c; } static Channel * client_request_agent(struct ssh *ssh, const char *request_type, int rchan) { Channel *c = NULL; int r, sock; if (!options.forward_agent) { error("Warning: ssh server tried agent forwarding."); error("Warning: this is probably a break-in attempt by a " "malicious server."); return NULL; } if (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_fr(r, "ssh_get_authentication_socket"); return NULL; } if ((r = ssh_agent_bind_hostkey(sock, ssh->kex->initial_hostkey, ssh->kex->session_id, ssh->kex->initial_sig, 1)) == 0) debug_f("bound agent to hostkey"); else debug2_fr(r, "ssh_agent_bind_hostkey"); - c = channel_new(ssh, "authentication agent connection", + c = channel_new(ssh, "agent-connection", SSH_CHANNEL_OPEN, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "authentication agent connection", 1); c->force_drain = 1; return c; } char * client_request_tun_fwd(struct ssh *ssh, int tun_mode, int local_tun, int remote_tun, channel_open_fn *cb, void *cbctx) { Channel *c; int r, fd; char *ifname = NULL; if (tun_mode == SSH_TUNMODE_NO) return 0; debug("Requesting tun unit %d in mode %d", local_tun, tun_mode); /* Open local tunnel device */ if ((fd = tun_open(local_tun, tun_mode, &ifname)) == -1) { error("Tunnel device open failed."); return NULL; } debug("Tunnel forwarding using interface %s", ifname); - c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1, + c = channel_new(ssh, "tun-connection", SSH_CHANNEL_OPENING, fd, fd, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); c->datagram = 1; #if defined(SSH_TUN_FILTER) if (options.tun_open == SSH_TUNMODE_POINTOPOINT) channel_register_filter(ssh, c->self, sys_tun_infilter, sys_tun_outfilter, NULL, NULL); #endif 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 || (r = sshpkt_put_u32(ssh, c->local_window_max)) != 0 || (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 || (r = sshpkt_put_u32(ssh, tun_mode)) != 0 || (r = sshpkt_put_u32(ssh, remote_tun)) != 0 || (r = sshpkt_send(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: send reply", __func__); return ifname; } /* XXXX move to generic input handler */ static int client_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = NULL; char *ctype = NULL; int r; u_int rchan; size_t len; u_int rmaxpack, rwindow; if ((r = sshpkt_get_cstring(ssh, &ctype, &len)) != 0 || (r = sshpkt_get_u32(ssh, &rchan)) != 0 || (r = sshpkt_get_u32(ssh, &rwindow)) != 0 || (r = sshpkt_get_u32(ssh, &rmaxpack)) != 0) goto out; debug("client_input_channel_open: ctype %s rchan %d win %d max %d", ctype, rchan, rwindow, rmaxpack); if (strcmp(ctype, "forwarded-tcpip") == 0) { c = client_request_forwarded_tcpip(ssh, ctype, rchan, rwindow, rmaxpack); } else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) { c = client_request_forwarded_streamlocal(ssh, ctype, rchan); } else if (strcmp(ctype, "x11") == 0) { c = client_request_x11(ssh, ctype, rchan); } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { c = client_request_agent(ssh, ctype, rchan); } if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { debug3("proxied to downstream: %s", ctype); } else if (c != NULL) { debug("confirm %s", ctype); c->remote_id = rchan; c->have_remote_id = 1; c->remote_window = rwindow; c->remote_maxpacket = rmaxpack; if (c->type != SSH_CHANNEL_CONNECTING) { if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 || (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || (r = sshpkt_put_u32(ssh, c->self)) != 0 || (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 || (r = sshpkt_send(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: send reply", __func__); } } else { debug("failure %s", ctype); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 || (r = sshpkt_put_u32(ssh, rchan)) != 0 || (r = sshpkt_put_u32(ssh, SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED)) != 0 || (r = sshpkt_put_cstring(ssh, "open failed")) != 0 || (r = sshpkt_put_cstring(ssh, "")) != 0 || (r = sshpkt_send(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: send failure", __func__); } r = 0; out: free(ctype); return r; } static int client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) { Channel *c = NULL; char *rtype = NULL; u_char reply; u_int id, exitval; int r, success = 0; if ((r = sshpkt_get_u32(ssh, &id)) != 0) return r; if (id <= INT_MAX) c = channel_lookup(ssh, id); if (channel_proxy_upstream(c, type, seq, ssh)) return 0; if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || (r = sshpkt_get_u8(ssh, &reply)) != 0) goto out; debug("client_input_channel_req: channel %u rtype %s reply %d", id, rtype, reply); if (c == NULL) { error("client_input_channel_req: channel %d: " "unknown channel", id); } else if (strcmp(rtype, "eow@openssh.com") == 0) { if ((r = sshpkt_get_end(ssh)) != 0) goto out; chan_rcvd_eow(ssh, c); } else if (strcmp(rtype, "exit-status") == 0) { if ((r = sshpkt_get_u32(ssh, &exitval)) != 0) goto out; if (c->ctl_chan != -1) { mux_exit_message(ssh, c, exitval); success = 1; } else if ((int)id == session_ident) { /* Record exit value of local session */ success = 1; exit_status = exitval; } else { /* Probably for a mux channel that has already closed */ debug_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_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 || (r = sshpkt_send(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: send failure", __func__); } r = 0; out: free(rtype); return r; } struct hostkeys_update_ctx { /* The hostname and (optionally) IP address string for the server */ char *host_str, *ip_str; /* * Keys received from the server and a flag for each indicating * whether they already exist in known_hosts. * keys_match is filled in by hostkeys_find() and later (for new * keys) by client_global_hostkeys_prove_confirm(). */ struct sshkey **keys; 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 * from the server (i.e. scheduled to be deleted). * Filled in by hostkeys_find(). */ 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 hostkeys_update_ctx_free(struct hostkeys_update_ctx *ctx) { size_t i; if (ctx == NULL) return; for (i = 0; i < ctx->nkeys; i++) sshkey_free(ctx->keys[i]); free(ctx->keys); free(ctx->keys_match); free(ctx->keys_verified); for (i = 0; i < ctx->nold; i++) sshkey_free(ctx->old_keys[i]); free(ctx->old_keys); free(ctx->host_str); free(ctx->ip_str); free(ctx); } /* * 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) { struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; size_t i; struct sshkey **tmp; 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])) 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_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_f("recallocarray failed nold = %zu", ctx->nold); ctx->old_keys = tmp; ctx->old_keys[ctx->nold++] = l->key; l->key = NULL; 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->old_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, 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_verified[i]) continue; if ((fp = sshkey_fingerprint(ctx->keys[i], options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) 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_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) { if (get_saved_tio() != NULL) { leave_raw_mode(1); was_raw = 1; } response = NULL; for (i = 0; !quit_pending && i < 3; i++) { free(response); response = read_passphrase("Accept updated hostkeys? " "(yes/no): ", RP_ECHO); if (response != NULL && strcasecmp(response, "yes") == 0) break; else if (quit_pending || response == NULL || strcasecmp(response, "no") == 0) { options.update_hostkeys = 0; break; } else { do_log2(loglevel, "Please enter " "\"yes\" or \"no\""); } } if (quit_pending || i >= 3 || response == NULL) options.update_hostkeys = 0; free(response); if (was_raw) enter_raw_mode(1); } 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). */ 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 client_global_hostkeys_prove_confirm(struct ssh *ssh, int type, u_int32_t seq, void *_ctx) { struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; size_t i, ndone; struct sshbuf *signdata; int r, plaintype; const u_char *sig; const char *rsa_kexalg = NULL; char *alg = NULL; size_t siglen; if (ctx->nnew == 0) fatal_f("ctx->nnew == 0"); /* sanity */ if (type != SSH2_MSG_REQUEST_SUCCESS) { error("Server failed to confirm ownership of " "private host keys"); hostkeys_update_ctx_free(ctx); return; } if (sshkey_type_plain(sshkey_type_from_name( ssh->kex->hostkey_alg)) == KEY_RSA) rsa_kexalg = ssh->kex->hostkey_alg; if ((signdata = sshbuf_new()) == NULL) 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_match[i] == 0. */ for (ndone = i = 0; i < ctx->nkeys; i++) { if (ctx->keys_match[i]) continue; plaintype = sshkey_type_plain(ctx->keys[i]->type); /* 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_stringb(signdata, ssh->kex->session_id)) != 0 || (r = sshkey_puts(ctx->keys[i], signdata)) != 0) fatal_fr(r, "compose signdata"); /* Extract and verify signature */ if ((r = sshpkt_get_string_direct(ssh, &sig, &siglen)) != 0) { error_fr(r, "parse sig"); goto out; } if ((r = sshkey_get_sigtype(sig, siglen, &alg)) != 0) { error_fr(r, "server gave unintelligible signature " "for %s key %zu", sshkey_type(ctx->keys[i]), i); goto out; } /* * Special case for RSA keys: if a RSA hostkey was negotiated, * then use its signature type for verification of RSA hostkey * proofs. Otherwise, accept only RSA-SHA256/512 signatures. */ if (plaintype == KEY_RSA && rsa_kexalg == NULL && match_pattern_list(alg, HOSTKEY_PROOF_RSA_ALGS, 0) != 1) { debug_f("server used untrusted RSA signature algorithm " "%s for key %zu, disregarding", alg, i); free(alg); /* zap the key from the list */ sshkey_free(ctx->keys[i]); ctx->keys[i] = NULL; ndone++; continue; } debug3_f("verify %s key %zu using sigalg %s", sshkey_type(ctx->keys[i]), i, alg); free(alg); if ((r = sshkey_verify(ctx->keys[i], sig, siglen, sshbuf_ptr(signdata), sshbuf_len(signdata), plaintype == KEY_RSA ? rsa_kexalg : NULL, 0, NULL)) != 0) { error_fr(r, "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_verified[i] = 1; ndone++; } /* Shouldn't happen */ if (ndone != ctx->nnew) fatal_f("ndone != ctx->nnew (%zu / %zu)", ndone, ctx->nnew); if ((r = sshpkt_get_end(ssh)) != 0) { error_f("protocol error"); goto out; } /* Make the edits to known_hosts */ update_known_hosts(ctx); out: hostkeys_update_ctx_free(ctx); hostkeys_update_complete = 1; client_repledge(); } /* * Returns non-zero if the key is accepted by HostkeyAlgorithms. * Made slightly less trivial by the multiple RSA signature algorithm names. */ static int key_accepted_by_hostkeyalgs(const struct sshkey *key) { const char *ktype = sshkey_ssh_name(key); const char *hostkeyalgs = options.hostkeyalgorithms; if (key->type == KEY_UNSPEC) return 0; if (key->type == KEY_RSA && (match_pattern_list("rsa-sha2-256", hostkeyalgs, 0) == 1 || match_pattern_list("rsa-sha2-512", hostkeyalgs, 0) == 1)) return 1; return match_pattern_list(ktype, hostkeyalgs, 0) == 1; } /* * Handle hostkeys-00@openssh.com global request to inform the client of all * the server's hostkeys. The keys are checked against the user's * HostkeyAlgorithms preference before they are accepted. */ static int client_input_hostkeys(struct ssh *ssh) { const u_char *blob = NULL; size_t i, len = 0; struct sshbuf *buf = NULL; struct sshkey *key = NULL, **tmp; int r, prove_sent = 0; char *fp; static int hostkeys_seen = 0; /* XXX use struct ssh */ extern struct sockaddr_storage hostaddr; /* XXX from ssh.c */ struct hostkeys_update_ctx *ctx = NULL; u_int want; if (hostkeys_seen) fatal_f("server already sent hostkeys"); if (!can_update_hostkeys()) return 1; hostkeys_seen = 1; ctx = xcalloc(1, sizeof(*ctx)); while (ssh_packet_remaining(ssh) > 0) { sshkey_free(key); key = NULL; if ((r = sshpkt_get_string_direct(ssh, &blob, &len)) != 0) { error_fr(r, "parse key"); goto out; } if ((r = sshkey_from_blob(blob, len, &key)) != 0) { 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_f("received %s key %s", sshkey_type(key), fp); free(fp); if (!key_accepted_by_hostkeyalgs(key)) { debug3_f("%s key not permitted by " "HostkeyAlgorithms", sshkey_ssh_name(key)); continue; } /* Skip certs */ if (sshkey_is_cert(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_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_f("recallocarray failed nkeys = %zu", ctx->nkeys); ctx->keys = tmp; ctx->keys[ctx->nkeys++] = key; key = NULL; } if (ctx->nkeys == 0) { debug_f("server sent no hostkeys"); goto out; } 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, options.port, &ctx->host_str, options.check_host_ip ? &ctx->ip_str : NULL); /* Find which keys we already know about. */ 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 = 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_match[i] == 0) ctx->nnew++; if ((ctx->keys_match[i] & want) != want) ctx->nincomplete++; } 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) { 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 (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_prove_confirm, ctx); ctx = NULL; /* will be freed in callback */ prove_sent = 1; /* Success */ out: hostkeys_update_ctx_free(ctx); sshkey_free(key); sshbuf_free(buf); if (!prove_sent) { /* UpdateHostkeys handling completed */ hostkeys_update_complete = 1; client_repledge(); } /* * NB. Return success for all cases. The server doesn't need to know * what the client does with its hosts file. */ return 1; } static int client_input_global_request(int type, u_int32_t seq, struct ssh *ssh) { char *rtype; u_char want_reply; int r, success = 0; if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || (r = sshpkt_get_u8(ssh, &want_reply)) != 0) goto out; debug("client_input_global_request: rtype %s want_reply %d", rtype, want_reply); if (strcmp(rtype, "hostkeys-00@openssh.com") == 0) success = client_input_hostkeys(ssh); if (want_reply) { if ((r = sshpkt_start(ssh, success ? SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE)) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) goto out; } r = 0; out: free(rtype); return 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, char **env) { size_t i, j, len; int matched, r; char *name, *val; Channel *c = NULL; debug2_f("id %d", id); if ((c = channel_lookup(ssh, id)) == NULL) fatal_f("channel %d: unknown channel", id); ssh_packet_set_interactive(ssh, want_tty, options.ip_qos_interactive, options.ip_qos_bulk); if (want_tty) { struct winsize ws; /* Store window size in the packet. */ if (ioctl(in_fd, TIOCGWINSZ, &ws) == -1) memset(&ws, 0, sizeof(ws)); channel_request_start(ssh, id, "pty-req", 1); client_expect_confirm(ssh, id, "PTY allocation", CONFIRM_TTY); if ((r = sshpkt_put_cstring(ssh, term != NULL ? term : "")) != 0 || (r = sshpkt_put_u32(ssh, (u_int)ws.ws_col)) != 0 || (r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 || (r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 || (r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0) fatal_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_fr(r, "send pty-req"); /* XXX wait for reply */ c->client_tty = 1; } /* Transfer any environment variables from client to server */ if (options.num_send_env != 0 && env != NULL) { debug("Sending environment."); for (i = 0; env[i] != NULL; i++) { /* Split */ name = xstrdup(env[i]); if ((val = strchr(name, '=')) == NULL) { free(name); continue; } *val++ = '\0'; matched = 0; for (j = 0; j < options.num_send_env; j++) { if (match_pattern(name, options.send_env[j])) { matched = 1; break; } } if (!matched) { debug3("Ignored env %s", name); free(name); continue; } client_send_env(ssh, id, name, val); free(name); } } for (i = 0; i < options.num_setenv; i++) { /* Split */ name = xstrdup(options.setenv[i]); if ((val = strchr(name, '=')) == NULL) { free(name); continue; } *val++ = '\0'; client_send_env(ssh, id, name, val); free(name); } len = sshbuf_len(cmd); if (len > 0) { if (len > 900) len = 900; if (want_subsystem) { debug("Sending subsystem: %.*s", (int)len, (const u_char*)sshbuf_ptr(cmd)); channel_request_start(ssh, id, "subsystem", 1); client_expect_confirm(ssh, id, "subsystem", CONFIRM_CLOSE); } else { debug("Sending command: %.*s", (int)len, (const u_char*)sshbuf_ptr(cmd)); channel_request_start(ssh, id, "exec", 1); client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE); } if ((r = sshpkt_put_stringb(ssh, cmd)) != 0 || (r = sshpkt_send(ssh)) != 0) 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_fr(r, "send shell"); } session_setup_complete = 1; client_repledge(); } static void client_init_dispatch(struct ssh *ssh) { ssh_dispatch_init(ssh, &dispatch_protocol_error); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_CLOSE, &channel_input_oclose); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_DATA, &channel_input_data); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EOF, &channel_input_ieof); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_REQUEST, &client_input_channel_req); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_SUCCESS, &channel_input_status_confirm); ssh_dispatch_set(ssh, SSH2_MSG_CHANNEL_FAILURE, &channel_input_status_confirm); ssh_dispatch_set(ssh, SSH2_MSG_GLOBAL_REQUEST, &client_input_global_request); /* rekeying */ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); /* global request reply messages */ ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_FAILURE, &client_global_request_reply); ssh_dispatch_set(ssh, SSH2_MSG_REQUEST_SUCCESS, &client_global_request_reply); } void client_stop_mux(void) { if (options.control_path != NULL && muxserver_sock != -1) unlink(options.control_path); /* * If we are in persist mode, or don't have a shell, signal that we * should close when all active channels are closed. */ if (options.control_persist || options.session_type == SESSION_TYPE_NONE) { session_closed = 1; setproctitle("[stopped mux]"); } } /* client specific fatal cleanup */ void cleanup_exit(int i) { leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); if (options.control_path != NULL && muxserver_sock != -1) unlink(options.control_path); ssh_kill_proxy_command(); _exit(i); } diff --git a/crypto/openssh/config.h b/crypto/openssh/config.h index 385e53c82ea3..23645cfe78c7 100644 --- a/crypto/openssh/config.h +++ b/crypto/openssh/config.h @@ -1,2042 +1,2051 @@ /* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.ac by autoheader. */ /* Define if building universal (internal helper macro) */ /* #undef AC_APPLE_UNIVERSAL_BUILD */ /* Define if you have a getaddrinfo that fails for the all-zeros IPv6 address */ /* #undef AIX_GETNAMEINFO_HACK */ /* Define if your AIX loginfailed() function takes 4 arguments (AIX >= 5.2) */ /* #undef AIX_LOGINFAILED_4ARG */ /* System only supports IPv4 audit records */ /* #undef AU_IPv4 */ /* Define if your resolver libs need this for getrrsetbyname */ /* #undef BIND_8_COMPAT */ /* The system has incomplete BSM API */ /* #undef BROKEN_BSM_API */ /* broken in chroots on older kernels */ /* #undef BROKEN_CLOSEFROM */ /* Define if cmsg_type is not passed correctly */ /* #undef BROKEN_CMSG_TYPE */ /* getaddrinfo is broken (if present) */ /* #undef BROKEN_GETADDRINFO */ /* getgroups(0,NULL) will return -1 */ /* #undef BROKEN_GETGROUPS */ /* getline is not what we expect */ /* #undef BROKEN_GETLINE */ /* FreeBSD glob does not do what we need */ #define BROKEN_GLOB 1 /* Define if you system's inet_ntoa is busted (e.g. Irix gcc issue) */ /* #undef BROKEN_INET_NTOA */ /* Define if your struct dirent expects you to allocate extra space for d_name */ /* #undef BROKEN_ONE_BYTE_DIRENT_D_NAME */ /* System poll(2) implementation is broken */ /* #undef BROKEN_POLL */ /* Can't do comparisons on readv */ /* #undef BROKEN_READV_COMPARISON */ /* NetBSD read function is sometimes redirected, breaking atomicio comparisons against it */ /* #undef BROKEN_READ_COMPARISON */ /* Needed for NeXT */ /* #undef BROKEN_SAVED_UIDS */ /* Define if your setregid() is broken */ /* #undef BROKEN_SETREGID */ /* Define if your setresgid() is broken */ /* #undef BROKEN_SETRESGID */ /* Define if your setresuid() is broken */ /* #undef BROKEN_SETRESUID */ /* Define if your setreuid() is broken */ /* #undef BROKEN_SETREUID */ /* LynxOS has broken setvbuf() implementation */ /* #undef BROKEN_SETVBUF */ /* QNX shadow support is broken */ /* #undef BROKEN_SHADOW_EXPIRE */ /* Define if your snprintf is busted */ /* #undef BROKEN_SNPRINTF */ /* strndup broken, see APAR IY61211 */ /* #undef BROKEN_STRNDUP */ /* strnlen broken, see APAR IY62551 */ /* #undef BROKEN_STRNLEN */ /* strnvis detected broken */ #define BROKEN_STRNVIS 1 /* tcgetattr with ICANON may hang */ /* #undef BROKEN_TCGETATTR_ICANON */ /* updwtmpx is broken (if present) */ /* #undef BROKEN_UPDWTMPX */ /* Define if you have BSD auth support */ /* #undef BSD_AUTH */ /* Define if you want to specify the path to your lastlog file */ /* #undef CONF_LASTLOG_FILE */ /* Define if you want to specify the path to your utmp file */ /* #undef CONF_UTMP_FILE */ /* Define if you want to specify the path to your wtmpx file */ /* #undef CONF_WTMPX_FILE */ /* Define if you want to specify the path to your wtmp file */ /* #undef CONF_WTMP_FILE */ /* Need to call setpgrp as root */ /* #undef DISABLE_FD_PASSING */ /* Define if you don't want to use lastlog */ /* #undef DISABLE_LASTLOG */ /* Define if you don't want to use your system's login() call */ /* #undef DISABLE_LOGIN */ /* Define if you don't want to use pututline() etc. to write [uw]tmp */ /* #undef DISABLE_PUTUTLINE */ /* Define if you don't want to use pututxline() etc. to write [uw]tmpx */ /* #undef DISABLE_PUTUTXLINE */ /* Define if you want to disable shadow passwords */ /* #undef DISABLE_SHADOW */ /* Define if you don't want to use utmp */ #define DISABLE_UTMP 1 /* Define if you don't want to use utmpx */ /* #undef DISABLE_UTMPX */ /* Define if you don't want to use wtmp */ #define DISABLE_WTMP 1 /* Define if you don't want to use wtmpx */ #define DISABLE_WTMPX 1 /* Enable for PKCS#11 support */ #define ENABLE_PKCS11 /**/ /* Enable for U2F/FIDO support */ #define ENABLE_SK /**/ /* Enable for built-in U2F/FIDO support */ /* #undef ENABLE_SK_INTERNAL */ /* define if fflush(NULL) does not work */ /* #undef FFLUSH_NULL_BUG */ /* File names may not contain backslash characters */ /* #undef FILESYSTEM_NO_BACKSLASH */ /* fsid_t has member val */ /* #undef FSID_HAS_VAL */ /* fsid_t has member __val */ /* #undef FSID_HAS___VAL */ /* getpgrp takes one arg */ #define GETPGRP_VOID 1 /* Conflicting defs for getspnam */ /* #undef GETSPNAM_CONFLICTING_DEFS */ /* Define if your system glob() function has the GLOB_ALTDIRFUNC extension */ #define GLOB_HAS_ALTDIRFUNC 1 /* Define if your system glob() function has gl_matchc options in glob_t */ #define GLOB_HAS_GL_MATCHC 1 /* Define if your system glob() function has gl_statv options in glob_t */ /* #undef GLOB_HAS_GL_STATV */ /* Define this if you want GSSAPI support in the version 2 protocol */ /* #undef GSSAPI */ /* Define if you want to use shadow password expire field */ /* #undef HAS_SHADOW_EXPIRE */ /* Define if your system uses access rights style file descriptor passing */ /* #undef HAVE_ACCRIGHTS_IN_MSGHDR */ /* Define if you have ut_addr in utmp.h */ /* #undef HAVE_ADDR_IN_UTMP */ /* Define if you have ut_addr in utmpx.h */ /* #undef HAVE_ADDR_IN_UTMPX */ /* Define if you have ut_addr_v6 in utmp.h */ /* #undef HAVE_ADDR_V6_IN_UTMP */ /* Define if you have ut_addr_v6 in utmpx.h */ /* #undef HAVE_ADDR_V6_IN_UTMPX */ /* Define to 1 if you have the `arc4random' function. */ #define HAVE_ARC4RANDOM 1 /* Define to 1 if you have the `arc4random_buf' function. */ #define HAVE_ARC4RANDOM_BUF 1 /* Define to 1 if you have the `arc4random_stir' function. */ /* #undef HAVE_ARC4RANDOM_STIR */ /* Define to 1 if you have the `arc4random_uniform' function. */ #define HAVE_ARC4RANDOM_UNIFORM 1 /* Define to 1 if you have the `asprintf' function. */ #define HAVE_ASPRINTF 1 /* OpenBSD's gcc has bounded */ /* #undef HAVE_ATTRIBUTE__BOUNDED__ */ /* Have attribute nonnull */ #define HAVE_ATTRIBUTE__NONNULL__ 1 /* OpenBSD's gcc has sentinel */ /* #undef HAVE_ATTRIBUTE__SENTINEL__ */ /* Define to 1 if you have the `aug_get_machine' function. */ /* #undef HAVE_AUG_GET_MACHINE */ /* Define to 1 if you have the `auth_hostok' function. */ #define HAVE_AUTH_HOSTOK 1 /* Define to 1 if you have the `auth_timeok' function. */ #define HAVE_AUTH_TIMEOK 1 /* Define to 1 if you have the `b64_ntop' function. */ /* #undef HAVE_B64_NTOP */ /* Define to 1 if you have the `b64_pton' function. */ /* #undef HAVE_B64_PTON */ /* Define if you have the basename function. */ #define HAVE_BASENAME 1 /* Define to 1 if you have the `bcopy' function. */ #define HAVE_BCOPY 1 /* Define to 1 if you have the `bcrypt_pbkdf' function. */ /* #undef HAVE_BCRYPT_PBKDF */ /* Define to 1 if you have the `bindresvport_sa' function. */ #define HAVE_BINDRESVPORT_SA 1 /* Define to 1 if you have the `blf_enc' function. */ /* #undef HAVE_BLF_ENC */ /* Define to 1 if you have the header file. */ /* #undef HAVE_BLF_H */ /* Define to 1 if you have the `Blowfish_expand0state' function. */ /* #undef HAVE_BLOWFISH_EXPAND0STATE */ /* Define to 1 if you have the `Blowfish_expandstate' function. */ /* #undef HAVE_BLOWFISH_EXPANDSTATE */ /* Define to 1 if you have the `Blowfish_initstate' function. */ /* #undef HAVE_BLOWFISH_INITSTATE */ /* Define to 1 if you have the `Blowfish_stream2word' function. */ /* #undef HAVE_BLOWFISH_STREAM2WORD */ /* Define to 1 if you have the `BN_is_prime_ex' function. */ #define HAVE_BN_IS_PRIME_EX 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_BSD_LIBUTIL_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_BSM_AUDIT_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_BSTRING_H */ /* Define to 1 if you have the `bzero' function. */ #define HAVE_BZERO 1 /* calloc(0, x) returns NULL */ #define HAVE_CALLOC 1 /* Define if you have caph_cache_tzdata */ #define HAVE_CAPH_CACHE_TZDATA 1 /* Define to 1 if you have the header file. */ #define HAVE_CAPSICUM_HELPERS_H 1 /* Define to 1 if you have the `cap_rights_limit' function. */ #define HAVE_CAP_RIGHTS_LIMIT 1 /* Define to 1 if you have the `clock' function. */ #define HAVE_CLOCK 1 /* Have clock_gettime */ #define HAVE_CLOCK_GETTIME 1 /* define if you have clock_t data type */ #define HAVE_CLOCK_T 1 /* Define to 1 if you have the `closefrom' function. */ #define HAVE_CLOSEFROM 1 /* Define to 1 if you have the `close_range' function. */ #define HAVE_CLOSE_RANGE 1 /* Define if gai_strerror() returns const char * */ #define HAVE_CONST_GAI_STRERROR_PROTO 1 /* Define if your system uses ancillary data style file descriptor passing */ #define HAVE_CONTROL_IN_MSGHDR 1 /* Define to 1 if you have the `crypt' function. */ #define HAVE_CRYPT 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_CRYPTO_SHA2_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_CRYPT_H */ /* Define if you are on Cygwin */ /* #undef HAVE_CYGWIN */ /* Define if your libraries define daemon() */ #define HAVE_DAEMON 1 /* Define to 1 if you have the declaration of `AI_NUMERICSERV', and to 0 if you don't. */ #define HAVE_DECL_AI_NUMERICSERV 1 /* Define to 1 if you have the declaration of `authenticate', and to 0 if you don't. */ /* #undef HAVE_DECL_AUTHENTICATE */ /* Define to 1 if you have the declaration of `bzero', and to 0 if you don't. */ #define HAVE_DECL_BZERO 1 /* Define to 1 if you have the declaration of `ftruncate', and to 0 if you don't. */ #define HAVE_DECL_FTRUNCATE 1 /* Define to 1 if you have the declaration of `getentropy', and to 0 if you don't. */ #define HAVE_DECL_GETENTROPY 1 /* Define to 1 if you have the declaration of `getpeereid', and to 0 if you don't. */ #define HAVE_DECL_GETPEEREID 1 /* Define to 1 if you have the declaration of `GLOB_NOMATCH', and to 0 if you don't. */ #define HAVE_DECL_GLOB_NOMATCH 1 /* Define to 1 if you have the declaration of `GSS_C_NT_HOSTBASED_SERVICE', and to 0 if you don't. */ /* #undef HAVE_DECL_GSS_C_NT_HOSTBASED_SERVICE */ /* Define to 1 if you have the declaration of `howmany', and to 0 if you don't. */ #define HAVE_DECL_HOWMANY 1 /* Define to 1 if you have the declaration of `h_errno', and to 0 if you don't. */ #define HAVE_DECL_H_ERRNO 1 /* Define to 1 if you have the declaration of `loginfailed', and to 0 if you don't. */ /* #undef HAVE_DECL_LOGINFAILED */ /* Define to 1 if you have the declaration of `loginrestrictions', and to 0 if you don't. */ /* #undef HAVE_DECL_LOGINRESTRICTIONS */ /* Define to 1 if you have the declaration of `loginsuccess', and to 0 if you don't. */ /* #undef HAVE_DECL_LOGINSUCCESS */ /* Define to 1 if you have the declaration of `MAXSYMLINKS', and to 0 if you don't. */ #define HAVE_DECL_MAXSYMLINKS 1 /* Define to 1 if you have the declaration of `memmem', and to 0 if you don't. */ #define HAVE_DECL_MEMMEM 1 /* Define to 1 if you have the declaration of `NFDBITS', and to 0 if you don't. */ #define HAVE_DECL_NFDBITS 1 /* Define to 1 if you have the declaration of `offsetof', and to 0 if you don't. */ #define HAVE_DECL_OFFSETOF 1 /* Define to 1 if you have the declaration of `O_NONBLOCK', and to 0 if you don't. */ #define HAVE_DECL_O_NONBLOCK 1 /* Define to 1 if you have the declaration of `passwdexpired', and to 0 if you don't. */ /* #undef HAVE_DECL_PASSWDEXPIRED */ /* Define to 1 if you have the declaration of `readv', and to 0 if you don't. */ #define HAVE_DECL_READV 1 /* Define to 1 if you have the declaration of `setauthdb', and to 0 if you don't. */ /* #undef HAVE_DECL_SETAUTHDB */ /* Define to 1 if you have the declaration of `SHUT_RD', and to 0 if you don't. */ #define HAVE_DECL_SHUT_RD 1 /* Define to 1 if you have the declaration of `UINT32_MAX', and to 0 if you don't. */ #define HAVE_DECL_UINT32_MAX 1 /* Define to 1 if you have the declaration of `writev', and to 0 if you don't. */ #define HAVE_DECL_WRITEV 1 /* Define to 1 if you have the declaration of `_getlong', and to 0 if you don't. */ #define HAVE_DECL__GETLONG 0 /* Define to 1 if you have the declaration of `_getshort', and to 0 if you don't. */ #define HAVE_DECL__GETSHORT 0 /* Define to 1 if you have the `DES_crypt' function. */ #define HAVE_DES_CRYPT 1 /* Define if you have /dev/ptmx */ /* #undef HAVE_DEV_PTMX */ /* Define if you have /dev/ptc */ /* #undef HAVE_DEV_PTS_AND_PTC */ /* Define to 1 if you have the header file. */ #define HAVE_DIRENT_H 1 /* Define to 1 if you have the `dirfd' function. */ #define HAVE_DIRFD 1 /* Define to 1 if you have the `dirname' function. */ #define HAVE_DIRNAME 1 /* Define to 1 if you have the `dlopen' function. */ #define HAVE_DLOPEN 1 /* Define to 1 if you have the `DSA_generate_parameters_ex' function. */ #define HAVE_DSA_GENERATE_PARAMETERS_EX 1 /* Define to 1 if you have the `EC_KEY_METHOD_new' function. */ #define HAVE_EC_KEY_METHOD_NEW 1 /* Define to 1 if you have the header file. */ #define HAVE_ELF_H 1 /* Define to 1 if you have the `endgrent' function. */ #define HAVE_ENDGRENT 1 /* Define to 1 if you have the header file. */ #define HAVE_ENDIAN_H 1 /* Define to 1 if you have the `endutent' function. */ /* #undef HAVE_ENDUTENT */ /* Define to 1 if you have the `endutxent' function. */ #define HAVE_ENDUTXENT 1 /* Define to 1 if you have the `err' function. */ #define HAVE_ERR 1 /* Define to 1 if you have the `errx' function. */ #define HAVE_ERRX 1 /* Define to 1 if you have the header file. */ #define HAVE_ERR_H 1 /* Define if your system has /etc/default/login */ /* #undef HAVE_ETC_DEFAULT_LOGIN */ /* Define to 1 if you have the `EVP_chacha20' function. */ #define HAVE_EVP_CHACHA20 1 /* Define to 1 if you have the `EVP_CIPHER_CTX_get_iv' function. */ /* #undef HAVE_EVP_CIPHER_CTX_GET_IV */ /* Define to 1 if you have the `EVP_CIPHER_CTX_get_updated_iv' function. */ #define HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV 1 /* Define to 1 if you have the `EVP_CIPHER_CTX_iv' function. */ #define HAVE_EVP_CIPHER_CTX_IV 1 /* Define to 1 if you have the `EVP_CIPHER_CTX_iv_noconst' function. */ #define HAVE_EVP_CIPHER_CTX_IV_NOCONST 1 /* Define to 1 if you have the `EVP_CIPHER_CTX_set_iv' function. */ /* #undef HAVE_EVP_CIPHER_CTX_SET_IV */ /* Define to 1 if you have the `EVP_DigestFinal_ex' function. */ #define HAVE_EVP_DIGESTFINAL_EX 1 /* Define to 1 if you have the `EVP_DigestInit_ex' function. */ #define HAVE_EVP_DIGESTINIT_EX 1 /* Define to 1 if you have the `EVP_MD_CTX_cleanup' function. */ /* #undef HAVE_EVP_MD_CTX_CLEANUP */ /* Define to 1 if you have the `EVP_MD_CTX_copy_ex' function. */ #define HAVE_EVP_MD_CTX_COPY_EX 1 /* Define to 1 if you have the `EVP_MD_CTX_init' function. */ /* #undef HAVE_EVP_MD_CTX_INIT */ +/* Define to 1 if you have the `EVP_PKEY_get_raw_private_key' function. */ +#define HAVE_EVP_PKEY_GET_RAW_PRIVATE_KEY 1 + +/* Define to 1 if you have the `EVP_PKEY_get_raw_public_key' function. */ +#define HAVE_EVP_PKEY_GET_RAW_PUBLIC_KEY 1 + /* Define to 1 if you have the `EVP_sha256' function. */ #define HAVE_EVP_SHA256 1 /* Define to 1 if you have the `EVP_sha384' function. */ #define HAVE_EVP_SHA384 1 /* Define to 1 if you have the `EVP_sha512' function. */ #define HAVE_EVP_SHA512 1 /* Define if you have ut_exit in utmp.h */ /* #undef HAVE_EXIT_IN_UTMP */ /* Define to 1 if you have the `explicit_bzero' function. */ #define HAVE_EXPLICIT_BZERO 1 /* Define to 1 if you have the `explicit_memset' function. */ /* #undef HAVE_EXPLICIT_MEMSET */ /* Define to 1 if you have the `fchmod' function. */ #define HAVE_FCHMOD 1 /* Define to 1 if you have the `fchmodat' function. */ #define HAVE_FCHMODAT 1 /* Define to 1 if you have the `fchown' function. */ #define HAVE_FCHOWN 1 /* Define to 1 if you have the `fchownat' function. */ #define HAVE_FCHOWNAT 1 /* Use F_CLOSEM fcntl for closefrom */ /* #undef HAVE_FCNTL_CLOSEM */ /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 /* Define to 1 if the system has the type `fd_mask'. */ #define HAVE_FD_MASK 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_FEATURES_H */ /* Define to 1 if you have the `fido_assert_set_clientdata' function. */ /* #undef HAVE_FIDO_ASSERT_SET_CLIENTDATA */ /* Define to 1 if you have the `fido_cred_prot' function. */ /* #undef HAVE_FIDO_CRED_PROT */ /* Define to 1 if you have the `fido_cred_set_clientdata' function. */ /* #undef HAVE_FIDO_CRED_SET_CLIENTDATA */ /* Define to 1 if you have the `fido_cred_set_prot' function. */ /* #undef HAVE_FIDO_CRED_SET_PROT */ /* Define to 1 if you have the `fido_dev_get_touch_begin' function. */ /* #undef HAVE_FIDO_DEV_GET_TOUCH_BEGIN */ /* Define to 1 if you have the `fido_dev_get_touch_status' function. */ /* #undef HAVE_FIDO_DEV_GET_TOUCH_STATUS */ /* Define to 1 if you have the `fido_dev_is_winhello' function. */ /* #undef HAVE_FIDO_DEV_IS_WINHELLO */ /* Define to 1 if you have the `fido_dev_supports_cred_prot' function. */ /* #undef HAVE_FIDO_DEV_SUPPORTS_CRED_PROT */ /* Define to 1 if you have the header file. */ #define HAVE_FLOATINGPOINT_H 1 /* Define to 1 if you have the `flock' function. */ #define HAVE_FLOCK 1 /* Define to 1 if you have the `fmt_scaled' function. */ /* #undef HAVE_FMT_SCALED */ /* Define to 1 if you have the `fnmatch' function. */ #define HAVE_FNMATCH 1 /* Define to 1 if you have the header file. */ #define HAVE_FNMATCH_H 1 /* Define to 1 if you have the `freeaddrinfo' function. */ #define HAVE_FREEADDRINFO 1 /* Define to 1 if you have the `freezero' function. */ /* #undef HAVE_FREEZERO */ /* Define to 1 if the system has the type `fsblkcnt_t'. */ #define HAVE_FSBLKCNT_T 1 /* Define to 1 if the system has the type `fsfilcnt_t'. */ #define HAVE_FSFILCNT_T 1 /* Define to 1 if you have the `fstatfs' function. */ #define HAVE_FSTATFS 1 /* Define to 1 if you have the `fstatvfs' function. */ #define HAVE_FSTATVFS 1 /* Define to 1 if you have the `futimes' function. */ #define HAVE_FUTIMES 1 /* Define to 1 if you have the `gai_strerror' function. */ #define HAVE_GAI_STRERROR 1 /* Define to 1 if you have the `getaddrinfo' function. */ #define HAVE_GETADDRINFO 1 /* Define to 1 if you have the `getaudit' function. */ /* #undef HAVE_GETAUDIT */ /* Define to 1 if you have the `getaudit_addr' function. */ /* #undef HAVE_GETAUDIT_ADDR */ /* Define to 1 if you have the `getcwd' function. */ #define HAVE_GETCWD 1 /* Define to 1 if you have the `getentropy' function. */ #define HAVE_GETENTROPY 1 /* Define to 1 if you have the `getgrouplist' function. */ #define HAVE_GETGROUPLIST 1 /* Define to 1 if you have the `getgrset' function. */ /* #undef HAVE_GETGRSET */ /* Define to 1 if you have the `getlastlogxbyname' function. */ /* #undef HAVE_GETLASTLOGXBYNAME */ /* Define to 1 if you have the `getline' function. */ #define HAVE_GETLINE 1 /* Define to 1 if you have the `getluid' function. */ /* #undef HAVE_GETLUID */ /* Define to 1 if you have the `getnameinfo' function. */ #define HAVE_GETNAMEINFO 1 /* Define to 1 if you have the `getopt' function. */ #define HAVE_GETOPT 1 /* Define to 1 if you have the header file. */ #define HAVE_GETOPT_H 1 /* Define if your getopt(3) defines and uses optreset */ #define HAVE_GETOPT_OPTRESET 1 /* Define if your libraries define getpagesize() */ #define HAVE_GETPAGESIZE 1 /* Define to 1 if you have the `getpeereid' function. */ #define HAVE_GETPEEREID 1 /* Define to 1 if you have the `getpeerucred' function. */ /* #undef HAVE_GETPEERUCRED */ /* Define to 1 if you have the `getpgid' function. */ #define HAVE_GETPGID 1 /* Define to 1 if you have the `getpgrp' function. */ #define HAVE_GETPGRP 1 /* Define to 1 if you have the `getpwanam' function. */ /* #undef HAVE_GETPWANAM */ /* Define to 1 if you have the `getrandom' function. */ #define HAVE_GETRANDOM 1 /* Define to 1 if you have the `getrlimit' function. */ #define HAVE_GETRLIMIT 1 /* Define if getrrsetbyname() exists */ /* #undef HAVE_GETRRSETBYNAME */ /* Define to 1 if you have the `getseuserbyname' function. */ /* #undef HAVE_GETSEUSERBYNAME */ /* Define to 1 if you have the `getsid' function. */ #define HAVE_GETSID 1 /* Define to 1 if you have the `gettimeofday' function. */ #define HAVE_GETTIMEOFDAY 1 /* Define to 1 if you have the `getttyent' function. */ #define HAVE_GETTTYENT 1 /* Define to 1 if you have the `getutent' function. */ /* #undef HAVE_GETUTENT */ /* Define to 1 if you have the `getutid' function. */ /* #undef HAVE_GETUTID */ /* Define to 1 if you have the `getutline' function. */ /* #undef HAVE_GETUTLINE */ /* Define to 1 if you have the `getutxent' function. */ #define HAVE_GETUTXENT 1 /* Define to 1 if you have the `getutxid' function. */ #define HAVE_GETUTXID 1 /* Define to 1 if you have the `getutxline' function. */ #define HAVE_GETUTXLINE 1 /* Define to 1 if you have the `getutxuser' function. */ #define HAVE_GETUTXUSER 1 /* Define to 1 if you have the `get_default_context_with_level' function. */ /* #undef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL */ /* Define to 1 if you have the `glob' function. */ #define HAVE_GLOB 1 /* Define to 1 if you have the header file. */ #define HAVE_GLOB_H 1 /* Define to 1 if you have the `group_from_gid' function. */ #define HAVE_GROUP_FROM_GID 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_GSSAPI_GENERIC_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_GSSAPI_GSSAPI_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_GSSAPI_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_GSSAPI_KRB5_H */ /* Define if HEADER.ad exists in arpa/nameser.h */ #define HAVE_HEADER_AD 1 /* Define to 1 if you have the `HMAC_CTX_init' function. */ /* #undef HAVE_HMAC_CTX_INIT */ /* Define if you have ut_host in utmp.h */ /* #undef HAVE_HOST_IN_UTMP */ /* Define if you have ut_host in utmpx.h */ #define HAVE_HOST_IN_UTMPX 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_IAF_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_IA_H */ /* Define if you have ut_id in utmp.h */ /* #undef HAVE_ID_IN_UTMP */ /* Define if you have ut_id in utmpx.h */ #define HAVE_ID_IN_UTMPX 1 /* Define to 1 if you have the header file. */ #define HAVE_IFADDRS_H 1 /* Define to 1 if you have the `inet_aton' function. */ #define HAVE_INET_ATON 1 /* Define to 1 if you have the `inet_ntoa' function. */ #define HAVE_INET_NTOA 1 /* Define to 1 if you have the `inet_ntop' function. */ #define HAVE_INET_NTOP 1 /* Define to 1 if you have the `innetgr' function. */ #define HAVE_INNETGR 1 /* define if you have int64_t data type */ #define HAVE_INT64_T 1 /* Define to 1 if the system has the type `intmax_t'. */ #define HAVE_INTMAX_T 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* define if you have intxx_t data type */ #define HAVE_INTXX_T 1 /* Define to 1 if the system has the type `in_addr_t'. */ #define HAVE_IN_ADDR_T 1 /* Define to 1 if the system has the type `in_port_t'. */ #define HAVE_IN_PORT_T 1 /* Define if you have isblank(3C). */ #define HAVE_ISBLANK 1 /* Define to 1 if you have the `killpg' function. */ #define HAVE_KILLPG 1 /* Define to 1 if you have the `krb5_cc_new_unique' function. */ /* #undef HAVE_KRB5_CC_NEW_UNIQUE */ /* Define to 1 if you have the `krb5_free_error_message' function. */ /* #undef HAVE_KRB5_FREE_ERROR_MESSAGE */ /* Define to 1 if you have the `krb5_get_error_message' function. */ /* #undef HAVE_KRB5_GET_ERROR_MESSAGE */ /* Define to 1 if you have the header file. */ #define HAVE_LANGINFO_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_LASTLOG_H */ /* Define if you want ldns support */ /* #undef HAVE_LDNS */ /* Define to 1 if you have the header file. */ /* #undef HAVE_LIBAUDIT_H */ /* Define to 1 if you have the `bsm' library (-lbsm). */ /* #undef HAVE_LIBBSM */ /* Define to 1 if you have the `dl' library (-ldl). */ #define HAVE_LIBDL 1 /* Define to 1 if you have the header file. */ #define HAVE_LIBGEN_H 1 /* Define if system has libiaf that supports set_id */ /* #undef HAVE_LIBIAF */ /* Define to 1 if you have the `network' library (-lnetwork). */ /* #undef HAVE_LIBNETWORK */ /* Define to 1 if you have the `pam' library (-lpam). */ #define HAVE_LIBPAM 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_LIBPROC_H */ /* Define to 1 if you have the `socket' library (-lsocket). */ /* #undef HAVE_LIBSOCKET */ /* Define to 1 if you have the header file. */ #define HAVE_LIBUTIL_H 1 /* Define to 1 if you have the `xnet' library (-lxnet). */ /* #undef HAVE_LIBXNET */ /* Define to 1 if you have the `z' library (-lz). */ #define HAVE_LIBZ 1 /* Define to 1 if you have the header file. */ #define HAVE_LIMITS_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_LINUX_AUDIT_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_LINUX_FILTER_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_LINUX_IF_TUN_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_LINUX_SECCOMP_H */ /* Define to 1 if you have the `llabs' function. */ #define HAVE_LLABS 1 /* Define to 1 if you have the header file. */ #define HAVE_LOCALE_H 1 /* Define to 1 if you have the `localtime_r' function. */ #define HAVE_LOCALTIME_R 1 /* Define to 1 if you have the `login' function. */ /* #undef HAVE_LOGIN */ /* Define to 1 if you have the header file. */ #define HAVE_LOGIN_CAP_H 1 /* Define to 1 if you have the `login_getcapbool' function. */ #define HAVE_LOGIN_GETCAPBOOL 1 /* Define to 1 if you have the `login_getpwclass' function. */ #define HAVE_LOGIN_GETPWCLASS 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_LOGIN_H */ /* Define to 1 if you have the `logout' function. */ /* #undef HAVE_LOGOUT */ /* Define to 1 if you have the `logwtmp' function. */ /* #undef HAVE_LOGWTMP */ /* Define to 1 if the system has the type `long double'. */ #define HAVE_LONG_DOUBLE 1 /* Define to 1 if the system has the type `long long'. */ #define HAVE_LONG_LONG 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MAILLOCK_H */ /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ #define HAVE_MALLOC 1 /* Define to 1 if you have the `mblen' function. */ #define HAVE_MBLEN 1 /* Define to 1 if you have the `mbtowc' function. */ #define HAVE_MBTOWC 1 /* Define to 1 if you have the `memmem' function. */ #define HAVE_MEMMEM 1 /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the `memset_s' function. */ #define HAVE_MEMSET_S 1 /* Define to 1 if you have the `mkdtemp' function. */ #define HAVE_MKDTEMP 1 /* define if you have mode_t data type */ #define HAVE_MODE_T 1 /* Some systems put nanosleep outside of libc */ #define HAVE_NANOSLEEP 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_NDIR_H */ /* Define to 1 if you have the header file. */ #define HAVE_NETDB_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_NETGROUP_H */ /* Define to 1 if you have the header file. */ #define HAVE_NET_IF_TUN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_NET_ROUTE_H 1 /* Define if you are on NeXT */ /* #undef HAVE_NEXT */ /* Define to 1 if the system has the type `nfds_t'. */ #define HAVE_NFDS_T 1 /* Define to 1 if you have the `ngetaddrinfo' function. */ /* #undef HAVE_NGETADDRINFO */ /* Define to 1 if you have the `nl_langinfo' function. */ #define HAVE_NL_LANGINFO 1 /* Define to 1 if you have the `nsleep' function. */ /* #undef HAVE_NSLEEP */ /* Define to 1 if you have the `ogetaddrinfo' function. */ /* #undef HAVE_OGETADDRINFO */ /* Define if you have an old version of PAM which takes only one argument to pam_strerror */ /* #undef HAVE_OLD_PAM */ /* Define to 1 if you have the `openlog_r' function. */ /* #undef HAVE_OPENLOG_R */ /* Define to 1 if you have the `openpty' function. */ #define HAVE_OPENPTY 1 /* as a macro */ #define HAVE_OPENSSL_ADD_ALL_ALGORITHMS 1 /* Define to 1 if you have the `OpenSSL_version' function. */ #define HAVE_OPENSSL_VERSION 1 /* Define to 1 if you have the `OpenSSL_version_num' function. */ #define HAVE_OPENSSL_VERSION_NUM 1 /* Define if you have Digital Unix Security Integration Architecture */ /* #undef HAVE_OSF_SIA */ /* Define to 1 if you have the `pam_getenvlist' function. */ #define HAVE_PAM_GETENVLIST 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_PAM_PAM_APPL_H */ /* Define to 1 if you have the `pam_putenv' function. */ #define HAVE_PAM_PUTENV 1 /* Define to 1 if you have the header file. */ #define HAVE_PATHS_H 1 /* Define if you have ut_pid in utmp.h */ /* #undef HAVE_PID_IN_UTMP */ /* define if you have pid_t data type */ #define HAVE_PID_T 1 /* Define to 1 if you have the `pledge' function. */ /* #undef HAVE_PLEDGE */ /* Define to 1 if you have the `poll' function. */ #define HAVE_POLL 1 /* Define to 1 if you have the header file. */ #define HAVE_POLL_H 1 /* Define to 1 if you have the `ppoll' function. */ #define HAVE_PPOLL 1 /* Define to 1 if you have the `prctl' function. */ /* #undef HAVE_PRCTL */ /* Define to 1 if you have the `priv_basicset' function. */ /* #undef HAVE_PRIV_BASICSET */ /* Define to 1 if you have the header file. */ /* #undef HAVE_PRIV_H */ /* Define to 1 if you have the `procctl' function. */ #define HAVE_PROCCTL 1 /* Define if you have /proc/$pid/fd */ /* #undef HAVE_PROC_PID */ /* Define to 1 if you have the `proc_pidinfo' function. */ /* #undef HAVE_PROC_PIDINFO */ /* Define to 1 if you have the `pselect' function. */ #define HAVE_PSELECT 1 /* Define to 1 if you have the `pstat' function. */ /* #undef HAVE_PSTAT */ /* Define to 1 if you have the header file. */ /* #undef HAVE_PTY_H */ /* Define to 1 if you have the `pututline' function. */ /* #undef HAVE_PUTUTLINE */ /* Define to 1 if you have the `pututxline' function. */ #define HAVE_PUTUTXLINE 1 /* Define to 1 if you have the `raise' function. */ #define HAVE_RAISE 1 /* Define to 1 if you have the `readpassphrase' function. */ #define HAVE_READPASSPHRASE 1 /* Define to 1 if you have the header file. */ #define HAVE_READPASSPHRASE_H 1 /* Define to 1 if your system has a GNU libc compatible `realloc' function, and to 0 otherwise. */ #define HAVE_REALLOC 1 /* Define to 1 if you have the `reallocarray' function. */ #define HAVE_REALLOCARRAY 1 /* Define to 1 if you have the `realpath' function. */ #define HAVE_REALPATH 1 /* Define to 1 if you have the `recallocarray' function. */ /* #undef HAVE_RECALLOCARRAY */ /* Define to 1 if you have the `recvmsg' function. */ #define HAVE_RECVMSG 1 /* sys/resource.h has RLIMIT_NPROC */ #define HAVE_RLIMIT_NPROC /**/ /* Define to 1 if you have the header file. */ #define HAVE_RPC_TYPES_H 1 /* Define to 1 if you have the `rresvport_af' function. */ #define HAVE_RRESVPORT_AF 1 /* Define to 1 if you have the `RSA_generate_key_ex' function. */ #define HAVE_RSA_GENERATE_KEY_EX 1 /* Define to 1 if you have the `RSA_get_default_method' function. */ #define HAVE_RSA_GET_DEFAULT_METHOD 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SANDBOX_H */ /* Define to 1 if you have the `sandbox_init' function. */ /* #undef HAVE_SANDBOX_INIT */ /* define if you have sa_family_t data type */ #define HAVE_SA_FAMILY_T 1 /* Define to 1 if you have the `scan_scaled' function. */ /* #undef HAVE_SCAN_SCALED */ /* Define if you have SecureWare-based protected password database */ /* #undef HAVE_SECUREWARE */ /* Define to 1 if you have the header file. */ #define HAVE_SECURITY_PAM_APPL_H 1 /* Define to 1 if you have the `sendmsg' function. */ #define HAVE_SENDMSG 1 /* Define to 1 if you have the `setauthdb' function. */ /* #undef HAVE_SETAUTHDB */ /* Define to 1 if you have the `setdtablesize' function. */ /* #undef HAVE_SETDTABLESIZE */ /* Define to 1 if you have the `setegid' function. */ #define HAVE_SETEGID 1 /* Define to 1 if you have the `setenv' function. */ #define HAVE_SETENV 1 /* Define to 1 if you have the `seteuid' function. */ #define HAVE_SETEUID 1 /* Define to 1 if you have the `setgroupent' function. */ #define HAVE_SETGROUPENT 1 /* Define to 1 if you have the `setgroups' function. */ #define HAVE_SETGROUPS 1 /* Define to 1 if you have the `setlinebuf' function. */ #define HAVE_SETLINEBUF 1 /* Define to 1 if you have the `setlogin' function. */ #define HAVE_SETLOGIN 1 /* Define to 1 if you have the `setluid' function. */ /* #undef HAVE_SETLUID */ /* Define to 1 if you have the `setpassent' function. */ #define HAVE_SETPASSENT 1 /* Define to 1 if you have the `setpcred' function. */ /* #undef HAVE_SETPCRED */ /* Define to 1 if you have the `setpflags' function. */ /* #undef HAVE_SETPFLAGS */ /* Define to 1 if you have the `setppriv' function. */ /* #undef HAVE_SETPPRIV */ /* Define to 1 if you have the `setproctitle' function. */ #define HAVE_SETPROCTITLE 1 /* Define to 1 if you have the `setregid' function. */ #define HAVE_SETREGID 1 /* Define to 1 if you have the `setresgid' function. */ #define HAVE_SETRESGID 1 /* Define to 1 if you have the `setresuid' function. */ #define HAVE_SETRESUID 1 /* Define to 1 if you have the `setreuid' function. */ #define HAVE_SETREUID 1 /* Define to 1 if you have the `setrlimit' function. */ #define HAVE_SETRLIMIT 1 /* Define to 1 if you have the `setsid' function. */ #define HAVE_SETSID 1 /* Define to 1 if you have the `setutent' function. */ /* #undef HAVE_SETUTENT */ /* Define to 1 if you have the `setutxdb' function. */ #define HAVE_SETUTXDB 1 /* Define to 1 if you have the `setutxent' function. */ #define HAVE_SETUTXENT 1 /* Define to 1 if you have the `setvbuf' function. */ #define HAVE_SETVBUF 1 /* Define to 1 if you have the `set_id' function. */ /* #undef HAVE_SET_ID */ /* Define to 1 if you have the `SHA256Update' function. */ /* #undef HAVE_SHA256UPDATE */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SHA2_H */ /* Define to 1 if you have the `SHA384Update' function. */ /* #undef HAVE_SHA384UPDATE */ /* Define to 1 if you have the `SHA512Update' function. */ /* #undef HAVE_SHA512UPDATE */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SHADOW_H */ /* Define to 1 if you have the `sigaction' function. */ #define HAVE_SIGACTION 1 /* Define to 1 if the system has the type `sighandler_t'. */ /* #undef HAVE_SIGHANDLER_T */ /* Define to 1 if you have the `sigvec' function. */ #define HAVE_SIGVEC 1 /* Define to 1 if the system has the type `sig_atomic_t'. */ #define HAVE_SIG_ATOMIC_T 1 /* define if you have size_t data type */ #define HAVE_SIZE_T 1 /* Define to 1 if you have the `snprintf' function. */ #define HAVE_SNPRINTF 1 /* Define to 1 if you have the `socketpair' function. */ #define HAVE_SOCKETPAIR 1 /* Have PEERCRED socket option */ /* #undef HAVE_SO_PEERCRED */ /* define if you have ssize_t data type */ #define HAVE_SSIZE_T 1 /* Fields in struct sockaddr_storage */ #define HAVE_SS_FAMILY_IN_SS 1 /* Define if you have ut_ss in utmpx.h */ /* #undef HAVE_SS_IN_UTMPX */ /* Define to 1 if you have the `statfs' function. */ #define HAVE_STATFS 1 /* Define to 1 if you have the `statvfs' function. */ #define HAVE_STATVFS 1 /* Define to 1 if you have the header file. */ #define HAVE_STDDEF_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDIO_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strcasestr' function. */ #define HAVE_STRCASESTR 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the `strftime' function. */ #define HAVE_STRFTIME 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strlcat' function. */ #define HAVE_STRLCAT 1 /* Define to 1 if you have the `strlcpy' function. */ #define HAVE_STRLCPY 1 /* Define to 1 if you have the `strmode' function. */ #define HAVE_STRMODE 1 /* Define to 1 if you have the `strndup' function. */ #define HAVE_STRNDUP 1 /* Define to 1 if you have the `strnlen' function. */ #define HAVE_STRNLEN 1 /* Define to 1 if you have the `strnvis' function. */ #define HAVE_STRNVIS 1 /* Define to 1 if you have the `strptime' function. */ #define HAVE_STRPTIME 1 /* Define to 1 if you have the `strsep' function. */ #define HAVE_STRSEP 1 /* Define to 1 if you have the `strsignal' function. */ #define HAVE_STRSIGNAL 1 /* Define to 1 if you have the `strtoll' function. */ #define HAVE_STRTOLL 1 /* Define to 1 if you have the `strtonum' function. */ #define HAVE_STRTONUM 1 /* Define to 1 if you have the `strtoul' function. */ #define HAVE_STRTOUL 1 /* Define to 1 if you have the `strtoull' function. */ #define HAVE_STRTOULL 1 /* define if you have struct addrinfo data type */ #define HAVE_STRUCT_ADDRINFO 1 /* define if you have struct in6_addr data type */ #define HAVE_STRUCT_IN6_ADDR 1 /* Define to 1 if `pw_change' is a member of `struct passwd'. */ #define HAVE_STRUCT_PASSWD_PW_CHANGE 1 /* Define to 1 if `pw_class' is a member of `struct passwd'. */ #define HAVE_STRUCT_PASSWD_PW_CLASS 1 /* Define to 1 if `pw_expire' is a member of `struct passwd'. */ #define HAVE_STRUCT_PASSWD_PW_EXPIRE 1 /* Define to 1 if `pw_gecos' is a member of `struct passwd'. */ #define HAVE_STRUCT_PASSWD_PW_GECOS 1 /* Define to 1 if `fd' is a member of `struct pollfd'. */ #define HAVE_STRUCT_POLLFD_FD 1 /* define if you have struct sockaddr_in6 data type */ #define HAVE_STRUCT_SOCKADDR_IN6 1 /* Define to 1 if `sin6_scope_id' is a member of `struct sockaddr_in6'. */ #define HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 1 /* define if you have struct sockaddr_storage data type */ #define HAVE_STRUCT_SOCKADDR_STORAGE 1 /* Define to 1 if `f_files' is a member of `struct statfs'. */ #define HAVE_STRUCT_STATFS_F_FILES 1 /* Define to 1 if `f_flags' is a member of `struct statfs'. */ #define HAVE_STRUCT_STATFS_F_FLAGS 1 /* Define to 1 if `st_blksize' is a member of `struct stat'. */ #define HAVE_STRUCT_STAT_ST_BLKSIZE 1 /* Define to 1 if `st_mtim' is a member of `struct stat'. */ #define HAVE_STRUCT_STAT_ST_MTIM 1 /* Define to 1 if `st_mtime' is a member of `struct stat'. */ #define HAVE_STRUCT_STAT_ST_MTIME 1 /* define if you have struct timespec */ #define HAVE_STRUCT_TIMESPEC 1 /* define if you have struct timeval */ #define HAVE_STRUCT_TIMEVAL 1 /* Define to 1 if you have the `swap32' function. */ /* #undef HAVE_SWAP32 */ /* Define to 1 if you have the `sysconf' function. */ #define HAVE_SYSCONF 1 /* Define if you have syslen in utmpx.h */ /* #undef HAVE_SYSLEN_IN_UTMPX */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_AUDIT_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_BITYPES_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_BSDTTY_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_BYTEORDER_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_CAPSICUM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_CDEFS_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_DIR_H */ /* Define if your system defines sys_errlist[] */ #define HAVE_SYS_ERRLIST 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_FILE_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_LABEL_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_MMAN_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_MOUNT_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_NDIR_H */ /* Define if your system defines sys_nerr */ /* #undef HAVE_SYS_NERR */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_POLL_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_PRCTL_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_PROCCTL_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_PSTAT_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_PTMS_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_PTRACE_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_RANDOM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SELECT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STATVFS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_STREAM_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_STROPTS_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_STRTIO_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_SYSCTL_H 1 /* Force use of sys/syslog.h on Ultrix */ /* #undef HAVE_SYS_SYSLOG_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_SYSMACROS_H */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIMERS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_UN_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_VFS_H */ /* Define to 1 if you have the `tcgetpgrp' function. */ #define HAVE_TCGETPGRP 1 /* Define to 1 if you have the `tcsendbreak' function. */ #define HAVE_TCSENDBREAK 1 /* Define to 1 if you have the `time' function. */ #define HAVE_TIME 1 /* Define to 1 if you have the `timegm' function. */ #define HAVE_TIMEGM 1 /* Define to 1 if you have the header file. */ #define HAVE_TIME_H 1 /* Define if you have ut_time in utmp.h */ /* #undef HAVE_TIME_IN_UTMP */ /* Define if you have ut_time in utmpx.h */ /* #undef HAVE_TIME_IN_UTMPX */ /* Define to 1 if you have the `timingsafe_bcmp' function. */ #define HAVE_TIMINGSAFE_BCMP 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_TMPDIR_H */ /* Define to 1 if you have the `truncate' function. */ #define HAVE_TRUNCATE 1 /* Define to 1 if you have the header file. */ #define HAVE_TTYENT_H 1 /* Define if you have ut_tv in utmp.h */ /* #undef HAVE_TV_IN_UTMP */ /* Define if you have ut_tv in utmpx.h */ #define HAVE_TV_IN_UTMPX 1 /* Define if you have ut_type in utmp.h */ /* #undef HAVE_TYPE_IN_UTMP */ /* Define if you have ut_type in utmpx.h */ #define HAVE_TYPE_IN_UTMPX 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_UCRED_H */ /* Define to 1 if the system has the type `uintmax_t'. */ #define HAVE_UINTMAX_T 1 /* define if you have uintxx_t data type */ #define HAVE_UINTXX_T 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the `unsetenv' function. */ #define HAVE_UNSETENV 1 /* Define to 1 if the system has the type `unsigned long long'. */ #define HAVE_UNSIGNED_LONG_LONG 1 /* Define to 1 if you have the `updwtmp' function. */ /* #undef HAVE_UPDWTMP */ /* Define to 1 if you have the `updwtmpx' function. */ /* #undef HAVE_UPDWTMPX */ /* Define to 1 if you have the header file. */ /* #undef HAVE_USERSEC_H */ /* Define to 1 if you have the `user_from_uid' function. */ #define HAVE_USER_FROM_UID 1 /* Define to 1 if you have the `usleep' function. */ #define HAVE_USLEEP 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_UTIL_H */ /* Define to 1 if you have the `utimensat' function. */ #define HAVE_UTIMENSAT 1 /* Define to 1 if you have the `utimes' function. */ #define HAVE_UTIMES 1 /* Define to 1 if you have the header file. */ #define HAVE_UTIME_H 1 /* Define to 1 if you have the `utmpname' function. */ /* #undef HAVE_UTMPNAME */ /* Define to 1 if you have the `utmpxname' function. */ /* #undef HAVE_UTMPXNAME */ /* Define to 1 if you have the header file. */ #define HAVE_UTMPX_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_UTMP_H */ /* define if you have u_char data type */ #define HAVE_U_CHAR 1 /* define if you have u_int data type */ #define HAVE_U_INT 1 /* define if you have u_int64_t data type */ #define HAVE_U_INT64_T 1 /* define if you have u_intxx_t data type */ #define HAVE_U_INTXX_T 1 /* Define to 1 if you have the `vasprintf' function. */ #define HAVE_VASPRINTF 1 /* Define if va_copy exists */ #define HAVE_VA_COPY 1 /* Define to 1 if you have the header file. */ #define HAVE_VIS_H 1 /* Define to 1 if you have the `vsnprintf' function. */ #define HAVE_VSNPRINTF 1 /* Define to 1 if you have the `waitpid' function. */ #define HAVE_WAITPID 1 /* Define to 1 if you have the `warn' function. */ #define HAVE_WARN 1 /* Define to 1 if you have the header file. */ #define HAVE_WCHAR_H 1 /* Define to 1 if you have the `wcwidth' function. */ #define HAVE_WCWIDTH 1 /* Define to 1 if you have the `_getlong' function. */ #define HAVE__GETLONG 1 /* Define to 1 if you have the `_getpty' function. */ /* #undef HAVE__GETPTY */ /* Define to 1 if you have the `_getshort' function. */ #define HAVE__GETSHORT 1 /* Define if you have struct __res_state _res as an extern */ #define HAVE__RES_EXTERN 1 /* Define to 1 if you have the `__b64_ntop' function. */ #define HAVE___B64_NTOP 1 /* Define to 1 if you have the `__b64_pton' function. */ #define HAVE___B64_PTON 1 /* Define if compiler implements __FUNCTION__ */ #define HAVE___FUNCTION__ 1 /* Define if libc defines __progname */ #define HAVE___PROGNAME 1 /* Fields in struct sockaddr_storage */ /* #undef HAVE___SS_FAMILY_IN_SS */ /* Define if __va_copy exists */ #define HAVE___VA_COPY 1 /* Define if compiler implements __func__ */ #define HAVE___func__ 1 /* Define this if you are using the Heimdal version of Kerberos V5 */ /* #undef HEIMDAL */ /* Define if you need to use IP address instead of hostname in $DISPLAY */ /* #undef IPADDR_IN_DISPLAY */ /* Detect IPv4 in IPv6 mapped addresses and treat as IPv4 */ /* #undef IPV4_IN_IPV6 */ /* Define if your system choked on IP TOS setting */ /* #undef IP_TOS_IS_BROKEN */ /* Define if you want Kerberos 5 support */ /* #undef KRB5 */ /* Define if pututxline updates lastlog too */ /* #undef LASTLOG_WRITE_PUTUTXLINE */ /* Define if you want TCP Wrappers support */ /* #undef LIBWRAP */ /* Define to whatever link() returns for "not supported" if it doesn't return EOPNOTSUPP. */ /* #undef LINK_OPNOTSUPP_ERRNO */ /* Adjust Linux out-of-memory killer */ /* #undef LINUX_OOM_ADJUST */ /* max value of long long calculated by configure */ /* #undef LLONG_MAX */ /* min value of long long calculated by configure */ /* #undef LLONG_MIN */ /* Account locked with pw(1) */ #define LOCKED_PASSWD_PREFIX "*LOCKED*" /* String used in /etc/passwd to denote locked account */ /* #undef LOCKED_PASSWD_STRING */ /* String used in /etc/passwd to denote locked account */ /* #undef LOCKED_PASSWD_SUBSTR */ /* Some systems need a utmpx entry for /bin/login to work */ /* #undef LOGIN_NEEDS_UTMPX */ /* Set this to your mail directory if you do not have _PATH_MAILDIR */ /* #undef MAIL_DIRECTORY */ /* Need setpgrp to for controlling tty */ /* #undef NEED_SETPGRP */ /* compiler does not accept __attribute__ on prototype args */ /* #undef NO_ATTRIBUTE_ON_PROTOTYPE_ARGS */ /* compiler does not accept __attribute__ on return types */ /* #undef NO_ATTRIBUTE_ON_RETURN_TYPE */ /* SA_RESTARTed signals do no interrupt select */ /* #undef NO_SA_RESTART */ /* Define to disable UID restoration test */ /* #undef NO_UID_RESTORATION_TEST */ /* Define if X11 doesn't support AF_UNIX sockets on that system */ /* #undef NO_X11_UNIX_SOCKETS */ /* Define if EVP_DigestUpdate returns void */ /* #undef OPENSSL_EVP_DIGESTUPDATE_VOID */ /* OpenSSL has ECC */ #define OPENSSL_HAS_ECC 1 +/* libcrypto has ed25519 support */ +/* #undef OPENSSL_HAS_ED25519 */ + /* libcrypto has NID_X9_62_prime256v1 */ #define OPENSSL_HAS_NISTP256 1 /* libcrypto has NID_secp384r1 */ #define OPENSSL_HAS_NISTP384 1 /* libcrypto has NID_secp521r1 */ #define OPENSSL_HAS_NISTP521 1 /* libcrypto is missing AES 192 and 256 bit functions */ /* #undef OPENSSL_LOBOTOMISED_AES */ /* Define if you want the OpenSSL internally seeded PRNG only */ #define OPENSSL_PRNG_ONLY 1 /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "openssh-unix-dev@mindrot.org" /* Define to the full name of this package. */ #define PACKAGE_NAME "OpenSSH" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "OpenSSH Portable" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "openssh" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "Portable" /* Define if you are using Solaris-derived PAM which passes pam_messages to the conversation function with an extra level of indirection */ /* #undef PAM_SUN_CODEBASE */ /* Work around problematic Linux PAM modules handling of PAM_TTY */ /* #undef PAM_TTY_KLUDGE */ /* must supply username to passwd */ /* #undef PASSWD_NEEDS_USERNAME */ /* System dirs owned by bin (uid 2) */ /* #undef PLATFORM_SYS_DIR_UID */ /* Port number of PRNGD/EGD random number socket */ /* #undef PRNGD_PORT */ /* Location of PRNGD/EGD random number socket */ /* #undef PRNGD_SOCKET */ /* read(1) can return 0 for a non-closed fd */ /* #undef PTY_ZEROREAD */ /* Sandbox using capsicum */ #define SANDBOX_CAPSICUM 1 /* Sandbox using Darwin sandbox_init(3) */ /* #undef SANDBOX_DARWIN */ /* no privsep sandboxing */ /* #undef SANDBOX_NULL */ /* Sandbox using pledge(2) */ /* #undef SANDBOX_PLEDGE */ /* Sandbox using setrlimit(2) */ /* #undef SANDBOX_RLIMIT */ /* Sandbox using seccomp filter */ /* #undef SANDBOX_SECCOMP_FILTER */ /* setrlimit RLIMIT_FSIZE works */ /* #undef SANDBOX_SKIP_RLIMIT_FSIZE */ /* define if setrlimit RLIMIT_NOFILE breaks things */ #define SANDBOX_SKIP_RLIMIT_NOFILE 1 /* Sandbox using Solaris/Illumos privileges */ /* #undef SANDBOX_SOLARIS */ /* Sandbox using systrace(4) */ /* #undef SANDBOX_SYSTRACE */ /* Specify the system call convention in use */ /* #undef SECCOMP_AUDIT_ARCH */ /* Define if your platform breaks doing a seteuid before a setuid */ /* #undef SETEUID_BREAKS_SETUID */ /* The size of `int', as computed by sizeof. */ #define SIZEOF_INT 4 /* The size of `long int', as computed by sizeof. */ #define SIZEOF_LONG_INT 8 /* The size of `long long int', as computed by sizeof. */ #define SIZEOF_LONG_LONG_INT 8 /* The size of `short int', as computed by sizeof. */ #define SIZEOF_SHORT_INT 2 /* The size of `time_t', as computed by sizeof. */ #ifdef __i386__ #define SIZEOF_TIME_T 4 #else #define SIZEOF_TIME_T 8 #endif /* Define as const if snprintf() can declare const char *fmt */ #define SNPRINTF_CONST const /* sockaddr_in has sin_len */ #define SOCK_HAS_LEN 1 /* Define to a Set Process Title type if your system is supported by bsd-setproctitle.c */ /* #undef SPT_TYPE */ /* Define if sshd somehow reacquires a controlling TTY after setsid() */ /* #undef SSHD_ACQUIRES_CTTY */ /* sshd PAM service name */ /* #undef SSHD_PAM_SERVICE */ /* Define if pam_chauthtok wants real uid set to the unpriv'ed user */ /* #undef SSHPAM_CHAUTHTOK_NEEDS_RUID */ /* Use audit debugging module */ /* #undef SSH_AUDIT_EVENTS */ /* Windows is sensitive to read buffer size */ /* #undef SSH_IOBUFSZ */ /* non-privileged user for privilege separation */ #define SSH_PRIVSEP_USER "sshd" /* Use tunnel device compatibility to OpenBSD */ /* #undef SSH_TUN_COMPAT_AF */ /* Open tunnel devices the FreeBSD way */ #define SSH_TUN_FREEBSD 1 /* Open tunnel devices the Linux tun/tap way */ /* #undef SSH_TUN_LINUX */ /* No layer 2 tunnel support */ /* #undef SSH_TUN_NO_L2 */ /* Open tunnel devices the OpenBSD way */ /* #undef SSH_TUN_OPENBSD */ /* Prepend the address family to IP tunnel traffic */ /* #undef SSH_TUN_PREPEND_AF */ /* Define to 1 if all of the C90 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ #define STDC_HEADERS 1 /* Define if you want a different $PATH for the superuser */ /* #undef SUPERUSER_PATH */ /* syslog_r function is safe to use in in a signal handler */ /* #undef SYSLOG_R_SAFE_IN_SIGHAND */ /* Support routing domains using Linux VRF */ /* #undef SYS_RDOMAIN_LINUX */ /* Support passwords > 8 chars */ /* #undef UNIXWARE_LONG_PASSWORDS */ /* Specify default $PATH */ /* #undef USER_PATH */ /* Define this if you want to use libkafs' AFS support */ /* #undef USE_AFS */ /* Use BSM audit module */ /* #undef USE_BSM_AUDIT */ /* Use btmp to log bad logins */ /* #undef USE_BTMP */ /* Use libedit for sftp */ #define USE_LIBEDIT 1 /* Use Linux audit module */ /* #undef USE_LINUX_AUDIT */ /* Enable OpenSSL engine support */ #define USE_OPENSSL_ENGINE 1 /* Define if you want to enable PAM support */ #define USE_PAM 1 /* Use PIPES instead of a socketpair() */ /* #undef USE_PIPES */ /* Define if you have Solaris privileges */ /* #undef USE_SOLARIS_PRIVS */ /* Define if you have Solaris process contracts */ /* #undef USE_SOLARIS_PROCESS_CONTRACTS */ /* Define if you have Solaris projects */ /* #undef USE_SOLARIS_PROJECTS */ /* compiler variable declarations after code */ #define VARIABLE_DECLARATION_AFTER_CODE 1 /* compiler supports variable length arrays */ #define VARIABLE_LENGTH_ARRAYS 1 /* Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp */ /* #undef WITH_ABBREV_NO_TTY */ /* Define if you want to enable AIX4's authenticate function */ /* #undef WITH_AIXAUTHENTICATE */ /* Define if you have/want arrays (cluster-wide session management, not C arrays) */ /* #undef WITH_IRIX_ARRAY */ /* Define if you want IRIX audit trails */ /* #undef WITH_IRIX_AUDIT */ /* Define if you want IRIX kernel jobs */ /* #undef WITH_IRIX_JOBS */ /* Define if you want IRIX project management */ /* #undef WITH_IRIX_PROJECT */ /* use libcrypto for cryptography */ #define WITH_OPENSSL 1 /* Define if you want SELinux support. */ /* #undef WITH_SELINUX */ /* Enable zlib */ #define WITH_ZLIB 1 /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN /* # undef WORDS_BIGENDIAN */ # endif #endif /* Define if xauth is found in your path */ #define XAUTH_PATH "/usr/local/bin/xauth" /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ /* Define for large files, on AIX-style hosts. */ /* #undef _LARGE_FILES */ /* log for bad login attempts */ /* #undef _PATH_BTMP */ /* Full path of your "passwd" program */ #define _PATH_PASSWD_PROG "/usr/bin/passwd" /* Specify location of ssh.pid */ #define _PATH_SSH_PIDDIR "/var/run" /* Define if we don't have struct __res_state in resolv.h */ /* #undef __res_state */ /* Define to rpl_calloc if the replacement function should be used. */ /* #undef calloc */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* Define to rpl_malloc if the replacement function should be used. */ /* #undef malloc */ /* Define to rpl_realloc if the replacement function should be used. */ /* #undef realloc */ /* type to use in place of socklen_t if not defined */ /* #undef socklen_t */ diff --git a/crypto/openssh/configure.ac b/crypto/openssh/configure.ac index 58a40dd174b5..1b81c812dd81 100644 --- a/crypto/openssh/configure.ac +++ b/crypto/openssh/configure.ac @@ -1,5729 +1,5766 @@ # # Copyright (c) 1999-2004 Damien Miller # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([ssh.c]) # Check for stale configure as early as possible. for i in $srcdir/configure.ac $srcdir/m4/*.m4; do if test "$i" -nt "$srcdir/configure"; then AC_MSG_ERROR([$i newer than configure, run autoreconf]) fi done AC_LANG([C]) AC_CONFIG_HEADERS([config.h]) AC_PROG_CC([cc gcc clang]) # 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 # Checks for programs. AC_PROG_AWK AC_PROG_CPP AC_PROG_RANLIB AC_PROG_INSTALL AC_PROG_EGREP AC_PROG_MKDIR_P AC_CHECK_TOOLS([AR], [ar]) AC_PATH_PROG([CAT], [cat]) AC_PATH_PROG([KILL], [kill]) AC_PATH_PROG([SED], [sed]) AC_PATH_PROG([TEST_MINUS_S_SH], [bash]) AC_PATH_PROG([TEST_MINUS_S_SH], [ksh]) AC_PATH_PROG([TEST_MINUS_S_SH], [sh]) AC_PATH_PROG([SH], [bash]) AC_PATH_PROG([SH], [ksh]) AC_PATH_PROG([SH], [sh]) AC_PATH_PROG([GROFF], [groff]) AC_PATH_PROG([NROFF], [nroff awf]) AC_PATH_PROG([MANDOC], [mandoc]) AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no]) AC_SUBST([TEST_SHELL], [sh]) dnl select manpage formatter to be used to build "cat" format pages. if test "x$MANDOC" != "x" ; then MANFMT="$MANDOC" elif test "x$NROFF" != "x" ; then MANFMT="$NROFF -mandoc" elif test "x$GROFF" != "x" ; then MANFMT="$GROFF -mandoc -Tascii" else AC_MSG_WARN([no manpage formatter found]) MANFMT="false" fi AC_SUBST([MANFMT]) dnl for buildpkg.sh AC_PATH_PROG([PATH_GROUPADD_PROG], [groupadd], [groupadd], [/usr/sbin${PATH_SEPARATOR}/etc]) AC_PATH_PROG([PATH_USERADD_PROG], [useradd], [useradd], [/usr/sbin${PATH_SEPARATOR}/etc]) AC_CHECK_PROG([MAKE_PACKAGE_SUPPORTED], [pkgmk], [yes], [no]) if test -x /sbin/sh; then AC_SUBST([STARTUP_SCRIPT_SHELL], [/sbin/sh]) else AC_SUBST([STARTUP_SCRIPT_SHELL], [/bin/sh]) fi # System features AC_SYS_LARGEFILE if test -z "$AR" ; then AC_MSG_ERROR([*** 'ar' missing, please install or fix your \$PATH ***]) fi AC_PATH_PROG([PATH_PASSWD_PROG], [passwd]) if test ! -z "$PATH_PASSWD_PROG" ; then AC_DEFINE_UNQUOTED([_PATH_PASSWD_PROG], ["$PATH_PASSWD_PROG"], [Full path of your "passwd" program]) fi dnl Since autoconf doesn't support it very well, we no longer allow users to dnl override LD, however keeping the hook here for now in case there's a use dnl use case we overlooked and someone needs to re-enable it. Unless a good dnl reason is found we'll be removing this in future. LD="$CC" AC_SUBST([LD]) AC_C_INLINE AC_CHECK_DECL([LLONG_MAX], [have_llong_max=1], , [#include ]) 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 #include ]) AC_CHECK_DECL([RLIMIT_NPROC], [AC_DEFINE([HAVE_RLIMIT_NPROC], [], [sys/resource.h has RLIMIT_NPROC])], , [ #include #include ]) AC_CHECK_DECL([PR_SET_NO_NEW_PRIVS], [have_linux_no_new_privs=1], , [ #include #include ]) openssl=yes openssl_bin=openssl AC_ARG_WITH([openssl], [ --without-openssl Disable use of OpenSSL; use only limited internal crypto **EXPERIMENTAL** ], [ if test "x$withval" = "xno" ; then openssl=no openssl_bin="" fi ] ) AC_MSG_CHECKING([whether OpenSSL will be used for cryptography]) if test "x$openssl" = "xyes" ; then AC_MSG_RESULT([yes]) AC_DEFINE_UNQUOTED([WITH_OPENSSL], [1], [use libcrypto for cryptography]) else AC_MSG_RESULT([no]) fi use_stack_protector=1 use_toolchain_hardening=1 AC_ARG_WITH([stackprotect], [ --without-stackprotect Don't use compiler's stack protection], [ if test "x$withval" = "xno"; then use_stack_protector=0 fi ]) AC_ARG_WITH([hardening], [ --without-hardening Don't use toolchain hardening flags], [ if test "x$withval" = "xno"; then use_toolchain_hardening=0 fi ]) # We use -Werror for the tests only so that we catch warnings like "this is # on by default" for things like -fPIE. AC_MSG_CHECKING([if $CC supports -Werror]) saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -Werror" AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int main(void) { return 0; }]])], [ AC_MSG_RESULT([yes]) WERROR="-Werror"], [ AC_MSG_RESULT([no]) WERROR="" ] ) CFLAGS="$saved_CFLAGS" if test "$GCC" = "yes" || test "$GCC" = "egcs"; then AC_MSG_CHECKING([gcc version]) GCC_VER=`$CC -v 2>&1 | $AWK '/gcc version /{print $3}'` case "$GCC_VER" in 1.*) no_attrib_nonnull=1 ;; 2.8* | 2.9*) no_attrib_nonnull=1 ;; 2.*) no_attrib_nonnull=1 ;; *) ;; esac AC_MSG_RESULT([$GCC_VER]) AC_MSG_CHECKING([clang version]) ver="`$CC -v 2>&1`" if echo "$ver" | grep "Apple" >/dev/null; then - CLANG_VER="apple-`echo "$ver" | \ - awk '/Apple LLVM/ {print $4"-"$5}'`" + CLANG_VER=apple-`echo "$ver" | grep 'clang version' | \ + $SED 's/.*clang version //g' | $AWK '{print $1}'` else - CLANG_VER=`echo "$ver" | $AWK '/clang version /{print $3}'` + CLANG_VER=`echo "$ver" | grep 'clang version' | \ + $SED 's/.*clang version //g' | $AWK '{print $1}'` fi AC_MSG_RESULT([$CLANG_VER]) OSSH_CHECK_CFLAG_COMPILE([-pipe]) OSSH_CHECK_CFLAG_COMPILE([-Wunknown-warning-option]) OSSH_CHECK_CFLAG_COMPILE([-Wno-error=format-truncation]) OSSH_CHECK_CFLAG_COMPILE([-Qunused-arguments]) OSSH_CHECK_CFLAG_COMPILE([-Wall]) OSSH_CHECK_CFLAG_COMPILE([-Wextra]) OSSH_CHECK_CFLAG_COMPILE([-Wpointer-arith]) OSSH_CHECK_CFLAG_COMPILE([-Wuninitialized]) OSSH_CHECK_CFLAG_COMPILE([-Wsign-compare]) OSSH_CHECK_CFLAG_COMPILE([-Wformat-security]) OSSH_CHECK_CFLAG_COMPILE([-Wsizeof-pointer-memaccess]) OSSH_CHECK_CFLAG_COMPILE([-Wpointer-sign], [-Wno-pointer-sign]) OSSH_CHECK_CFLAG_COMPILE([-Wunused-parameter], [-Wno-unused-parameter]) OSSH_CHECK_CFLAG_COMPILE([-Wunused-result], [-Wno-unused-result]) OSSH_CHECK_CFLAG_COMPILE([-Wimplicit-fallthrough]) OSSH_CHECK_CFLAG_COMPILE([-Wmisleading-indentation]) OSSH_CHECK_CFLAG_COMPILE([-Wbitwise-instead-of-logical]) OSSH_CHECK_CFLAG_COMPILE([-fno-strict-aliasing]) if test "x$use_toolchain_hardening" = "x1"; then OSSH_CHECK_CFLAG_COMPILE([-mretpoline]) # clang OSSH_CHECK_LDFLAG_LINK([-Wl,-z,retpolineplt]) OSSH_CHECK_CFLAG_COMPILE([-D_FORTIFY_SOURCE=2]) OSSH_CHECK_LDFLAG_LINK([-Wl,-z,relro]) OSSH_CHECK_LDFLAG_LINK([-Wl,-z,now]) OSSH_CHECK_LDFLAG_LINK([-Wl,-z,noexecstack]) # NB. -ftrapv expects certain support functions to be present in # the compiler library (libgcc or similar) to detect integer operations # that can overflow. We must check that the result of enabling it # actually links. The test program compiled/linked includes a number # of integer operations that should exercise this. OSSH_CHECK_CFLAG_LINK([-ftrapv]) # clang 15 seems to have a bug in -fzero-call-used-regs=all. See # https://bugzilla.mindrot.org/show_bug.cgi?id=3475 and # https://github.com/llvm/llvm-project/issues/59242 + # clang 17 has a different bug that causes an ICE when using this + # flag at all (https://bugzilla.mindrot.org/show_bug.cgi?id=3629) case "$CLANG_VER" in - 15.*|apple*) OSSH_CHECK_CFLAG_COMPILE([-fzero-call-used-regs=used]) ;; - *) OSSH_CHECK_CFLAG_COMPILE([-fzero-call-used-regs=all]) ;; + apple-15*) OSSH_CHECK_CFLAG_LINK([-fzero-call-used-regs=used]) ;; + 17*) ;; + *) OSSH_CHECK_CFLAG_LINK([-fzero-call-used-regs=used]) ;; esac OSSH_CHECK_CFLAG_COMPILE([-ftrivial-auto-var-init=zero]) fi AC_MSG_CHECKING([if $CC accepts -fno-builtin-memset]) saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fno-builtin-memset" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ char b[10]; memset(b, 0, sizeof(b)); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) CFLAGS="$saved_CFLAGS" ] ) # -fstack-protector-all doesn't always work for some GCC versions # and/or platforms, so we test if we can. If it's not supported # on a given platform gcc will emit a warning so we use -Werror. if test "x$use_stack_protector" = "x1"; then for t in -fstack-protector-strong -fstack-protector-all \ -fstack-protector; do AC_MSG_CHECKING([if $CC supports $t]) saved_CFLAGS="$CFLAGS" saved_LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS $t -Werror" LDFLAGS="$LDFLAGS $t -Werror" AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} ]], [[ char x[256]; 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 int func (int t) {char b[100]; snprintf(b,sizeof b,"%d",t); return t;} ]], [[ char x[256]; snprintf(x, sizeof(x), "XXX%d", func(1)); ]])], [ AC_MSG_RESULT([yes]) break ], [ AC_MSG_RESULT([no]) ], [ AC_MSG_WARN([cross compiling: cannot test]) break ] ) ], [ AC_MSG_RESULT([no]) ] ) CFLAGS="$saved_CFLAGS" LDFLAGS="$saved_LDFLAGS" done fi if test -z "$have_llong_max"; then # retry LLONG_MAX with -std=gnu99, needed on some Linuxes unset ac_cv_have_decl_LLONG_MAX saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -std=gnu99" AC_CHECK_DECL([LLONG_MAX], [have_llong_max=1], [CFLAGS="$saved_CFLAGS"], [#include ] ) fi fi AC_MSG_CHECKING([if compiler allows __attribute__ on return types]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ #include __attribute__((__unused__)) static void foo(void){return;}]], [[ exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_DEFINE(NO_ATTRIBUTE_ON_RETURN_TYPE, 1, [compiler does not accept __attribute__ on return types]) ] ) AC_MSG_CHECKING([if compiler allows __attribute__ prototype args]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ #include typedef void foo(const char *, ...) __attribute__((format(printf, 1, 2)));]], [[ exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_DEFINE(NO_ATTRIBUTE_ON_PROTOTYPE_ARGS, 1, [compiler does not accept __attribute__ on prototype args]) ] ) 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]) ] ) AC_MSG_CHECKING([if compiler accepts variable declarations after code]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include ]], [[ int a; a = 1; int b = 1; exit(a-b); ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE(VARIABLE_DECLARATION_AFTER_CODE, [1], [compiler variable declarations after code]) ], [ AC_MSG_RESULT([no]) ] ) if test "x$no_attrib_nonnull" != "x1" ; then AC_DEFINE([HAVE_ATTRIBUTE__NONNULL__], [1], [Have attribute nonnull]) fi AC_ARG_WITH([rpath], [ --without-rpath Disable auto-added -R linker paths], [ if test "x$withval" = "xno" ; then rpath_opt="" elif test "x$withval" = "xyes" ; then rpath_opt="-R" else rpath_opt="$withval" fi ] ) # Allow user to specify flags AC_ARG_WITH([cflags], [ --with-cflags Specify additional flags to pass to compiler], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then CFLAGS="$CFLAGS $withval" fi ] ) AC_ARG_WITH([cflags-after], [ --with-cflags-after Specify additional flags to pass to compiler after configure], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then CFLAGS_AFTER="$withval" fi ] ) AC_ARG_WITH([cppflags], [ --with-cppflags Specify additional flags to pass to preprocessor] , [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then CPPFLAGS="$CPPFLAGS $withval" fi ] ) AC_ARG_WITH([ldflags], [ --with-ldflags Specify additional flags to pass to linker], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then LDFLAGS="$LDFLAGS $withval" fi ] ) AC_ARG_WITH([ldflags-after], [ --with-ldflags-after Specify additional flags to pass to linker after configure], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then LDFLAGS_AFTER="$withval" fi ] ) AC_ARG_WITH([libs], [ --with-libs Specify additional libraries to link with], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then LIBS="$LIBS $withval" fi ] ) AC_ARG_WITH([Werror], [ --with-Werror Build main code with -Werror], [ if test -n "$withval" && test "x$withval" != "xno"; then werror_flags="-Werror" if test "x${withval}" != "xyes"; then werror_flags="$withval" fi fi ] ) dnl On some old platforms, sys/stat.h requires sys/types.h, but autoconf-2.71's dnl AC_CHECK_INCLUDES_DEFAULT checks for them in the opposite order. If we dnl haven't detected it, recheck. if test "x$ac_cv_header_sys_stat_h" != "xyes"; then unset ac_cv_header_sys_stat_h AC_CHECK_HEADERS([sys/stat.h]) fi AC_CHECK_HEADERS([ \ blf.h \ bstring.h \ crypt.h \ crypto/sha2.h \ dirent.h \ endian.h \ elf.h \ err.h \ features.h \ fcntl.h \ floatingpoint.h \ fnmatch.h \ getopt.h \ glob.h \ ia.h \ iaf.h \ ifaddrs.h \ inttypes.h \ langinfo.h \ limits.h \ locale.h \ login.h \ maillock.h \ ndir.h \ net/if_tun.h \ netdb.h \ netgroup.h \ pam/pam_appl.h \ paths.h \ poll.h \ pty.h \ readpassphrase.h \ rpc/types.h \ security/pam_appl.h \ sha2.h \ shadow.h \ stddef.h \ stdint.h \ string.h \ strings.h \ sys/bitypes.h \ sys/byteorder.h \ sys/bsdtty.h \ sys/cdefs.h \ sys/dir.h \ sys/file.h \ sys/mman.h \ sys/label.h \ sys/ndir.h \ sys/param.h \ sys/poll.h \ sys/prctl.h \ sys/procctl.h \ sys/pstat.h \ sys/ptrace.h \ sys/random.h \ sys/select.h \ sys/stream.h \ sys/stropts.h \ sys/strtio.h \ sys/statvfs.h \ sys/sysmacros.h \ sys/time.h \ sys/timers.h \ sys/vfs.h \ time.h \ tmpdir.h \ ttyent.h \ ucred.h \ unistd.h \ usersec.h \ util.h \ utime.h \ utmp.h \ utmpx.h \ vis.h \ wchar.h \ ]) # On some platforms (eg SunOS4) sys/audit.h requires sys/[time|types|label.h] # to be included first. AC_CHECK_HEADERS([sys/audit.h], [], [], [ #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_LABEL_H # include #endif ]) # sys/capsicum.h requires sys/types.h AC_CHECK_HEADERS([sys/capsicum.h capsicum_helpers.h], [], [], [ #ifdef HAVE_SYS_TYPES_H # include #endif ]) AC_MSG_CHECKING([for caph_cache_tzdata]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include ]], [[caph_cache_tzdata();]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_CAPH_CACHE_TZDATA], [1], [Define if you have caph_cache_tzdata]) ], [ AC_MSG_RESULT([no]) ] ) # net/route.h requires sys/socket.h and sys/types.h. # sys/sysctl.h also requires sys/param.h AC_CHECK_HEADERS([net/route.h sys/sysctl.h], [], [], [ #ifdef HAVE_SYS_TYPES_H # include #endif #include #include ]) # lastlog.h requires sys/time.h to be included first on Solaris AC_CHECK_HEADERS([lastlog.h], [], [], [ #ifdef HAVE_SYS_TIME_H # include #endif ]) # sys/ptms.h requires sys/stream.h to be included first on Solaris AC_CHECK_HEADERS([sys/ptms.h], [], [], [ #ifdef HAVE_SYS_STREAM_H # include #endif ]) # login_cap.h requires sys/types.h on NetBSD AC_CHECK_HEADERS([login_cap.h], [], [], [ #include ]) # older BSDs need sys/param.h before sys/mount.h AC_CHECK_HEADERS([sys/mount.h], [], [], [ #include ]) # Android requires sys/socket.h to be included before sys/un.h AC_CHECK_HEADERS([sys/un.h], [], [], [ #include #include ]) # Messages for features tested for in target-specific section SIA_MSG="no" SPC_MSG="no" SP_MSG="no" SPP_MSG="no" # Support for Solaris/Illumos privileges (this test is used by both # the --with-solaris-privs option and --with-sandbox=solaris). SOLARIS_PRIVS="no" # Check for some target-specific stuff case "$host" in *-*-aix*) # Some versions of VAC won't allow macro redefinitions at # -qlanglevel=ansi, and autoconf 2.60 sometimes insists on using that # particularly with older versions of vac or xlc. # It also throws errors about null macro arguments, but these are # not fatal. AC_MSG_CHECKING([if compiler allows macro redefinitions]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ #define testmacro foo #define testmacro bar]], [[ exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) CC="`echo $CC | sed 's/-qlanglvl\=ansi//g'`" CFLAGS="`echo $CFLAGS | sed 's/-qlanglvl\=ansi//g'`" CPPFLAGS="`echo $CPPFLAGS | sed 's/-qlanglvl\=ansi//g'`" ] ) AC_MSG_CHECKING([how to specify blibpath for linker ($LD)]) if (test -z "$blibpath"); then blibpath="/usr/lib:/lib" fi saved_LDFLAGS="$LDFLAGS" if test "$GCC" = "yes"; then flags="-Wl,-blibpath: -Wl,-rpath, -blibpath:" else flags="-blibpath: -Wl,-blibpath: -Wl,-rpath," fi for tryflags in $flags ;do if (test -z "$blibflags"); then LDFLAGS="$saved_LDFLAGS $tryflags$blibpath" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [blibflags=$tryflags], []) fi done if (test -z "$blibflags"); then AC_MSG_RESULT([not found]) AC_MSG_ERROR([*** must be able to specify blibpath on AIX - check config.log]) else AC_MSG_RESULT([$blibflags]) fi LDFLAGS="$saved_LDFLAGS" dnl Check for authenticate. Might be in libs.a on older AIXes AC_CHECK_FUNC([authenticate], [AC_DEFINE([WITH_AIXAUTHENTICATE], [1], [Define if you want to enable AIX4's authenticate function])], [AC_CHECK_LIB([s], [authenticate], [ AC_DEFINE([WITH_AIXAUTHENTICATE]) LIBS="$LIBS -ls" ]) ]) dnl Check for various auth function declarations in headers. AC_CHECK_DECLS([authenticate, loginrestrictions, loginsuccess, passwdexpired, setauthdb], , , [#include ]) dnl Check if loginfailed is declared and takes 4 arguments (AIX >= 5.2) AC_CHECK_DECLS([loginfailed], [AC_MSG_CHECKING([if loginfailed takes 4 arguments]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ (void)loginfailed("user","host","tty",0); ]])], [AC_MSG_RESULT([yes]) AC_DEFINE([AIX_LOGINFAILED_4ARG], [1], [Define if your AIX loginfailed() function takes 4 arguments (AIX >= 5.2)])], [AC_MSG_RESULT([no]) ])], [], [#include ] ) AC_CHECK_FUNCS([getgrset setauthdb]) AC_CHECK_DECL([F_CLOSEM], AC_DEFINE([HAVE_FCNTL_CLOSEM], [1], [Use F_CLOSEM fcntl for closefrom]), [], [ #include #include ] ) check_for_aix_broken_getaddrinfo=1 AC_DEFINE([SETEUID_BREAKS_SETUID], [1], [Define if your platform breaks doing a seteuid before a setuid]) AC_DEFINE([BROKEN_SETREUID], [1], [Define if your setreuid() is broken]) AC_DEFINE([BROKEN_SETREGID], [1], [Define if your setregid() is broken]) dnl AIX handles lastlog as part of its login message AC_DEFINE([DISABLE_LASTLOG], [1], [Define if you don't want to use lastlog]) AC_DEFINE([LOGIN_NEEDS_UTMPX], [1], [Some systems need a utmpx entry for /bin/login to work]) AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV], [Define to a Set Process Title type if your system is supported by bsd-setproctitle.c]) AC_DEFINE([SSHPAM_CHAUTHTOK_NEEDS_RUID], [1], [AIX 5.2 and 5.3 (and presumably newer) require this]) AC_DEFINE([PTY_ZEROREAD], [1], [read(1) can return 0 for a non-closed fd]) AC_DEFINE([PLATFORM_SYS_DIR_UID], 2, [System dirs owned by bin (uid 2)]) AC_DEFINE([BROKEN_STRNDUP], 1, [strndup broken, see APAR IY61211]) AC_DEFINE([BROKEN_STRNLEN], 1, [strnlen broken, see APAR IY62551]) ;; *-*-android*) AC_DEFINE([DISABLE_UTMP], [1], [Define if you don't want to use utmp]) AC_DEFINE([DISABLE_WTMP], [1], [Define if you don't want to use wtmp]) ;; *-*-cygwin*) LIBS="$LIBS /usr/lib/textreadmode.o" AC_DEFINE([HAVE_CYGWIN], [1], [Define if you are on Cygwin]) AC_DEFINE([USE_PIPES], [1], [Use PIPES instead of a socketpair()]) AC_DEFINE([NO_UID_RESTORATION_TEST], [1], [Define to disable UID restoration test]) AC_DEFINE([DISABLE_SHADOW], [1], [Define if you want to disable shadow passwords]) AC_DEFINE([NO_X11_UNIX_SOCKETS], [1], [Define if X11 doesn't support AF_UNIX sockets on that system]) AC_DEFINE([DISABLE_FD_PASSING], [1], [Define if your platform needs to skip post auth file descriptor passing]) AC_DEFINE([SSH_IOBUFSZ], [65535], [Windows is sensitive to read buffer size]) AC_DEFINE([FILESYSTEM_NO_BACKSLASH], [1], [File names may not contain backslash characters]) # Cygwin defines optargs, optargs as declspec(dllimport) for historical # reasons which cause compile warnings, so we disable those warnings. OSSH_CHECK_CFLAG_COMPILE([-Wno-attributes]) ;; *-*-dgux*) AC_DEFINE([IP_TOS_IS_BROKEN], [1], [Define if your system choked on IP TOS setting]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) ;; *-*-darwin*) use_pie=auto AC_MSG_CHECKING([if we have working getaddrinfo]) AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include #include int main(void) { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) exit(0); else exit(1); } ]])], [AC_MSG_RESULT([working])], [AC_MSG_RESULT([buggy]) AC_DEFINE([BROKEN_GETADDRINFO], [1], [getaddrinfo is broken (if present)]) ], [AC_MSG_RESULT([assume it is working])]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([BROKEN_GLOB], [1], [OS X glob does not do what we expect]) AC_DEFINE_UNQUOTED([BIND_8_COMPAT], [1], [Define if your resolver libs need this for getrrsetbyname]) AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way]) AC_DEFINE([SSH_TUN_COMPAT_AF], [1], [Use tunnel device compatibility to OpenBSD]) AC_DEFINE([SSH_TUN_PREPEND_AF], [1], [Prepend the address family to IP tunnel traffic]) m4_pattern_allow([AU_IPv]) AC_CHECK_DECL([AU_IPv4], [], AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) [#include ] AC_DEFINE([LASTLOG_WRITE_PUTUTXLINE], [1], [Define if pututxline updates lastlog too]) ) AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV], [Define to a Set Process Title type if your system is supported by bsd-setproctitle.c]) AC_CHECK_FUNCS([sandbox_init]) AC_CHECK_HEADERS([sandbox.h]) AC_CHECK_LIB([sandbox], [sandbox_apply], [ SSHDLIBS="$SSHDLIBS -lsandbox" ]) # proc_pidinfo()-based closefrom() replacement. AC_CHECK_HEADERS([libproc.h]) AC_CHECK_FUNCS([proc_pidinfo]) # poll(2) is broken for character-special devices (at least). # cf. Apple bug 3710161 (not public, but searchable) AC_DEFINE([BROKEN_POLL], [1], [System poll(2) implementation is broken]) ;; *-*-dragonfly*) SSHDLIBS="$SSHDLIBS" TEST_MALLOC_OPTIONS="AFGJPRX" ;; *-*-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*) # first we define all of the options common to all HP-UX releases CPPFLAGS="$CPPFLAGS -D_HPUX_SOURCE -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1" IPADDR_IN_DISPLAY=yes AC_DEFINE([USE_PIPES]) AC_DEFINE([LOGIN_NEEDS_UTMPX]) AC_DEFINE([LOCKED_PASSWD_STRING], ["*"], [String used in /etc/passwd to denote locked account]) AC_DEFINE([SPT_TYPE], [SPT_PSTAT]) AC_DEFINE([PLATFORM_SYS_DIR_UID], 2, [System dirs owned by bin (uid 2)]) maildir="/var/mail" LIBS="$LIBS -lsec" AC_CHECK_LIB([xnet], [t_error], , [AC_MSG_ERROR([*** -lxnet needed on HP-UX - check config.log ***])]) # next, we define all of the options specific to major releases case "$host" in *-*-hpux10*) if test -z "$GCC"; then CFLAGS="$CFLAGS -Ae" fi AC_DEFINE([BROKEN_GETLINE], [1], [getline is not what we expect]) ;; *-*-hpux11*) AC_DEFINE([PAM_SUN_CODEBASE], [1], [Define if you are using Solaris-derived PAM which passes pam_messages to the conversation function with an extra level of indirection]) AC_DEFINE([DISABLE_UTMP], [1], [Define if you don't want to use utmp]) AC_DEFINE([USE_BTMP], [1], [Use btmp to log bad logins]) check_for_hpux_broken_getaddrinfo=1 check_for_conflicting_getspnam=1 ;; esac # lastly, we define options specific to minor releases case "$host" in *-*-hpux10.26) AC_DEFINE([HAVE_SECUREWARE], [1], [Define if you have SecureWare-based protected password database]) disable_ptmx_check=yes LIBS="$LIBS -lsecpw" ;; esac ;; *-*-irix5*) PATH="$PATH:/usr/etc" AC_DEFINE([BROKEN_INET_NTOA], [1], [Define if you system's inet_ntoa is busted (e.g. Irix gcc issue)]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([WITH_ABBREV_NO_TTY], [1], [Define if you shouldn't strip 'tty' from your ttyname in [uw]tmp]) AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"]) ;; *-*-irix6*) PATH="$PATH:/usr/etc" AC_DEFINE([WITH_IRIX_ARRAY], [1], [Define if you have/want arrays (cluster-wide session management, not C arrays)]) AC_DEFINE([WITH_IRIX_PROJECT], [1], [Define if you want IRIX project management]) AC_DEFINE([WITH_IRIX_AUDIT], [1], [Define if you want IRIX audit trails]) AC_CHECK_FUNC([jlimit_startjob], [AC_DEFINE([WITH_IRIX_JOBS], [1], [Define if you want IRIX kernel jobs])]) AC_DEFINE([BROKEN_INET_NTOA]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([BROKEN_UPDWTMPX], [1], [updwtmpx is broken (if present)]) AC_DEFINE([WITH_ABBREV_NO_TTY]) AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"]) ;; *-*-k*bsd*-gnu | *-*-kopensolaris*-gnu) AC_DEFINE([PAM_TTY_KLUDGE]) AC_DEFINE([LOCKED_PASSWD_PREFIX], ["!"]) AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV]) AC_DEFINE([_PATH_BTMP], ["/var/log/btmp"], [log for bad login attempts]) AC_DEFINE([USE_BTMP], [1], [Use btmp to log bad logins]) ;; *-*-linux*) no_dev_ptmx=1 use_pie=auto check_for_openpty_ctty_bug=1 dnl Target SUSv3/POSIX.1-2001 plus BSD specifics. dnl _DEFAULT_SOURCE is the new name for _BSD_SOURCE dnl _GNU_SOURCE is needed for setres*id prototypes. CPPFLAGS="$CPPFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_DEFAULT_SOURCE -D_GNU_SOURCE" AC_DEFINE([BROKEN_CLOSEFROM], [1], [broken in chroots on older kernels]) AC_DEFINE([PAM_TTY_KLUDGE], [1], [Work around problematic Linux PAM modules handling of PAM_TTY]) AC_DEFINE([LOCKED_PASSWD_PREFIX], ["!"], [String used in /etc/passwd to denote locked account]) AC_DEFINE([SPT_TYPE], [SPT_REUSEARGV]) AC_DEFINE([LINK_OPNOTSUPP_ERRNO], [EPERM], [Define to whatever link() returns for "not supported" if it doesn't return EOPNOTSUPP.]) AC_DEFINE([_PATH_BTMP], ["/var/log/btmp"], [log for bad login attempts]) AC_DEFINE([USE_BTMP]) AC_DEFINE([LINUX_OOM_ADJUST], [1], [Adjust Linux out-of-memory killer]) inet6_default_4in6=yes case `uname -r` in 1.*|2.0.*) AC_DEFINE([BROKEN_CMSG_TYPE], [1], [Define if cmsg_type is not passed correctly]) ;; esac # tun(4) forwarding compat code AC_CHECK_HEADERS([linux/if_tun.h]) if test "x$ac_cv_header_linux_if_tun_h" = "xyes" ; then AC_DEFINE([SSH_TUN_LINUX], [1], [Open tunnel devices the Linux tun/tap way]) AC_DEFINE([SSH_TUN_COMPAT_AF], [1], [Use tunnel device compatibility to OpenBSD]) AC_DEFINE([SSH_TUN_PREPEND_AF], [1], [Prepend the address family to IP tunnel traffic]) fi AC_CHECK_HEADER([linux/if.h], AC_DEFINE([SYS_RDOMAIN_LINUX], [1], [Support routing domains using Linux VRF]), [], [ #ifdef HAVE_SYS_TYPES_H # include #endif ]) AC_CHECK_HEADERS([linux/seccomp.h linux/filter.h linux/audit.h], [], [], [#include ]) # Obtain MIPS ABI case "$host" in mips*) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if _MIPS_SIM != _ABIO32 #error #endif ]])],[mips_abi="o32"],[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if _MIPS_SIM != _ABIN32 #error #endif ]])],[mips_abi="n32"],[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #if _MIPS_SIM != _ABI64 #error #endif ]])],[mips_abi="n64"],[AC_MSG_ERROR([unknown MIPS ABI]) ]) ]) ]) ;; esac AC_MSG_CHECKING([for seccomp architecture]) seccomp_audit_arch= case "$host" in x86_64-*) seccomp_audit_arch=AUDIT_ARCH_X86_64 ;; i*86-*) seccomp_audit_arch=AUDIT_ARCH_I386 ;; arm*-*) seccomp_audit_arch=AUDIT_ARCH_ARM ;; aarch64*-*) seccomp_audit_arch=AUDIT_ARCH_AARCH64 ;; s390x-*) seccomp_audit_arch=AUDIT_ARCH_S390X ;; s390-*) seccomp_audit_arch=AUDIT_ARCH_S390 ;; powerpc-*) seccomp_audit_arch=AUDIT_ARCH_PPC ;; powerpc64-*) seccomp_audit_arch=AUDIT_ARCH_PPC64 ;; powerpc64le-*) seccomp_audit_arch=AUDIT_ARCH_PPC64LE ;; mips-*) seccomp_audit_arch=AUDIT_ARCH_MIPS ;; mipsel-*) seccomp_audit_arch=AUDIT_ARCH_MIPSEL ;; mips64-*) case "$mips_abi" in "n32") seccomp_audit_arch=AUDIT_ARCH_MIPS64N32 ;; "n64") seccomp_audit_arch=AUDIT_ARCH_MIPS64 ;; esac ;; mips64el-*) case "$mips_abi" in "n32") seccomp_audit_arch=AUDIT_ARCH_MIPSEL64N32 ;; "n64") seccomp_audit_arch=AUDIT_ARCH_MIPSEL64 ;; esac ;; riscv64-*) seccomp_audit_arch=AUDIT_ARCH_RISCV64 ;; esac if test "x$seccomp_audit_arch" != "x" ; then AC_MSG_RESULT(["$seccomp_audit_arch"]) AC_DEFINE_UNQUOTED([SECCOMP_AUDIT_ARCH], [$seccomp_audit_arch], [Specify the system call convention in use]) else AC_MSG_RESULT([architecture not supported]) fi ;; *-*-minix) AC_DEFINE([SETEUID_BREAKS_SETUID]) # poll(2) seems to choke on /dev/null; "Bad file descriptor" AC_DEFINE([BROKEN_POLL], [1], [System poll(2) implementation is broken]) ;; mips-sony-bsd|mips-sony-newsos4) AC_DEFINE([NEED_SETPGRP], [1], [Need setpgrp to acquire controlling tty]) SONY=1 ;; *-*-netbsd*) if test "x$withval" != "xno" ; then rpath_opt="-R" fi CPPFLAGS="$CPPFLAGS -D_OPENBSD_SOURCE" AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way]) AC_CHECK_HEADER([net/if_tap.h], , AC_DEFINE([SSH_TUN_NO_L2], [1], [No layer 2 tunnel support])) AC_DEFINE([SSH_TUN_PREPEND_AF], [1], [Prepend the address family to IP tunnel traffic]) TEST_MALLOC_OPTIONS="AJRX" AC_DEFINE([BROKEN_READ_COMPARISON], [1], [NetBSD read function is sometimes redirected, breaking atomicio comparisons against it]) ;; *-*-freebsd*) SKIP_DISABLE_LASTLOG_DEFINE=yes AC_DEFINE([LOCKED_PASSWD_PREFIX], ["*LOCKED*"], [Account locked with pw(1)]) AC_DEFINE([SSH_TUN_FREEBSD], [1], [Open tunnel devices the FreeBSD way]) AC_CHECK_HEADER([net/if_tap.h], , AC_DEFINE([SSH_TUN_NO_L2], [1], [No layer 2 tunnel support])) AC_DEFINE([BROKEN_GLOB], [1], [FreeBSD glob does not do what we need]) TEST_MALLOC_OPTIONS="AJRX" # Preauth crypto occasionally uses file descriptors for crypto offload # and will crash if they cannot be opened. AC_DEFINE([SANDBOX_SKIP_RLIMIT_NOFILE], [1], [define if setrlimit RLIMIT_NOFILE breaks things]) case "$host" in *-*-freebsd9.*|*-*-freebsd10.*) # Capsicum on 9 and 10 do not allow ppoll() so don't auto-enable. disable_capsicum=yes esac ;; *-*-bsdi*) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) ;; *-next-*) conf_lastlog_location="/usr/adm/lastlog" conf_utmp_location=/etc/utmp conf_wtmp_location=/usr/adm/wtmp maildir=/usr/spool/mail AC_DEFINE([HAVE_NEXT], [1], [Define if you are on NeXT]) AC_DEFINE([USE_PIPES]) AC_DEFINE([BROKEN_SAVED_UIDS], [1], [Needed for NeXT]) ;; *-*-openbsd*) use_pie=auto AC_DEFINE([HAVE_ATTRIBUTE__SENTINEL__], [1], [OpenBSD's gcc has sentinel]) AC_DEFINE([HAVE_ATTRIBUTE__BOUNDED__], [1], [OpenBSD's gcc has bounded]) AC_DEFINE([SSH_TUN_OPENBSD], [1], [Open tunnel devices the OpenBSD way]) AC_DEFINE([SYSLOG_R_SAFE_IN_SIGHAND], [1], [syslog_r function is safe to use in in a signal handler]) TEST_MALLOC_OPTIONS="AFGJPRX" ;; *-*-solaris*) if test "x$withval" != "xno" ; then rpath_opt="-R" fi AC_DEFINE([PAM_SUN_CODEBASE]) AC_DEFINE([LOGIN_NEEDS_UTMPX]) AC_DEFINE([PAM_TTY_KLUDGE]) AC_DEFINE([SSHPAM_CHAUTHTOK_NEEDS_RUID], [1], [Define if pam_chauthtok wants real uid set to the unpriv'ed user]) AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"]) # Pushing STREAMS modules will cause sshd to acquire a controlling tty. AC_DEFINE([SSHD_ACQUIRES_CTTY], [1], [Define if sshd somehow reacquires a controlling TTY after setsid()]) AC_DEFINE([PASSWD_NEEDS_USERNAME], [1], [must supply username to passwd in case the name is longer than 8 chars]) AC_DEFINE([BROKEN_TCGETATTR_ICANON], [1], [tcgetattr with ICANON may hang]) external_path_file=/etc/default/login # hardwire lastlog location (can't detect it on some versions) conf_lastlog_location="/var/adm/lastlog" AC_MSG_CHECKING([for obsolete utmp and wtmp in solaris2.x]) sol2ver=`echo "$host"| sed -e 's/.*[[0-9]]\.//'` if test "$sol2ver" -ge 8; then AC_MSG_RESULT([yes]) AC_DEFINE([DISABLE_UTMP]) AC_DEFINE([DISABLE_WTMP], [1], [Define if you don't want to use wtmp]) else AC_MSG_RESULT([no]) fi AC_CHECK_FUNCS([setpflags]) AC_CHECK_FUNCS([setppriv]) AC_CHECK_FUNCS([priv_basicset]) AC_CHECK_HEADERS([priv.h]) AC_ARG_WITH([solaris-contracts], [ --with-solaris-contracts Enable Solaris process contracts (experimental)], [ AC_CHECK_LIB([contract], [ct_tmpl_activate], [ AC_DEFINE([USE_SOLARIS_PROCESS_CONTRACTS], [1], [Define if you have Solaris process contracts]) LIBS="$LIBS -lcontract" SPC_MSG="yes" ], ) ], ) AC_ARG_WITH([solaris-projects], [ --with-solaris-projects Enable Solaris projects (experimental)], [ AC_CHECK_LIB([project], [setproject], [ AC_DEFINE([USE_SOLARIS_PROJECTS], [1], [Define if you have Solaris projects]) LIBS="$LIBS -lproject" SP_MSG="yes" ], ) ], ) AC_ARG_WITH([solaris-privs], [ --with-solaris-privs Enable Solaris/Illumos privileges (experimental)], [ AC_MSG_CHECKING([for Solaris/Illumos privilege support]) if test "x$ac_cv_func_setppriv" = "xyes" -a \ "x$ac_cv_header_priv_h" = "xyes" ; then SOLARIS_PRIVS=yes AC_MSG_RESULT([found]) AC_DEFINE([NO_UID_RESTORATION_TEST], [1], [Define to disable UID restoration test]) AC_DEFINE([USE_SOLARIS_PRIVS], [1], [Define if you have Solaris privileges]) SPP_MSG="yes" else AC_MSG_RESULT([not found]) AC_MSG_ERROR([*** must have support for Solaris privileges to use --with-solaris-privs]) fi ], ) TEST_SHELL=$SHELL # let configure find us a capable shell ;; *-*-sunos4*) CPPFLAGS="$CPPFLAGS -DSUNOS4" AC_CHECK_FUNCS([getpwanam]) AC_DEFINE([PAM_SUN_CODEBASE]) conf_utmp_location=/etc/utmp conf_wtmp_location=/var/adm/wtmp conf_lastlog_location=/var/adm/lastlog AC_DEFINE([USE_PIPES]) AC_DEFINE([DISABLE_UTMPX], [1], [no utmpx]) ;; *-ncr-sysv*) LIBS="$LIBS -lc89" AC_DEFINE([USE_PIPES]) AC_DEFINE([SSHD_ACQUIRES_CTTY]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) ;; *-sni-sysv*) # /usr/ucblib MUST NOT be searched on ReliantUNIX AC_CHECK_LIB([dl], [dlsym], ,) # -lresolv needs to be at the end of LIBS or DNS lookups break AC_CHECK_LIB([resolv], [res_query], [ LIBS="$LIBS -lresolv" ]) IPADDR_IN_DISPLAY=yes AC_DEFINE([USE_PIPES]) AC_DEFINE([IP_TOS_IS_BROKEN]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([SSHD_ACQUIRES_CTTY]) external_path_file=/etc/default/login # /usr/ucblib/libucb.a no longer needed on ReliantUNIX # Attention: always take care to bind libsocket and libnsl before libc, # otherwise you will find lots of "SIOCGPGRP errno 22" on syslog ;; # UnixWare 1.x, UnixWare 2.x, and others based on code from Univel. *-*-sysv4.2*) AC_DEFINE([USE_PIPES]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([PASSWD_NEEDS_USERNAME], [1], [must supply username to passwd]) AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"]) TEST_SHELL=$SHELL # let configure find us a capable shell ;; # UnixWare 7.x, OpenUNIX 8 *-*-sysv5*) CPPFLAGS="$CPPFLAGS -Dvsnprintf=_xvsnprintf -Dsnprintf=_xsnprintf" AC_DEFINE([UNIXWARE_LONG_PASSWORDS], [1], [Support passwords > 8 chars]) AC_DEFINE([USE_PIPES]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_GETADDRINFO]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([PASSWD_NEEDS_USERNAME]) AC_DEFINE([BROKEN_TCGETATTR_ICANON]) TEST_SHELL=$SHELL # let configure find us a capable shell case "$host" in *-*-sysv5SCO_SV*) # SCO OpenServer 6.x maildir=/var/spool/mail AC_DEFINE([BROKEN_UPDWTMPX]) AC_CHECK_LIB([prot], [getluid], [ LIBS="$LIBS -lprot" AC_CHECK_FUNCS([getluid setluid], , , [-lprot]) ], , ) ;; *) AC_DEFINE([LOCKED_PASSWD_STRING], ["*LK*"]) ;; esac ;; *-*-sysv*) ;; # SCO UNIX and OEM versions of SCO UNIX *-*-sco3.2v4*) AC_MSG_ERROR("This Platform is no longer supported.") ;; # SCO OpenServer 5.x *-*-sco3.2v5*) if test -z "$GCC"; then CFLAGS="$CFLAGS -belf" fi LIBS="$LIBS -lprot -lx -ltinfo -lm" no_dev_ptmx=1 AC_DEFINE([USE_PIPES]) AC_DEFINE([HAVE_SECUREWARE]) AC_DEFINE([DISABLE_SHADOW]) AC_DEFINE([DISABLE_FD_PASSING]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_GETADDRINFO]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([WITH_ABBREV_NO_TTY]) AC_DEFINE([BROKEN_UPDWTMPX]) AC_DEFINE([PASSWD_NEEDS_USERNAME]) AC_CHECK_FUNCS([getluid setluid]) MANTYPE=man TEST_SHELL=$SHELL # let configure find us a capable shell SKIP_DISABLE_LASTLOG_DEFINE=yes ;; *-dec-osf*) AC_MSG_CHECKING([for Digital Unix SIA]) no_osfsia="" AC_ARG_WITH([osfsia], [ --with-osfsia Enable Digital Unix SIA], [ if test "x$withval" = "xno" ; then AC_MSG_RESULT([disabled]) no_osfsia=1 fi ], ) if test -z "$no_osfsia" ; then if test -f /etc/sia/matrix.conf; then AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_OSF_SIA], [1], [Define if you have Digital Unix Security Integration Architecture]) AC_DEFINE([DISABLE_LOGIN], [1], [Define if you don't want to use your system's login() call]) AC_DEFINE([DISABLE_FD_PASSING]) LIBS="$LIBS -lsecurity -ldb -lm -laud" SIA_MSG="yes" else AC_MSG_RESULT([no]) AC_DEFINE([LOCKED_PASSWD_SUBSTR], ["Nologin"], [String used in /etc/passwd to denote locked account]) fi fi AC_DEFINE([BROKEN_GETADDRINFO]) AC_DEFINE([SETEUID_BREAKS_SETUID]) AC_DEFINE([BROKEN_SETREUID]) AC_DEFINE([BROKEN_SETREGID]) AC_DEFINE([BROKEN_READV_COMPARISON], [1], [Can't do comparisons on readv]) ;; *-*-nto-qnx*) AC_DEFINE([USE_PIPES]) AC_DEFINE([NO_X11_UNIX_SOCKETS]) AC_DEFINE([DISABLE_LASTLOG]) AC_DEFINE([SSHD_ACQUIRES_CTTY]) AC_DEFINE([BROKEN_SHADOW_EXPIRE], [1], [QNX shadow support is broken]) enable_etc_default_login=no # has incompatible /etc/default/login case "$host" in *-*-nto-qnx6*) AC_DEFINE([DISABLE_FD_PASSING]) ;; esac ;; *-*-ultrix*) AC_DEFINE([BROKEN_GETGROUPS], [1], [getgroups(0,NULL) will return -1]) AC_DEFINE([NEED_SETPGRP], [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_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([*** compiler cannot create working executables, check config.log ***]) ], [ AC_MSG_WARN([cross compiling: not checking compiler sanity]) ] ) dnl Checks for header files. # Checks for libraries. AC_CHECK_FUNC([setsockopt], , [AC_CHECK_LIB([socket], [setsockopt])]) dnl IRIX and Solaris 2.5.1 have dirname() in libgen AC_CHECK_FUNCS([dirname], [AC_CHECK_HEADERS([libgen.h])] , [ AC_CHECK_LIB([gen], [dirname], [ AC_CACHE_CHECK([for broken dirname], ac_cv_have_broken_dirname, [ save_LIBS="$LIBS" LIBS="$LIBS -lgen" AC_RUN_IFELSE( [AC_LANG_SOURCE([[ #include #include #include int main(int argc, char **argv) { char *s, buf[32]; strncpy(buf,"/etc", 32); s = dirname(buf); if (!s || strncmp(s, "/", 32) != 0) { exit(1); } else { exit(0); } } ]])], [ ac_cv_have_broken_dirname="no" ], [ ac_cv_have_broken_dirname="yes" ], [ ac_cv_have_broken_dirname="no" ], ) LIBS="$save_LIBS" ]) if test "x$ac_cv_have_broken_dirname" = "xno" ; then LIBS="$LIBS -lgen" AC_DEFINE([HAVE_DIRNAME]) AC_CHECK_HEADERS([libgen.h]) fi ]) ]) AC_CHECK_FUNC([getspnam], , [AC_CHECK_LIB([gen], [getspnam], [LIBS="$LIBS -lgen"])]) AC_SEARCH_LIBS([basename], [gen], [AC_DEFINE([HAVE_BASENAME], [1], [Define if you have the basename function.])]) dnl zlib defaults to enabled zlib=yes AC_ARG_WITH([zlib], [ --with-zlib=PATH Use zlib in PATH], [ if test "x$withval" = "xno" ; then zlib=no elif test "x$withval" != "xyes"; then if test -d "$withval/lib"; then if test -n "${rpath_opt}"; then LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}" else LDFLAGS="-L${withval}/lib ${LDFLAGS}" fi else if test -n "${rpath_opt}"; then LDFLAGS="-L${withval} ${rpath_opt}${withval} ${LDFLAGS}" else LDFLAGS="-L${withval} ${LDFLAGS}" fi fi if test -d "$withval/include"; then CPPFLAGS="-I${withval}/include ${CPPFLAGS}" else CPPFLAGS="-I${withval} ${CPPFLAGS}" fi fi ] ) # These libraries are needed for anything that links in the channel code. CHANNELLIBS="" AC_MSG_CHECKING([for zlib]) if test "x${zlib}" = "xno"; then AC_MSG_RESULT([no]) else saved_LIBS="$LIBS" CHANNELLIBS="$CHANNELLIBS -lz" 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" dnl Check default zlib install dir if test -n "${rpath_opt}"; then LDFLAGS="-L/usr/local/lib ${rpath_opt}/usr/local/lib ${saved_LDFLAGS}" else LDFLAGS="-L/usr/local/lib ${saved_LDFLAGS}" fi CPPFLAGS="-I/usr/local/include ${saved_CPPFLAGS}" AC_TRY_LINK_FUNC([deflate], [AC_DEFINE([HAVE_LIBZ])], [ AC_MSG_ERROR([*** zlib missing - please install first or check config.log ***]) ] ) ] ) AC_ARG_WITH([zlib-version-check], [ --without-zlib-version-check Disable zlib version check], [ if test "x$withval" = "xno" ; then zlib_check_nonfatal=1 fi ] ) AC_MSG_CHECKING([for possibly buggy zlib]) AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include #include #include ]], [[ int a=0, b=0, c=0, d=0, n, v; n = sscanf(ZLIB_VERSION, "%d.%d.%d.%d", &a, &b, &c, &d); if (n < 1) exit(1); v = a*1000000 + b*10000 + c*100 + d; fprintf(stderr, "found zlib version %s (%d)\n", ZLIB_VERSION, v); /* 1.1.4 is OK */ if (a == 1 && b == 1 && c >= 4) exit(0); /* 1.2.3 and up are OK */ if (v >= 1020300) exit(0); exit(2); ]])], AC_MSG_RESULT([no]), [ AC_MSG_RESULT([yes]) if test -z "$zlib_check_nonfatal" ; then AC_MSG_ERROR([*** zlib too old - check config.log *** Your reported zlib version has known security problems. It's possible your vendor has fixed these problems without changing the version number. If you are sure this is the case, you can disable the check by running "./configure --without-zlib-version-check". If you are in doubt, upgrade zlib to version 1.2.3 or greater. See http://www.gzip.org/zlib/ for details.]) else AC_MSG_WARN([zlib version may have security problems]) fi ], [ AC_MSG_WARN([cross compiling: not checking zlib version]) ] ) LIBS="$saved_LIBS" fi dnl UnixWare 2.x AC_CHECK_FUNC([strcasecmp], [], [ AC_CHECK_LIB([resolv], [strcasecmp], [LIBS="$LIBS -lresolv"]) ] ) AC_CHECK_FUNCS([utimes], [], [ AC_CHECK_LIB([c89], [utimes], [AC_DEFINE([HAVE_UTIMES]) LIBS="$LIBS -lc89"]) ] ) dnl Checks for libutil functions AC_CHECK_HEADERS([bsd/libutil.h libutil.h]) AC_SEARCH_LIBS([fmt_scaled], [util bsd]) AC_SEARCH_LIBS([scan_scaled], [util bsd]) AC_SEARCH_LIBS([login], [util bsd]) AC_SEARCH_LIBS([logout], [util bsd]) AC_SEARCH_LIBS([logwtmp], [util bsd]) AC_SEARCH_LIBS([openpty], [util bsd]) AC_SEARCH_LIBS([updwtmp], [util bsd]) AC_CHECK_FUNCS([fmt_scaled scan_scaled login logout openpty updwtmp logwtmp]) # On some platforms, inet_ntop and gethostbyname may be found in libresolv # or libnsl. AC_SEARCH_LIBS([inet_ntop], [resolv nsl]) AC_SEARCH_LIBS([gethostbyname], [resolv nsl]) # 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 AC_FUNC_MALLOC AC_FUNC_REALLOC # autoconf doesn't have AC_FUNC_CALLOC so fake it if malloc returns NULL; AC_MSG_CHECKING([if calloc(0, N) returns non-null]) AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[ #include ]], [[ void *p = calloc(0, 1); exit(p == NULL); ]] )], [ func_calloc_0_nonnull=yes ], [ func_calloc_0_nonnull=no ], [ AC_MSG_WARN([cross compiling: assuming same as malloc]) func_calloc_0_nonnull="$ac_cv_func_malloc_0_nonnull"] ) AC_MSG_RESULT([$func_calloc_0_nonnull]) if test "x$func_calloc_0_nonnull" = "xyes"; then AC_DEFINE(HAVE_CALLOC, 1, [calloc(0, x) returns non-null]) else AC_DEFINE(HAVE_CALLOC, 0, [calloc(0, x) returns NULL]) AC_DEFINE(calloc, rpl_calloc, [Define to rpl_calloc if the replacement function should be used.]) fi # Check for ALTDIRFUNC glob() extension AC_MSG_CHECKING([for GLOB_ALTDIRFUNC support]) AC_EGREP_CPP([FOUNDIT], [ #include #ifdef GLOB_ALTDIRFUNC FOUNDIT #endif ], [ AC_DEFINE([GLOB_HAS_ALTDIRFUNC], [1], [Define if your system glob() function has the GLOB_ALTDIRFUNC extension]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ] ) # Check for g.gl_matchc glob() extension AC_MSG_CHECKING([for gl_matchc field in glob_t]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ glob_t g; g.gl_matchc = 1; ]])], [ AC_DEFINE([GLOB_HAS_GL_MATCHC], [1], [Define if your system glob() function has gl_matchc options in glob_t]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) # Check for g.gl_statv glob() extension AC_MSG_CHECKING([for gl_statv and GLOB_KEEPSTAT extensions for glob]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ #ifndef GLOB_KEEPSTAT #error "glob does not support GLOB_KEEPSTAT extension" #endif glob_t g; g.gl_statv = NULL; ]])], [ AC_DEFINE([GLOB_HAS_GL_STATV], [1], [Define if your system glob() function has gl_statv options in glob_t]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) AC_CHECK_DECLS([GLOB_NOMATCH], , , [#include ]) AC_CHECK_DECL([VIS_ALL], , AC_DEFINE(BROKEN_STRNVIS, 1, [missing VIS_ALL]), [#include ]) AC_MSG_CHECKING([whether struct dirent allocates space for d_name]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include ]], [[ struct dirent d; exit(sizeof(d.d_name)<=sizeof(char)); ]])], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_DEFINE([BROKEN_ONE_BYTE_DIRENT_D_NAME], [1], [Define if your struct dirent expects you to allocate extra space for d_name]) ], [ AC_MSG_WARN([cross compiling: assuming BROKEN_ONE_BYTE_DIRENT_D_NAME]) AC_DEFINE([BROKEN_ONE_BYTE_DIRENT_D_NAME]) ] ) AC_MSG_CHECKING([for /proc/pid/fd directory]) if test -d "/proc/$$/fd" ; then AC_DEFINE([HAVE_PROC_PID], [1], [Define if you have /proc/$pid/fd]) AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi # Check whether user wants TCP wrappers support TCPW_MSG="no" AC_ARG_WITH([tcp-wrappers], [ --with-tcp-wrappers[[=PATH]] Enable tcpwrappers support (optionally in PATH)], [ if test "x$withval" != "xno" ; then saved_LIBS="$LIBS" saved_LDFLAGS="$LDFLAGS" saved_CPPFLAGS="$CPPFLAGS" if test -n "${withval}" && \ test "x${withval}" != "xyes"; then if test -d "${withval}/lib"; then if test -n "${need_dash_r}"; then LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}" else LDFLAGS="-L${withval}/lib ${LDFLAGS}" fi else if test -n "${need_dash_r}"; then LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}" else LDFLAGS="-L${withval} ${LDFLAGS}" fi fi if test -d "${withval}/include"; then CPPFLAGS="-I${withval}/include ${CPPFLAGS}" else CPPFLAGS="-I${withval} ${CPPFLAGS}" fi fi LIBS="-lwrap $LIBS" AC_MSG_CHECKING([for libwrap]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include #include #include int deny_severity = 0, allow_severity = 0; ]], [[ hosts_access(0); ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([LIBWRAP], [1], [Define if you want TCP Wrappers support]) SSHDLIBS="$SSHDLIBS -lwrap" TCPW_MSG="yes" ], [ AC_MSG_ERROR([*** libwrap missing]) ]) LIBS="$saved_LIBS" fi ] ) # Check whether user wants to use ldns LDNS_MSG="no" AC_ARG_WITH(ldns, [ --with-ldns[[=PATH]] Use ldns for DNSSEC support (optionally in PATH)], [ ldns="" if test "x$withval" = "xyes" ; then AC_PATH_TOOL([LDNSCONFIG], [ldns-config], [no]) if test "x$LDNSCONFIG" = "xno"; then LIBS="-lldns $LIBS" ldns=yes else LIBS="$LIBS `$LDNSCONFIG --libs`" CPPFLAGS="$CPPFLAGS `$LDNSCONFIG --cflags`" ldns=yes fi elif test "x$withval" != "xno" ; then CPPFLAGS="$CPPFLAGS -I${withval}/include" LDFLAGS="$LDFLAGS -L${withval}/lib" LIBS="-lldns $LIBS" ldns=yes fi # Verify that it works. if test "x$ldns" = "xyes" ; then AC_DEFINE(HAVE_LDNS, 1, [Define if you want ldns support]) LDNS_MSG="yes" AC_MSG_CHECKING([for ldns support]) AC_LINK_IFELSE( [AC_LANG_SOURCE([[ #include #include #ifdef HAVE_STDINT_H # include #endif #include int main(void) { ldns_status status = ldns_verify_trusted(NULL, NULL, NULL, NULL); status=LDNS_STATUS_OK; exit(0); } ]]) ], [AC_MSG_RESULT(yes)], [ AC_MSG_RESULT(no) AC_MSG_ERROR([** Incomplete or missing ldns libraries.]) ]) fi ]) # Check whether user wants libedit support LIBEDIT_MSG="no" AC_ARG_WITH([libedit], [ --with-libedit[[=PATH]] Enable libedit support for sftp], [ if test "x$withval" != "xno" ; then if test "x$withval" = "xyes" ; then if test "x$PKGCONFIG" != "xno"; then AC_MSG_CHECKING([if $PKGCONFIG knows about libedit]) if "$PKGCONFIG" libedit; then AC_MSG_RESULT([yes]) use_pkgconfig_for_libedit=yes else AC_MSG_RESULT([no]) fi fi else CPPFLAGS="$CPPFLAGS -I${withval}/include" if test -n "${rpath_opt}"; then LDFLAGS="-L${withval}/lib ${rpath_opt}${withval}/lib ${LDFLAGS}" else LDFLAGS="-L${withval}/lib ${LDFLAGS}" fi fi if test "x$use_pkgconfig_for_libedit" = "xyes"; then LIBEDIT=`$PKGCONFIG --libs libedit` CPPFLAGS="$CPPFLAGS `$PKGCONFIG --cflags libedit`" else LIBEDIT="-ledit -lcurses" fi OTHERLIBS=`echo $LIBEDIT | sed 's/-ledit//'` AC_CHECK_LIB([edit], [el_init], [ AC_DEFINE([USE_LIBEDIT], [1], [Use libedit for sftp]) LIBEDIT_MSG="yes" AC_SUBST([LIBEDIT]) ], [ AC_MSG_ERROR([libedit not found]) ], [ $OTHERLIBS ] ) AC_MSG_CHECKING([if libedit version is compatible]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ #include #include ]], [[ int i = H_SETSIZE; el_init("", NULL, NULL, NULL); exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([libedit version is not compatible]) ] ) fi ] ) AUDIT_MODULE=none AC_ARG_WITH([audit], [ --with-audit=module Enable audit support (modules=debug,bsm,linux)], [ AC_MSG_CHECKING([for supported audit module]) case "$withval" in bsm) AC_MSG_RESULT([bsm]) AUDIT_MODULE=bsm dnl Checks for headers, libs and functions AC_CHECK_HEADERS([bsm/audit.h], [], [AC_MSG_ERROR([BSM enabled and bsm/audit.h not found])], [ #ifdef HAVE_TIME_H # include #endif ] ) AC_CHECK_LIB([bsm], [getaudit], [], [AC_MSG_ERROR([BSM enabled and required library not found])]) AC_CHECK_FUNCS([getaudit], [], [AC_MSG_ERROR([BSM enabled and required function not found])]) # These are optional AC_CHECK_FUNCS([getaudit_addr aug_get_machine]) AC_DEFINE([USE_BSM_AUDIT], [1], [Use BSM audit module]) if test "$sol2ver" -ge 11; then SSHDLIBS="$SSHDLIBS -lscf" AC_DEFINE([BROKEN_BSM_API], [1], [The system has incomplete BSM API]) fi ;; linux) AC_MSG_RESULT([linux]) AUDIT_MODULE=linux dnl Checks for headers, libs and functions AC_CHECK_HEADERS([libaudit.h]) SSHDLIBS="$SSHDLIBS -laudit" AC_DEFINE([USE_LINUX_AUDIT], [1], [Use Linux audit module]) ;; debug) AUDIT_MODULE=debug AC_MSG_RESULT([debug]) AC_DEFINE([SSH_AUDIT_EVENTS], [1], [Use audit debugging module]) ;; no) AC_MSG_RESULT([no]) ;; *) AC_MSG_ERROR([Unknown audit module $withval]) ;; esac ] ) AC_ARG_WITH([pie], [ --with-pie Build Position Independent Executables if possible], [ if test "x$withval" = "xno"; then use_pie=no fi if test "x$withval" = "xyes"; then use_pie=yes fi ] ) if test "x$use_pie" = "x"; then use_pie=no fi if test "x$use_toolchain_hardening" != "x1" && test "x$use_pie" = "xauto"; then # Turn off automatic PIE when toolchain hardening is off. use_pie=no fi if test "x$use_pie" = "xauto"; then # Automatic PIE requires gcc >= 4.x AC_MSG_CHECKING([for gcc >= 4.x]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ #if !defined(__GNUC__) || __GNUC__ < 4 #error gcc is too old #endif ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) use_pie=no ] ) fi if test "x$use_pie" != "xno"; then SAVED_CFLAGS="$CFLAGS" SAVED_LDFLAGS="$LDFLAGS" OSSH_CHECK_CFLAG_COMPILE([-fPIE]) OSSH_CHECK_LDFLAG_LINK([-pie]) # We use both -fPIE and -pie or neither. AC_MSG_CHECKING([whether both -fPIE and -pie are supported]) if echo "x $CFLAGS" | grep ' -fPIE' >/dev/null 2>&1 && \ echo "x $LDFLAGS" | grep ' -pie' >/dev/null 2>&1 ; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) CFLAGS="$SAVED_CFLAGS" LDFLAGS="$SAVED_LDFLAGS" fi fi 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([ \ auth_hostok \ auth_timeok \ Blowfish_initstate \ Blowfish_expandstate \ Blowfish_expand0state \ Blowfish_stream2word \ SHA256Update \ SHA384Update \ SHA512Update \ asprintf \ b64_ntop \ __b64_ntop \ b64_pton \ __b64_pton \ bcopy \ bcrypt_pbkdf \ bindresvport_sa \ blf_enc \ bzero \ cap_rights_limit \ clock \ closefrom \ close_range \ dirfd \ endgrent \ err \ errx \ explicit_bzero \ explicit_memset \ fchmod \ fchmodat \ fchown \ fchownat \ flock \ fnmatch \ freeaddrinfo \ freezero \ fstatfs \ fstatvfs \ futimes \ getaddrinfo \ getcwd \ getentropy \ getgrouplist \ getline \ getnameinfo \ getopt \ getpagesize \ getpeereid \ getpeerucred \ getpgid \ _getpty \ getrlimit \ getrandom \ getsid \ getttyent \ glob \ group_from_gid \ inet_aton \ inet_ntoa \ inet_ntop \ innetgr \ killpg \ llabs \ localtime_r \ login_getcapbool \ login_getpwclass \ memmem \ memmove \ memset_s \ mkdtemp \ ngetaddrinfo \ nsleep \ ogetaddrinfo \ openlog_r \ pledge \ poll \ ppoll \ prctl \ procctl \ pselect \ pstat \ raise \ readpassphrase \ reallocarray \ realpath \ recvmsg \ recallocarray \ rresvport_af \ sendmsg \ setdtablesize \ setegid \ setenv \ seteuid \ setgroupent \ setgroups \ setlinebuf \ setlogin \ setpassent\ setpcred \ setproctitle \ setregid \ setreuid \ setrlimit \ setsid \ setvbuf \ sigaction \ sigvec \ snprintf \ socketpair \ statfs \ statvfs \ strcasestr \ strdup \ strerror \ strlcat \ strlcpy \ strmode \ strndup \ strnlen \ strnvis \ strptime \ strsignal \ strtonum \ strtoll \ strtoul \ strtoull \ swap32 \ sysconf \ tcgetpgrp \ timegm \ timingsafe_bcmp \ truncate \ unsetenv \ updwtmpx \ utimensat \ user_from_uid \ usleep \ vasprintf \ vsnprintf \ waitpid \ warn \ ]) AC_CHECK_DECLS([bzero, memmem]) dnl Wide character support. AC_CHECK_FUNCS([mblen mbtowc nl_langinfo wcwidth]) TEST_SSH_UTF8=${TEST_SSH_UTF8:=yes} AC_MSG_CHECKING([for utf8 locale support]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include ]], [[ char *loc = setlocale(LC_CTYPE, "en_US.UTF-8"); if (loc != NULL) exit(0); exit(1); ]])], AC_MSG_RESULT(yes), [AC_MSG_RESULT(no) TEST_SSH_UTF8=no], AC_MSG_WARN([cross compiling: assuming yes]) ) AC_LINK_IFELSE( [AC_LANG_PROGRAM( [[ #include ]], [[ return (isblank('a')); ]])], [AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).]) ]) disable_pkcs11= AC_ARG_ENABLE([pkcs11], [ --disable-pkcs11 disable PKCS#11 support code [no]], [ if test "x$enableval" = "xno" ; then disable_pkcs11=1 fi ] ) 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], [ enable_sk_internal=$withval ] ) 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], [ AC_DEFINE([HAVE_GAI_STRERROR]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #include const char *gai_strerror(int); ]], [[ char *str; str = gai_strerror(0); ]])], [ AC_DEFINE([HAVE_CONST_GAI_STRERROR_PROTO], [1], [Define if gai_strerror() returns const char *])], [])]) AC_SEARCH_LIBS([nanosleep], [rt posix4], [AC_DEFINE([HAVE_NANOSLEEP], [1], [Some systems put nanosleep outside of libc])]) AC_SEARCH_LIBS([clock_gettime], [rt], [AC_DEFINE([HAVE_CLOCK_GETTIME], [1], [Have clock_gettime])]) dnl 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])], [], [ #ifdef HAVE_STRING_H # include #endif ]) dnl tcsendbreak might be a macro AC_CHECK_DECL([tcsendbreak], [AC_DEFINE([HAVE_TCSENDBREAK])], [AC_CHECK_FUNCS([tcsendbreak])], [#include ] ) AC_CHECK_DECLS([h_errno], , ,[#include ]) AC_CHECK_DECLS([SHUT_RD, getpeereid], , , [ #include #include #include ]) AC_CHECK_DECLS([O_NONBLOCK], , , [ #include #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_FCNTL_H # include #endif ]) AC_CHECK_DECLS([ftruncate, getentropy], , , [ #include #include ]) AC_CHECK_DECLS([readv, writev], , , [ #include #include #include ]) AC_CHECK_DECLS([MAXSYMLINKS], , , [ #include ]) AC_CHECK_DECLS([offsetof], , , [ #include ]) # extra bits for select(2) AC_CHECK_DECLS([howmany, NFDBITS], [], [], [[ #include #include #ifdef HAVE_SYS_SYSMACROS_H #include #endif #ifdef HAVE_SYS_SELECT_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_UNISTD_H #include #endif ]]) AC_CHECK_TYPES([fd_mask], [], [], [[ #include #include #ifdef HAVE_SYS_SELECT_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_UNISTD_H #include #endif ]]) AC_CHECK_FUNCS([setresuid], [ dnl Some platorms have setresuid that isn't implemented, test for this AC_MSG_CHECKING([if setresuid seems to work]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include ]], [[ errno=0; setresuid(0,0,0); if (errno==ENOSYS) exit(1); else exit(0); ]])], [AC_MSG_RESULT([yes])], [AC_DEFINE([BROKEN_SETRESUID], [1], [Define if your setresuid() is broken]) AC_MSG_RESULT([not implemented])], [AC_MSG_WARN([cross compiling: not checking setresuid])] ) ]) AC_CHECK_FUNCS([setresgid], [ dnl Some platorms have setresgid that isn't implemented, test for this AC_MSG_CHECKING([if setresgid seems to work]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include ]], [[ errno=0; setresgid(0,0,0); if (errno==ENOSYS) exit(1); else exit(0); ]])], [AC_MSG_RESULT([yes])], [AC_DEFINE([BROKEN_SETRESGID], [1], [Define if your setresgid() is broken]) AC_MSG_RESULT([not implemented])], [AC_MSG_WARN([cross compiling: not checking setresuid])] ) ]) AC_MSG_CHECKING([for working fflush(NULL)]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include ]], [[fflush(NULL); exit(0);]])], AC_MSG_RESULT([yes]), [AC_MSG_RESULT([no]) AC_DEFINE([FFLUSH_NULL_BUG], [1], [define if fflush(NULL) does not work])], AC_MSG_WARN([cross compiling: assuming working]) ) dnl Checks for time functions AC_CHECK_FUNCS([gettimeofday time]) dnl Checks for utmp functions AC_CHECK_FUNCS([endutent getutent getutid getutline pututline setutent]) AC_CHECK_FUNCS([utmpname]) dnl Checks for utmpx functions AC_CHECK_FUNCS([endutxent getutxent getutxid getutxline getutxuser pututxline]) AC_CHECK_FUNCS([setutxdb setutxent utmpxname]) dnl Checks for lastlog functions AC_CHECK_FUNCS([getlastlogxbyname]) AC_CHECK_FUNC([daemon], [AC_DEFINE([HAVE_DAEMON], [1], [Define if your libraries define daemon()])], [AC_CHECK_LIB([bsd], [daemon], [LIBS="$LIBS -lbsd"; AC_DEFINE([HAVE_DAEMON])])] ) AC_CHECK_FUNC([getpagesize], [AC_DEFINE([HAVE_GETPAGESIZE], [1], [Define if your libraries define getpagesize()])], [AC_CHECK_LIB([ucb], [getpagesize], [LIBS="$LIBS -lucb"; AC_DEFINE([HAVE_GETPAGESIZE])])] ) # Check for broken snprintf if test "x$ac_cv_func_snprintf" = "xyes" ; then AC_MSG_CHECKING([whether snprintf correctly terminates long strings]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include ]], [[ char b[5]; snprintf(b,5,"123456789"); exit(b[4]!='\0'); ]])], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_DEFINE([BROKEN_SNPRINTF], [1], [Define if your snprintf is busted]) AC_MSG_WARN([****** Your snprintf() function is broken, complain to your vendor]) ], [ AC_MSG_WARN([cross compiling: Assuming working snprintf()]) ] ) fi if test "x$ac_cv_func_snprintf" = "xyes" ; then AC_MSG_CHECKING([whether snprintf understands %zu]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include ]], [[ size_t a = 1, b = 2; char z[128]; snprintf(z, sizeof z, "%zu%zu", a, b); exit(strcmp(z, "12")); ]])], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_DEFINE([BROKEN_SNPRINTF], [1], [snprintf does not understand %zu]) ], [ AC_MSG_WARN([cross compiling: Assuming working snprintf()]) ] ) fi # We depend on vsnprintf returning the right thing on overflow: the # number of characters it tried to create (as per SUSv3) if test "x$ac_cv_func_vsnprintf" = "xyes" ; then AC_MSG_CHECKING([whether vsnprintf returns correct values on overflow]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include int x_snprintf(char *str, size_t count, const char *fmt, ...) { size_t ret; va_list ap; va_start(ap, fmt); ret = vsnprintf(str, count, fmt, ap); va_end(ap); return ret; } ]], [[ char x[1]; if (x_snprintf(x, 1, "%s %d", "hello", 12345) != 11) return 1; if (x_snprintf(NULL, 0, "%s %d", "hello", 12345) != 11) return 1; return 0; ]])], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_DEFINE([BROKEN_SNPRINTF], [1], [Define if your snprintf is busted]) AC_MSG_WARN([****** Your vsnprintf() function is broken, complain to your vendor]) ], [ AC_MSG_WARN([cross compiling: Assuming working vsnprintf()]) ] ) fi # On systems where [v]snprintf is broken, but is declared in stdio, # check that the fmt argument is const char * or just char *. # This is only useful for when BROKEN_SNPRINTF AC_MSG_CHECKING([whether snprintf can declare const char *fmt]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include int snprintf(char *a, size_t b, const char *c, ...) { return 0; } ]], [[ snprintf(0, 0, 0); ]])], [AC_MSG_RESULT([yes]) AC_DEFINE([SNPRINTF_CONST], [const], [Define as const if snprintf() can declare const char *fmt])], [AC_MSG_RESULT([no]) AC_DEFINE([SNPRINTF_CONST], [/* not const */])]) # Check for missing getpeereid (or equiv) support NO_PEERCHECK="" if test "x$ac_cv_func_getpeereid" != "xyes" -a "x$ac_cv_func_getpeerucred" != "xyes"; then AC_MSG_CHECKING([whether system supports SO_PEERCRED getsockopt]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[int i = SO_PEERCRED;]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_SO_PEERCRED], [1], [Have PEERCRED socket option]) ], [AC_MSG_RESULT([no]) NO_PEERCHECK=1 ]) fi dnl 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 #ifdef HAVE_PTY_H # include #endif #include #include #include ]], [[ pid_t pid; int fd, ptyfd, ttyfd, status; pid = fork(); if (pid < 0) { /* failed */ exit(1); } else if (pid > 0) { /* parent */ waitpid(pid, &status, 0); if (WIFEXITED(status)) exit(WEXITSTATUS(status)); else exit(2); } else { /* child */ close(0); close(1); close(2); setsid(); openpty(&ptyfd, &ttyfd, NULL, NULL, NULL); fd = open("/dev/tty", O_RDWR | O_NOCTTY); if (fd >= 0) exit(3); /* Acquired ctty: broken */ else exit(0); /* Did not acquire ctty: OK */ } ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_DEFINE([SSHD_ACQUIRES_CTTY]) ], [ AC_MSG_RESULT([cross-compiling, assuming yes]) ] ) fi if test "x$ac_cv_func_getaddrinfo" = "xyes" && \ test "x$check_for_hpux_broken_getaddrinfo" = "x1"; then AC_MSG_CHECKING([if getaddrinfo seems to work]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include #include #define TEST_PORT "2222" ]], [[ int err, sock; struct addrinfo *gai_ai, *ai, hints; char ntop[NI_MAXHOST], strport[NI_MAXSERV], *name = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai); if (err != 0) { fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err)); exit(1); } for (ai = gai_ai; ai != NULL; ai = ai->ai_next) { if (ai->ai_family != AF_INET6) continue; err = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV); if (err != 0) { if (err == EAI_SYSTEM) perror("getnameinfo EAI_SYSTEM"); else fprintf(stderr, "getnameinfo failed: %s\n", gai_strerror(err)); exit(2); } sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock < 0) perror("socket"); if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { if (errno == EBADF) exit(3); } } exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_DEFINE([BROKEN_GETADDRINFO]) ], [ AC_MSG_RESULT([cross-compiling, assuming yes]) ] ) fi if test "x$ac_cv_func_getaddrinfo" = "xyes" && \ test "x$check_for_aix_broken_getaddrinfo" = "x1"; then AC_MSG_CHECKING([if getaddrinfo seems to work]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include #include #define TEST_PORT "2222" ]], [[ int err, sock; struct addrinfo *gai_ai, *ai, hints; char ntop[NI_MAXHOST], strport[NI_MAXSERV], *name = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; err = getaddrinfo(name, TEST_PORT, &hints, &gai_ai); if (err != 0) { fprintf(stderr, "getaddrinfo failed (%s)", gai_strerror(err)); exit(1); } for (ai = gai_ai; ai != NULL; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue; err = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV); if (ai->ai_family == AF_INET && err != 0) { perror("getnameinfo"); exit(2); } } exit(0); ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([AIX_GETNAMEINFO_HACK], [1], [Define if you have a getaddrinfo that fails for the all-zeros IPv6 address]) ], [ AC_MSG_RESULT([no]) AC_DEFINE([BROKEN_GETADDRINFO]) ], [ AC_MSG_RESULT([cross-compiling, assuming no]) ] ) fi if test "x$ac_cv_func_getaddrinfo" = "xyes"; then AC_CHECK_DECLS(AI_NUMERICSERV, , , [#include #include #include ]) 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 #include ]], [[ exit(0); ]])], [ AC_MSG_RESULT([no]) ], [ AC_MSG_RESULT([yes]) AC_DEFINE([GETSPNAM_CONFLICTING_DEFS], [1], [Conflicting defs for getspnam]) ] ) fi dnl NetBSD added an strnvis and unfortunately made it incompatible with the dnl existing one in OpenBSD and Linux's libbsd (the former having existed dnl for over ten years). Despite this incompatibility being reported during dnl development (see http://gnats.netbsd.org/44977) they still shipped it. dnl Even more unfortunately FreeBSD and later MacOS picked up this incompatible dnl implementation. Try to detect this mess, and assume the only safe option dnl if we're cross compiling. dnl dnl OpenBSD, 2001: strnvis(char *dst, const char *src, size_t dlen, int flag); dnl NetBSD: 2012, strnvis(char *dst, size_t dlen, const char *src, int flag); if test "x$ac_cv_func_strnvis" = "xyes"; then AC_MSG_CHECKING([for working strnvis]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include static void sighandler(int sig) { _exit(1); } ]], [[ char dst[16]; signal(SIGSEGV, sighandler); if (strnvis(dst, "src", 4, 0) && strcmp(dst, "src") == 0) exit(0); exit(1) ]])], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_DEFINE([BROKEN_STRNVIS], [1], [strnvis detected broken])], [AC_MSG_WARN([cross compiling: assuming broken]) AC_DEFINE([BROKEN_STRNVIS], [1], [strnvis assumed broken])] ) fi AC_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( [AC_LANG_PROGRAM([[$ac_includes_default]], [[ getpgrp(); ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([GETPGRP_VOID], [1], [getpgrp takes zero args])], [ AC_MSG_RESULT([no]) AC_DEFINE([GETPGRP_VOID], [0], [getpgrp takes one arg])] ) ]) # Search for OpenSSL saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" openssl_bin_PATH="$PATH" AC_ARG_WITH([ssl-dir], [ --with-ssl-dir=PATH Specify path to OpenSSL installation ], [ if test "x$openssl" = "xno" ; then AC_MSG_ERROR([cannot use --with-ssl-dir when OpenSSL disabled]) fi if test "x$withval" != "xno" ; then case "$withval" in # Relative paths ./*|../*) withval="`pwd`/$withval" esac if test -d "$withval/lib"; then libcrypto_path="${withval}/lib" elif test -d "$withval/lib64"; then libcrypto_path="$withval/lib64" else # Built but not installed libcrypto_path="${withval}" fi if test -n "${rpath_opt}"; then LDFLAGS="-L${libcrypto_path} ${rpath_opt}${libcrypto_path} ${LDFLAGS}" else LDFLAGS="-L${libcrypto_path} ${LDFLAGS}" fi if test -d "$withval/include"; then CPPFLAGS="-I${withval}/include ${CPPFLAGS}" else CPPFLAGS="-I${withval} ${CPPFLAGS}" fi openssl_bin_PATH="${PATH}${PATH_SEPARATOR}${withval}/bin${PATH_SEPARATOR}${withval}/apps" fi ] ) AC_PATH_PROGS([openssl_bin], openssl, [], [$openssl_bin_PATH]) AC_SUBST(OPENSSL_BIN, [${openssl_bin}]) AC_ARG_WITH([openssl-header-check], [ --without-openssl-header-check Disable OpenSSL version consistency check], [ if test "x$withval" = "xno" ; then openssl_check_nonfatal=1 fi ] ) openssl_engine=no AC_ARG_WITH([ssl-engine], [ --with-ssl-engine Enable OpenSSL (hardware) ENGINE support ], [ if test "x$withval" != "xno" ; then if test "x$openssl" = "xno" ; then AC_MSG_ERROR([cannot use --with-ssl-engine when OpenSSL disabled]) fi openssl_engine=yes fi ] ) nocrypto_saved_LIBS="$LIBS" if test "x$openssl" = "xyes" ; then LIBS="-lcrypto $LIBS" CHANNELLIBS="-lcrypto $CHANNELLIBS" AC_TRY_LINK_FUNC([RAND_add], , [AC_MSG_ERROR([*** working libcrypto not found, check config.log])]) AC_CHECK_HEADER([openssl/opensslv.h], , [AC_MSG_ERROR([*** OpenSSL headers missing - please install first or check config.log ***])]) # Determine OpenSSL header version AC_MSG_CHECKING([OpenSSL header version]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #define DATA "conftest.sslincver" ]], [[ FILE *fd; int rc; fd = fopen(DATA,"w"); if(fd == NULL) exit(1); if ((rc = fprintf(fd, "%08lx (%s)\n", (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) < 0) exit(1); exit(0); ]])], [ ssl_header_ver=`cat conftest.sslincver` AC_MSG_RESULT([$ssl_header_ver]) ], [ AC_MSG_RESULT([not found]) AC_MSG_ERROR([OpenSSL version header not found.]) ], [ AC_MSG_WARN([cross compiling: not checking]) ] ) # Determining OpenSSL library version is version dependent. AC_CHECK_FUNCS([OpenSSL_version OpenSSL_version_num]) # Determine OpenSSL library version AC_MSG_CHECKING([OpenSSL library version]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include #define DATA "conftest.ssllibver" ]], [[ FILE *f; /* We need these legacy bits to warn for old libcrypto */ #ifndef OPENSSL_VERSION # define OPENSSL_VERSION SSLEAY_VERSION #endif #ifndef HAVE_OPENSSL_VERSION # define OpenSSL_version SSLeay_version #endif #ifndef HAVE_OPENSSL_VERSION_NUM # define OpenSSL_version_num SSLeay #endif if ((f = fopen(DATA, "w")) == NULL) exit(1); if (fprintf(f, "%08lx (%s)", (unsigned long)OpenSSL_version_num(), OpenSSL_version(OPENSSL_VERSION)) < 0) exit(1); #ifdef LIBRESSL_VERSION_NUMBER if (fprintf(f, " libressl-%08lx", LIBRESSL_VERSION_NUMBER) < 0) exit(1); #endif if (fputc('\n', f) == EOF || fclose(f) == EOF) exit(1); exit(0); ]])], [ sslver=`cat conftest.ssllibver` ssl_showver=`echo "$sslver" | sed 's/ libressl-.*//'` # Check version is supported. case "$sslver" in 100*|10100*) # 1.0.x, 1.1.0x AC_MSG_ERROR([OpenSSL >= 1.1.1 required (have "$ssl_showver")]) ;; 101*) ;; # 1.1.x 200*) # LibreSSL lver=`echo "$sslver" | sed 's/.*libressl-//'` case "$lver" in 2*|300*) # 2.x, 3.0.0 AC_MSG_ERROR([LibreSSL >= 3.1.0 required (have "$ssl_showver")]) ;; *) ;; # Assume all other versions are good. esac ;; 300*) # OpenSSL 3; we use the 1.1x API CPPFLAGS="$CPPFLAGS -DOPENSSL_API_COMPAT=0x10100000L" ;; - 301*|302*) + 301*|302*|303*) # OpenSSL development branch; request 1.1x API CPPFLAGS="$CPPFLAGS -DOPENSSL_API_COMPAT=0x10100000L" ;; *) AC_MSG_ERROR([Unknown/unsupported OpenSSL version ("$ssl_showver")]) ;; esac AC_MSG_RESULT([$ssl_showver]) ], [ AC_MSG_RESULT([not found]) AC_MSG_ERROR([OpenSSL library not found.]) ], [ AC_MSG_WARN([cross compiling: not checking]) ] ) case "$host" in x86_64-*) case "$sslver" in 3000004*) AC_MSG_ERROR([OpenSSL 3.0.4 has a potential RCE in its RSA implementation (CVE-2022-2274)]) ;; esac esac # Sanity check OpenSSL headers AC_MSG_CHECKING([whether OpenSSL's headers match the library]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include ]], [[ exit(OpenSSL_version_num() == OPENSSL_VERSION_NUMBER ? 0 : 1); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) if test "x$openssl_check_nonfatal" = "x"; then AC_MSG_ERROR([Your OpenSSL headers do not match your library. Check config.log for details. If you are sure your installation is consistent, you can disable the check by running "./configure --without-openssl-header-check". Also see contrib/findssl.sh for help identifying header/library mismatches. ]) else AC_MSG_WARN([Your OpenSSL headers do not match your library. Check config.log for details. Also see contrib/findssl.sh for help identifying header/library mismatches.]) fi ], [ AC_MSG_WARN([cross compiling: not checking]) ] ) AC_MSG_CHECKING([if programs using OpenSSL functions will link]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include ]], [[ ERR_load_crypto_strings(); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) LIBS="$LIBS -ldl" AC_MSG_CHECKING([if programs using OpenSSL need -ldl]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include ]], [[ ERR_load_crypto_strings(); ]])], [ AC_MSG_RESULT([yes]) CHANNELLIBS="$CHANNELLIBS -ldl" ], [ AC_MSG_RESULT([no]) ] ) ] ) AC_CHECK_FUNCS([ \ BN_is_prime_ex \ DES_crypt \ DSA_generate_parameters_ex \ EVP_DigestFinal_ex \ EVP_DigestInit_ex \ EVP_MD_CTX_cleanup \ EVP_MD_CTX_copy_ex \ EVP_MD_CTX_init \ HMAC_CTX_init \ RSA_generate_key_ex \ RSA_get_default_method \ ]) # OpenSSL_add_all_algorithms may be a macro. AC_CHECK_FUNC(OpenSSL_add_all_algorithms, AC_DEFINE(HAVE_OPENSSL_ADD_ALL_ALGORITHMS, 1, [as a function]), AC_CHECK_DECL(OpenSSL_add_all_algorithms, AC_DEFINE(HAVE_OPENSSL_ADD_ALL_ALGORITHMS, 1, [as a macro]), , [[#include ]] ) ) # LibreSSL/OpenSSL API differences AC_CHECK_FUNCS([ \ 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 \ ]) if test "x$openssl_engine" = "xyes" ; then AC_MSG_CHECKING([for OpenSSL ENGINE support]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ ENGINE_load_builtin_engines(); ENGINE_register_all_complete(); ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([USE_OPENSSL_ENGINE], [1], [Enable OpenSSL engine support]) ], [ AC_MSG_ERROR([OpenSSL ENGINE support not found]) ]) fi # Check for OpenSSL without EVP_aes_{192,256}_cbc AC_MSG_CHECKING([whether OpenSSL has crippled AES support]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include ]], [[ exit(EVP_aes_192_cbc() == NULL || EVP_aes_256_cbc() == NULL); ]])], [ AC_MSG_RESULT([no]) ], [ AC_MSG_RESULT([yes]) AC_DEFINE([OPENSSL_LOBOTOMISED_AES], [1], [libcrypto is missing AES 192 and 256 bit functions]) ] ) AC_MSG_CHECKING([if EVP_DigestUpdate returns an int]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include ]], [[ if(EVP_DigestUpdate(NULL, NULL,0)) exit(0); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_DEFINE([OPENSSL_EVP_DIGESTUPDATE_VOID], [1], [Define if EVP_DigestUpdate returns void]) ] ) # Check for various EVP support in OpenSSL AC_CHECK_FUNCS([EVP_sha256 EVP_sha384 EVP_sha512 EVP_chacha20]) # Check complete ECC support in OpenSSL AC_MSG_CHECKING([whether OpenSSL has NID_X9_62_prime256v1]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include #include ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); const EVP_MD *m = EVP_sha256(); /* We need this too */ ]])], [ AC_MSG_RESULT([yes]) enable_nistp256=1 ], [ AC_MSG_RESULT([no]) ] ) AC_MSG_CHECKING([whether OpenSSL has NID_secp384r1]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include #include ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp384r1); const EVP_MD *m = EVP_sha384(); /* We need this too */ ]])], [ AC_MSG_RESULT([yes]) enable_nistp384=1 ], [ AC_MSG_RESULT([no]) ] ) AC_MSG_CHECKING([whether OpenSSL has NID_secp521r1]) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include #include ]], [[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1); const EVP_MD *m = EVP_sha512(); /* We need this too */ ]])], [ AC_MSG_RESULT([yes]) AC_MSG_CHECKING([if OpenSSL's NID_secp521r1 is functional]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #include #include #include #include ]],[[ EC_KEY *e = EC_KEY_new_by_curve_name(NID_secp521r1); const EVP_MD *m = EVP_sha512(); /* We need this too */ exit(e == NULL || m == NULL); ]])], [ AC_MSG_RESULT([yes]) enable_nistp521=1 ], [ AC_MSG_RESULT([no]) ], [ AC_MSG_WARN([cross-compiling: assuming yes]) enable_nistp521=1 ] )], AC_MSG_RESULT([no]) ) if test x$enable_nistp256 = x1 || test x$enable_nistp384 = x1 || \ test x$enable_nistp521 = x1; then AC_DEFINE(OPENSSL_HAS_ECC, [1], [OpenSSL has ECC]) AC_CHECK_FUNCS([EC_KEY_METHOD_new]) openssl_ecc=yes else openssl_ecc=no fi if test x$enable_nistp256 = x1; then AC_DEFINE([OPENSSL_HAS_NISTP256], [1], [libcrypto has NID_X9_62_prime256v1]) else unsupported_algorithms="$unsupported_algorithms \ ecdsa-sha2-nistp256 \ ecdh-sha2-nistp256 \ ecdsa-sha2-nistp256-cert-v01@openssh.com" fi if test x$enable_nistp384 = x1; then AC_DEFINE([OPENSSL_HAS_NISTP384], [1], [libcrypto has NID_secp384r1]) else unsupported_algorithms="$unsupported_algorithms \ ecdsa-sha2-nistp384 \ ecdh-sha2-nistp384 \ ecdsa-sha2-nistp384-cert-v01@openssh.com" fi if test x$enable_nistp521 = x1; then AC_DEFINE([OPENSSL_HAS_NISTP521], [1], [libcrypto has NID_secp521r1]) else unsupported_algorithms="$unsupported_algorithms \ ecdh-sha2-nistp521 \ ecdsa-sha2-nistp521 \ ecdsa-sha2-nistp521-cert-v01@openssh.com" fi + + # Check libcrypto ED25519 support + AC_CHECK_FUNCS([EVP_PKEY_get_raw_public_key]) + AC_CHECK_FUNCS([EVP_PKEY_get_raw_private_key]) + AC_MSG_CHECKING([whether OpenSSL has ED25519 support]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ + #include + #include + ]], [[ + unsigned char buf[64]; + memset(buf, 0, sizeof(buf)); + exit(EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, + buf, sizeof(buf)) == NULL); + ]])], + [ + AC_MSG_RESULT([yes]) + AC_DEFINE([OPENSSL_HAS_ED25519], [1], + [libcrypto has ed25519 support]) + ], + [ + AC_MSG_RESULT([no]) + ] + ) 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" 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" != "xno" ; then 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="-lprivatefido2 -lprivatecbor" fi OTHERLIBS=`echo $LIBFIDO2 | sed 's/-lfido2//'` fido2_error= AC_CHECK_LIB([privatefido2], [fido_init], [ ], [ fido2_error="missing/unusable libfido2" ], [ $OTHERLIBS ] ) AC_CHECK_HEADER([fido.h], [], [ fido2_error="missing fido.h from libfido2" ]) AC_CHECK_HEADER([fido/credman.h], [], [ fido2_error="missing fido/credman.h from libfido2" ], [ #include ] ) AC_MSG_CHECKING([for usable libfido2 installation]) if test ! -z "$fido2_error" ; then AC_MSG_RESULT([$fido2_error]) if test "x$enable_sk_internal" = "xyes" ; then AC_MSG_ERROR([No usable libfido2 library/headers found]) fi LIBFIDO2="" else AC_MSG_RESULT([yes]) AC_SUBST([LIBFIDO2]) AC_DEFINE([ENABLE_SK_INTERNAL], [], [Enable for built-in U2F/FIDO support]) enable_sk="built-in" saved_LIBS="$LIBS" LIBS="$LIBFIDO2 $LIBS" AC_CHECK_FUNCS([ \ fido_assert_set_clientdata \ fido_cred_prot \ fido_cred_set_prot \ fido_cred_set_clientdata \ fido_dev_get_touch_begin \ fido_dev_get_touch_status \ fido_dev_supports_cred_prot \ fido_dev_is_winhello \ ]) LIBS="$saved_LIBS" fi fi AC_CHECK_FUNCS([ \ arc4random \ arc4random_buf \ arc4random_stir \ arc4random_uniform \ ]) ### Configure cryptographic random number support # Check whether OpenSSL seeds itself if test "x$openssl" = "xyes" ; then AC_MSG_CHECKING([whether OpenSSL's PRNG is internally seeded]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include ]], [[ exit(RAND_status() == 1 ? 0 : 1); ]])], [ OPENSSL_SEEDS_ITSELF=yes AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ], [ AC_MSG_WARN([cross compiling: assuming yes]) # This is safe, since we will fatal() at runtime if # OpenSSL is not seeded correctly. OPENSSL_SEEDS_ITSELF=yes ] ) fi # PRNGD TCP socket AC_ARG_WITH([prngd-port], [ --with-prngd-port=PORT read entropy from PRNGD/EGD TCP localhost:PORT], [ case "$withval" in no) withval="" ;; [[0-9]]*) ;; *) AC_MSG_ERROR([You must specify a numeric port number for --with-prngd-port]) ;; esac if test ! -z "$withval" ; then PRNGD_PORT="$withval" AC_DEFINE_UNQUOTED([PRNGD_PORT], [$PRNGD_PORT], [Port number of PRNGD/EGD random number socket]) fi ] ) # PRNGD Unix domain socket AC_ARG_WITH([prngd-socket], [ --with-prngd-socket=FILE read entropy from PRNGD/EGD socket FILE (default=/var/run/egd-pool)], [ case "$withval" in yes) withval="/var/run/egd-pool" ;; no) withval="" ;; /*) ;; *) AC_MSG_ERROR([You must specify an absolute path to the entropy socket]) ;; esac if test ! -z "$withval" ; then if test ! -z "$PRNGD_PORT" ; then AC_MSG_ERROR([You may not specify both a PRNGD/EGD port and socket]) fi if test ! -r "$withval" ; then AC_MSG_WARN([Entropy socket is not readable]) fi PRNGD_SOCKET="$withval" AC_DEFINE_UNQUOTED([PRNGD_SOCKET], ["$PRNGD_SOCKET"], [Location of PRNGD/EGD random number socket]) fi ], [ # Check for existing socket only if we don't have a random device already if test "x$OPENSSL_SEEDS_ITSELF" != "xyes" ; then AC_MSG_CHECKING([for PRNGD/EGD socket]) # Insert other locations here for sock in /var/run/egd-pool /dev/egd-pool /etc/entropy; do if test -r $sock && $TEST_MINUS_S_SH -c "test -S $sock -o -p $sock" ; then PRNGD_SOCKET="$sock" AC_DEFINE_UNQUOTED([PRNGD_SOCKET], ["$PRNGD_SOCKET"]) break; fi done if test ! -z "$PRNGD_SOCKET" ; then AC_MSG_RESULT([$PRNGD_SOCKET]) else AC_MSG_RESULT([not found]) fi fi ] ) # Which randomness source do we use? if test ! -z "$PRNGD_PORT" ; then RAND_MSG="PRNGd port $PRNGD_PORT" elif test ! -z "$PRNGD_SOCKET" ; then RAND_MSG="PRNGd socket $PRNGD_SOCKET" elif test ! -z "$OPENSSL_SEEDS_ITSELF" ; then AC_DEFINE([OPENSSL_PRNG_ONLY], [1], [Define if you want the OpenSSL internally seeded PRNG only]) RAND_MSG="OpenSSL internal ONLY" elif test "x$openssl" = "xno" ; then AC_MSG_WARN([OpenSSH will use /dev/urandom as a source of random numbers. It will fail if this device is not supported or accessible]) else AC_MSG_ERROR([OpenSSH has no source of random numbers. Please configure OpenSSL with an entropy source or re-run configure using one of the --with-prngd-port or --with-prngd-socket options]) fi LIBS="$nocrypto_saved_LIBS" saved_LIBS="$LIBS" AC_CHECK_LIB([iaf], [ia_openinfo], [ LIBS="$LIBS -liaf" AC_CHECK_FUNCS([set_id], [SSHDLIBS="$SSHDLIBS -liaf" AC_DEFINE([HAVE_LIBIAF], [1], [Define if system has libiaf that supports set_id]) ]) ]) LIBS="$saved_LIBS" # Check for crypt() in libcrypt. If we have it, we only need it for sshd. saved_LIBS="$LIBS" AC_CHECK_LIB([crypt], [crypt], [ LIBS="-lcrypt $LIBS" SSHDLIBS="-lcrypt $SSHDLIBS" ]) AC_CHECK_FUNCS([crypt]) LIBS="$saved_LIBS" # Check for PAM libs PAM_MSG="no" AC_ARG_WITH([pam], [ --with-pam Enable PAM support ], [ if test "x$withval" != "xno" ; then if test "x$ac_cv_header_security_pam_appl_h" != "xyes" && \ test "x$ac_cv_header_pam_pam_appl_h" != "xyes" ; then AC_MSG_ERROR([PAM headers not found]) fi saved_LIBS="$LIBS" AC_CHECK_LIB([dl], [dlopen], , ) AC_CHECK_LIB([pam], [pam_set_item], , [AC_MSG_ERROR([*** libpam missing])]) AC_CHECK_FUNCS([pam_getenvlist]) AC_CHECK_FUNCS([pam_putenv]) LIBS="$saved_LIBS" PAM_MSG="yes" SSHDLIBS="$SSHDLIBS -lpam" AC_DEFINE([USE_PAM], [1], [Define if you want to enable PAM support]) if test $ac_cv_lib_dl_dlopen = yes; then case "$LIBS" in *-ldl*) # libdl already in LIBS ;; *) SSHDLIBS="$SSHDLIBS -ldl" ;; esac fi fi ] ) AC_ARG_WITH([pam-service], [ --with-pam-service=name Specify PAM service name ], [ if test "x$withval" != "xno" && \ test "x$withval" != "xyes" ; then AC_DEFINE_UNQUOTED([SSHD_PAM_SERVICE], ["$withval"], [sshd PAM service name]) fi ] ) # Check for older PAM if test "x$PAM_MSG" = "xyes" ; then # Check PAM strerror arguments (old PAM) AC_MSG_CHECKING([whether pam_strerror takes only one argument]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #if defined(HAVE_SECURITY_PAM_APPL_H) #include #elif defined (HAVE_PAM_PAM_APPL_H) #include #endif ]], [[ (void)pam_strerror((pam_handle_t *)NULL, -1); ]])], [AC_MSG_RESULT([no])], [ AC_DEFINE([HAVE_OLD_PAM], [1], [Define if you have an old version of PAM which takes only one argument to pam_strerror]) AC_MSG_RESULT([yes]) PAM_MSG="yes (old library)" ]) fi case "$host" in *-*-cygwin*) SSH_PRIVSEP_USER=CYGWIN_SSH_PRIVSEP_USER ;; *) SSH_PRIVSEP_USER=sshd ;; esac AC_ARG_WITH([privsep-user], [ --with-privsep-user=user Specify non-privileged user for privilege separation], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then SSH_PRIVSEP_USER=$withval fi ] ) if test "x$SSH_PRIVSEP_USER" = "xCYGWIN_SSH_PRIVSEP_USER" ; then AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], [CYGWIN_SSH_PRIVSEP_USER], [Cygwin function to fetch non-privileged user for privilege separation]) else AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], ["$SSH_PRIVSEP_USER"], [non-privileged user for privilege separation]) fi AC_SUBST([SSH_PRIVSEP_USER]) if test "x$have_linux_no_new_privs" = "x1" ; then AC_CHECK_DECL([SECCOMP_MODE_FILTER], [have_seccomp_filter=1], , [ #include #include ]) fi if test "x$have_seccomp_filter" = "x1" ; then AC_MSG_CHECKING([kernel for seccomp_filter support]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include #include #include #include #include ]], [[ int i = $seccomp_audit_arch; errno = 0; prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL, 0, 0); exit(errno == EFAULT ? 0 : 1); ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) # Disable seccomp filter as a target have_seccomp_filter=0 ] ) fi AC_CHECK_MEMBERS([struct pollfd.fd], [], [], [[ #include #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_SYS_POLL_H #include #endif ]]) AC_CHECK_TYPES([nfds_t], , , [ #include #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_SYS_POLL_H #include #endif ]) # Decide which sandbox style to use sandbox_arg="" AC_ARG_WITH([sandbox], [ --with-sandbox=style Specify privilege separation sandbox (no, capsicum, darwin, rlimit, seccomp_filter, systrace, pledge)], [ if test "x$withval" = "xyes" ; then sandbox_arg="" else sandbox_arg="$withval" fi ] ) if test "x$sandbox_arg" != "xno"; then # POSIX specifies that poll() "shall fail with EINVAL if the nfds argument # is greater than OPEN_MAX". On some platforms that includes implementions # of select in userspace on top of poll() so check both work with rlimit # NOFILES so check that both work before enabling the rlimit sandbox. AC_MSG_CHECKING([if select and/or poll works with descriptor rlimit]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #ifdef HAVE_SYS_TIME_H # include #endif #include #ifdef HAVE_SYS_SELECT_H # include #endif #ifdef HAVE_POLL_H # include #elif HAVE_SYS_POLL_H # include #endif #include #include #include ]],[[ struct rlimit rl_zero; int fd, r; fd_set fds; struct timeval tv; #ifdef HAVE_POLL struct pollfd pfd; #endif fd = open("/dev/null", O_RDONLY); FD_ZERO(&fds); FD_SET(fd, &fds); rl_zero.rlim_cur = rl_zero.rlim_max = 0; setrlimit(RLIMIT_FSIZE, &rl_zero); setrlimit(RLIMIT_NOFILE, &rl_zero); tv.tv_sec = 1; tv.tv_usec = 0; r = select(fd+1, &fds, NULL, NULL, &tv); if (r == -1) exit(1); #ifdef HAVE_POLL pfd.fd = fd; pfd.events = POLLIN; r = poll(&pfd, 1, 1); if (r == -1) exit(2); #endif exit(0); ]])], [AC_MSG_RESULT([yes]) select_works_with_rlimit=yes], [AC_MSG_RESULT([no]) select_works_with_rlimit=no], [AC_MSG_WARN([cross compiling: assuming no]) select_works_with_rlimit=no] ) AC_MSG_CHECKING([if setrlimit(RLIMIT_NOFILE,{0,0}) works]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include ]],[[ struct rlimit rl_zero; int r; rl_zero.rlim_cur = rl_zero.rlim_max = 0; r = setrlimit(RLIMIT_NOFILE, &rl_zero); exit (r == -1 ? 1 : 0); ]])], [AC_MSG_RESULT([yes]) rlimit_nofile_zero_works=yes], [AC_MSG_RESULT([no]) rlimit_nofile_zero_works=no], [AC_MSG_WARN([cross compiling: assuming yes]) rlimit_nofile_zero_works=yes] ) AC_MSG_CHECKING([if setrlimit RLIMIT_FSIZE works]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include ]],[[ struct rlimit rl_zero; rl_zero.rlim_cur = rl_zero.rlim_max = 0; exit(setrlimit(RLIMIT_FSIZE, &rl_zero) != 0); ]])], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_DEFINE(SANDBOX_SKIP_RLIMIT_FSIZE, 1, [setrlimit RLIMIT_FSIZE works])], [AC_MSG_WARN([cross compiling: assuming yes])] ) fi if test "x$sandbox_arg" = "xpledge" || \ ( test -z "$sandbox_arg" && test "x$ac_cv_func_pledge" = "xyes" ) ; then test "x$ac_cv_func_pledge" != "xyes" && \ AC_MSG_ERROR([pledge sandbox requires pledge(2) support]) SANDBOX_STYLE="pledge" AC_DEFINE([SANDBOX_PLEDGE], [1], [Sandbox using pledge(2)]) elif test "x$sandbox_arg" = "xsystrace" || \ ( test -z "$sandbox_arg" && test "x$have_systr_policy_kill" = "x1" ) ; then test "x$have_systr_policy_kill" != "x1" && \ AC_MSG_ERROR([systrace sandbox requires systrace headers and SYSTR_POLICY_KILL support]) SANDBOX_STYLE="systrace" AC_DEFINE([SANDBOX_SYSTRACE], [1], [Sandbox using systrace(4)]) elif test "x$sandbox_arg" = "xdarwin" || \ ( test -z "$sandbox_arg" && test "x$ac_cv_func_sandbox_init" = "xyes" && \ test "x$ac_cv_header_sandbox_h" = "xyes") ; then test "x$ac_cv_func_sandbox_init" != "xyes" -o \ "x$ac_cv_header_sandbox_h" != "xyes" && \ AC_MSG_ERROR([Darwin seatbelt sandbox requires sandbox.h and sandbox_init function]) SANDBOX_STYLE="darwin" AC_DEFINE([SANDBOX_DARWIN], [1], [Sandbox using Darwin sandbox_init(3)]) elif test "x$sandbox_arg" = "xseccomp_filter" || \ ( test -z "$sandbox_arg" && \ test "x$have_seccomp_filter" = "x1" && \ test "x$ac_cv_header_elf_h" = "xyes" && \ test "x$ac_cv_header_linux_audit_h" = "xyes" && \ test "x$ac_cv_header_linux_filter_h" = "xyes" && \ test "x$seccomp_audit_arch" != "x" && \ test "x$have_linux_no_new_privs" = "x1" && \ test "x$ac_cv_func_prctl" = "xyes" ) ; then test "x$seccomp_audit_arch" = "x" && \ AC_MSG_ERROR([seccomp_filter sandbox not supported on $host]) test "x$have_linux_no_new_privs" != "x1" && \ AC_MSG_ERROR([seccomp_filter sandbox requires PR_SET_NO_NEW_PRIVS]) test "x$have_seccomp_filter" != "x1" && \ AC_MSG_ERROR([seccomp_filter sandbox requires seccomp headers]) test "x$ac_cv_func_prctl" != "xyes" && \ AC_MSG_ERROR([seccomp_filter sandbox requires prctl function]) SANDBOX_STYLE="seccomp_filter" AC_DEFINE([SANDBOX_SECCOMP_FILTER], [1], [Sandbox using seccomp filter]) elif test "x$sandbox_arg" = "xcapsicum" || \ ( test -z "$sandbox_arg" && \ test "x$disable_capsicum" != "xyes" && \ test "x$ac_cv_header_sys_capsicum_h" = "xyes" && \ test "x$ac_cv_func_cap_rights_limit" = "xyes") ; then test "x$ac_cv_header_sys_capsicum_h" != "xyes" && \ AC_MSG_ERROR([capsicum sandbox requires sys/capsicum.h header]) test "x$ac_cv_func_cap_rights_limit" != "xyes" && \ AC_MSG_ERROR([capsicum sandbox requires cap_rights_limit function]) SANDBOX_STYLE="capsicum" AC_DEFINE([SANDBOX_CAPSICUM], [1], [Sandbox using capsicum]) elif test "x$sandbox_arg" = "xrlimit" || \ ( test -z "$sandbox_arg" && test "x$ac_cv_func_setrlimit" = "xyes" && \ test "x$select_works_with_rlimit" = "xyes" && \ test "x$rlimit_nofile_zero_works" = "xyes" ) ; then test "x$ac_cv_func_setrlimit" != "xyes" && \ AC_MSG_ERROR([rlimit sandbox requires setrlimit function]) test "x$select_works_with_rlimit" != "xyes" && \ AC_MSG_ERROR([rlimit sandbox requires select to work with rlimit]) SANDBOX_STYLE="rlimit" AC_DEFINE([SANDBOX_RLIMIT], [1], [Sandbox using setrlimit(2)]) elif test "x$sandbox_arg" = "xsolaris" || \ ( test -z "$sandbox_arg" && test "x$SOLARIS_PRIVS" = "xyes" ) ; then SANDBOX_STYLE="solaris" AC_DEFINE([SANDBOX_SOLARIS], [1], [Sandbox using Solaris/Illumos privileges]) elif test -z "$sandbox_arg" || test "x$sandbox_arg" = "xno" || \ test "x$sandbox_arg" = "xnone" || test "x$sandbox_arg" = "xnull" ; then SANDBOX_STYLE="none" AC_DEFINE([SANDBOX_NULL], [1], [no privsep sandboxing]) else AC_MSG_ERROR([unsupported --with-sandbox]) fi # Cheap hack to ensure NEWS-OS libraries are arranged right. if test ! -z "$SONY" ; then LIBS="$LIBS -liberty"; fi # Check for long long datatypes AC_CHECK_TYPES([long long, unsigned long long, long double]) # Check datatype sizes AC_CHECK_SIZEOF([short int]) AC_CHECK_SIZEOF([int]) AC_CHECK_SIZEOF([long int]) AC_CHECK_SIZEOF([long long int]) AC_CHECK_SIZEOF([time_t], [], [[ #include #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_TIME_H # include #endif ]] ) # Sanity check long long for some platforms (AIX) if test "x$ac_cv_sizeof_long_long_int" = "x4" ; then ac_cv_sizeof_long_long_int=0 fi # compute LLONG_MIN and LLONG_MAX if we don't know them. if test -z "$have_llong_max" && 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__ #endif #define __USE_ISOC99 #include #define DATA "conftest.llminmax" #define my_abs(a) ((a) < 0 ? ((a) * -1) : (a)) /* * printf in libc on some platforms (eg old Tru64) does not understand %lld so * we do this the hard way. */ static int fprint_ll(FILE *f, long long n) { unsigned int i; int l[sizeof(long long) * 8]; if (n < 0) if (fprintf(f, "-") < 0) return -1; for (i = 0; n != 0; i++) { l[i] = my_abs(n % 10); n /= 10; } do { if (fprintf(f, "%d", l[--i]) < 0) return -1; } while (i != 0); if (fprintf(f, " ") < 0) return -1; return 0; } ]], [[ FILE *f; long long i, llmin, llmax = 0; if((f = fopen(DATA,"w")) == NULL) exit(1); #if defined(LLONG_MIN) && defined(LLONG_MAX) fprintf(stderr, "Using system header for LLONG_MIN and LLONG_MAX\n"); llmin = LLONG_MIN; llmax = LLONG_MAX; #else fprintf(stderr, "Calculating LLONG_MIN and LLONG_MAX\n"); /* This will work on one's complement and two's complement */ for (i = 1; i > llmax; i <<= 1, i++) llmax = i; llmin = llmax + 1LL; /* wrap */ #endif /* Sanity check */ if (llmin + 1 < llmin || llmin - 1 < llmin || llmax + 1 > llmax || llmax - 1 > llmax || llmin == llmax || llmin == 0 || llmax == 0 || llmax < LONG_MAX || llmin > LONG_MIN) { fprintf(f, "unknown unknown\n"); exit(2); } if (fprint_ll(f, llmin) < 0) exit(3); if (fprint_ll(f, llmax) < 0) exit(4); if (fclose(f) < 0) exit(5); exit(0); ]])], [ llong_min=`$AWK '{print $1}' conftest.llminmax` llong_max=`$AWK '{print $2}' conftest.llminmax` AC_MSG_RESULT([$llong_max]) AC_DEFINE_UNQUOTED([LLONG_MAX], [${llong_max}LL], [max value of long long calculated by configure]) AC_MSG_CHECKING([for min value of long long]) AC_MSG_RESULT([$llong_min]) AC_DEFINE_UNQUOTED([LLONG_MIN], [${llong_min}LL], [min value of long long calculated by configure]) ], [ AC_MSG_RESULT([not found]) ], [ AC_MSG_WARN([cross compiling: not checking]) ] ) fi 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, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ u_int a; a = 1;]])], [ ac_cv_have_u_int="yes" ], [ ac_cv_have_u_int="no" ]) ]) if test "x$ac_cv_have_u_int" = "xyes" ; then AC_DEFINE([HAVE_U_INT], [1], [define if you have u_int data type]) have_u_int=1 fi AC_CACHE_CHECK([for intXX_t types], ac_cv_have_intxx_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ int8_t a; int16_t b; int32_t c; a = b = c = 1;]])], [ ac_cv_have_intxx_t="yes" ], [ ac_cv_have_intxx_t="no" ]) ]) if test "x$ac_cv_have_intxx_t" = "xyes" ; then AC_DEFINE([HAVE_INTXX_T], [1], [define if you have intxx_t data type]) have_intxx_t=1 fi if (test -z "$have_intxx_t" && \ test "x$ac_cv_header_stdint_h" = "xyes") then AC_MSG_CHECKING([for intXX_t types in stdint.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ int8_t a; int16_t b; int32_t c; a = b = c = 1;]])], [ AC_DEFINE([HAVE_INTXX_T]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) fi AC_CACHE_CHECK([for int64_t type], ac_cv_have_int64_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #ifdef HAVE_STDINT_H # include #endif #include #ifdef HAVE_SYS_BITYPES_H # include #endif ]], [[ int64_t a; a = 1; ]])], [ ac_cv_have_int64_t="yes" ], [ ac_cv_have_int64_t="no" ]) ]) if test "x$ac_cv_have_int64_t" = "xyes" ; then AC_DEFINE([HAVE_INT64_T], [1], [define if you have int64_t data type]) fi AC_CACHE_CHECK([for u_intXX_t types], ac_cv_have_u_intxx_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;]])], [ ac_cv_have_u_intxx_t="yes" ], [ ac_cv_have_u_intxx_t="no" ]) ]) if test "x$ac_cv_have_u_intxx_t" = "xyes" ; then AC_DEFINE([HAVE_U_INTXX_T], [1], [define if you have u_intxx_t data type]) have_u_intxx_t=1 fi if test -z "$have_u_intxx_t" ; then AC_MSG_CHECKING([for u_intXX_t types in sys/socket.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ u_int8_t a; u_int16_t b; u_int32_t c; a = b = c = 1;]])], [ AC_DEFINE([HAVE_U_INTXX_T]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) fi AC_CACHE_CHECK([for u_int64_t types], ac_cv_have_u_int64_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ u_int64_t a; a = 1;]])], [ ac_cv_have_u_int64_t="yes" ], [ ac_cv_have_u_int64_t="no" ]) ]) if test "x$ac_cv_have_u_int64_t" = "xyes" ; then AC_DEFINE([HAVE_U_INT64_T], [1], [define if you have u_int64_t data type]) have_u_int64_t=1 fi if (test -z "$have_u_int64_t" && \ test "x$ac_cv_header_sys_bitypes_h" = "xyes") then AC_MSG_CHECKING([for u_int64_t type in sys/bitypes.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ u_int64_t a; a = 1]])], [ AC_DEFINE([HAVE_U_INT64_T]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) fi if test -z "$have_u_intxx_t" ; then AC_CACHE_CHECK([for uintXX_t types], ac_cv_have_uintxx_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ uint8_t a; uint16_t b; uint32_t c; a = b = c = 1; ]])], [ ac_cv_have_uintxx_t="yes" ], [ ac_cv_have_uintxx_t="no" ]) ]) if test "x$ac_cv_have_uintxx_t" = "xyes" ; then AC_DEFINE([HAVE_UINTXX_T], [1], [define if you have uintxx_t data type]) fi fi if (test -z "$have_uintxx_t" && \ test "x$ac_cv_header_stdint_h" = "xyes") then AC_MSG_CHECKING([for uintXX_t types in stdint.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ uint8_t a; uint16_t b; uint32_t c; a = b = c = 1;]])], [ AC_DEFINE([HAVE_UINTXX_T]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) fi if (test -z "$have_uintxx_t" && \ test "x$ac_cv_header_inttypes_h" = "xyes") then AC_MSG_CHECKING([for uintXX_t types in inttypes.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ uint8_t a; uint16_t b; uint32_t c; a = b = c = 1;]])], [ AC_DEFINE([HAVE_UINTXX_T]) AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) ]) fi if (test -z "$have_u_intxx_t" || test -z "$have_intxx_t" && \ test "x$ac_cv_header_sys_bitypes_h" = "xyes") then AC_MSG_CHECKING([for intXX_t and u_intXX_t types in sys/bitypes.h]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ int8_t a; int16_t b; int32_t c; u_int8_t e; u_int16_t f; u_int32_t g; a = b = c = e = f = g = 1; ]])], [ AC_DEFINE([HAVE_U_INTXX_T]) AC_DEFINE([HAVE_INTXX_T]) AC_MSG_RESULT([yes]) ], [AC_MSG_RESULT([no]) ]) fi AC_CACHE_CHECK([for u_char], ac_cv_have_u_char, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ u_char foo; foo = 125; ]])], [ ac_cv_have_u_char="yes" ], [ ac_cv_have_u_char="no" ]) ]) if test "x$ac_cv_have_u_char" = "xyes" ; then AC_DEFINE([HAVE_U_CHAR], [1], [define if you have u_char data type]) fi AC_CHECK_TYPES([intmax_t, uintmax_t], , , [ #include #ifdef HAVE_STDINT_H # include #endif ]) TYPE_SOCKLEN_T AC_CHECK_TYPES([sig_atomic_t, sighandler_t], , , [#include ]) AC_CHECK_TYPES([fsblkcnt_t, fsfilcnt_t], , , [ #include #ifdef HAVE_SYS_BITYPES_H #include #endif #ifdef HAVE_SYS_STATFS_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif ]) AC_CHECK_MEMBERS([struct statfs.f_files, struct statfs.f_flags], [], [], [[ #include #include #ifdef HAVE_SYS_BITYPES_H #include #endif #ifdef HAVE_SYS_STATFS_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif #ifdef HAVE_SYS_VFS_H #include #endif #ifdef HAVE_SYS_MOUNT_H #include #endif ]]) AC_CHECK_TYPES([in_addr_t, in_port_t], , , [#include #include ]) AC_CACHE_CHECK([for size_t], ac_cv_have_size_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ size_t foo; foo = 1235; ]])], [ ac_cv_have_size_t="yes" ], [ ac_cv_have_size_t="no" ]) ]) if test "x$ac_cv_have_size_t" = "xyes" ; then AC_DEFINE([HAVE_SIZE_T], [1], [define if you have size_t data type]) fi AC_CACHE_CHECK([for ssize_t], ac_cv_have_ssize_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ ssize_t foo; foo = 1235; ]])], [ ac_cv_have_ssize_t="yes" ], [ ac_cv_have_ssize_t="no" ]) ]) if test "x$ac_cv_have_ssize_t" = "xyes" ; then AC_DEFINE([HAVE_SSIZE_T], [1], [define if you have ssize_t data type]) fi AC_CACHE_CHECK([for clock_t], ac_cv_have_clock_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ clock_t foo; foo = 1235; ]])], [ ac_cv_have_clock_t="yes" ], [ ac_cv_have_clock_t="no" ]) ]) if test "x$ac_cv_have_clock_t" = "xyes" ; then AC_DEFINE([HAVE_CLOCK_T], [1], [define if you have clock_t data type]) fi AC_CACHE_CHECK([for sa_family_t], ac_cv_have_sa_family_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ sa_family_t foo; foo = 1235; ]])], [ ac_cv_have_sa_family_t="yes" ], [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #include ]], [[ sa_family_t foo; foo = 1235; ]])], [ ac_cv_have_sa_family_t="yes" ], [ ac_cv_have_sa_family_t="no" ] ) ]) ]) if test "x$ac_cv_have_sa_family_t" = "xyes" ; then AC_DEFINE([HAVE_SA_FAMILY_T], [1], [define if you have sa_family_t data type]) fi AC_CACHE_CHECK([for pid_t], ac_cv_have_pid_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ pid_t foo; foo = 1235; ]])], [ ac_cv_have_pid_t="yes" ], [ ac_cv_have_pid_t="no" ]) ]) if test "x$ac_cv_have_pid_t" = "xyes" ; then AC_DEFINE([HAVE_PID_T], [1], [define if you have pid_t data type]) fi AC_CACHE_CHECK([for mode_t], ac_cv_have_mode_t, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ mode_t foo; foo = 1235; ]])], [ ac_cv_have_mode_t="yes" ], [ ac_cv_have_mode_t="no" ]) ]) if test "x$ac_cv_have_mode_t" = "xyes" ; then AC_DEFINE([HAVE_MODE_T], [1], [define if you have mode_t data type]) fi AC_CACHE_CHECK([for struct sockaddr_storage], ac_cv_have_struct_sockaddr_storage, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ struct sockaddr_storage s; ]])], [ ac_cv_have_struct_sockaddr_storage="yes" ], [ ac_cv_have_struct_sockaddr_storage="no" ]) ]) if test "x$ac_cv_have_struct_sockaddr_storage" = "xyes" ; then AC_DEFINE([HAVE_STRUCT_SOCKADDR_STORAGE], [1], [define if you have struct sockaddr_storage data type]) fi AC_CACHE_CHECK([for struct sockaddr_in6], ac_cv_have_struct_sockaddr_in6, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ struct sockaddr_in6 s; s.sin6_family = 0; ]])], [ ac_cv_have_struct_sockaddr_in6="yes" ], [ ac_cv_have_struct_sockaddr_in6="no" ]) ]) if test "x$ac_cv_have_struct_sockaddr_in6" = "xyes" ; then AC_DEFINE([HAVE_STRUCT_SOCKADDR_IN6], [1], [define if you have struct sockaddr_in6 data type]) fi AC_CACHE_CHECK([for struct in6_addr], ac_cv_have_struct_in6_addr, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ struct in6_addr s; s.s6_addr[0] = 0; ]])], [ ac_cv_have_struct_in6_addr="yes" ], [ ac_cv_have_struct_in6_addr="no" ]) ]) if test "x$ac_cv_have_struct_in6_addr" = "xyes" ; then AC_DEFINE([HAVE_STRUCT_IN6_ADDR], [1], [define if you have struct in6_addr data type]) dnl Now check for sin6_scope_id AC_CHECK_MEMBERS([struct sockaddr_in6.sin6_scope_id], , , [ #ifdef HAVE_SYS_TYPES_H #include #endif #include ]) fi AC_CACHE_CHECK([for struct addrinfo], ac_cv_have_struct_addrinfo, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #include ]], [[ struct addrinfo s; s.ai_flags = AI_PASSIVE; ]])], [ ac_cv_have_struct_addrinfo="yes" ], [ ac_cv_have_struct_addrinfo="no" ]) ]) if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then AC_DEFINE([HAVE_STRUCT_ADDRINFO], [1], [define if you have struct addrinfo data type]) fi AC_CACHE_CHECK([for struct timeval], ac_cv_have_struct_timeval, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ struct timeval tv; tv.tv_sec = 1;]])], [ ac_cv_have_struct_timeval="yes" ], [ ac_cv_have_struct_timeval="no" ]) ]) if test "x$ac_cv_have_struct_timeval" = "xyes" ; then AC_DEFINE([HAVE_STRUCT_TIMEVAL], [1], [define if you have struct timeval]) have_struct_timeval=1 fi AC_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" && \ test "x$ac_cv_sizeof_long_int" != "x8" && \ test "x$ac_cv_sizeof_long_long_int" = "x0" ; then echo "OpenSSH requires int64_t support. Contact your vendor or install" echo "an alternative compiler (I.E., GCC) before continuing." echo "" exit 1; else dnl test snprintf (broken on SCO w/gcc) AC_RUN_IFELSE( [AC_LANG_SOURCE([[ #include #include #include #ifdef HAVE_SNPRINTF int main(void) { char buf[50]; char expected_out[50]; int mazsize = 50 ; #if (SIZEOF_LONG_INT == 8) long int num = 0x7fffffffffffffff; #else long long num = 0x7fffffffffffffffll; #endif strcpy(expected_out, "9223372036854775807"); snprintf(buf, mazsize, "%lld", num); if(strcmp(buf, expected_out) != 0) exit(1); exit(0); } #else int main(void) { exit(0); } #endif ]])], [ true ], [ AC_DEFINE([BROKEN_SNPRINTF]) ], AC_MSG_WARN([cross compiling: Assuming working snprintf()]) ) fi dnl Checks for structure members OSSH_CHECK_HEADER_FOR_FIELD([ut_host], [utmp.h], [HAVE_HOST_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_host], [utmpx.h], [HAVE_HOST_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([syslen], [utmpx.h], [HAVE_SYSLEN_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([ut_pid], [utmp.h], [HAVE_PID_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_type], [utmp.h], [HAVE_TYPE_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_type], [utmpx.h], [HAVE_TYPE_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([ut_tv], [utmp.h], [HAVE_TV_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_id], [utmp.h], [HAVE_ID_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_id], [utmpx.h], [HAVE_ID_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([ut_addr], [utmp.h], [HAVE_ADDR_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_addr], [utmpx.h], [HAVE_ADDR_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([ut_addr_v6], [utmp.h], [HAVE_ADDR_V6_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_addr_v6], [utmpx.h], [HAVE_ADDR_V6_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([ut_exit], [utmp.h], [HAVE_EXIT_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_time], [utmp.h], [HAVE_TIME_IN_UTMP]) OSSH_CHECK_HEADER_FOR_FIELD([ut_time], [utmpx.h], [HAVE_TIME_IN_UTMPX]) OSSH_CHECK_HEADER_FOR_FIELD([ut_tv], [utmpx.h], [HAVE_TV_IN_UTMPX]) 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]) AC_CHECK_MEMBERS([struct stat.st_mtime]) AC_CHECK_MEMBERS([struct passwd.pw_gecos, struct passwd.pw_class, struct passwd.pw_change, struct passwd.pw_expire], [], [], [[ #include #include ]]) AC_CHECK_MEMBER([struct __res_state.retrans], [], [AC_DEFINE([__res_state], [state], [Define if we don't have struct __res_state in resolv.h])], [[ #include #if HAVE_SYS_TYPES_H # include #endif #include #include #include ]]) AC_CHECK_MEMBER([struct sockaddr_in.sin_len], [AC_DEFINE([SOCK_HAS_LEN], [1], [sockaddr_in has sin_len])], [], [AC_LANG_SOURCE([[ #include #include #include ]])] ) AC_CACHE_CHECK([for ss_family field in struct sockaddr_storage], ac_cv_have_ss_family_in_struct_ss, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ struct sockaddr_storage s; s.ss_family = 1; ]])], [ ac_cv_have_ss_family_in_struct_ss="yes" ], [ ac_cv_have_ss_family_in_struct_ss="no" ]) ]) if test "x$ac_cv_have_ss_family_in_struct_ss" = "xyes" ; then AC_DEFINE([HAVE_SS_FAMILY_IN_SS], [1], [Fields in struct sockaddr_storage]) fi AC_CACHE_CHECK([for __ss_family field in struct sockaddr_storage], ac_cv_have___ss_family_in_struct_ss, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ struct sockaddr_storage s; s.__ss_family = 1; ]])], [ ac_cv_have___ss_family_in_struct_ss="yes" ], [ ac_cv_have___ss_family_in_struct_ss="no" ]) ]) if test "x$ac_cv_have___ss_family_in_struct_ss" = "xyes" ; then AC_DEFINE([HAVE___SS_FAMILY_IN_SS], [1], [Fields in struct sockaddr_storage]) fi dnl make sure we're using the real structure members and not defines AC_CACHE_CHECK([for msg_accrights field in struct msghdr], ac_cv_have_accrights_in_msghdr, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #include #include ]], [[ #ifdef msg_accrights #error "msg_accrights is a macro" exit(1); #endif struct msghdr m; m.msg_accrights = 0; exit(0); ]])], [ ac_cv_have_accrights_in_msghdr="yes" ], [ ac_cv_have_accrights_in_msghdr="no" ] ) ]) if test "x$ac_cv_have_accrights_in_msghdr" = "xyes" ; then AC_DEFINE([HAVE_ACCRIGHTS_IN_MSGHDR], [1], [Define if your system uses access rights style file descriptor passing]) fi AC_MSG_CHECKING([if struct statvfs.f_fsid is integral type]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_SYS_MOUNT_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif ]], [[ struct statvfs s; s.f_fsid = 0; ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_MSG_CHECKING([if fsid_t has member val]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ fsid_t t; t.val[0] = 0; ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([FSID_HAS_VAL], [1], [fsid_t has member val]) ], [ AC_MSG_RESULT([no]) ]) AC_MSG_CHECKING([if f_fsid has member __val]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ fsid_t t; t.__val[0] = 0; ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([FSID_HAS___VAL], [1], [fsid_t has member __val]) ], [ AC_MSG_RESULT([no]) ]) ]) AC_CACHE_CHECK([for msg_control field in struct msghdr], ac_cv_have_control_in_msghdr, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #include #include ]], [[ #ifdef msg_control #error "msg_control is a macro" exit(1); #endif struct msghdr m; m.msg_control = 0; exit(0); ]])], [ ac_cv_have_control_in_msghdr="yes" ], [ ac_cv_have_control_in_msghdr="no" ] ) ]) if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then AC_DEFINE([HAVE_CONTROL_IN_MSGHDR], [1], [Define if your system uses ancillary data style file descriptor passing]) fi AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ extern char *__progname; printf("%s", __progname); ]])], [ ac_cv_libc_defines___progname="yes" ], [ ac_cv_libc_defines___progname="no" ]) ]) if test "x$ac_cv_libc_defines___progname" = "xyes" ; then AC_DEFINE([HAVE___PROGNAME], [1], [Define if libc defines __progname]) fi AC_CACHE_CHECK([whether $CC implements __FUNCTION__], ac_cv_cc_implements___FUNCTION__, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ printf("%s", __FUNCTION__); ]])], [ ac_cv_cc_implements___FUNCTION__="yes" ], [ ac_cv_cc_implements___FUNCTION__="no" ]) ]) if test "x$ac_cv_cc_implements___FUNCTION__" = "xyes" ; then AC_DEFINE([HAVE___FUNCTION__], [1], [Define if compiler implements __FUNCTION__]) fi AC_CACHE_CHECK([whether $CC implements __func__], ac_cv_cc_implements___func__, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ printf("%s", __func__); ]])], [ ac_cv_cc_implements___func__="yes" ], [ ac_cv_cc_implements___func__="no" ]) ]) if test "x$ac_cv_cc_implements___func__" = "xyes" ; then AC_DEFINE([HAVE___func__], [1], [Define if compiler implements __func__]) fi AC_CACHE_CHECK([whether va_copy exists], ac_cv_have_va_copy, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include va_list x,y; ]], [[ va_copy(x,y); ]])], [ ac_cv_have_va_copy="yes" ], [ ac_cv_have_va_copy="no" ]) ]) if test "x$ac_cv_have_va_copy" = "xyes" ; then AC_DEFINE([HAVE_VA_COPY], [1], [Define if va_copy exists]) fi AC_CACHE_CHECK([whether __va_copy exists], ac_cv_have___va_copy, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include va_list x,y; ]], [[ __va_copy(x,y); ]])], [ ac_cv_have___va_copy="yes" ], [ ac_cv_have___va_copy="no" ]) ]) if test "x$ac_cv_have___va_copy" = "xyes" ; then AC_DEFINE([HAVE___VA_COPY], [1], [Define if __va_copy exists]) fi AC_CACHE_CHECK([whether getopt has optreset support], ac_cv_have_getopt_optreset, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ extern int optreset; optreset = 0; ]])], [ ac_cv_have_getopt_optreset="yes" ], [ ac_cv_have_getopt_optreset="no" ]) ]) if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then AC_DEFINE([HAVE_GETOPT_OPTRESET], [1], [Define if your getopt(3) defines and uses optreset]) fi AC_CACHE_CHECK([if libc defines sys_errlist], ac_cv_libc_defines_sys_errlist, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #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" ]) ]) if test "x$ac_cv_libc_defines_sys_errlist" = "xyes" ; then AC_DEFINE([HAVE_SYS_ERRLIST], [1], [Define if your system defines sys_errlist[]]) fi AC_CACHE_CHECK([if libc defines sys_nerr], ac_cv_libc_defines_sys_nerr, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ extern int sys_nerr; printf("%i", sys_nerr);]])], [ ac_cv_libc_defines_sys_nerr="yes" ], [ ac_cv_libc_defines_sys_nerr="no" ]) ]) if test "x$ac_cv_libc_defines_sys_nerr" = "xyes" ; then AC_DEFINE([HAVE_SYS_NERR], [1], [Define if your system defines sys_nerr]) fi # Check libraries needed by DNS fingerprint support AC_SEARCH_LIBS([getrrsetbyname], [resolv], [AC_DEFINE([HAVE_GETRRSETBYNAME], [1], [Define if getrrsetbyname() exists])], [ # Needed by our getrrsetbyname() AC_SEARCH_LIBS([res_query], [resolv]) AC_SEARCH_LIBS([dn_expand], [resolv]) AC_MSG_CHECKING([if res_query will link]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include #include #include #include ]], [[ res_query (0, 0, 0, 0, 0); ]])], AC_MSG_RESULT([yes]), [AC_MSG_RESULT([no]) saved_LIBS="$LIBS" LIBS="$LIBS -lresolv" AC_MSG_CHECKING([for res_query in -lresolv]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include #include #include #include ]], [[ res_query (0, 0, 0, 0, 0); ]])], [AC_MSG_RESULT([yes])], [LIBS="$saved_LIBS" AC_MSG_RESULT([no])]) ]) AC_CHECK_FUNCS([_getshort _getlong]) AC_CHECK_DECLS([_getshort, _getlong], , , [#include #include ]) AC_CHECK_MEMBER([HEADER.ad], [AC_DEFINE([HAVE_HEADER_AD], [1], [Define if HEADER.ad exists in arpa/nameser.h])], , [#include ]) ]) AC_MSG_CHECKING([if struct __res_state _res is an extern]) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #if HAVE_SYS_TYPES_H # include #endif #include #include #include extern struct __res_state _res; ]], [[ struct __res_state *volatile p = &_res; /* force resolution of _res */ return 0; ]],)], [AC_MSG_RESULT([yes]) AC_DEFINE([HAVE__RES_EXTERN], [1], [Define if you have struct __res_state _res as an extern]) ], [ AC_MSG_RESULT([no]) ] ) # Check whether user wants SELinux support SELINUX_MSG="no" LIBSELINUX="" AC_ARG_WITH([selinux], [ --with-selinux Enable SELinux support], [ if test "x$withval" != "xno" ; then save_LIBS="$LIBS" AC_DEFINE([WITH_SELINUX], [1], [Define if you want SELinux support.]) SELINUX_MSG="yes" AC_CHECK_HEADER([selinux/selinux.h], , AC_MSG_ERROR([SELinux support requires selinux.h header])) AC_CHECK_LIB([selinux], [setexeccon], [ LIBSELINUX="-lselinux" LIBS="$LIBS -lselinux" ], AC_MSG_ERROR([SELinux support requires libselinux library])) AC_CHECK_FUNCS([getseuserbyname get_default_context_with_level]) LIBS="$save_LIBS $LIBSELINUX" fi ] ) AC_SUBST([SSHDLIBS]) # Check whether user wants Kerberos 5 support KRB5_MSG="no" AC_ARG_WITH([kerberos5], [ --with-kerberos5=PATH Enable Kerberos 5 support], [ if test "x$withval" != "xno" ; then if test "x$withval" = "xyes" ; then KRB5ROOT="/usr/local" else KRB5ROOT=${withval} fi AC_DEFINE([KRB5], [1], [Define if you want Kerberos 5 support]) KRB5_MSG="yes" use_pkgconfig_for_krb5= if test "x$PKGCONFIG" != "xno"; then AC_MSG_CHECKING([if $PKGCONFIG knows about kerberos5]) if "$PKGCONFIG" krb5; then AC_MSG_RESULT([yes]) use_pkgconfig_for_krb5=yes else AC_MSG_RESULT([no]) fi fi if test "x$use_pkgconfig_for_krb5" = "xyes"; then K5CFLAGS=`$PKGCONFIG --cflags krb5` K5LIBS=`$PKGCONFIG --libs krb5` CPPFLAGS="$CPPFLAGS $K5CFLAGS" AC_MSG_CHECKING([for gssapi support]) if "$PKGCONFIG" krb5-gssapi; then AC_MSG_RESULT([yes]) AC_DEFINE([GSSAPI], [1], [Define this if you want GSSAPI support in the version 2 protocol]) GSSCFLAGS="`$PKGCONFIG --cflags krb5-gssapi`" GSSLIBS="`$PKGCONFIG --libs krb5-gssapi`" CPPFLAGS="$CPPFLAGS $GSSCFLAGS" else AC_MSG_RESULT([no]) fi AC_MSG_CHECKING([whether we are using Heimdal]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ char *tmp = heimdal_version; ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([HEIMDAL], [1], [Define this if you are using the Heimdal version of Kerberos V5]) ], [AC_MSG_RESULT([no]) ]) else AC_PATH_TOOL([KRB5CONF], [krb5-config], [$KRB5ROOT/bin/krb5-config], [$KRB5ROOT/bin:$PATH]) if test -x $KRB5CONF ; then K5CFLAGS="`$KRB5CONF --cflags`" K5LIBS="`$KRB5CONF --libs`" CPPFLAGS="$CPPFLAGS $K5CFLAGS" AC_MSG_CHECKING([for gssapi support]) if $KRB5CONF | grep gssapi >/dev/null ; then AC_MSG_RESULT([yes]) AC_DEFINE([GSSAPI], [1], [Define this if you want GSSAPI support in the version 2 protocol]) GSSCFLAGS="`$KRB5CONF --cflags gssapi`" GSSLIBS="`$KRB5CONF --libs gssapi`" CPPFLAGS="$CPPFLAGS $GSSCFLAGS" else AC_MSG_RESULT([no]) fi AC_MSG_CHECKING([whether we are using Heimdal]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ char *tmp = heimdal_version; ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([HEIMDAL], [1], [Define this if you are using the Heimdal version of Kerberos V5]) ], [AC_MSG_RESULT([no]) ]) else CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include" LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib" AC_MSG_CHECKING([whether we are using Heimdal]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ char *tmp = heimdal_version; ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE([HEIMDAL]) K5LIBS="-lkrb5" K5LIBS="$K5LIBS -lcom_err -lasn1" AC_CHECK_LIB([roken], [net_write], [K5LIBS="$K5LIBS -lroken"]) AC_CHECK_LIB([des], [des_cbc_encrypt], [K5LIBS="$K5LIBS -ldes"]) ], [ AC_MSG_RESULT([no]) K5LIBS="-lkrb5 -lk5crypto -lcom_err" ]) AC_SEARCH_LIBS([dn_expand], [resolv]) AC_CHECK_LIB([gssapi_krb5], [gss_init_sec_context], [ AC_DEFINE([GSSAPI]) GSSLIBS="-lgssapi_krb5" ], [ AC_CHECK_LIB([gssapi], [gss_init_sec_context], [ AC_DEFINE([GSSAPI]) GSSLIBS="-lgssapi" ], [ AC_CHECK_LIB([gss], [gss_init_sec_context], [ AC_DEFINE([GSSAPI]) GSSLIBS="-lgss" ], AC_MSG_WARN([Cannot find any suitable gss-api library - build may fail])) ]) ]) AC_CHECK_HEADER([gssapi.h], , [ unset ac_cv_header_gssapi_h CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi" AC_CHECK_HEADERS([gssapi.h], , AC_MSG_WARN([Cannot find any suitable gss-api header - build may fail]) ) ] ) oldCPP="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi" AC_CHECK_HEADER([gssapi_krb5.h], , [ CPPFLAGS="$oldCPP" ]) fi fi if test -n "${rpath_opt}" ; then LDFLAGS="$LDFLAGS ${rpath_opt}${KRB5ROOT}/lib" fi if test ! -z "$blibpath" ; then blibpath="$blibpath:${KRB5ROOT}/lib" fi AC_CHECK_HEADERS([gssapi.h gssapi/gssapi.h]) AC_CHECK_HEADERS([gssapi_krb5.h gssapi/gssapi_krb5.h]) AC_CHECK_HEADERS([gssapi_generic.h gssapi/gssapi_generic.h]) AC_SEARCH_LIBS([k_hasafs], [kafs], [AC_DEFINE([USE_AFS], [1], [Define this if you want to use libkafs' AFS support])]) AC_CHECK_DECLS([GSS_C_NT_HOSTBASED_SERVICE], [], [], [[ #ifdef HAVE_GSSAPI_H # include #elif defined(HAVE_GSSAPI_GSSAPI_H) # include #endif #ifdef HAVE_GSSAPI_GENERIC_H # include #elif defined(HAVE_GSSAPI_GSSAPI_GENERIC_H) # include #endif ]]) saved_LIBS="$LIBS" LIBS="$LIBS $K5LIBS" AC_CHECK_FUNCS([krb5_cc_new_unique krb5_get_error_message krb5_free_error_message]) LIBS="$saved_LIBS" fi ] ) AC_SUBST([GSSLIBS]) AC_SUBST([K5LIBS]) AC_SUBST([CHANNELLIBS]) # Looking for programs, paths and files PRIVSEP_PATH=/var/empty AC_ARG_WITH([privsep-path], [ --with-privsep-path=xxx Path for privilege separation chroot (default=/var/empty)], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then PRIVSEP_PATH=$withval fi ] ) AC_SUBST([PRIVSEP_PATH]) AC_ARG_WITH([xauth], [ --with-xauth=PATH Specify path to xauth program ], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then xauth_path=$withval fi ], [ TestPath="$PATH" TestPath="${TestPath}${PATH_SEPARATOR}/usr/X/bin" TestPath="${TestPath}${PATH_SEPARATOR}/usr/bin/X11" TestPath="${TestPath}${PATH_SEPARATOR}/usr/X11R6/bin" TestPath="${TestPath}${PATH_SEPARATOR}/usr/openwin/bin" AC_PATH_PROG([xauth_path], [xauth], , [$TestPath]) if (test ! -z "$xauth_path" && test -x "/usr/openwin/bin/xauth") ; then xauth_path="/usr/openwin/bin/xauth" fi ] ) STRIP_OPT=-s AC_ARG_ENABLE([strip], [ --disable-strip Disable calling strip(1) on install], [ if test "x$enableval" = "xno" ; then STRIP_OPT= fi ] ) AC_SUBST([STRIP_OPT]) if test -z "$xauth_path" ; then XAUTH_PATH="undefined" AC_SUBST([XAUTH_PATH]) else AC_DEFINE_UNQUOTED([XAUTH_PATH], ["$xauth_path"], [Define if xauth is found in your path]) XAUTH_PATH=$xauth_path AC_SUBST([XAUTH_PATH]) fi dnl # --with-maildir=/path/to/mail gets top priority. dnl # if maildir is set in the platform case statement above we use that. dnl # Otherwise we run a program to get the dir from system headers. dnl # We first look for _PATH_MAILDIR then MAILDIR then _PATH_MAIL dnl # If we find _PATH_MAILDIR we do nothing because that is what dnl # session.c expects anyway. Otherwise we set to the value found dnl # stripping any trailing slash. If for some strage reason our program dnl # does not find what it needs, we default to /var/spool/mail. # Check for mail directory AC_ARG_WITH([maildir], [ --with-maildir=/path/to/mail Specify your system mail directory], [ if test "X$withval" != X && test "x$withval" != xno && \ test "x${withval}" != xyes; then AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["$withval"], [Set this to your mail directory if you do not have _PATH_MAILDIR]) fi ],[ if test "X$maildir" != "X"; then AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["$maildir"]) else AC_MSG_CHECKING([Discovering system mail directory]) AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #include #include #include #ifdef HAVE_PATHS_H #include #endif #ifdef HAVE_MAILLOCK_H #include #endif #define DATA "conftest.maildir" ]], [[ FILE *fd; int rc; fd = fopen(DATA,"w"); if(fd == NULL) exit(1); #if defined (_PATH_MAILDIR) if ((rc = fprintf(fd ,"_PATH_MAILDIR:%s\n", _PATH_MAILDIR)) <0) exit(1); #elif defined (MAILDIR) if ((rc = fprintf(fd ,"MAILDIR:%s\n", MAILDIR)) <0) exit(1); #elif defined (_PATH_MAIL) if ((rc = fprintf(fd ,"_PATH_MAIL:%s\n", _PATH_MAIL)) <0) exit(1); #else exit (2); #endif exit(0); ]])], [ maildir_what=`awk -F: '{print $1}' conftest.maildir` maildir=`awk -F: '{print $2}' conftest.maildir \ | sed 's|/$||'` AC_MSG_RESULT([Using: $maildir from $maildir_what]) if test "x$maildir_what" != "x_PATH_MAILDIR"; then AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["$maildir"]) fi ], [ if test "X$ac_status" = "X2";then # our test program didn't find it. Default to /var/spool/mail AC_MSG_RESULT([Using: default value of /var/spool/mail]) AC_DEFINE_UNQUOTED([MAIL_DIRECTORY], ["/var/spool/mail"]) else AC_MSG_RESULT([*** not found ***]) fi ], [ AC_MSG_WARN([cross compiling: use --with-maildir=/path/to/mail]) ] ) fi ] ) # maildir if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes"; then AC_MSG_WARN([cross compiling: Disabling /dev/ptmx test]) disable_ptmx_check=yes fi if test -z "$no_dev_ptmx" ; then if test "x$disable_ptmx_check" != "xyes" ; then AC_CHECK_FILE(["/dev/ptmx"], [ AC_DEFINE_UNQUOTED([HAVE_DEV_PTMX], [1], [Define if you have /dev/ptmx]) have_dev_ptmx=1 ] ) fi fi if test ! -z "$cross_compiling" && test "x$cross_compiling" != "xyes"; then AC_CHECK_FILE(["/dev/ptc"], [ AC_DEFINE_UNQUOTED([HAVE_DEV_PTS_AND_PTC], [1], [Define if you have /dev/ptc]) have_dev_ptc=1 ] ) else AC_MSG_WARN([cross compiling: Disabling /dev/ptc test]) fi # Options from here on. Some of these are preset by platform above AC_ARG_WITH([mantype], [ --with-mantype=man|cat|doc Set man page type], [ case "$withval" in man|cat|doc) MANTYPE=$withval ;; *) AC_MSG_ERROR([invalid man type: $withval]) ;; esac ] ) if test -z "$MANTYPE"; then if ${MANDOC} ${srcdir}/ssh.1 >/dev/null 2>&1; then MANTYPE=doc elif ${NROFF} -mdoc ${srcdir}/ssh.1 >/dev/null 2>&1; then MANTYPE=doc elif ${NROFF} -man ${srcdir}/ssh.1 >/dev/null 2>&1; then MANTYPE=man else MANTYPE=cat fi fi AC_SUBST([MANTYPE]) if test "$MANTYPE" = "doc"; then mansubdir=man; else mansubdir=$MANTYPE; fi AC_SUBST([mansubdir]) # Whether to disable shadow password support AC_ARG_WITH([shadow], [ --without-shadow Disable shadow password support], [ if test "x$withval" = "xno" ; then AC_DEFINE([DISABLE_SHADOW]) disable_shadow=yes fi ] ) if test -z "$disable_shadow" ; then AC_MSG_CHECKING([if the systems has expire shadow information]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include struct spwd sp; ]], [[ sp.sp_expire = sp.sp_lstchg = sp.sp_inact = 0; ]])], [ sp_expire_available=yes ], [ ]) if test "x$sp_expire_available" = "xyes" ; then AC_MSG_RESULT([yes]) AC_DEFINE([HAS_SHADOW_EXPIRE], [1], [Define if you want to use shadow password expire field]) else AC_MSG_RESULT([no]) fi fi # Use ip address instead of hostname in $DISPLAY if test ! -z "$IPADDR_IN_DISPLAY" ; then DISPLAY_HACK_MSG="yes" AC_DEFINE([IPADDR_IN_DISPLAY], [1], [Define if you need to use IP address instead of hostname in $DISPLAY]) else DISPLAY_HACK_MSG="no" AC_ARG_WITH([ipaddr-display], [ --with-ipaddr-display Use ip address instead of hostname in $DISPLAY], [ if test "x$withval" != "xno" ; then AC_DEFINE([IPADDR_IN_DISPLAY]) DISPLAY_HACK_MSG="yes" fi ] ) fi # check for /etc/default/login and use it if present. AC_ARG_ENABLE([etc-default-login], [ --disable-etc-default-login Disable using PATH from /etc/default/login [no]], [ if test "x$enableval" = "xno"; then AC_MSG_NOTICE([/etc/default/login handling disabled]) etc_default_login=no else etc_default_login=yes fi ], [ if test ! -z "$cross_compiling" && test "x$cross_compiling" = "xyes"; then AC_MSG_WARN([cross compiling: not checking /etc/default/login]) etc_default_login=no else etc_default_login=yes fi ] ) if test "x$etc_default_login" != "xno"; then AC_CHECK_FILE(["/etc/default/login"], [ external_path_file=/etc/default/login ]) if test "x$external_path_file" = "x/etc/default/login"; then AC_DEFINE([HAVE_ETC_DEFAULT_LOGIN], [1], [Define if your system has /etc/default/login]) fi fi dnl BSD systems use /etc/login.conf so --with-default-path= has no effect if test $ac_cv_func_login_getcapbool = "yes" && \ test $ac_cv_header_login_cap_h = "yes" ; then external_path_file=/etc/login.conf fi # Whether to mess with the default path SERVER_PATH_MSG="(default)" AC_ARG_WITH([default-path], [ --with-default-path= Specify default $PATH environment for server], [ if test "x$external_path_file" = "x/etc/login.conf" ; then AC_MSG_WARN([ --with-default-path=PATH has no effect on this system. Edit /etc/login.conf instead.]) elif test "x$withval" != "xno" ; then if test ! -z "$external_path_file" ; then AC_MSG_WARN([ --with-default-path=PATH will only be used if PATH is not defined in $external_path_file .]) fi user_path="$withval" SERVER_PATH_MSG="$withval" fi ], [ if test "x$external_path_file" = "x/etc/login.conf" ; then AC_MSG_WARN([Make sure the path to scp is in /etc/login.conf]) else if test ! -z "$external_path_file" ; then AC_MSG_WARN([ If PATH is defined in $external_path_file, ensure the path to scp is included, otherwise scp will not work.]) fi AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ /* find out what STDPATH is */ #include #include #ifdef HAVE_PATHS_H # include #endif #ifndef _PATH_STDPATH # ifdef _PATH_USERPATH /* Irix */ # define _PATH_STDPATH _PATH_USERPATH # else # define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin" # endif #endif #include #include #include #define DATA "conftest.stdpath" ]], [[ FILE *fd; int rc; fd = fopen(DATA,"w"); if(fd == NULL) exit(1); if ((rc = fprintf(fd,"%s", _PATH_STDPATH)) < 0) exit(1); exit(0); ]])], [ user_path=`cat conftest.stdpath` ], [ user_path="/usr/bin:/bin:/usr/sbin:/sbin" ], [ user_path="/usr/bin:/bin:/usr/sbin:/sbin" ] ) # make sure $bindir is in USER_PATH so scp will work t_bindir="${bindir}" while echo "${t_bindir}" | egrep '\$\{|NONE/' >/dev/null 2>&1; do t_bindir=`eval echo ${t_bindir}` case $t_bindir in NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$prefix~"` ;; esac case $t_bindir in NONE/*) t_bindir=`echo $t_bindir | sed "s~NONE~$ac_default_prefix~"` ;; esac done echo $user_path | grep ":$t_bindir" > /dev/null 2>&1 if test $? -ne 0 ; then echo $user_path | grep "^$t_bindir" > /dev/null 2>&1 if test $? -ne 0 ; then user_path=$user_path:$t_bindir AC_MSG_RESULT([Adding $t_bindir to USER_PATH so scp will work]) fi fi fi ] ) if test "x$external_path_file" != "x/etc/login.conf" ; then AC_DEFINE_UNQUOTED([USER_PATH], ["$user_path"], [Specify default $PATH]) AC_SUBST([user_path]) fi # Set superuser path separately to user path AC_ARG_WITH([superuser-path], [ --with-superuser-path= Specify different path for super-user], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then AC_DEFINE_UNQUOTED([SUPERUSER_PATH], ["$withval"], [Define if you want a different $PATH for the superuser]) superuser_path=$withval fi ] ) AC_MSG_CHECKING([if we need to convert IPv4 in IPv6-mapped addresses]) IPV4_IN6_HACK_MSG="no" AC_ARG_WITH(4in6, [ --with-4in6 Check for and convert IPv4 in IPv6 mapped addresses], [ if test "x$withval" != "xno" ; then AC_MSG_RESULT([yes]) AC_DEFINE([IPV4_IN_IPV6], [1], [Detect IPv4 in IPv6 mapped addresses and treat as IPv4]) IPV4_IN6_HACK_MSG="yes" else AC_MSG_RESULT([no]) fi ], [ if test "x$inet6_default_4in6" = "xyes"; then AC_MSG_RESULT([yes (default)]) AC_DEFINE([IPV4_IN_IPV6]) IPV4_IN6_HACK_MSG="yes" else AC_MSG_RESULT([no (default)]) fi ] ) # Whether to enable BSD auth support BSD_AUTH_MSG=no AC_ARG_WITH([bsd-auth], [ --with-bsd-auth Enable BSD auth support], [ if test "x$withval" != "xno" ; then AC_DEFINE([BSD_AUTH], [1], [Define if you have BSD auth support]) BSD_AUTH_MSG=yes fi ] ) # Where to place sshd.pid piddir=/var/run # make sure the directory exists if test ! -d $piddir ; then piddir=`eval echo ${sysconfdir}` case $piddir in NONE/*) piddir=`echo $piddir | sed "s~NONE~$ac_default_prefix~"` ;; esac fi AC_ARG_WITH([pid-dir], [ --with-pid-dir=PATH Specify location of sshd.pid file], [ if test -n "$withval" && test "x$withval" != "xno" && \ test "x${withval}" != "xyes"; then piddir=$withval if test ! -d $piddir ; then AC_MSG_WARN([** no $piddir directory on this system **]) fi fi ] ) AC_DEFINE_UNQUOTED([_PATH_SSH_PIDDIR], ["$piddir"], [Specify location of ssh.pid]) AC_SUBST([piddir]) dnl allow user to disable some login recording features AC_ARG_ENABLE([lastlog], [ --disable-lastlog disable use of lastlog even if detected [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_LASTLOG]) fi ] ) AC_ARG_ENABLE([utmp], [ --disable-utmp disable use of utmp even if detected [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_UTMP]) fi ] ) AC_ARG_ENABLE([utmpx], [ --disable-utmpx disable use of utmpx even if detected [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_UTMPX], [1], [Define if you don't want to use utmpx]) fi ] ) AC_ARG_ENABLE([wtmp], [ --disable-wtmp disable use of wtmp even if detected [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_WTMP]) fi ] ) AC_ARG_ENABLE([wtmpx], [ --disable-wtmpx disable use of wtmpx even if detected [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_WTMPX], [1], [Define if you don't want to use wtmpx]) fi ] ) AC_ARG_ENABLE([libutil], [ --disable-libutil disable use of libutil (login() etc.) [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_LOGIN]) fi ] ) AC_ARG_ENABLE([pututline], [ --disable-pututline disable use of pututline() etc. ([uw]tmp) [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_PUTUTLINE], [1], [Define if you don't want to use pututline() etc. to write [uw]tmp]) fi ] ) AC_ARG_ENABLE([pututxline], [ --disable-pututxline disable use of pututxline() etc. ([uw]tmpx) [no]], [ if test "x$enableval" = "xno" ; then AC_DEFINE([DISABLE_PUTUTXLINE], [1], [Define if you don't want to use pututxline() etc. to write [uw]tmpx]) fi ] ) AC_ARG_WITH([lastlog], [ --with-lastlog=FILE|DIR specify lastlog location [common locations]], [ if test "x$withval" = "xno" ; then AC_DEFINE([DISABLE_LASTLOG]) elif test -n "$withval" && test "x${withval}" != "xyes"; then conf_lastlog_location=$withval fi ] ) dnl lastlog, [uw]tmpx? detection dnl NOTE: set the paths in the platform section to avoid the dnl need for command-line parameters dnl lastlog and [uw]tmp are subject to a file search if all else fails dnl lastlog detection dnl NOTE: the code itself will detect if lastlog is a directory AC_MSG_CHECKING([if your system defines LASTLOG_FILE]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #ifdef HAVE_LASTLOG_H # include #endif #ifdef HAVE_PATHS_H # include #endif #ifdef HAVE_LOGIN_H # include #endif ]], [[ char *lastlog = LASTLOG_FILE; ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) AC_MSG_CHECKING([if your system defines _PATH_LASTLOG]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #ifdef HAVE_LASTLOG_H # include #endif #ifdef HAVE_PATHS_H # include #endif ]], [[ char *lastlog = _PATH_LASTLOG; ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) system_lastlog_path=no ]) ]) if test -z "$conf_lastlog_location"; then if test x"$system_lastlog_path" = x"no" ; then for f in /var/log/lastlog /usr/adm/lastlog /var/adm/lastlog /etc/security/lastlog ; do if (test -d "$f" || test -f "$f") ; then conf_lastlog_location=$f fi done if test -z "$conf_lastlog_location"; then AC_MSG_WARN([** Cannot find lastlog **]) dnl Don't define DISABLE_LASTLOG - that means we don't try wtmp/wtmpx fi fi fi if test -n "$conf_lastlog_location"; then AC_DEFINE_UNQUOTED([CONF_LASTLOG_FILE], ["$conf_lastlog_location"], [Define if you want to specify the path to your lastlog file]) fi dnl utmp detection AC_MSG_CHECKING([if your system defines UTMP_FILE]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #ifdef HAVE_PATHS_H # include #endif ]], [[ char *utmp = UTMP_FILE; ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) system_utmp_path=no ]) if test -z "$conf_utmp_location"; then if test x"$system_utmp_path" = x"no" ; then for f in /etc/utmp /usr/adm/utmp /var/run/utmp; do if test -f $f ; then conf_utmp_location=$f fi done if test -z "$conf_utmp_location"; then AC_DEFINE([DISABLE_UTMP]) fi fi fi if test -n "$conf_utmp_location"; then AC_DEFINE_UNQUOTED([CONF_UTMP_FILE], ["$conf_utmp_location"], [Define if you want to specify the path to your utmp file]) fi dnl wtmp detection AC_MSG_CHECKING([if your system defines WTMP_FILE]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #ifdef HAVE_PATHS_H # include #endif ]], [[ char *wtmp = WTMP_FILE; ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) system_wtmp_path=no ]) if test -z "$conf_wtmp_location"; then if test x"$system_wtmp_path" = x"no" ; then for f in /usr/adm/wtmp /var/log/wtmp; do if test -f $f ; then conf_wtmp_location=$f fi done if test -z "$conf_wtmp_location"; then AC_DEFINE([DISABLE_WTMP]) fi fi fi if test -n "$conf_wtmp_location"; then AC_DEFINE_UNQUOTED([CONF_WTMP_FILE], ["$conf_wtmp_location"], [Define if you want to specify the path to your wtmp file]) fi dnl wtmpx detection AC_MSG_CHECKING([if your system defines WTMPX_FILE]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include #ifdef HAVE_UTMPX_H #include #endif #ifdef HAVE_PATHS_H # include #endif ]], [[ char *wtmpx = WTMPX_FILE; ]])], [ AC_MSG_RESULT([yes]) ], [ AC_MSG_RESULT([no]) system_wtmpx_path=no ]) if test -z "$conf_wtmpx_location"; then if test x"$system_wtmpx_path" = x"no" ; then AC_DEFINE([DISABLE_WTMPX]) fi else AC_DEFINE_UNQUOTED([CONF_WTMPX_FILE], ["$conf_wtmpx_location"], [Define if you want to specify the path to your wtmpx file]) fi if test ! -z "$blibpath" ; then LDFLAGS="$LDFLAGS $blibflags$blibpath" AC_MSG_WARN([Please check and edit blibpath in LDFLAGS in Makefile]) fi AC_CHECK_MEMBER([struct lastlog.ll_line], [], [ if test x$SKIP_DISABLE_LASTLOG_DEFINE != "xyes" ; then AC_DEFINE([DISABLE_LASTLOG]) fi ], [ #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_UTMP_H #include #endif #ifdef HAVE_UTMPX_H #include #endif #ifdef HAVE_LASTLOG_H #include #endif ]) AC_CHECK_MEMBER([struct utmp.ut_line], [], [ AC_DEFINE([DISABLE_UTMP]) AC_DEFINE([DISABLE_WTMP]) ], [ #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_UTMP_H #include #endif #ifdef HAVE_UTMPX_H #include #endif #ifdef HAVE_LASTLOG_H #include #endif ]) dnl Adding -Werror to CFLAGS early prevents configure tests from running. dnl Add now. CFLAGS="$CFLAGS $werror_flags" if test "x$ac_cv_func_getaddrinfo" != "xyes" ; then TEST_SSH_IPV6=no else TEST_SSH_IPV6=yes fi AC_CHECK_DECL([BROKEN_GETADDRINFO], [TEST_SSH_IPV6=no]) AC_SUBST([TEST_SSH_IPV6], [$TEST_SSH_IPV6]) AC_SUBST([TEST_SSH_UTF8], [$TEST_SSH_UTF8]) AC_SUBST([TEST_MALLOC_OPTIONS], [$TEST_MALLOC_OPTIONS]) AC_SUBST([UNSUPPORTED_ALGORITHMS], [$unsupported_algorithms]) AC_SUBST([DEPEND], [$(cat $srcdir/.depend)]) +# Binaries for interop tests. +AC_PATH_PROG([PLINK], [plink]) +AC_PATH_PROG([PUTTYGEN], [puttygen]) +AC_PATH_PROG([CONCH], [conch]) +AC_PATH_PROG([DROPBEAR], [dropbear]) +AC_PATH_PROG([DBCLIENT], [dbclient]) +AC_PATH_PROG([DROPBEARKEY], [dropbearkey]) +AC_PATH_PROG([DROPBEARCONVERT], [dropbearconvert]) + 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 \ survey.sh]) AC_OUTPUT # Print summary of options # Someone please show me a better way :) A=`eval echo ${prefix}` ; A=`eval echo ${A}` B=`eval echo ${bindir}` ; B=`eval echo ${B}` C=`eval echo ${sbindir}` ; C=`eval echo ${C}` D=`eval echo ${sysconfdir}` ; D=`eval echo ${D}` E=`eval echo ${libexecdir}/ssh-askpass` ; E=`eval echo ${E}` F=`eval echo ${mandir}/${mansubdir}X` ; F=`eval echo ${F}` G=`eval echo ${piddir}` ; G=`eval echo ${G}` H=`eval echo ${PRIVSEP_PATH}` ; H=`eval echo ${H}` I=`eval echo ${user_path}` ; I=`eval echo ${I}` J=`eval echo ${superuser_path}` ; J=`eval echo ${J}` echo "" echo "OpenSSH has been configured with the following options:" echo " User binaries: $B" echo " System binaries: $C" echo " Configuration files: $D" echo " Askpass program: $E" echo " Manual pages: $F" echo " PID file: $G" echo " Privilege separation chroot path: $H" if test "x$external_path_file" = "x/etc/login.conf" ; then echo " At runtime, sshd will use the path defined in $external_path_file" echo " Make sure the path to scp is present, otherwise scp will not work" else echo " sshd default user PATH: $I" if test ! -z "$external_path_file"; then echo " (If PATH is set in $external_path_file it will be used instead. If" echo " used, ensure the path to scp is present, otherwise scp will not work.)" fi fi if test ! -z "$superuser_path" ; then echo " sshd superuser user PATH: $J" fi echo " Manpage format: $MANTYPE" echo " PAM support: $PAM_MSG" echo " OSF SIA support: $SIA_MSG" echo " KerberosV support: $KRB5_MSG" echo " SELinux support: $SELINUX_MSG" echo " TCP Wrappers support: $TCPW_MSG" echo " libedit support: $LIBEDIT_MSG" echo " libldns support: $LDNS_MSG" echo " Solaris process contract support: $SPC_MSG" echo " Solaris project support: $SP_MSG" echo " Solaris privilege support: $SPP_MSG" echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" echo " BSD Auth support: $BSD_AUTH_MSG" echo " Random number source: $RAND_MSG" echo " Privsep sandbox style: $SANDBOX_STYLE" echo " PKCS#11 support: $enable_pkcs11" echo " U2F/FIDO support: $enable_sk" echo "" echo " Host: ${host}" echo " Compiler: ${CC}" echo " Compiler flags: ${CFLAGS}" echo "Preprocessor flags: ${CPPFLAGS}" echo " Linker flags: ${LDFLAGS}" echo " Libraries: ${LIBS}" if test ! -z "${CHANNELLIBS}"; then echo " +for channels: ${CHANNELLIBS}" fi if test ! -z "${LIBFIDO2}"; then echo " +for FIDO2: ${LIBFIDO2}" fi if test ! -z "${SSHDLIBS}"; then echo " +for sshd: ${SSHDLIBS}" fi echo "" if test "x$MAKE_PACKAGE_SUPPORTED" = "xyes" ; then echo "SVR4 style packages are supported with \"make package\"" echo "" fi if test "x$PAM_MSG" = "xyes" ; then echo "PAM is enabled. You may need to install a PAM control file " echo "for sshd, otherwise password authentication may fail. " echo "Example PAM control files can be found in the contrib/ " echo "subdirectory" echo "" fi if test ! -z "$NO_PEERCHECK" ; then echo "WARNING: the operating system that you are using does not" echo "appear to support getpeereid(), getpeerucred() or the" echo "SO_PEERCRED getsockopt() option. These facilities are used to" echo "enforce security checks to prevent unauthorised connections to" echo "ssh-agent. Their absence increases the risk that a malicious" echo "user can connect to your agent." echo "" fi if test "$AUDIT_MODULE" = "bsm" ; then echo "WARNING: BSM audit support is currently considered EXPERIMENTAL." echo "See the Solaris section in README.platform for details." fi diff --git a/crypto/openssh/contrib/redhat/openssh.spec b/crypto/openssh/contrib/redhat/openssh.spec index 7a167d4456d1..0524a72b40af 100644 --- a/crypto/openssh/contrib/redhat/openssh.spec +++ b/crypto/openssh/contrib/redhat/openssh.spec @@ -1,850 +1,854 @@ -%global ver 9.5p1 +%global ver 9.6p1 %global rel 1%{?dist} # OpenSSH privilege separation requires a user & group ID %global sshd_uid 74 %global sshd_gid 74 # Version of ssh-askpass %global aversion 1.2.4.1 # Do we want to disable building of x11-askpass? (1=yes 0=no) %global no_x11_askpass 0 # Do we want to disable building of gnome-askpass? (1=yes 0=no) %global no_gnome_askpass 0 # Do we want to link against a static libcrypto? (1=yes 0=no) %global static_libcrypto 0 # Do we want smartcard support (1=yes 0=no) %global scard 0 # Use GTK2 instead of GNOME in gnome-ssh-askpass %global gtk2 1 # Use build6x options for older RHEL builds # RHEL 7 not yet supported %if 0%{?rhel} > 6 %global build6x 0 %else %global build6x 1 %endif -%if 0%{?fedora} >= 26 -%global compat_openssl 1 -%else -%global compat_openssl 0 +%global without_openssl 0 +# build without openssl where 1.1.1 is not available +%if 0%{?fedora} <= 28 +%global without_openssl 1 +%endif +%if 0%{?rhel} <= 7 +%global without_openssl 1 %endif # Do we want kerberos5 support (1=yes 0=no) %global kerberos5 1 # Reserve options to override askpass settings with: # rpm -ba|--rebuild --define 'skip_xxx 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:%global gtk2 0} # Is this a build for RHL 6.x or earlier? %{?build_6x:%global build6x 1} # If this is RHL 6.x, the default configuration has sysconfdir in /usr/etc. %if %{build6x} %global _sysconfdir /etc %endif # Options for static OpenSSL link: # rpm -ba|--rebuild --define "static_openssl 1" %{?static_openssl:%global static_libcrypto 1} # Options for Smartcard support: (needs libsectok and openssl-engine) # rpm -ba|--rebuild --define "smartcard 1" %{?smartcard:%global scard 1} # Is this a build for the rescue CD (without PAM)? (1=yes 0=no) %global rescue 0 %{?build_rescue:%global rescue 1} # Turn off some stuff for resuce builds %if %{rescue} %global kerberos5 0 %endif Summary: The OpenSSH implementation of SSH protocol version 2. Name: openssh Version: %{ver} %if %{rescue} Release: %{rel}rescue %else Release: %{rel} %endif URL: https://www.openssh.com/portable.html Source0: https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: http://www.jmknoble.net/software/x11-ssh-askpass/x11-ssh-askpass-%{aversion}.tar.gz License: BSD Group: Applications/Internet BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot Obsoletes: ssh %if %{build6x} PreReq: initscripts >= 5.00 %else Requires: initscripts >= 5.20 %endif BuildRequires: perl -%if %{compat_openssl} -BuildRequires: compat-openssl10-devel -%else -BuildRequires: openssl-devel >= 1.0.1 -BuildRequires: openssl-devel < 1.1 +%if ! %{without_openssl} +BuildRequires: openssl-devel >= 1.1.1 %endif BuildRequires: /bin/login %if ! %{build6x} BuildRequires: glibc-devel, pam %else BuildRequires: /usr/include/security/pam_appl.h %endif %if ! %{no_x11_askpass} BuildRequires: /usr/include/X11/Xlib.h # Xt development tools BuildRequires: libXt-devel # Provides xmkmf BuildRequires: imake # Rely on relatively recent gtk BuildRequires: gtk2-devel %endif %if ! %{no_gnome_askpass} BuildRequires: pkgconfig %endif %if %{kerberos5} BuildRequires: krb5-devel BuildRequires: krb5-libs %endif %package clients Summary: OpenSSH clients. Requires: openssh = %{version}-%{release} Group: Applications/Internet Obsoletes: ssh-clients %package server Summary: The OpenSSH server daemon. Group: System Environment/Daemons Obsoletes: ssh-server Requires: openssh = %{version}-%{release}, chkconfig >= 0.9 %if ! %{build6x} Requires: /etc/pam.d/system-auth %endif %package askpass Summary: A passphrase dialog for OpenSSH and X. Group: Applications/Internet Requires: openssh = %{version}-%{release} Obsoletes: ssh-extras %package askpass-gnome Summary: A passphrase dialog for OpenSSH, X, and GNOME. Group: Applications/Internet Requires: openssh = %{version}-%{release} Obsoletes: ssh-extras %description SSH (Secure SHell) is a program for logging into and executing commands on a remote machine. SSH is intended to replace rlogin and rsh, and to provide secure encrypted communications between two untrusted hosts over an insecure network. X11 connections and arbitrary TCP/IP ports can also be forwarded over the secure channel. OpenSSH is OpenBSD's version of the last free version of SSH, bringing it up to date in terms of security and features, as well as removing all patented algorithms to separate libraries. This package includes the core files necessary for both the OpenSSH client and server. To make this package useful, you should also install openssh-clients, openssh-server, or both. %description clients OpenSSH is a free version of SSH (Secure SHell), a program for logging into and executing commands on a remote machine. This package includes the clients necessary to make encrypted connections to SSH servers. You'll also need to install the openssh package on OpenSSH clients. %description server OpenSSH is a free version of SSH (Secure SHell), a program for logging into and executing commands on a remote machine. This package contains the secure shell daemon (sshd). The sshd daemon allows SSH clients to securely connect to your SSH server. You also need to have the openssh package installed. %description askpass OpenSSH is a free version of SSH (Secure SHell), a program for logging into and executing commands on a remote machine. This package contains an X11 passphrase dialog for OpenSSH. %description askpass-gnome OpenSSH is a free version of SSH (Secure SHell), a program for logging into and executing commands on a remote machine. This package contains an X11 passphrase dialog for OpenSSH and the GNOME GUI desktop environment. %prep %if ! %{no_x11_askpass} %setup -q -a 1 %else %setup -q %endif %build %if %{rescue} CFLAGS="$RPM_OPT_FLAGS -Os"; export CFLAGS %endif %configure \ --sysconfdir=%{_sysconfdir}/ssh \ --libexecdir=%{_libexecdir}/openssh \ --datadir=%{_datadir}/openssh \ --with-default-path=/usr/local/bin:/bin:/usr/bin \ --with-superuser-path=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin \ --with-privsep-path=%{_var}/empty/sshd \ --mandir=%{_mandir} \ --with-mantype=man \ --disable-strip \ +%if %{without_openssl} + --without-openssl \ +%endif %if %{scard} --with-smartcard \ %endif %if %{rescue} --without-pam \ %else --with-pam \ %endif %if %{kerberos5} --with-kerberos5=$K5DIR \ %endif %if %{static_libcrypto} perl -pi -e "s|-lcrypto|%{_libdir}/libcrypto.a|g" Makefile %endif make %if ! %{no_x11_askpass} pushd x11-ssh-askpass-%{aversion} %configure --libexecdir=%{_libexecdir}/openssh xmkmf -a make popd %endif # Define a variable to toggle gnome1/gtk2 building. This is necessary # because RPM doesn't handle nested %if statements. %if %{gtk2} gtk2=yes %else gtk2=no %endif %if ! %{no_gnome_askpass} pushd contrib if [ $gtk2 = yes ] ; then make gnome-ssh-askpass2 mv gnome-ssh-askpass2 gnome-ssh-askpass else make gnome-ssh-askpass1 mv gnome-ssh-askpass1 gnome-ssh-askpass fi popd %endif %install rm -rf $RPM_BUILD_ROOT mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/ssh mkdir -p -m755 $RPM_BUILD_ROOT%{_libexecdir}/openssh mkdir -p -m755 $RPM_BUILD_ROOT%{_var}/empty/sshd make install DESTDIR=$RPM_BUILD_ROOT install -d $RPM_BUILD_ROOT/etc/pam.d/ install -d $RPM_BUILD_ROOT/etc/rc.d/init.d install -d $RPM_BUILD_ROOT%{_libexecdir}/openssh -%if %{build6x} -install -m644 contrib/redhat/sshd.pam.old $RPM_BUILD_ROOT/etc/pam.d/sshd -%else -install -m644 contrib/redhat/sshd.pam $RPM_BUILD_ROOT/etc/pam.d/sshd -%endif +install -m644 contrib/redhat/sshd.pam $RPM_BUILD_ROOT/etc/pam.d/sshd install -m755 contrib/redhat/sshd.init $RPM_BUILD_ROOT/etc/rc.d/init.d/sshd %if ! %{no_x11_askpass} install x11-ssh-askpass-%{aversion}/x11-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/x11-ssh-askpass ln -s x11-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/ssh-askpass %endif %if ! %{no_gnome_askpass} install contrib/gnome-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/gnome-ssh-askpass %endif %if ! %{scard} rm -f $RPM_BUILD_ROOT/usr/share/openssh/Ssh.bin %endif %if ! %{no_gnome_askpass} install -m 755 -d $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/ install -m 755 contrib/redhat/gnome-ssh-askpass.csh $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/ install -m 755 contrib/redhat/gnome-ssh-askpass.sh $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/ %endif perl -pi -e "s|$RPM_BUILD_ROOT||g" $RPM_BUILD_ROOT%{_mandir}/man*/* %clean rm -rf $RPM_BUILD_ROOT %triggerun server -- ssh-server if [ "$1" != 0 -a -r /var/run/sshd.pid ] ; then touch /var/run/sshd.restart fi %triggerun server -- openssh-server < 2.5.0p1 # Count the number of HostKey and HostDsaKey statements we have. gawk 'BEGIN {IGNORECASE=1} /^hostkey/ || /^hostdsakey/ {sawhostkey = sawhostkey + 1} END {exit sawhostkey}' /etc/ssh/sshd_config # And if we only found one, we know the client was relying on the old default # behavior, which loaded the the SSH2 DSA host key when HostDsaKey wasn't # specified. Now that HostKey is used for both SSH1 and SSH2 keys, specifying # one nullifies the default, which would have loaded both. if [ $? -eq 1 ] ; then echo HostKey /etc/ssh/ssh_host_rsa_key >> /etc/ssh/sshd_config echo HostKey /etc/ssh/ssh_host_dsa_key >> /etc/ssh/sshd_config fi %triggerpostun server -- ssh-server if [ "$1" != 0 ] ; then /sbin/chkconfig --add sshd if test -f /var/run/sshd.restart ; then rm -f /var/run/sshd.restart /sbin/service sshd start > /dev/null 2>&1 || : fi fi %pre server %{_sbindir}/groupadd -r -g %{sshd_gid} sshd 2>/dev/null || : %{_sbindir}/useradd -d /var/empty/sshd -s /bin/false -u %{sshd_uid} \ -g sshd -M -r sshd 2>/dev/null || : %post server /sbin/chkconfig --add sshd %postun server /sbin/service sshd condrestart > /dev/null 2>&1 || : %preun server if [ "$1" = 0 ] then /sbin/service sshd stop > /dev/null 2>&1 || : /sbin/chkconfig --del sshd fi %files %defattr(-,root,root) %doc CREDITS ChangeLog INSTALL LICENCE OVERVIEW README* PROTOCOL* TODO %attr(0755,root,root) %{_bindir}/scp %attr(0644,root,root) %{_mandir}/man1/scp.1* %attr(0755,root,root) %dir %{_sysconfdir}/ssh %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/moduli %if ! %{rescue} %attr(0755,root,root) %{_bindir}/ssh-keygen %attr(0644,root,root) %{_mandir}/man1/ssh-keygen.1* %attr(0755,root,root) %dir %{_libexecdir}/openssh %attr(4711,root,root) %{_libexecdir}/openssh/ssh-keysign %attr(0755,root,root) %{_libexecdir}/openssh/ssh-pkcs11-helper %attr(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 %attr(0644,root,root) %{_datadir}/openssh/Ssh.bin %endif %files clients %defattr(-,root,root) %attr(0755,root,root) %{_bindir}/ssh %attr(0644,root,root) %{_mandir}/man1/ssh.1* %attr(0644,root,root) %{_mandir}/man5/ssh_config.5* %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config %if ! %{rescue} %attr(2755,root,nobody) %{_bindir}/ssh-agent %attr(0755,root,root) %{_bindir}/ssh-add %attr(0755,root,root) %{_bindir}/ssh-keyscan %attr(0755,root,root) %{_bindir}/sftp %attr(0644,root,root) %{_mandir}/man1/ssh-agent.1* %attr(0644,root,root) %{_mandir}/man1/ssh-add.1* %attr(0644,root,root) %{_mandir}/man1/ssh-keyscan.1* %attr(0644,root,root) %{_mandir}/man1/sftp.1* %endif %if ! %{rescue} %files server %defattr(-,root,root) %dir %attr(0111,root,root) %{_var}/empty/sshd %attr(0755,root,root) %{_sbindir}/sshd %attr(0755,root,root) %{_libexecdir}/openssh/sftp-server %attr(0644,root,root) %{_mandir}/man8/sshd.8* %attr(0644,root,root) %{_mandir}/man5/moduli.5* %attr(0644,root,root) %{_mandir}/man5/sshd_config.5* %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %attr(0755,root,root) %dir %{_sysconfdir}/ssh %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config %attr(0600,root,root) %config(noreplace) /etc/pam.d/sshd %attr(0755,root,root) %config /etc/rc.d/init.d/sshd %endif %if ! %{no_x11_askpass} %files askpass %defattr(-,root,root) %doc x11-ssh-askpass-%{aversion}/README %doc x11-ssh-askpass-%{aversion}/ChangeLog %doc x11-ssh-askpass-%{aversion}/SshAskpass*.ad %{_libexecdir}/openssh/ssh-askpass %attr(0755,root,root) %{_libexecdir}/openssh/x11-ssh-askpass %endif %if ! %{no_gnome_askpass} %files askpass-gnome %defattr(-,root,root) %attr(0755,root,root) %config %{_sysconfdir}/profile.d/gnome-ssh-askpass.* %attr(0755,root,root) %{_libexecdir}/openssh/gnome-ssh-askpass %endif %changelog +* Mon Oct 16 2023 Fabio Pedretti +- Remove reference of dropped sshd.pam.old file +- Update openssl-devel dependency to require >= 1.1.1 +- Build with --without-openssl elsewhere + * Thu Oct 28 2021 Damien Miller - Remove remaining traces of --with-md5-passwords * 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. - Remove SSH1 from description. - Don't strip binaries at build time so that debuginfo package can be created. * Sun Nov 16 2014 Nico Kadel-Garcia - Add '--mandir' and '--with-mantype' for RHEL 5 compatibility - Add 'dist' option to 'ver' so package names reflect OS at build time - Always include x11-ssh-askpass tarball in SRPM - Add openssh-x11-aspass BuildRequires for libXT-devel, imake, gtk2-devel - Discard 'K5DIR' reporting, not usable inside 'mock' for RHEL 5 compatibility - Discard obsolete '--with-rsh' configure option - Update openssl-devel dependency to 0.9.8f, as found in autoconf * Wed Jul 14 2010 Tim Rice - test for skip_x11_askpass (line 77) should have been for no_x11_askpass * Mon Jun 2 2003 Damien Miller - Remove noip6 option. This may be controlled at run-time in client config file using new AddressFamily directive * Mon May 12 2003 Damien Miller - Don't install profile.d scripts when not building with GNOME/GTK askpass (patch from bet@rahul.net) * Tue Oct 01 2002 Damien Miller - Install ssh-agent setgid nobody to prevent ptrace() key theft attacks * Mon Sep 30 2002 Damien Miller - Use contrib/ Makefile for building askpass programs * Fri Jun 21 2002 Damien Miller - Merge in spec changes from seba@iq.pl (Sebastian Pachuta) - Add new {ssh,sshd}_config.5 manpages - Add new ssh-keysign program and remove setuid from ssh client * Fri May 10 2002 Damien Miller - Merge in spec changes from RedHat, reorgansie a little - Add Privsep user, group and directory * Thu Mar 7 2002 Nalin Dahyabhai 3.1p1-2 - bump and grind (through the build system) * Thu Mar 7 2002 Nalin Dahyabhai 3.1p1-1 - require sharutils for building (mindrot #137) - require db1-devel only when building for 6.x (#55105), which probably won't work anyway (3.1 requires OpenSSL 0.9.6 to build), but what the heck - require pam-devel by file (not by package name) again - add Markus's patch to compile with OpenSSL 0.9.5a (from http://bugzilla.mindrot.org/show_bug.cgi?id=141) and apply it if we're building for 6.x * Thu Mar 7 2002 Nalin Dahyabhai 3.1p1-0 - update to 3.1p1 * Tue Mar 5 2002 Nalin Dahyabhai SNAP-20020305 - update to SNAP-20020305 - drop debug patch, fixed upstream * Wed Feb 20 2002 Nalin Dahyabhai SNAP-20020220 - update to SNAP-20020220 for testing purposes (you've been warned, if there's anything to be warned about, gss patches won't apply, I don't mind) * Wed Feb 13 2002 Nalin Dahyabhai 3.0.2p1-3 - add patches from Simon Wilkinson and Nicolas Williams for GSSAPI key exchange, authentication, and named key support * Wed Jan 23 2002 Nalin Dahyabhai 3.0.2p1-2 - remove dependency on db1-devel, which has just been swallowed up whole by gnome-libs-devel * Sat Dec 29 2001 Nalin Dahyabhai - adjust build dependencies so that build6x actually works right (fix from Hugo van der Kooij) * Tue Dec 4 2001 Nalin Dahyabhai 3.0.2p1-1 - update to 3.0.2p1 * Fri Nov 16 2001 Nalin Dahyabhai 3.0.1p1-1 - update to 3.0.1p1 * Tue Nov 13 2001 Nalin Dahyabhai - update to current CVS (not for use in distribution) * Thu Nov 8 2001 Nalin Dahyabhai 3.0p1-1 - merge some of Damien Miller changes from the upstream 3.0p1 spec file and init script * Wed Nov 7 2001 Nalin Dahyabhai - update to 3.0p1 - update to x11-ssh-askpass 1.2.4.1 - change build dependency on a file from pam-devel to the pam-devel package - replace primes with moduli * Thu Sep 27 2001 Nalin Dahyabhai 2.9p2-9 - incorporate fix from Markus Friedl's advisory for IP-based authorization bugs * Thu Sep 13 2001 Bernhard Rosenkraenzer 2.9p2-8 - Merge changes to rescue build from current sysadmin survival cd * Thu Sep 6 2001 Nalin Dahyabhai 2.9p2-7 - fix scp's server's reporting of file sizes, and build with the proper preprocessor define to get large-file capable open(), stat(), etc. (sftp has been doing this correctly all along) (#51827) - configure without --with-ipv4-default on RHL 7.x and newer (#45987,#52247) - pull cvs patch to fix support for /etc/nologin for non-PAM logins (#47298) - mark profile.d scriptlets as config files (#42337) - refer to Jason Stone's mail for zsh workaround for exit-hanging quasi-bug - change a couple of log() statements to debug() statements (#50751) - pull cvs patch to add -t flag to sshd (#28611) - clear fd_sets correctly (one bit per FD, not one byte per FD) (#43221) * Mon Aug 20 2001 Nalin Dahyabhai 2.9p2-6 - add db1-devel as a BuildPrerequisite (noted by Hans Ecke) * Thu Aug 16 2001 Nalin Dahyabhai - pull cvs patch to fix remote port forwarding with protocol 2 * Thu Aug 9 2001 Nalin Dahyabhai - pull cvs patch to add session initialization to no-pty sessions - pull cvs patch to not cut off challengeresponse auth needlessly - refuse to do X11 forwarding if xauth isn't there, handy if you enable it by default on a system that doesn't have X installed (#49263) * Wed Aug 8 2001 Nalin Dahyabhai - don't apply patches to code we don't intend to build (spotted by Matt Galgoci) * Mon Aug 6 2001 Nalin Dahyabhai - pass OPTIONS correctly to initlog (#50151) * Wed Jul 25 2001 Nalin Dahyabhai - switch to x11-ssh-askpass 1.2.2 * Wed Jul 11 2001 Nalin Dahyabhai - rebuild in new environment * Mon Jun 25 2001 Nalin Dahyabhai - disable the gssapi patch * Mon Jun 18 2001 Nalin Dahyabhai - update to 2.9p2 - refresh to a new version of the gssapi patch * Thu Jun 7 2001 Nalin Dahyabhai - change Copyright: BSD to License: BSD - add Markus Friedl's unverified patch for the cookie file deletion problem so that we can verify it - drop patch to check if xauth is present (was folded into cookie patch) - don't apply gssapi patches for the errata candidate - clear supplemental groups list at startup * Fri May 25 2001 Nalin Dahyabhai - fix an error parsing the new default sshd_config - add a fix from Markus Friedl (via openssh-unix-dev) for ssh-keygen not dealing with comments right * Thu May 24 2001 Nalin Dahyabhai - add in Simon Wilkinson's GSSAPI patch to give it some testing in-house, to be removed before the next beta cycle because it's a big departure from the upstream version * Thu May 3 2001 Nalin Dahyabhai - finish marking strings in the init script for translation - modify init script to source /etc/sysconfig/sshd and pass $OPTIONS to sshd at startup (change merged from openssh.com init script, originally by Pekka Savola) - refuse to do X11 forwarding if xauth isn't there, handy if you enable it by default on a system that doesn't have X installed * Wed May 2 2001 Nalin Dahyabhai - update to 2.9 - drop various patches that came from or went upstream or to or from CVS * Wed Apr 18 2001 Nalin Dahyabhai - only require initscripts 5.00 on 6.2 (reported by Peter Bieringer) * Sun Apr 8 2001 Preston Brown - remove explicit openssl requirement, fixes builddistro issue - make initscript stop() function wait until sshd really dead to avoid races in condrestart * Mon Apr 2 2001 Nalin Dahyabhai - mention that challengereponse supports PAM, so disabling password doesn't limit users to pubkey and rsa auth (#34378) - bypass the daemon() function in the init script and call initlog directly, because daemon() won't start a daemon it detects is already running (like open connections) - require the version of openssl we had when we were built * Fri Mar 23 2001 Nalin Dahyabhai - make do_pam_setcred() smart enough to know when to establish creds and when to reinitialize them - add in a couple of other fixes from Damien for inclusion in the errata * Thu Mar 22 2001 Nalin Dahyabhai - update to 2.5.2p2 - call setcred() again after initgroups, because the "creds" could actually be group memberships * Tue Mar 20 2001 Nalin Dahyabhai - update to 2.5.2p1 (includes endianness fixes in the rijndael implementation) - don't enable challenge-response by default until we find a way to not have too many userauth requests (we may make up to six pubkey and up to three password attempts as it is) - remove build dependency on rsh to match openssh.com's packages more closely * Sat Mar 3 2001 Nalin Dahyabhai - remove dependency on openssl -- would need to be too precise * Fri Mar 2 2001 Nalin Dahyabhai - rebuild in new environment * Mon Feb 26 2001 Nalin Dahyabhai - Revert the patch to move pam_open_session. - Init script and spec file changes from Pekka Savola. (#28750) - Patch sftp to recognize '-o protocol' arguments. (#29540) * Thu Feb 22 2001 Nalin Dahyabhai - Chuck the closing patch. - Add a trigger to add host keys for protocol 2 to the config file, now that configuration file syntax requires us to specify it with HostKey if we specify any other HostKey values, which we do. * Tue Feb 20 2001 Nalin Dahyabhai - Redo patch to move pam_open_session after the server setuid()s to the user. - Rework the nopam patch to use be picked up by autoconf. * Mon Feb 19 2001 Nalin Dahyabhai - Update for 2.5.1p1. - Add init script mods from Pekka Savola. - Tweak the init script to match the CVS contrib script more closely. - Redo patch to ssh-add to try to adding both identity and id_dsa to also try adding id_rsa. * Fri Feb 16 2001 Nalin Dahyabhai - Update for 2.5.0p1. - Use $RPM_OPT_FLAGS instead of -O when building gnome-ssh-askpass - Resync with parts of Damien Miller's openssh.spec from CVS, including update of x11 askpass to 1.2.0. - Only require openssl (don't prereq) because we generate keys in the init script now. * Tue Feb 13 2001 Nalin Dahyabhai - Don't open a PAM session until we've forked and become the user (#25690). - Apply Andrew Bartlett's patch for letting pam_authenticate() know which host the user is attempting a login from. - Resync with parts of Damien Miller's openssh.spec from CVS. - Don't expose KbdInt responses in debug messages (from CVS). - Detect and handle errors in rsa_{public,private}_decrypt (from CVS). * Wed Feb 7 2001 Trond Eivind Glomsrxd - i18n-tweak to initscript. * Tue Jan 23 2001 Nalin Dahyabhai - More gettextizing. - Close all files after going into daemon mode (needs more testing). - Extract patch from CVS to handle auth banners (in the client). - Extract patch from CVS to handle compat weirdness. * Fri Jan 19 2001 Nalin Dahyabhai - Finish with the gettextizing. * Thu Jan 18 2001 Nalin Dahyabhai - Fix a bug in auth2-pam.c (#23877) - Gettextize the init script. * Wed Dec 20 2000 Nalin Dahyabhai - Incorporate a switch for using PAM configs for 6.x, just in case. * Tue Dec 5 2000 Nalin Dahyabhai - Incorporate Bero's changes for a build specifically for rescue CDs. * Wed Nov 29 2000 Nalin Dahyabhai - Don't treat pam_setcred() failure as fatal unless pam_authenticate() has succeeded, to allow public-key authentication after a failure with "none" authentication. (#21268) * Tue Nov 28 2000 Nalin Dahyabhai - Update to x11-askpass 1.1.1. (#21301) - Don't second-guess fixpaths, which causes paths to get fixed twice. (#21290) * Mon Nov 27 2000 Nalin Dahyabhai - Merge multiple PAM text messages into subsequent prompts when possible when doing keyboard-interactive authentication. * Sun Nov 26 2000 Nalin Dahyabhai - Disable the built-in MD5 password support. We're using PAM. - Take a crack at doing keyboard-interactive authentication with PAM, and enable use of it in the default client configuration so that the client will try it when the server disallows password authentication. - Build with debugging flags. Build root policies strip all binaries anyway. * Tue Nov 21 2000 Nalin Dahyabhai - Use DESTDIR instead of %%makeinstall. - Remove /usr/X11R6/bin from the path-fixing patch. * Mon Nov 20 2000 Nalin Dahyabhai - Add the primes file from the latest snapshot to the main package (#20884). - Add the dev package to the prereq list (#19984). - Remove the default path and mimic login's behavior in the server itself. * Fri Nov 17 2000 Nalin Dahyabhai - Resync with conditional options in Damien Miller's .spec file for an errata. - Change libexecdir from %%{_libexecdir}/ssh to %%{_libexecdir}/openssh. * Tue Nov 7 2000 Nalin Dahyabhai - Update to OpenSSH 2.3.0p1. - Update to x11-askpass 1.1.0. - Enable keyboard-interactive authentication. * Mon Oct 30 2000 Nalin Dahyabhai - Update to ssh-askpass-x11 1.0.3. - Change authentication related messages to be private (#19966). * Tue Oct 10 2000 Nalin Dahyabhai - Patch ssh-keygen to be able to list signatures for DSA public key files it generates. * Thu Oct 5 2000 Nalin Dahyabhai - Add BuildRequires on /usr/include/security/pam_appl.h to be sure we always build PAM authentication in. - Try setting SSH_ASKPASS if gnome-ssh-askpass is installed. - Clean out no-longer-used patches. - Patch ssh-add to try to add both identity and id_dsa, and to error only when neither exists. * Mon Oct 2 2000 Nalin Dahyabhai - Update x11-askpass to 1.0.2. (#17835) - Add BuildRequiress for /bin/login and /usr/bin/rsh so that configure will always find them in the right place. (#17909) - Set the default path to be the same as the one supplied by /bin/login, but add /usr/X11R6/bin. (#17909) - Try to handle obsoletion of ssh-server more cleanly. Package names are different, but init script name isn't. (#17865) * Wed Sep 6 2000 Nalin Dahyabhai - Update to 2.2.0p1. (#17835) - Tweak the init script to allow proper restarting. (#18023) * Wed Aug 23 2000 Nalin Dahyabhai - Update to 20000823 snapshot. - Change subpackage requirements from %%{version} to %%{version}-%%{release} - Back out the pipe patch. * Mon Jul 17 2000 Nalin Dahyabhai - Update to 2.1.1p4, which includes fixes for config file parsing problems. - Move the init script back. - Add Damien's quick fix for wackiness. * Wed Jul 12 2000 Nalin Dahyabhai - Update to 2.1.1p3, which includes fixes for X11 forwarding and strtok(). * Thu Jul 6 2000 Nalin Dahyabhai - Move condrestart to server postun. - Move key generation to init script. - Actually use the right patch for moving the key generation to the init script. - Clean up the init script a bit. * Wed Jul 5 2000 Nalin Dahyabhai - Fix X11 forwarding, from mail post by Chan Shih-Ping Richard. * Sun Jul 2 2000 Nalin Dahyabhai - Update to 2.1.1p2. - Use of strtok() considered harmful. * Sat Jul 1 2000 Nalin Dahyabhai - Get the build root out of the man pages. * Thu Jun 29 2000 Nalin Dahyabhai - Add and use condrestart support in the init script. - Add newer initscripts as a prereq. * Tue Jun 27 2000 Nalin Dahyabhai - Build in new environment (release 2) - Move -clients subpackage to Applications/Internet group * Fri Jun 9 2000 Nalin Dahyabhai - Update to 2.2.1p1 * Sat Jun 3 2000 Nalin Dahyabhai - Patch to build with neither RSA nor RSAref. - Miscellaneous FHS-compliance tweaks. - Fix for possibly-compressed man pages. * Wed Mar 15 2000 Damien Miller - Updated for new location - Updated for new gnome-ssh-askpass build * Sun Dec 26 1999 Damien Miller - Added Jim Knoble's askpass * Mon Nov 15 1999 Damien Miller - Split subpackages further based on patch from jim knoble * Sat Nov 13 1999 Damien Miller - Added 'Obsoletes' directives * Tue Nov 09 1999 Damien Miller - Use make install - Subpackages * Mon Nov 08 1999 Damien Miller - Added links for slogin - Fixed perms on manpages * Sat Oct 30 1999 Damien Miller - Renamed init script * Fri Oct 29 1999 Damien Miller - Back to old binary names * Thu Oct 28 1999 Damien Miller - Use autoconf - New binary names * Wed Oct 27 1999 Damien Miller - Initial RPMification, based on Jan "Yenya" Kasprzak's spec. diff --git a/crypto/openssh/contrib/suse/openssh.spec b/crypto/openssh/contrib/suse/openssh.spec index 921d0f5a4d67..b5082f0d5d8c 100644 --- a/crypto/openssh/contrib/suse/openssh.spec +++ b/crypto/openssh/contrib/suse/openssh.spec @@ -1,245 +1,245 @@ # Default values for additional components %define build_x11_askpass 1 # Define the UID/GID to use for privilege separation %define sshd_gid 65 %define sshd_uid 71 # The version of x11-ssh-askpass to use %define xversion 1.2.4.1 # Allow the ability to override defaults with -D skip_xxx=1 %{?skip_x11_askpass:%define build_x11_askpass 0} Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation Name: openssh -Version: 9.5p1 +Version: 9.6p1 URL: https://www.openssh.com/ Release: 1 Source0: openssh-%{version}.tar.gz Source1: x11-ssh-askpass-%{xversion}.tar.gz License: BSD Group: Productivity/Networking/SSH BuildRoot: %{_tmppath}/openssh-%{version}-buildroot PreReq: openssl Obsoletes: ssh Provides: ssh # # (Build[ing] Prereq[uisites] only work for RPM 2.95 and newer.) # building prerequisites -- stuff for # OpenSSL (openssl-devel), # and Gnome (glibdev, gtkdev, and gnlibsd) # BuildPrereq: openssl BuildPrereq: zlib-devel #BuildPrereq: glibdev #BuildPrereq: gtkdev #BuildPrereq: gnlibsd %package askpass Summary: A passphrase dialog for OpenSSH and the X window System. Group: Productivity/Networking/SSH Requires: openssh = %{version} Obsoletes: ssh-extras Provides: openssh:${_libdir}/ssh/ssh-askpass %if %{build_x11_askpass} BuildPrereq: XFree86-devel %endif %description Ssh (Secure Shell) is a program for logging into a remote machine and for executing commands in a remote machine. It is intended to replace rlogin and rsh, and provide secure encrypted communications between two untrusted hosts over an insecure network. X11 connections and arbitrary TCP/IP ports can also be forwarded over the secure channel. OpenSSH is OpenBSD's rework of the last free version of SSH, bringing it up to date in terms of security and features, as well as removing all patented algorithms to separate libraries (OpenSSL). This package includes all files necessary for both the OpenSSH client and server. %description askpass Ssh (Secure Shell) is a program for logging into a remote machine and for executing commands in a remote machine. It is intended to replace rlogin and rsh, and provide secure encrypted communications between two untrusted hosts over an insecure network. X11 connections and arbitrary TCP/IP ports can also be forwarded over the secure channel. OpenSSH is OpenBSD's rework of the last free version of SSH, bringing it up to date in terms of security and features, as well as removing all patented algorithms to separate libraries (OpenSSL). This package contains an X Window System passphrase dialog for OpenSSH. %changelog * 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 - Overhaul to deal with newer versions of SuSE and OpenSSH * Mon Jun 12 2000 Damien Miller - Glob manpages to catch compressed files * Wed Mar 15 2000 Damien Miller - Updated for new location - Updated for new gnome-ssh-askpass build * Sun Dec 26 1999 Chris Saia - Made symlink to gnome-ssh-askpass called ssh-askpass * Wed Nov 24 1999 Chris Saia - Removed patches that included /etc/pam.d/sshd, /sbin/init.d/rc.sshd, and /var/adm/fillup-templates/rc.config.sshd, since Damien merged these into his released tarfile - Changed permissions on ssh_config in the install procedure to 644 from 600 even though it was correct in the %files section and thus right in the RPMs - Postinstall script for the server now only prints "Generating SSH host key..." if we need to actually do this, in order to eliminate a confusing message if an SSH host key is already in place - Marked all manual pages as %doc(umentation) * Mon Nov 22 1999 Chris Saia - Added flag to configure daemon with TCP Wrappers support - Added building prerequisites (works in RPM 3.0 and newer) * Thu Nov 18 1999 Chris Saia - Made this package correct for SuSE. - Changed instances of pam_pwdb.so to pam_unix.so, since it works more properly with SuSE, and lib_pwdb.so isn't installed by default. * Mon Nov 15 1999 Damien Miller - Split subpackages further based on patch from jim knoble * Sat Nov 13 1999 Damien Miller - Added 'Obsoletes' directives * Tue Nov 09 1999 Damien Miller - Use make install - Subpackages * Mon Nov 08 1999 Damien Miller - Added links for slogin - Fixed perms on manpages * Sat Oct 30 1999 Damien Miller - Renamed init script * Fri Oct 29 1999 Damien Miller - Back to old binary names * Thu Oct 28 1999 Damien Miller - Use autoconf - New binary names * Wed Oct 27 1999 Damien Miller - Initial RPMification, based on Jan "Yenya" Kasprzak's spec. %prep %if %{build_x11_askpass} %setup -q -a 1 %else %setup -q %endif %build CFLAGS="$RPM_OPT_FLAGS" \ %configure --prefix=/usr \ --sysconfdir=%{_sysconfdir}/ssh \ --mandir=%{_mandir} \ --with-privsep-path=/var/lib/empty \ --with-pam \ --libexecdir=%{_libdir}/ssh make %if %{build_x11_askpass} cd x11-ssh-askpass-%{xversion} %configure --mandir=/usr/X11R6/man \ --libexecdir=%{_libdir}/ssh xmkmf -a make cd .. %endif %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT/ install -d $RPM_BUILD_ROOT/etc/pam.d/ install -d $RPM_BUILD_ROOT/etc/init.d/ install -d $RPM_BUILD_ROOT/var/adm/fillup-templates install -m644 contrib/sshd.pam.generic $RPM_BUILD_ROOT/etc/pam.d/sshd install -m744 contrib/suse/rc.sshd $RPM_BUILD_ROOT/etc/init.d/sshd install -m744 contrib/suse/sysconfig.ssh \ $RPM_BUILD_ROOT/var/adm/fillup-templates %if %{build_x11_askpass} cd x11-ssh-askpass-%{xversion} make install install.man BINDIR=%{_libdir}/ssh DESTDIR=$RPM_BUILD_ROOT/ rm -f $RPM_BUILD_ROOT/usr/share/Ssh.bin %endif %clean rm -rf $RPM_BUILD_ROOT %pre /usr/sbin/groupadd -g %{sshd_gid} -o -r sshd 2> /dev/null || : /usr/sbin/useradd -r -o -g sshd -u %{sshd_uid} -s /bin/false -c "SSH Privilege Separation User" -d /var/lib/sshd sshd 2> /dev/null || : %post /usr/bin/ssh-keygen -A %{fillup_and_insserv -n -y ssh sshd} %run_permissions %verifyscript %verify_permissions -e /etc/ssh/sshd_config -e /etc/ssh/ssh_config -e /usr/bin/ssh %preun %stop_on_removal sshd %postun %restart_on_update sshd %{insserv_cleanup} %files %defattr(-,root,root) %doc ChangeLog OVERVIEW README* PROTOCOL* %doc TODO CREDITS LICENCE %attr(0755,root,root) %dir %{_sysconfdir}/ssh %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/moduli %attr(0644,root,root) %config(noreplace) /etc/pam.d/sshd %attr(0755,root,root) %config /etc/init.d/sshd %attr(0755,root,root) %{_bindir}/ssh-keygen %attr(0755,root,root) %{_bindir}/scp %attr(0755,root,root) %{_bindir}/ssh %attr(0755,root,root) %{_bindir}/ssh-agent %attr(0755,root,root) %{_bindir}/ssh-add %attr(0755,root,root) %{_bindir}/ssh-keyscan %attr(0755,root,root) %{_bindir}/sftp %attr(0755,root,root) %{_sbindir}/sshd %attr(0755,root,root) %dir %{_libdir}/ssh %attr(0755,root,root) %{_libdir}/ssh/sftp-server %attr(4711,root,root) %{_libdir}/ssh/ssh-keysign %attr(0755,root,root) %{_libdir}/ssh/ssh-pkcs11-helper %attr(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* %attr(0644,root,root) %doc %{_mandir}/man1/ssh-add.1* %attr(0644,root,root) %doc %{_mandir}/man1/ssh-agent.1* %attr(0644,root,root) %doc %{_mandir}/man1/ssh-keygen.1* %attr(0644,root,root) %doc %{_mandir}/man1/ssh-keyscan.1* %attr(0644,root,root) %doc %{_mandir}/man5/moduli.5* %attr(0644,root,root) %doc %{_mandir}/man5/ssh_config.5* %attr(0644,root,root) %doc %{_mandir}/man5/sshd_config.5* %attr(0644,root,root) %doc %{_mandir}/man8/sftp-server.8* %attr(0644,root,root) %doc %{_mandir}/man8/ssh-keysign.8* %attr(0644,root,root) %doc %{_mandir}/man8/ssh-pkcs11-helper.8* %attr(0644,root,root) %doc %{_mandir}/man8/ssh-sk-helper.8* %attr(0644,root,root) %doc %{_mandir}/man8/sshd.8* %attr(0644,root,root) /var/adm/fillup-templates/sysconfig.ssh %if %{build_x11_askpass} %files askpass %defattr(-,root,root) %doc x11-ssh-askpass-%{xversion}/README %doc x11-ssh-askpass-%{xversion}/ChangeLog %doc x11-ssh-askpass-%{xversion}/SshAskpass*.ad %attr(0755,root,root) %{_libdir}/ssh/ssh-askpass %attr(0755,root,root) %{_libdir}/ssh/x11-ssh-askpass %attr(0644,root,root) %doc /usr/X11R6/man/man1/ssh-askpass.1x* %attr(0644,root,root) %doc /usr/X11R6/man/man1/x11-ssh-askpass.1x* %attr(0644,root,root) %config /usr/X11R6/lib/X11/app-defaults/SshAskpass %endif diff --git a/crypto/openssh/kex.c b/crypto/openssh/kex.c index 2cb5ab3cf07c..cbb2af5965c0 100644 --- a/crypto/openssh/kex.c +++ b/crypto/openssh/kex.c @@ -1,1526 +1,1667 @@ -/* $OpenBSD: kex.c,v 1.181 2023/08/28 03:28:43 djm Exp $ */ +/* $OpenBSD: kex.c,v 1.184 2023/12/18 14:45:49 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #ifdef HAVE_POLL_H #include #endif #ifdef WITH_OPENSSL #include #include #endif #include "ssh.h" #include "ssh2.h" #include "atomicio.h" #include "version.h" #include "packet.h" #include "compat.h" #include "cipher.h" #include "sshkey.h" #include "kex.h" #include "log.h" #include "mac.h" #include "match.h" #include "misc.h" #include "dispatch.h" #include "monitor.h" #include "myproposal.h" #include "ssherr.h" #include "sshbuf.h" #include "digest.h" #include "xmalloc.h" /* prototype */ static int kex_choose_conf(struct ssh *, uint32_t seq); static int kex_input_newkeys(int, u_int32_t, struct ssh *); static const char * const proposal_names[PROPOSAL_MAX] = { "KEX algorithms", "host key algorithms", "ciphers ctos", "ciphers stoc", "MACs ctos", "MACs stoc", "compression ctos", "compression stoc", "languages ctos", "languages stoc", }; struct kexalg { char *name; u_int type; int ec_nid; int hash_alg; }; static const struct kexalg kexalgs[] = { #ifdef WITH_OPENSSL { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, { KEX_DH14_SHA1, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, { KEX_DH14_SHA256, KEX_DH_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, { KEX_DH16_SHA512, KEX_DH_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, { KEX_DH18_SHA512, KEX_DH_GRP18_SHA512, 0, SSH_DIGEST_SHA512 }, { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, #ifdef HAVE_EVP_SHA256 { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, #endif /* HAVE_EVP_SHA256 */ #ifdef OPENSSL_HAS_ECC { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, SSH_DIGEST_SHA384 }, # ifdef OPENSSL_HAS_NISTP521 { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, SSH_DIGEST_SHA512 }, # endif /* OPENSSL_HAS_NISTP521 */ #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ #if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL) { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, { KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, #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}, }; char * kex_alg_list(char sep) { char *ret = NULL, *tmp; size_t nlen, rlen = 0; const struct kexalg *k; for (k = kexalgs; k->name != NULL; k++) { if (ret != NULL) ret[rlen++] = sep; nlen = strlen(k->name); if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { free(ret); return NULL; } ret = tmp; memcpy(ret + rlen, k->name, nlen + 1); rlen += nlen; } return ret; } static const struct kexalg * kex_alg_by_name(const char *name) { const struct kexalg *k; for (k = kexalgs; k->name != NULL; k++) { if (strcmp(k->name, name) == 0) return k; } return NULL; } /* Validate KEX method name list */ int kex_names_valid(const char *names) { char *s, *cp, *p; if (names == NULL || strcmp(names, "") == 0) return 0; if ((s = cp = strdup(names)) == NULL) return 0; for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { if (kex_alg_by_name(p) == NULL) { error("Unsupported KEX algorithm \"%.100s\"", p); free(s); return 0; } } debug3("kex names ok: [%s]", names); free(s); return 1; } /* returns non-zero if proposal contains any algorithm from algs */ static int has_any_alg(const char *proposal, const char *algs) { char *cp; if ((cp = match_list(proposal, algs, NULL)) == NULL) return 0; free(cp); return 1; } /* * Concatenate algorithm names, avoiding duplicates in the process. * Caller must free returned string. */ char * kex_names_cat(const char *a, const char *b) { char *ret = NULL, *tmp = NULL, *cp, *p; size_t len; if (a == NULL || *a == '\0') return strdup(b); if (b == NULL || *b == '\0') return strdup(a); if (strlen(b) > 1024*1024) return NULL; len = strlen(a) + strlen(b) + 2; if ((tmp = cp = strdup(b)) == NULL || (ret = calloc(1, len)) == NULL) { free(tmp); return NULL; } strlcpy(ret, a, len); for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { if (has_any_alg(ret, p)) continue; /* Algorithm already present */ if (strlcat(ret, ",", len) >= len || strlcat(ret, p, len) >= len) { free(tmp); free(ret); return NULL; /* Shouldn't happen */ } } free(tmp); return ret; } /* * Assemble a list of algorithms from a default list and a string from a * configuration file. The user-provided string may begin with '+' to * indicate that it should be appended to the default, '-' that the * specified names should be removed, or '^' that they should be placed * at the head. */ int kex_assemble_names(char **listp, const char *def, const char *all) { char *cp, *tmp, *patterns; char *list = NULL, *ret = NULL, *matching = NULL, *opatterns = NULL; int r = SSH_ERR_INTERNAL_ERROR; if (listp == NULL || def == NULL || all == NULL) return SSH_ERR_INVALID_ARGUMENT; if (*listp == NULL || **listp == '\0') { if ((*listp = strdup(def)) == NULL) return SSH_ERR_ALLOC_FAIL; return 0; } list = *listp; *listp = NULL; if (*list == '+') { /* Append names to default list */ if ((tmp = kex_names_cat(def, list + 1)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } free(list); list = tmp; } else if (*list == '-') { /* Remove names from default list */ if ((*listp = match_filter_denylist(def, list + 1)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } free(list); /* filtering has already been done */ return 0; } else if (*list == '^') { /* Place names at head of default list */ if ((tmp = kex_names_cat(list + 1, def)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } free(list); list = tmp; } else { /* Explicit list, overrides default - just use "list" as is */ } /* * The supplied names may be a pattern-list. For the -list case, * the patterns are applied above. For the +list and explicit list * cases we need to do it now. */ ret = NULL; if ((patterns = opatterns = strdup(list)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } /* Apply positive (i.e. non-negated) patterns from the list */ while ((cp = strsep(&patterns, ",")) != NULL) { if (*cp == '!') { /* negated matches are not supported here */ r = SSH_ERR_INVALID_ARGUMENT; goto fail; } free(matching); if ((matching = match_filter_allowlist(all, cp)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } if ((tmp = kex_names_cat(ret, matching)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto fail; } free(ret); ret = tmp; } if (ret == NULL || *ret == '\0') { /* An empty name-list is an error */ /* XXX better error code? */ r = SSH_ERR_INVALID_ARGUMENT; goto fail; } /* success */ *listp = ret; ret = NULL; r = 0; fail: free(matching); free(opatterns); free(list); free(ret); return r; } /* * Fill out a proposal array with dynamically allocated values, which may * be modified as required for compatibility reasons. * Any of the options may be NULL, in which case the default is used. * Array contents must be freed by calling kex_proposal_free_entries. */ void kex_proposal_populate_entries(struct ssh *ssh, char *prop[PROPOSAL_MAX], const char *kexalgos, const char *ciphers, const char *macs, const char *comp, const char *hkalgs) { const char *defpropserver[PROPOSAL_MAX] = { KEX_SERVER }; const char *defpropclient[PROPOSAL_MAX] = { KEX_CLIENT }; const char **defprop = ssh->kex->server ? defpropserver : defpropclient; u_int i; char *cp; if (prop == NULL) fatal_f("proposal missing"); /* Append EXT_INFO signalling to KexAlgorithms */ if (kexalgos == NULL) kexalgos = defprop[PROPOSAL_KEX_ALGS]; if ((cp = kex_names_cat(kexalgos, ssh->kex->server ? - "kex-strict-s-v00@openssh.com" : + "ext-info-s,kex-strict-s-v00@openssh.com" : "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL) fatal_f("kex_names_cat"); for (i = 0; i < PROPOSAL_MAX; i++) { switch(i) { case PROPOSAL_KEX_ALGS: prop[i] = compat_kex_proposal(ssh, cp); break; case PROPOSAL_ENC_ALGS_CTOS: case PROPOSAL_ENC_ALGS_STOC: prop[i] = xstrdup(ciphers ? ciphers : defprop[i]); break; case PROPOSAL_MAC_ALGS_CTOS: case PROPOSAL_MAC_ALGS_STOC: prop[i] = xstrdup(macs ? macs : defprop[i]); break; case PROPOSAL_COMP_ALGS_CTOS: case PROPOSAL_COMP_ALGS_STOC: prop[i] = xstrdup(comp ? comp : defprop[i]); break; case PROPOSAL_SERVER_HOST_KEY_ALGS: prop[i] = xstrdup(hkalgs ? hkalgs : defprop[i]); break; default: prop[i] = xstrdup(defprop[i]); } } free(cp); } void kex_proposal_free_entries(char *prop[PROPOSAL_MAX]) { u_int i; for (i = 0; i < PROPOSAL_MAX; i++) free(prop[i]); } /* put algorithm proposal into buffer */ int kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX]) { u_int i; int r; sshbuf_reset(b); /* * add a dummy cookie, the cookie will be overwritten by * kex_send_kexinit(), each time a kexinit is set */ for (i = 0; i < KEX_COOKIE_LEN; i++) { if ((r = sshbuf_put_u8(b, 0)) != 0) return r; } for (i = 0; i < PROPOSAL_MAX; i++) { if ((r = sshbuf_put_cstring(b, proposal[i])) != 0) return r; } if ((r = sshbuf_put_u8(b, 0)) != 0 || /* first_kex_packet_follows */ (r = sshbuf_put_u32(b, 0)) != 0) /* uint32 reserved */ return r; return 0; } /* parse buffer and return algorithm proposal */ int kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp) { struct sshbuf *b = NULL; u_char v; u_int i; char **proposal = NULL; int r; *propp = NULL; if ((proposal = calloc(PROPOSAL_MAX, sizeof(char *))) == NULL) return SSH_ERR_ALLOC_FAIL; if ((b = sshbuf_fromb(raw)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) { /* skip cookie */ 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_fr(r, "parse proposal %u", i); goto out; } debug2("%s: %s", proposal_names[i], proposal[i]); } /* first kex follows / reserved */ if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */ (r = sshbuf_get_u32(b, &i)) != 0) { /* reserved */ error_fr(r, "parse"); goto out; } if (first_kex_follows != NULL) *first_kex_follows = v; debug2("first_kex_follows %d ", v); debug2("reserved %u ", i); r = 0; *propp = proposal; out: if (r != 0 && proposal != NULL) kex_prop_free(proposal); sshbuf_free(b); return r; } void kex_prop_free(char **proposal) { u_int i; if (proposal == NULL) return; for (i = 0; i < PROPOSAL_MAX; i++) free(proposal[i]); free(proposal); } int kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh) { int r; /* If in strict mode, any unexpected message is an error */ if ((ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) { ssh_packet_disconnect(ssh, "strict KEX violation: " "unexpected packet type %u (seqnr %u)", type, seq); } error_f("type %u seq %u", type, seq); if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || (r = sshpkt_put_u32(ssh, seq)) != 0 || (r = sshpkt_send(ssh)) != 0) return r; return 0; } static void kex_reset_dispatch(struct ssh *ssh) { ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN, SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error); } +void +kex_set_server_sig_algs(struct ssh *ssh, const char *allowed_algs) +{ + char *alg, *oalgs, *algs, *sigalgs; + const char *sigalg; + + /* + * NB. allowed algorithms may contain certificate algorithms that + * map to a specific plain signature type, e.g. + * rsa-sha2-512-cert-v01@openssh.com => rsa-sha2-512 + * We need to be careful here to match these, retain the mapping + * and only add each signature algorithm once. + */ + if ((sigalgs = sshkey_alg_list(0, 1, 1, ',')) == NULL) + fatal_f("sshkey_alg_list failed"); + oalgs = algs = xstrdup(allowed_algs); + free(ssh->kex->server_sig_algs); + ssh->kex->server_sig_algs = NULL; + for ((alg = strsep(&algs, ",")); alg != NULL && *alg != '\0'; + (alg = strsep(&algs, ","))) { + if ((sigalg = sshkey_sigalg_by_name(alg)) == NULL) + continue; + if (!has_any_alg(sigalg, sigalgs)) + continue; + /* Don't add an algorithm twice. */ + if (ssh->kex->server_sig_algs != NULL && + has_any_alg(sigalg, ssh->kex->server_sig_algs)) + continue; + xextendf(&ssh->kex->server_sig_algs, ",", "%s", sigalg); + } + free(oalgs); + free(sigalgs); + if (ssh->kex->server_sig_algs == NULL) + ssh->kex->server_sig_algs = xstrdup(""); +} + static int -kex_send_ext_info(struct ssh *ssh) +kex_compose_ext_info_server(struct ssh *ssh, struct sshbuf *m) { int r; - char *algs; - debug("Sending SSH2_MSG_EXT_INFO"); - if ((algs = sshkey_alg_list(0, 1, 1, ',')) == NULL) + if (ssh->kex->server_sig_algs == NULL && + (ssh->kex->server_sig_algs = sshkey_alg_list(0, 1, 1, ',')) == NULL) return SSH_ERR_ALLOC_FAIL; - /* XXX filter algs list by allowed pubkey/hostbased types */ - if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || - (r = sshpkt_put_u32(ssh, 3)) != 0 || - (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || - (r = sshpkt_put_cstring(ssh, algs)) != 0 || - (r = sshpkt_put_cstring(ssh, + if ((r = sshbuf_put_u32(m, 3)) != 0 || + (r = sshbuf_put_cstring(m, "server-sig-algs")) != 0 || + (r = sshbuf_put_cstring(m, ssh->kex->server_sig_algs)) != 0 || + (r = sshbuf_put_cstring(m, "publickey-hostbound@openssh.com")) != 0 || - (r = sshpkt_put_cstring(ssh, "0")) != 0 || - (r = sshpkt_put_cstring(ssh, "ping@openssh.com")) != 0 || - (r = sshpkt_put_cstring(ssh, "0")) != 0 || - (r = sshpkt_send(ssh)) != 0) { + (r = sshbuf_put_cstring(m, "0")) != 0 || + (r = sshbuf_put_cstring(m, "ping@openssh.com")) != 0 || + (r = sshbuf_put_cstring(m, "0")) != 0) { + error_fr(r, "compose"); + return r; + } + return 0; +} + +static int +kex_compose_ext_info_client(struct ssh *ssh, struct sshbuf *m) +{ + int r; + + if ((r = sshbuf_put_u32(m, 1)) != 0 || + (r = sshbuf_put_cstring(m, "ext-info-in-auth@openssh.com")) != 0 || + (r = sshbuf_put_cstring(m, "0")) != 0) { error_fr(r, "compose"); goto out; } /* success */ r = 0; out: - free(algs); + return r; +} + +static int +kex_maybe_send_ext_info(struct ssh *ssh) +{ + int r; + struct sshbuf *m = NULL; + + if ((ssh->kex->flags & KEX_INITIAL) == 0) + return 0; + if (!ssh->kex->ext_info_c && !ssh->kex->ext_info_s) + return 0; + + /* Compose EXT_INFO packet. */ + if ((m = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + if (ssh->kex->ext_info_c && + (r = kex_compose_ext_info_server(ssh, m)) != 0) + goto fail; + if (ssh->kex->ext_info_s && + (r = kex_compose_ext_info_client(ssh, m)) != 0) + goto fail; + + /* Send the actual KEX_INFO packet */ + debug("Sending SSH2_MSG_EXT_INFO"); + if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || + (r = sshpkt_putb(ssh, m)) != 0 || + (r = sshpkt_send(ssh)) != 0) { + error_f("send EXT_INFO"); + goto fail; + } + + r = 0; + + fail: + sshbuf_free(m); return r; } +int +kex_server_update_ext_info(struct ssh *ssh) +{ + int r; + + if ((ssh->kex->flags & KEX_HAS_EXT_INFO_IN_AUTH) == 0) + return 0; + + debug_f("Sending SSH2_MSG_EXT_INFO"); + if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 || + (r = sshpkt_put_u32(ssh, 1)) != 0 || + (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || + (r = sshpkt_put_cstring(ssh, ssh->kex->server_sig_algs)) != 0 || + (r = sshpkt_send(ssh)) != 0) { + error_f("send EXT_INFO"); + return r; + } + return 0; +} + int kex_send_newkeys(struct ssh *ssh) { int r; kex_reset_dispatch(ssh); if ((r = sshpkt_start(ssh, SSH2_MSG_NEWKEYS)) != 0 || (r = sshpkt_send(ssh)) != 0) return r; debug("SSH2_MSG_NEWKEYS sent"); ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys); - if (ssh->kex->ext_info_c && (ssh->kex->flags & KEX_INITIAL) != 0) - if ((r = kex_send_ext_info(ssh)) != 0) - return r; + if ((r = kex_maybe_send_ext_info(ssh)) != 0) + return r; debug("expecting SSH2_MSG_NEWKEYS"); return 0; } /* Check whether an ext_info value contains the expected version string */ static int kex_ext_info_check_ver(struct kex *kex, const char *name, const u_char *val, size_t len, const char *want_ver, u_int flag) { if (memchr(val, '\0', len) != NULL) { error("SSH2_MSG_EXT_INFO: %s value contains nul byte", name); return SSH_ERR_INVALID_FORMAT; } debug_f("%s=<%s>", name, val); if (strcmp(val, want_ver) == 0) kex->flags |= flag; else debug_f("unsupported version of %s extension", name); return 0; } +static int +kex_ext_info_client_parse(struct ssh *ssh, const char *name, + const u_char *value, size_t vlen) +{ + int r; + + /* NB. some messages are only accepted in the initial EXT_INFO */ + if (strcmp(name, "server-sig-algs") == 0) { + /* Ensure no \0 lurking in value */ + if (memchr(value, '\0', vlen) != NULL) { + error_f("nul byte in %s", name); + return SSH_ERR_INVALID_FORMAT; + } + debug_f("%s=<%s>", name, value); + free(ssh->kex->server_sig_algs); + ssh->kex->server_sig_algs = xstrdup((const char *)value); + } else if (ssh->kex->ext_info_received == 1 && + strcmp(name, "publickey-hostbound@openssh.com") == 0) { + if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen, + "0", KEX_HAS_PUBKEY_HOSTBOUND)) != 0) { + return r; + } + } else if (ssh->kex->ext_info_received == 1 && + strcmp(name, "ping@openssh.com") == 0) { + if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen, + "0", KEX_HAS_PING)) != 0) { + return r; + } + } else + debug_f("%s (unrecognised)", name); + + return 0; +} + +static int +kex_ext_info_server_parse(struct ssh *ssh, const char *name, + const u_char *value, size_t vlen) +{ + int r; + + if (strcmp(name, "ext-info-in-auth@openssh.com") == 0) { + if ((r = kex_ext_info_check_ver(ssh->kex, name, value, vlen, + "0", KEX_HAS_EXT_INFO_IN_AUTH)) != 0) { + return r; + } + } else + debug_f("%s (unrecognised)", name); + return 0; +} + int kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; + const int max_ext_info = kex->server ? 1 : 2; u_int32_t i, ninfo; char *name; u_char *val; size_t vlen; int r; debug("SSH2_MSG_EXT_INFO received"); + if (++kex->ext_info_received > max_ext_info) { + error("too many SSH2_MSG_EXT_INFO messages sent by peer"); + return dispatch_protocol_error(type, seq, ssh); + } ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error); if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0) return r; if (ninfo >= 1024) { error("SSH2_MSG_EXT_INFO with too many entries, expected " "<=1024, received %u", ninfo); return dispatch_protocol_error(type, seq, ssh); } for (i = 0; i < ninfo; i++) { if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0) return r; if ((r = sshpkt_get_string(ssh, &val, &vlen)) != 0) { free(name); return r; } - if (strcmp(name, "server-sig-algs") == 0) { - /* Ensure no \0 lurking in value */ - if (memchr(val, '\0', vlen) != NULL) { - error_f("nul byte in %s", name); - free(name); - free(val); - return SSH_ERR_INVALID_FORMAT; - } - debug_f("%s=<%s>", name, val); - kex->server_sig_algs = val; - val = NULL; - } else if (strcmp(name, - "publickey-hostbound@openssh.com") == 0) { - if ((r = kex_ext_info_check_ver(kex, name, val, vlen, - "0", KEX_HAS_PUBKEY_HOSTBOUND)) != 0) { - free(name); - free(val); + debug3_f("extension %s", name); + if (kex->server) { + if ((r = kex_ext_info_server_parse(ssh, name, + val, vlen)) != 0) return r; - } - } else if (strcmp(name, "ping@openssh.com") == 0) { - if ((r = kex_ext_info_check_ver(kex, name, val, vlen, - "0", KEX_HAS_PING)) != 0) { - free(name); - free(val); + } else { + if ((r = kex_ext_info_client_parse(ssh, name, + val, vlen)) != 0) return r; - } - } else - debug_f("%s (unrecognised)", name); + } free(name); free(val); } return sshpkt_get_end(ssh); } static int kex_input_newkeys(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; int r; debug("SSH2_MSG_NEWKEYS received"); + if (kex->ext_info_c && (kex->flags & KEX_INITIAL) != 0) + ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_input_ext_info); ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error); ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); if ((r = sshpkt_get_end(ssh)) != 0) return r; if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0) return r; kex->done = 1; kex->flags &= ~KEX_INITIAL; sshbuf_reset(kex->peer); /* sshbuf_reset(kex->my); */ kex->flags &= ~KEX_INIT_SENT; free(kex->name); kex->name = NULL; return 0; } int kex_send_kexinit(struct ssh *ssh) { u_char *cookie; struct kex *kex = ssh->kex; int r; if (kex == NULL) { error_f("no kex"); return SSH_ERR_INTERNAL_ERROR; } if (kex->flags & KEX_INIT_SENT) return 0; kex->done = 0; /* generate a random cookie */ if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) { 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_f("buffer error"); return SSH_ERR_INTERNAL_ERROR; } arc4random_buf(cookie, KEX_COOKIE_LEN); if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 || (r = sshpkt_putb(ssh, kex->my)) != 0 || (r = sshpkt_send(ssh)) != 0) { error_fr(r, "compose reply"); return r; } debug("SSH2_MSG_KEXINIT sent"); kex->flags |= KEX_INIT_SENT; return 0; } int kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) { struct kex *kex = ssh->kex; const u_char *ptr; u_int i; size_t dlen; int r; debug("SSH2_MSG_KEXINIT received"); if (kex == NULL) { error_f("no kex"); return SSH_ERR_INTERNAL_ERROR; } ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error); ptr = sshpkt_ptr(ssh, &dlen); if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) return r; /* discard packet */ for (i = 0; i < KEX_COOKIE_LEN; i++) { if ((r = sshpkt_get_u8(ssh, NULL)) != 0) { error_fr(r, "discard cookie"); return r; } } for (i = 0; i < PROPOSAL_MAX; i++) { if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) { error_fr(r, "discard proposal"); return r; } } /* * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported * KEX method has the server move first, but a server might be using * a custom method or one that we otherwise don't support. We should * be prepared to remember first_kex_follows here so we can eat a * packet later. * XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means * for cases where the server *doesn't* go first. I guess we should * ignore it when it is set for these cases, which is what we do now. */ if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */ (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */ (r = sshpkt_get_end(ssh)) != 0) return r; if (!(kex->flags & KEX_INIT_SENT)) if ((r = kex_send_kexinit(ssh)) != 0) return r; if ((r = kex_choose_conf(ssh, seq)) != 0) return r; if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) return (kex->kex[kex->kex_type])(ssh); error_f("unknown kex type %u", kex->kex_type); return SSH_ERR_INTERNAL_ERROR; } struct kex * kex_new(void) { struct kex *kex; if ((kex = calloc(1, sizeof(*kex))) == NULL || (kex->peer = sshbuf_new()) == NULL || (kex->my = sshbuf_new()) == NULL || (kex->client_version = sshbuf_new()) == NULL || (kex->server_version = sshbuf_new()) == NULL || (kex->session_id = sshbuf_new()) == NULL) { kex_free(kex); return NULL; } return kex; } void kex_free_newkeys(struct newkeys *newkeys) { if (newkeys == NULL) return; if (newkeys->enc.key) { explicit_bzero(newkeys->enc.key, newkeys->enc.key_len); free(newkeys->enc.key); newkeys->enc.key = NULL; } if (newkeys->enc.iv) { explicit_bzero(newkeys->enc.iv, newkeys->enc.iv_len); free(newkeys->enc.iv); newkeys->enc.iv = NULL; } free(newkeys->enc.name); explicit_bzero(&newkeys->enc, sizeof(newkeys->enc)); free(newkeys->comp.name); explicit_bzero(&newkeys->comp, sizeof(newkeys->comp)); mac_clear(&newkeys->mac); if (newkeys->mac.key) { explicit_bzero(newkeys->mac.key, newkeys->mac.key_len); free(newkeys->mac.key); newkeys->mac.key = NULL; } free(newkeys->mac.name); explicit_bzero(&newkeys->mac, sizeof(newkeys->mac)); freezero(newkeys, sizeof(*newkeys)); } void kex_free(struct kex *kex) { u_int mode; if (kex == NULL) return; #ifdef WITH_OPENSSL DH_free(kex->dh); #ifdef OPENSSL_HAS_ECC EC_KEY_free(kex->ec_client_key); #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ for (mode = 0; mode < MODE_MAX; mode++) { kex_free_newkeys(kex->newkeys[mode]); kex->newkeys[mode] = NULL; } sshbuf_free(kex->peer); sshbuf_free(kex->my); sshbuf_free(kex->client_version); sshbuf_free(kex->server_version); sshbuf_free(kex->client_pub); sshbuf_free(kex->session_id); sshbuf_free(kex->initial_sig); sshkey_free(kex->initial_hostkey); free(kex->failed_choice); free(kex->hostkey_alg); free(kex->name); free(kex); } int kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX]) { int r; if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0) return r; ssh->kex->flags = KEX_INITIAL; kex_reset_dispatch(ssh); ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); return 0; } int kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX]) { int r; if ((r = kex_ready(ssh, proposal)) != 0) return r; if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */ kex_free(ssh->kex); ssh->kex = NULL; return r; } return 0; } /* * Request key re-exchange, returns 0 on success or a ssherr.h error * code otherwise. Must not be called if KEX is incomplete or in-progress. */ int kex_start_rekex(struct ssh *ssh) { if (ssh->kex == NULL) { error_f("no kex"); return SSH_ERR_INTERNAL_ERROR; } if (ssh->kex->done == 0) { error_f("requested twice"); return SSH_ERR_INTERNAL_ERROR; } ssh->kex->done = 0; return kex_send_kexinit(ssh); } static int choose_enc(struct sshenc *enc, char *client, char *server) { char *name = match_list(client, server, NULL); if (name == NULL) return SSH_ERR_NO_CIPHER_ALG_MATCH; if ((enc->cipher = cipher_by_name(name)) == NULL) { error_f("unsupported cipher %s", name); free(name); return SSH_ERR_INTERNAL_ERROR; } enc->name = name; enc->enabled = 0; enc->iv = NULL; enc->iv_len = cipher_ivlen(enc->cipher); enc->key = NULL; enc->key_len = cipher_keylen(enc->cipher); enc->block_size = cipher_blocksize(enc->cipher); return 0; } static int choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server) { char *name = match_list(client, server, NULL); if (name == NULL) return SSH_ERR_NO_MAC_ALG_MATCH; if (mac_setup(mac, name) < 0) { error_f("unsupported MAC %s", name); free(name); return SSH_ERR_INTERNAL_ERROR; } mac->name = name; mac->key = NULL; mac->enabled = 0; return 0; } static int choose_comp(struct sshcomp *comp, char *client, char *server) { char *name = match_list(client, server, NULL); if (name == NULL) return SSH_ERR_NO_COMPRESS_ALG_MATCH; #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 #endif /* WITH_ZLIB */ if (strcmp(name, "none") == 0) { comp->type = COMP_NONE; } else { error_f("unsupported compression scheme %s", name); free(name); return SSH_ERR_INTERNAL_ERROR; } comp->name = name; return 0; } static int choose_kex(struct kex *k, char *client, char *server) { const struct kexalg *kexalg; k->name = match_list(client, server, NULL); debug("kex: algorithm: %s", k->name ? k->name : "(no match)"); if (k->name == NULL) return SSH_ERR_NO_KEX_ALG_MATCH; if ((kexalg = kex_alg_by_name(k->name)) == NULL) { error_f("unsupported KEX method %s", k->name); return SSH_ERR_INTERNAL_ERROR; } k->kex_type = kexalg->type; k->hash_alg = kexalg->hash_alg; k->ec_nid = kexalg->ec_nid; return 0; } static int choose_hostkeyalg(struct kex *k, char *client, char *server) { free(k->hostkey_alg); k->hostkey_alg = match_list(client, server, NULL); debug("kex: host key algorithm: %s", k->hostkey_alg ? k->hostkey_alg : "(no match)"); if (k->hostkey_alg == NULL) return SSH_ERR_NO_HOSTKEY_ALG_MATCH; k->hostkey_type = sshkey_type_from_name(k->hostkey_alg); if (k->hostkey_type == KEY_UNSPEC) { 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); return 0; } static int proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX]) { static int check[] = { PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1 }; int *idx; char *p; for (idx = &check[0]; *idx != -1; idx++) { if ((p = strchr(my[*idx], ',')) != NULL) *p = '\0'; if ((p = strchr(peer[*idx], ',')) != NULL) *p = '\0'; if (strcmp(my[*idx], peer[*idx]) != 0) { debug2("proposal mismatch: my %s peer %s", my[*idx], peer[*idx]); return (0); } } debug2("proposals match"); return (1); } static int kexalgs_contains(char **peer, const char *ext) { return has_any_alg(peer[PROPOSAL_KEX_ALGS], ext); } static int kex_choose_conf(struct ssh *ssh, uint32_t seq) { struct kex *kex = ssh->kex; struct newkeys *newkeys; char **my = NULL, **peer = NULL; char **cprop, **sprop; int nenc, nmac, ncomp; u_int mode, ctos, need, dh_need, authlen; int r, first_kex_follows; debug2("local %s KEXINIT proposal", kex->server ? "server" : "client"); if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0) goto out; debug2("peer %s KEXINIT proposal", kex->server ? "client" : "server"); if ((r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0) goto out; if (kex->server) { cprop=peer; sprop=my; } else { cprop=my; sprop=peer; } /* Check whether peer supports ext_info/kex_strict */ if ((kex->flags & KEX_INITIAL) != 0) { if (kex->server) { kex->ext_info_c = kexalgs_contains(peer, "ext-info-c"); kex->kex_strict = kexalgs_contains(peer, "kex-strict-c-v00@openssh.com"); } else { + kex->ext_info_s = kexalgs_contains(peer, "ext-info-s"); kex->kex_strict = kexalgs_contains(peer, "kex-strict-s-v00@openssh.com"); } if (kex->kex_strict) { debug3_f("will use strict KEX ordering"); if (seq != 0) ssh_packet_disconnect(ssh, "strict KEX violation: " "KEXINIT was not the first packet"); } } /* Check whether client supports rsa-sha2 algorithms */ if (kex->server && (kex->flags & KEX_INITIAL)) { if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS], "rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com")) kex->flags |= KEX_RSA_SHA2_256_SUPPORTED; if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS], "rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com")) kex->flags |= KEX_RSA_SHA2_512_SUPPORTED; } /* Algorithm Negotiation */ if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS])) != 0) { kex->failed_choice = peer[PROPOSAL_KEX_ALGS]; peer[PROPOSAL_KEX_ALGS] = NULL; goto out; } if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) { kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS]; peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL; goto out; } for (mode = 0; mode < MODE_MAX; mode++) { if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } kex->newkeys[mode] = newkeys; ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; if ((r = choose_enc(&newkeys->enc, cprop[nenc], sprop[nenc])) != 0) { kex->failed_choice = peer[nenc]; peer[nenc] = NULL; goto out; } authlen = cipher_authlen(newkeys->enc.cipher); /* ignore mac for authenticated encryption */ if (authlen == 0 && (r = choose_mac(ssh, &newkeys->mac, cprop[nmac], sprop[nmac])) != 0) { kex->failed_choice = peer[nmac]; peer[nmac] = NULL; goto out; } if ((r = choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp])) != 0) { kex->failed_choice = peer[ncomp]; peer[ncomp] = NULL; goto out; } debug("kex: %s cipher: %s MAC: %s compression: %s", ctos ? "client->server" : "server->client", newkeys->enc.name, authlen == 0 ? newkeys->mac.name : "", newkeys->comp.name); } need = dh_need = 0; for (mode = 0; mode < MODE_MAX; mode++) { newkeys = kex->newkeys[mode]; need = MAXIMUM(need, newkeys->enc.key_len); need = MAXIMUM(need, newkeys->enc.block_size); need = MAXIMUM(need, newkeys->enc.iv_len); need = MAXIMUM(need, newkeys->mac.key_len); dh_need = MAXIMUM(dh_need, cipher_seclen(newkeys->enc.cipher)); dh_need = MAXIMUM(dh_need, newkeys->enc.block_size); dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len); dh_need = MAXIMUM(dh_need, newkeys->mac.key_len); } /* XXX need runden? */ kex->we_need = need; kex->dh_need = dh_need; /* ignore the next message if the proposals do not match */ if (first_kex_follows && !proposals_match(my, peer)) ssh->dispatch_skip_packets = 1; r = 0; out: kex_prop_free(my); kex_prop_free(peer); return r; } static int derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, const struct sshbuf *shared_secret, u_char **keyp) { struct kex *kex = ssh->kex; struct ssh_digest_ctx *hashctx = NULL; char c = id; u_int have; size_t mdsz; u_char *digest; int r; if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0) return SSH_ERR_INVALID_ARGUMENT; if ((digest = calloc(1, ROUNDUP(need, mdsz))) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* K1 = HASH(K || H || "A" || session_id) */ if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL || ssh_digest_update_buffer(hashctx, shared_secret) != 0 || ssh_digest_update(hashctx, hash, hashlen) != 0 || ssh_digest_update(hashctx, &c, 1) != 0 || ssh_digest_update_buffer(hashctx, kex->session_id) != 0 || ssh_digest_final(hashctx, digest, mdsz) != 0) { r = SSH_ERR_LIBCRYPTO_ERROR; error_f("KEX hash failed"); goto out; } ssh_digest_free(hashctx); hashctx = NULL; /* * expand key: * Kn = HASH(K || H || K1 || K2 || ... || Kn-1) * Key = K1 || K2 || ... || Kn */ for (have = mdsz; need > have; have += mdsz) { if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL || ssh_digest_update_buffer(hashctx, shared_secret) != 0 || ssh_digest_update(hashctx, hash, hashlen) != 0 || ssh_digest_update(hashctx, digest, have) != 0 || ssh_digest_final(hashctx, digest + have, mdsz) != 0) { error_f("KDF failed"); r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } ssh_digest_free(hashctx); hashctx = NULL; } #ifdef DEBUG_KEX fprintf(stderr, "key '%c'== ", c); dump_digest("key", digest, need); #endif *keyp = digest; digest = NULL; r = 0; out: free(digest); ssh_digest_free(hashctx); return r; } #define NKEYS 6 int kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen, const struct sshbuf *shared_secret) { struct kex *kex = ssh->kex; u_char *keys[NKEYS]; u_int i, j, mode, ctos; int r; /* save initial hash as session id */ if ((kex->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, shared_secret, &keys[i])) != 0) { for (j = 0; j < i; j++) free(keys[j]); return r; } } for (mode = 0; mode < MODE_MAX; mode++) { ctos = (!kex->server && mode == MODE_OUT) || (kex->server && mode == MODE_IN); kex->newkeys[mode]->enc.iv = keys[ctos ? 0 : 1]; kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3]; kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5]; } return 0; } int kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp) { struct kex *kex = ssh->kex; *pubp = NULL; *prvp = NULL; if (kex->load_host_public_key == NULL || kex->load_host_private_key == NULL) { error_f("missing hostkey loader"); return SSH_ERR_INVALID_ARGUMENT; } *pubp = kex->load_host_public_key(kex->hostkey_type, kex->hostkey_nid, ssh); *prvp = kex->load_host_private_key(kex->hostkey_type, kex->hostkey_nid, ssh); if (*pubp == NULL) return SSH_ERR_NO_HOSTKEY_LOADED; return 0; } int kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key) { struct kex *kex = ssh->kex; if (kex->verify_host_key == NULL) { error_f("missing hostkey verifier"); return SSH_ERR_INVALID_ARGUMENT; } if (server_host_key->type != kex->hostkey_type || (kex->hostkey_type == KEY_ECDSA && server_host_key->ecdsa_nid != kex->hostkey_nid)) return SSH_ERR_KEY_TYPE_MISMATCH; if (kex->verify_host_key(server_host_key, ssh) == -1) return SSH_ERR_SIGNATURE_INVALID; return 0; } #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void dump_digest(const char *msg, const u_char *digest, int len) { fprintf(stderr, "%s\n", msg); sshbuf_dump_data(digest, len, stderr); } #endif /* * Send a plaintext error message to the peer, suffixed by \r\n. * Only used during banner exchange, and there only for the server. */ static void send_error(struct ssh *ssh, char *msg) { char *crnl = "\r\n"; if (!ssh->kex->server) return; if (atomicio(vwrite, ssh_packet_get_connection_out(ssh), msg, strlen(msg)) != strlen(msg) || atomicio(vwrite, ssh_packet_get_connection_out(ssh), crnl, strlen(crnl)) != strlen(crnl)) error_f("write: %.100s", strerror(errno)); } /* * Sends our identification string and waits for the peer's. Will block for * up to timeout_ms (or indefinitely if timeout_ms <= 0). * Returns on 0 success or a ssherr.h code on failure. */ int kex_exchange_identification(struct ssh *ssh, int timeout_ms, const char *version_addendum) { int remote_major, remote_minor, mismatch, oerrno = 0; size_t len, n; int r, expect_nl; u_char c; struct sshbuf *our_version = ssh->kex->server ? ssh->kex->server_version : ssh->kex->client_version; struct sshbuf *peer_version = ssh->kex->server ? ssh->kex->client_version : ssh->kex->server_version; char *our_version_string = NULL, *peer_version_string = NULL; char *cp, *remote_version = NULL; /* Prepare and send our banner */ sshbuf_reset(our_version); if (version_addendum != NULL && *version_addendum == '\0') version_addendum = NULL; - if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%.100s%s%s\r\n", + if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%s%s%s\r\n", PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, version_addendum == NULL ? "" : " ", version_addendum == NULL ? "" : version_addendum)) != 0) { 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)) { 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 */ oerrno = errno; error_fr(r, "sshbuf_consume_end"); goto out; } our_version_string = sshbuf_dup_string(our_version); if (our_version_string == NULL) { error_f("sshbuf_dup_string failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } debug("Local version string %.100s", our_version_string); /* Read other side's version identification. */ for (n = 0; ; n++) { if (n >= SSH_MAX_PRE_BANNER_LINES) { send_error(ssh, "No SSH identification string " "received."); error_f("No SSH version received in first %u lines " "from server", SSH_MAX_PRE_BANNER_LINES); r = SSH_ERR_INVALID_FORMAT; goto out; } sshbuf_reset(peer_version); expect_nl = 0; for (;;) { if (timeout_ms > 0) { r = waitrfd(ssh_packet_get_connection_in(ssh), &timeout_ms, NULL); if (r == -1 && errno == ETIMEDOUT) { send_error(ssh, "Timed out waiting " "for SSH identification string."); error("Connection timed out during " "banner exchange"); r = SSH_ERR_CONN_TIMEOUT; goto out; } else if (r == -1) { oerrno = errno; error_f("%s", strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; goto out; } } len = atomicio(read, ssh_packet_get_connection_in(ssh), &c, 1); if (len != 1 && errno == EPIPE) { verbose_f("Connection closed by remote host"); r = SSH_ERR_CONN_CLOSED; goto out; } else if (len != 1) { oerrno = errno; error_f("read: %.100s", strerror(errno)); r = SSH_ERR_SYSTEM_ERROR; goto out; } if (c == '\r') { expect_nl = 1; continue; } if (c == '\n') break; if (c == '\0' || expect_nl) { verbose_f("banner line contains invalid " "characters"); goto invalid; } if ((r = sshbuf_put_u8(peer_version, c)) != 0) { oerrno = errno; error_fr(r, "sshbuf_put"); goto out; } if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) { verbose_f("banner line too long"); goto invalid; } } /* Is this an actual protocol banner? */ if (sshbuf_len(peer_version) > 4 && memcmp(sshbuf_ptr(peer_version), "SSH-", 4) == 0) break; /* If not, then just log the line and continue */ if ((cp = sshbuf_dup_string(peer_version)) == NULL) { error_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) { verbose_f("client sent invalid protocol identifier " "\"%.256s\"", cp); free(cp); goto invalid; } debug_f("banner line %zu: %s", n, cp); free(cp); } peer_version_string = sshbuf_dup_string(peer_version); if (peer_version_string == NULL) fatal_f("sshbuf_dup_string failed"); /* XXX must be same size for sscanf */ if ((remote_version = calloc(1, sshbuf_len(peer_version))) == NULL) { error_f("calloc failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } /* * Check that the versions match. In future this might accept * several versions and set appropriate flags to handle them. */ if (sscanf(peer_version_string, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor, remote_version) != 3) { error("Bad remote protocol version identification: '%.100s'", peer_version_string); invalid: send_error(ssh, "Invalid SSH identification string."); r = SSH_ERR_INVALID_FORMAT; goto out; } debug("Remote protocol version %d.%d, remote software version %.100s", remote_major, remote_minor, remote_version); compat_banner(ssh, remote_version); mismatch = 0; switch (remote_major) { case 2: break; case 1: if (remote_minor != 99) mismatch = 1; break; default: mismatch = 1; break; } if (mismatch) { error("Protocol major versions differ: %d vs. %d", PROTOCOL_MAJOR_2, remote_major); send_error(ssh, "Protocol major versions differ."); r = SSH_ERR_NO_PROTOCOL_VERSION; goto out; } if (ssh->kex->server && (ssh->compat & SSH_BUG_PROBE) != 0) { logit("probed from %s port %d with %s. Don't panic.", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), peer_version_string); r = SSH_ERR_CONN_CLOSED; /* XXX */ goto out; } if (ssh->kex->server && (ssh->compat & SSH_BUG_SCANNER) != 0) { logit("scanned from %s port %d with %s. Don't panic.", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), peer_version_string); r = SSH_ERR_CONN_CLOSED; /* XXX */ goto out; } /* success */ r = 0; out: free(our_version_string); free(peer_version_string); free(remote_version); if (r == SSH_ERR_SYSTEM_ERROR) errno = oerrno; return r; } diff --git a/crypto/openssh/kex.h b/crypto/openssh/kex.h index 272ebb43d79d..ba3a6a4eaf36 100644 --- a/crypto/openssh/kex.h +++ b/crypto/openssh/kex.h @@ -1,271 +1,276 @@ -/* $OpenBSD: kex.h,v 1.120 2023/12/18 14:45:17 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.121 2023/12/18 14:45:49 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef KEX_H #define KEX_H #include "mac.h" #include "crypto_api.h" #ifdef WITH_OPENSSL # include # include # include # ifdef OPENSSL_HAS_ECC # include # else /* OPENSSL_HAS_ECC */ # define EC_KEY void # define EC_GROUP void # define EC_POINT void # endif /* OPENSSL_HAS_ECC */ #else /* WITH_OPENSSL */ # define DH void # define BIGNUM void # define EC_KEY void # define EC_GROUP void # define EC_POINT void #endif /* WITH_OPENSSL */ #define KEX_COOKIE_LEN 16 #define KEX_DH1 "diffie-hellman-group1-sha1" #define KEX_DH14_SHA1 "diffie-hellman-group14-sha1" #define KEX_DH14_SHA256 "diffie-hellman-group14-sha256" #define KEX_DH16_SHA512 "diffie-hellman-group16-sha512" #define KEX_DH18_SHA512 "diffie-hellman-group18-sha512" #define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1" #define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256" #define KEX_ECDH_SHA2_NISTP256 "ecdh-sha2-nistp256" #define KEX_ECDH_SHA2_NISTP384 "ecdh-sha2-nistp384" #define KEX_ECDH_SHA2_NISTP521 "ecdh-sha2-nistp521" #define KEX_CURVE25519_SHA256 "curve25519-sha256" #define KEX_CURVE25519_SHA256_OLD "curve25519-sha256@libssh.org" #define KEX_SNTRUP761X25519_SHA512 "sntrup761x25519-sha512@openssh.com" #define COMP_NONE 0 /* pre-auth compression (COMP_ZLIB) is only supported in the client */ #define COMP_ZLIB 1 #define COMP_DELAYED 2 #define CURVE25519_SIZE 32 enum kex_init_proposals { PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, PROPOSAL_ENC_ALGS_CTOS, PROPOSAL_ENC_ALGS_STOC, PROPOSAL_MAC_ALGS_CTOS, PROPOSAL_MAC_ALGS_STOC, PROPOSAL_COMP_ALGS_CTOS, PROPOSAL_COMP_ALGS_STOC, PROPOSAL_LANG_CTOS, PROPOSAL_LANG_STOC, PROPOSAL_MAX }; enum kex_modes { MODE_IN, MODE_OUT, MODE_MAX }; enum kex_exchange { KEX_DH_GRP1_SHA1, KEX_DH_GRP14_SHA1, KEX_DH_GRP14_SHA256, KEX_DH_GRP16_SHA512, KEX_DH_GRP18_SHA512, KEX_DH_GEX_SHA1, KEX_DH_GEX_SHA256, KEX_ECDH_SHA2, KEX_C25519_SHA256, KEX_KEM_SNTRUP761X25519_SHA512, KEX_MAX }; /* kex->flags */ #define KEX_INIT_SENT 0x0001 #define KEX_INITIAL 0x0002 #define KEX_HAS_PUBKEY_HOSTBOUND 0x0004 #define KEX_RSA_SHA2_256_SUPPORTED 0x0008 /* only set in server for now */ #define KEX_RSA_SHA2_512_SUPPORTED 0x0010 /* only set in server for now */ #define KEX_HAS_PING 0x0020 +#define KEX_HAS_EXT_INFO_IN_AUTH 0x0040 struct sshenc { char *name; const struct sshcipher *cipher; int enabled; u_int key_len; u_int iv_len; u_int block_size; u_char *key; u_char *iv; }; struct sshcomp { u_int type; int enabled; char *name; }; struct newkeys { struct sshenc enc; struct sshmac mac; struct sshcomp comp; }; struct ssh; struct sshbuf; struct kex { struct newkeys *newkeys[MODE_MAX]; u_int we_need; u_int dh_need; int server; char *name; char *hostkey_alg; int hostkey_type; int hostkey_nid; u_int kex_type; char *server_sig_algs; int ext_info_c; + int ext_info_s; int kex_strict; + int ext_info_received; struct sshbuf *my; struct sshbuf *peer; struct sshbuf *client_version; struct sshbuf *server_version; struct sshbuf *session_id; struct sshbuf *initial_sig; struct sshkey *initial_hostkey; sig_atomic_t done; u_int flags; int hash_alg; int ec_nid; char *failed_choice; int (*verify_host_key)(struct sshkey *, struct ssh *); struct sshkey *(*load_host_public_key)(int, int, struct ssh *); struct sshkey *(*load_host_private_key)(int, int, struct ssh *); int (*host_key_index)(struct sshkey *, int, struct ssh *); int (*sign)(struct ssh *, struct sshkey *, struct sshkey *, u_char **, size_t *, const u_char *, size_t, const char *); int (*kex[KEX_MAX])(struct ssh *); /* kex specific state */ DH *dh; /* DH */ u_int min, max, nbits; /* GEX */ EC_KEY *ec_client_key; /* ECDH */ const EC_GROUP *ec_group; /* ECDH */ u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 + KEM */ u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */ u_char sntrup761_client_key[crypto_kem_sntrup761_SECRETKEYBYTES]; /* KEM */ struct sshbuf *client_pub; }; int kex_names_valid(const char *); char *kex_alg_list(char); char *kex_names_cat(const char *, const char *); int kex_assemble_names(char **, const char *, const char *); void kex_proposal_populate_entries(struct ssh *, char *prop[PROPOSAL_MAX], const char *, const char *, const char *, const char *, const char *); void kex_proposal_free_entries(char *prop[PROPOSAL_MAX]); int kex_exchange_identification(struct ssh *, int, const char *); struct kex *kex_new(void); int kex_ready(struct ssh *, char *[PROPOSAL_MAX]); int kex_setup(struct ssh *, char *[PROPOSAL_MAX]); void kex_free_newkeys(struct newkeys *); void kex_free(struct kex *); int kex_buf2prop(struct sshbuf *, int *, char ***); int kex_prop2buf(struct sshbuf *, char *proposal[PROPOSAL_MAX]); void kex_prop_free(char **); int kex_load_hostkey(struct ssh *, struct sshkey **, struct sshkey **); int kex_verify_host_key(struct ssh *, struct sshkey *); int kex_send_kexinit(struct ssh *); int kex_input_kexinit(int, u_int32_t, struct ssh *); int kex_input_ext_info(int, u_int32_t, struct ssh *); int kex_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 *); +int kex_server_update_ext_info(struct ssh *); +void kex_set_server_sig_algs(struct ssh *, const char *); int kexgex_client(struct ssh *); int kexgex_server(struct ssh *); int kex_gen_client(struct ssh *); int kex_gen_server(struct ssh *); int kex_dh_keypair(struct kex *); int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); int kex_dh_dec(struct kex *, const struct sshbuf *, struct sshbuf **); int kex_ecdh_keypair(struct kex *); int kex_ecdh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); int kex_ecdh_dec(struct kex *, const struct sshbuf *, struct sshbuf **); int kex_c25519_keypair(struct kex *); int kex_c25519_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); int kex_c25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **); int kex_kem_sntrup761x25519_keypair(struct kex *); int kex_kem_sntrup761x25519_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); int kex_kem_sntrup761x25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **); int kex_dh_keygen(struct kex *); int kex_dh_compute_key(struct kex *, BIGNUM *, struct sshbuf *); int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, const struct sshbuf *, const struct sshbuf *, const struct sshbuf *, int, int, int, const BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, const u_char *, size_t, u_char *, size_t *); void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); int kexc25519_shared_key(const u_char key[CURVE25519_SIZE], const u_char pub[CURVE25519_SIZE], struct sshbuf *out) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void dump_digest(const char *, const u_char *, int); #endif #if !defined(WITH_OPENSSL) || !defined(OPENSSL_HAS_ECC) # undef EC_KEY # undef EC_GROUP # undef EC_POINT #endif #endif diff --git a/crypto/openssh/log.c b/crypto/openssh/log.c index 99bf046a792a..9fc1a2e2eaf6 100644 --- a/crypto/openssh/log.c +++ b/crypto/openssh/log.c @@ -1,500 +1,504 @@ -/* $OpenBSD: log.c,v 1.60 2021/09/16 15:11:19 djm Exp $ */ +/* $OpenBSD: log.c,v 1.61 2023/12/06 21:06:48 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) # include #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 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; #define LOG_SYSLOG_VIS (VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL) #define LOG_STDERR_VIS (VIS_SAFE|VIS_OCTAL) /* textual representation of log-facilities/levels */ static struct { const char *name; SyslogFacility val; } log_facilities[] = { { "DAEMON", SYSLOG_FACILITY_DAEMON }, { "USER", SYSLOG_FACILITY_USER }, { "AUTH", SYSLOG_FACILITY_AUTH }, #ifdef LOG_AUTHPRIV { "AUTHPRIV", SYSLOG_FACILITY_AUTHPRIV }, #endif { "LOCAL0", SYSLOG_FACILITY_LOCAL0 }, { "LOCAL1", SYSLOG_FACILITY_LOCAL1 }, { "LOCAL2", SYSLOG_FACILITY_LOCAL2 }, { "LOCAL3", SYSLOG_FACILITY_LOCAL3 }, { "LOCAL4", SYSLOG_FACILITY_LOCAL4 }, { "LOCAL5", SYSLOG_FACILITY_LOCAL5 }, { "LOCAL6", SYSLOG_FACILITY_LOCAL6 }, { "LOCAL7", SYSLOG_FACILITY_LOCAL7 }, { NULL, SYSLOG_FACILITY_NOT_SET } }; static struct { const char *name; LogLevel val; } log_levels[] = { { "QUIET", SYSLOG_LEVEL_QUIET }, { "FATAL", SYSLOG_LEVEL_FATAL }, { "ERROR", SYSLOG_LEVEL_ERROR }, { "INFO", SYSLOG_LEVEL_INFO }, { "VERBOSE", SYSLOG_LEVEL_VERBOSE }, { "DEBUG", SYSLOG_LEVEL_DEBUG1 }, { "DEBUG1", SYSLOG_LEVEL_DEBUG1 }, { "DEBUG2", SYSLOG_LEVEL_DEBUG2 }, { "DEBUG3", SYSLOG_LEVEL_DEBUG3 }, { NULL, SYSLOG_LEVEL_NOT_SET } }; LogLevel log_level_get(void) { return log_level; } SyslogFacility log_facility_number(char *name) { int i; if (name != NULL) for (i = 0; log_facilities[i].name; i++) if (strcasecmp(log_facilities[i].name, name) == 0) return log_facilities[i].val; return SYSLOG_FACILITY_NOT_SET; } const char * log_facility_name(SyslogFacility facility) { u_int i; for (i = 0; log_facilities[i].name; i++) if (log_facilities[i].val == facility) return log_facilities[i].name; return NULL; } LogLevel log_level_number(char *name) { int i; if (name != NULL) for (i = 0; log_levels[i].name; i++) if (strcasecmp(log_levels[i].name, name) == 0) return log_levels[i].val; return SYSLOG_LEVEL_NOT_SET; } const char * log_level_name(LogLevel level) { u_int i; for (i = 0; log_levels[i].name != NULL; i++) if (log_levels[i].val == level) return log_levels[i].name; return NULL; } void log_verbose_add(const char *s) { char **tmp; /* 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 log_verbose_reset(void) { size_t i; for (i = 0; i < nlog_verbose; i++) free(log_verbose[i]); free(log_verbose); log_verbose = NULL; nlog_verbose = 0; } /* * Initialize the log. */ void 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; #endif argv0 = av0; if (log_change_level(level) != 0) { fprintf(stderr, "Unrecognized internal syslog level code %d\n", (int) level); exit(1); } log_handler = NULL; log_handler_ctx = NULL; log_on_stderr = on_stderr; if (on_stderr) return; switch (facility) { case SYSLOG_FACILITY_DAEMON: log_facility = LOG_DAEMON; break; case SYSLOG_FACILITY_USER: log_facility = LOG_USER; break; case SYSLOG_FACILITY_AUTH: log_facility = LOG_AUTH; break; #ifdef LOG_AUTHPRIV case SYSLOG_FACILITY_AUTHPRIV: log_facility = LOG_AUTHPRIV; break; #endif case SYSLOG_FACILITY_LOCAL0: log_facility = LOG_LOCAL0; break; case SYSLOG_FACILITY_LOCAL1: log_facility = LOG_LOCAL1; break; case SYSLOG_FACILITY_LOCAL2: log_facility = LOG_LOCAL2; break; case SYSLOG_FACILITY_LOCAL3: log_facility = LOG_LOCAL3; break; case SYSLOG_FACILITY_LOCAL4: log_facility = LOG_LOCAL4; break; case SYSLOG_FACILITY_LOCAL5: log_facility = LOG_LOCAL5; break; case SYSLOG_FACILITY_LOCAL6: log_facility = LOG_LOCAL6; break; case SYSLOG_FACILITY_LOCAL7: log_facility = LOG_LOCAL7; break; default: fprintf(stderr, "Unrecognized internal syslog facility code %d\n", (int) facility); exit(1); } /* * If an external library (eg libwrap) attempts to use syslog * immediately after reexec, syslog may be pointing to the wrong * facility, so we force an open/close of syslog here. */ #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata); closelog_r(&sdata); #else openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); closelog(); #endif } int log_change_level(LogLevel new_log_level) { /* no-op if log_init has not been called */ if (argv0 == NULL) return 0; switch (new_log_level) { case SYSLOG_LEVEL_QUIET: case SYSLOG_LEVEL_FATAL: case SYSLOG_LEVEL_ERROR: case SYSLOG_LEVEL_INFO: case SYSLOG_LEVEL_VERBOSE: case SYSLOG_LEVEL_DEBUG1: case SYSLOG_LEVEL_DEBUG2: case SYSLOG_LEVEL_DEBUG3: log_level = new_log_level; return 0; default: return -1; } } int log_is_on_stderr(void) { return log_on_stderr && log_stderr_fd == STDERR_FILENO; } /* redirect what would usually get written to stderr to specified file */ void 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)); exit(1); } log_stderr_fd = fd; } #define MSGBUFSIZ 1024 void set_log_handler(log_handler_fn *handler, void *ctx) { log_handler = handler; log_handler_ctx = ctx; } static void do_log(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; #endif char msgbuf[MSGBUFSIZ]; char fmtbuf[MSGBUFSIZ]; char *txt = NULL; int pri = LOG_INFO; int saved_errno = errno; log_handler_fn *tmp_handler; const char *progname = argv0 != NULL ? argv0 : __progname; if (!force && level > log_level) return; switch (level) { case SYSLOG_LEVEL_FATAL: if (!log_on_stderr) txt = "fatal"; pri = LOG_CRIT; break; case SYSLOG_LEVEL_ERROR: if (!log_on_stderr) txt = "error"; pri = LOG_ERR; break; case SYSLOG_LEVEL_INFO: pri = LOG_INFO; break; case SYSLOG_LEVEL_VERBOSE: pri = LOG_INFO; break; case SYSLOG_LEVEL_DEBUG1: txt = "debug1"; pri = LOG_DEBUG; break; case SYSLOG_LEVEL_DEBUG2: txt = "debug2"; pri = LOG_DEBUG; break; case SYSLOG_LEVEL_DEBUG3: txt = "debug3"; pri = LOG_DEBUG; break; default: txt = "internal error"; pri = LOG_ERR; break; } if (txt != NULL && log_handler == NULL) { snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt); vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, 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, force, fmtbuf, log_handler_ctx); log_handler = tmp_handler; } else if (log_on_stderr) { snprintf(msgbuf, sizeof msgbuf, "%s%s%.*s\r\n", (log_on_stderr > 1) ? progname : "", (log_on_stderr > 1) ? ": " : "", (int)sizeof msgbuf - 3, fmtbuf); (void)write(log_stderr_fd, msgbuf, strlen(msgbuf)); } else { #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) openlog_r(progname, LOG_PID, log_facility, &sdata); syslog_r(pri, &sdata, "%.500s", fmtbuf); closelog_r(&sdata); #else openlog(progname, LOG_PID, log_facility); syslog(pri, "%.500s", fmtbuf); closelog(); #endif } 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; + /* short circuit processing early if we're not going to log anything */ + if (nlog_verbose == 0 && level > log_level) + return; + snprintf(tag, sizeof(tag), "%.48s:%.48s():%d (pid=%ld)", (cp = strrchr(file, '/')) == NULL ? file : cp + 1, func, line, (long)getpid()); for (i = 0; i < nlog_verbose; i++) { if (match_pattern_list(tag, log_verbose[i], 0) == 1) { forced = 1; break; } } if (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(level, forced, suffix, fmt2, args); } void sshlogdirect(LogLevel level, int forced, const char *fmt, ...) { va_list args; va_start(args, fmt); do_log(level, forced, NULL, fmt, args); va_end(args); } diff --git a/crypto/openssh/m4/openssh.m4 b/crypto/openssh/m4/openssh.m4 index 8c33c701b8b4..5d4c56280fce 100644 --- a/crypto/openssh/m4/openssh.m4 +++ b/crypto/openssh/m4/openssh.m4 @@ -1,203 +1,217 @@ dnl OpenSSH-specific autoconf macros dnl -dnl OSSH_CHECK_CFLAG_COMPILE(check_flag[, define_flag]) -dnl Check that $CC accepts a flag 'check_flag'. If it is supported append -dnl 'define_flag' to $CFLAGS. If 'define_flag' is not specified, then append -dnl 'check_flag'. -AC_DEFUN([OSSH_CHECK_CFLAG_COMPILE], [{ - AC_MSG_CHECKING([if $CC supports compile flag $1]) - saved_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $WERROR $1" - _define_flag="$2" - test "x$_define_flag" = "x" && _define_flag="$1" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ +dnl The test program that is used to try to trigger various compiler +dnl behaviours. +AC_DEFUN([OSSH_COMPILER_FLAG_TEST_PROGRAM], + [AC_LANG_SOURCE([[ #include +#include #include +#include +#include /* Trivial function to help test for -fzero-call-used-regs */ -void f(int n) {} +int f(int n) {return rand() % n;} +char *f2(char *s, ...) { + char ret[64]; + va_list args; + va_start(args, s); + vsnprintf(ret, sizeof(ret), s, args); + va_end(args); + return strdup(ret); +} int main(int argc, char **argv) { (void)argv; + char b[256], *cp; /* 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; - f(0); - printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o); + f(1); + snprintf(b, sizeof b, "%d %d %d %f %f %lld %lld\n", i,j,k,l,m,n,o); + if (write(1, b, 0) == -1) exit(0); + cp = f2("%d %d %d %f %f %lld %lld\n", i,j,k,l,m,n,o); + free(cp); /* * 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); } - ]])], + ]])] +) + +dnl OSSH_CHECK_CFLAG_COMPILE(check_flag[, define_flag]) +dnl Check that $CC accepts a flag 'check_flag'. If it is supported append +dnl 'define_flag' to $CFLAGS. If 'define_flag' is not specified, then append +dnl 'check_flag'. +AC_DEFUN([OSSH_CHECK_CFLAG_COMPILE], [{ + AC_MSG_CHECKING([if $CC supports compile flag $1]) + saved_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $WERROR $1" + _define_flag="$2" + test "x$_define_flag" = "x" && _define_flag="$1" + AC_COMPILE_IFELSE([OSSH_COMPILER_FLAG_TEST_PROGRAM], [ if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then AC_MSG_RESULT([no]) CFLAGS="$saved_CFLAGS" else - AC_MSG_RESULT([yes]) - CFLAGS="$saved_CFLAGS $_define_flag" + dnl If we are compiling natively, try running the program. + AC_RUN_IFELSE([OSSH_COMPILER_FLAG_TEST_PROGRAM], + [ AC_MSG_RESULT([yes]) + CFLAGS="$saved_CFLAGS $_define_flag" ], + [ AC_MSG_RESULT([no, fails at run time]) + CFLAGS="$saved_CFLAGS" ], + [ AC_MSG_RESULT([yes]) + CFLAGS="$saved_CFLAGS $_define_flag" ], + ) fi], [ AC_MSG_RESULT([no]) CFLAGS="$saved_CFLAGS" ] ) }]) dnl OSSH_CHECK_CFLAG_LINK(check_flag[, define_flag]) dnl Check that $CC accepts a flag 'check_flag'. If it is supported append dnl 'define_flag' to $CFLAGS. If 'define_flag' is not specified, then append dnl 'check_flag'. AC_DEFUN([OSSH_CHECK_CFLAG_LINK], [{ AC_MSG_CHECKING([if $CC supports compile flag $1 and linking succeeds]) saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR $1" _define_flag="$2" test "x$_define_flag" = "x" && _define_flag="$1" - AC_LINK_IFELSE([AC_LANG_SOURCE([[ -#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; - long long int p = n * o; - printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p); - exit(0); -} - ]])], + AC_LINK_IFELSE([OSSH_COMPILER_FLAG_TEST_PROGRAM], [ if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then AC_MSG_RESULT([no]) CFLAGS="$saved_CFLAGS" else - AC_MSG_RESULT([yes]) - CFLAGS="$saved_CFLAGS $_define_flag" + dnl If we are compiling natively, try running the program. + AC_RUN_IFELSE([OSSH_COMPILER_FLAG_TEST_PROGRAM], + [ AC_MSG_RESULT([yes]) + CFLAGS="$saved_CFLAGS $_define_flag" ], + [ AC_MSG_RESULT([no, fails at run time]) + CFLAGS="$saved_CFLAGS" ], + [ AC_MSG_RESULT([yes]) + CFLAGS="$saved_CFLAGS $_define_flag" ], + ) fi], [ AC_MSG_RESULT([no]) CFLAGS="$saved_CFLAGS" ] ) }]) dnl OSSH_CHECK_LDFLAG_LINK(check_flag[, define_flag]) dnl Check that $LD accepts a flag 'check_flag'. If it is supported append dnl 'define_flag' to $LDFLAGS. If 'define_flag' is not specified, then append dnl 'check_flag'. AC_DEFUN([OSSH_CHECK_LDFLAG_LINK], [{ AC_MSG_CHECKING([if $LD supports link flag $1]) saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR $1" _define_flag="$2" test "x$_define_flag" = "x" && _define_flag="$1" - AC_LINK_IFELSE([AC_LANG_SOURCE([[ -#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; - long long p = n * o; - printf("%d %d %d %f %f %lld %lld %lld\n", i, j, k, l, m, n, o, p); - exit(0); -} - ]])], + AC_LINK_IFELSE([OSSH_COMPILER_FLAG_TEST_PROGRAM], [ if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then AC_MSG_RESULT([no]) LDFLAGS="$saved_LDFLAGS" else - AC_MSG_RESULT([yes]) - LDFLAGS="$saved_LDFLAGS $_define_flag" + dnl If we are compiling natively, try running the program. + AC_RUN_IFELSE([OSSH_COMPILER_FLAG_TEST_PROGRAM], + [ AC_MSG_RESULT([yes]) + LDFLAGS="$saved_LDFLAGS $_define_flag" ], + [ AC_MSG_RESULT([no, fails at run time]) + LDFLAGS="$saved_LDFLAGS" ], + [ AC_MSG_RESULT([yes]) + LDFLAGS="$saved_LDFLAGS $_define_flag" ] + ) fi ], [ AC_MSG_RESULT([no]) LDFLAGS="$saved_LDFLAGS" ] ) }]) 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], [ # 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_%'` dnl ossh_varname="ossh_cv_$ossh_safe""_has_"$1 AC_MSG_CHECKING(for $1 field in $2) AC_CACHE_VAL($ossh_varname, [ AC_EGREP_HEADER($1, $2, [ dnl eval "$ossh_varname=yes" dnl ], [ dnl eval "$ossh_varname=no" dnl ]) dnl ]) ossh_result=`eval 'echo $'"$ossh_varname"` if test -n "`echo $ossh_varname`"; then AC_MSG_RESULT($ossh_result) if test "x$ossh_result" = "xyes"; then AC_DEFINE($3, 1, [Define if you have $1 in $2]) fi else AC_MSG_RESULT(no) fi ]) dnl Check for socklen_t: historically on BSD it is an int, and in dnl POSIX 1g it is a type of its own, but some platforms use different dnl types for the argument to getsockopt, getpeername, etc. So we dnl have to test to find something that will work. AC_DEFUN([TYPE_SOCKLEN_T], [ AC_CHECK_TYPE([socklen_t], ,[ AC_MSG_CHECKING([for socklen_t equivalent]) AC_CACHE_VAL([curl_cv_socklen_t_equiv], [ # Systems have either "struct sockaddr *" or # "void *" as the second argument to getpeername curl_cv_socklen_t_equiv= for arg2 in "struct sockaddr" void; do for t in int size_t unsigned long "unsigned long"; do 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 ]) done done if test "x$curl_cv_socklen_t_equiv" = x; then AC_MSG_ERROR([Cannot find a type to use in place of socklen_t]) fi ]) AC_MSG_RESULT($curl_cv_socklen_t_equiv) AC_DEFINE_UNQUOTED(socklen_t, $curl_cv_socklen_t_equiv, [type to use in place of socklen_t if not defined])], [#include #include ]) ]) diff --git a/crypto/openssh/misc.c b/crypto/openssh/misc.c index 42582c61829a..3db2e4d0b01c 100644 --- a/crypto/openssh/misc.c +++ b/crypto/openssh/misc.c @@ -1,3028 +1,3065 @@ -/* $OpenBSD: misc.c,v 1.187 2023/08/28 03:31:16 djm Exp $ */ +/* $OpenBSD: misc.c,v 1.189 2023/10/12 03:36:32 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005-2020 Damien Miller. All rights reserved. * Copyright (c) 2004 Henning Brauer * * 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 #ifdef HAVE_LIBGEN_H # include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_NLIST_H #include #endif #include #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_PATHS_H # include #include #include #endif #ifdef SSH_TUN_OPENBSD #include #endif #include "xmalloc.h" #include "misc.h" #include "log.h" #include "ssh.h" #include "sshbuf.h" #include "ssherr.h" #include "platform.h" /* remove newline at end of string */ char * chop(char *s) { char *t = s; while (*t) { if (*t == '\n' || *t == '\r') { *t = '\0'; return s; } t++; } return s; } /* remove whitespace from end of string */ void rtrim(char *s) { size_t i; if ((i = strlen(s)) == 0) return; for (i--; i > 0; i--) { if (isspace((unsigned char)s[i])) s[i] = '\0'; } } /* set/unset filedescriptor to non-blocking */ int set_nonblock(int fd) { int val; val = fcntl(fd, F_GETFL); if (val == -1) { error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); return (-1); } if (val & O_NONBLOCK) { debug3("fd %d is O_NONBLOCK", fd); return (0); } debug2("fd %d setting O_NONBLOCK", fd); val |= O_NONBLOCK; if (fcntl(fd, F_SETFL, val) == -1) { debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd, strerror(errno)); return (-1); } return (0); } int unset_nonblock(int fd) { int val; val = fcntl(fd, F_GETFL); if (val == -1) { error("fcntl(%d, F_GETFL): %s", fd, strerror(errno)); return (-1); } if (!(val & O_NONBLOCK)) { debug3("fd %d is not O_NONBLOCK", fd); return (0); } debug("fd %d clearing O_NONBLOCK", fd); val &= ~O_NONBLOCK; if (fcntl(fd, F_SETFL, val) == -1) { debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s", fd, strerror(errno)); return (-1); } return (0); } const char * ssh_gai_strerror(int gaierr) { if (gaierr == EAI_SYSTEM && errno != 0) return strerror(errno); return gai_strerror(gaierr); } /* disable nagle on socket */ void set_nodelay(int fd) { int opt; socklen_t optlen; optlen = sizeof opt; if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) { debug("getsockopt TCP_NODELAY: %.100s", strerror(errno)); return; } if (opt == 1) { debug2("fd %d is TCP_NODELAY", fd); return; } opt = 1; debug2("fd %d setting TCP_NODELAY", fd); if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1) error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); } /* Allow local port reuse in TIME_WAIT */ int set_reuseaddr(int fd) { int on = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { error("setsockopt SO_REUSEADDR fd %d: %s", fd, strerror(errno)); return -1; } return 0; } /* Get/set routing domain */ char * get_rdomain(int fd) { #if defined(HAVE_SYS_GET_RDOMAIN) return sys_get_rdomain(fd); #elif defined(__OpenBSD__) int rtable; char *ret; socklen_t len = sizeof(rtable); if (getsockopt(fd, SOL_SOCKET, SO_RTABLE, &rtable, &len) == -1) { error("Failed to get routing domain for fd %d: %s", fd, strerror(errno)); return NULL; } xasprintf(&ret, "%d", rtable); return ret; #else /* defined(__OpenBSD__) */ return NULL; #endif } int set_rdomain(int fd, const char *name) { #if defined(HAVE_SYS_SET_RDOMAIN) return sys_set_rdomain(fd, name); #elif defined(__OpenBSD__) int rtable; const char *errstr; if (name == NULL) return 0; /* default table */ rtable = (int)strtonum(name, 0, 255, &errstr); if (errstr != NULL) { /* Shouldn't happen */ error("Invalid routing domain \"%s\": %s", name, errstr); return -1; } if (setsockopt(fd, SOL_SOCKET, SO_RTABLE, &rtable, sizeof(rtable)) == -1) { error("Failed to set routing domain %d on fd %d: %s", rtable, fd, strerror(errno)); return -1; } return 0; #else /* defined(__OpenBSD__) */ error("Setting routing domain is not supported on this platform"); return -1; #endif } 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: %s", 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 events on fd. Updates * *timeoutp with time remaining. * Returns 0 if fd ready or -1 on timeout or error (see errno). */ static int waitfd(int fd, int *timeoutp, short events, volatile sig_atomic_t *stop) { struct pollfd pfd; struct timespec timeout; int oerrno, r; sigset_t nsigset, osigset; if (timeoutp && *timeoutp == -1) timeoutp = NULL; pfd.fd = fd; pfd.events = events; ptimeout_init(&timeout); if (timeoutp != NULL) ptimeout_deadline_ms(&timeout, *timeoutp); if (stop != NULL) sigfillset(&nsigset); for (; timeoutp == NULL || *timeoutp >= 0;) { if (stop != NULL) { sigprocmask(SIG_BLOCK, &nsigset, &osigset); if (*stop) { sigprocmask(SIG_SETMASK, &osigset, NULL); errno = EINTR; return -1; } } r = ppoll(&pfd, 1, ptimeout_get_tsp(&timeout), stop != NULL ? &osigset : NULL); oerrno = errno; if (stop != NULL) sigprocmask(SIG_SETMASK, &osigset, NULL); if (timeoutp) *timeoutp = ptimeout_get_ms(&timeout); errno = oerrno; if (r > 0) return 0; else if (r == -1 && errno != EAGAIN && errno != EINTR) return -1; else if (r == 0) break; } /* timeout */ errno = ETIMEDOUT; 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, volatile sig_atomic_t *stop) { return waitfd(fd, timeoutp, POLLIN, stop); } /* * Attempt a non-blocking connect(2) to the specified address, waiting up to * *timeoutp milliseconds for the connection to complete. If the timeout is * <=0, then wait indefinitely. * * Returns 0 on success or -1 on failure. */ int timeout_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen, int *timeoutp) { int optval = 0; socklen_t optlen = sizeof(optval); /* No timeout: just do a blocking connect() */ if (timeoutp == NULL || *timeoutp <= 0) return connect(sockfd, serv_addr, addrlen); set_nonblock(sockfd); 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 (waitfd(sockfd, timeoutp, POLLIN | POLLOUT, NULL) == -1) return -1; /* Completed or failed */ if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) { debug("getsockopt: %s", strerror(errno)); return -1; } if (optval != 0) { errno = optval; return -1; } unset_nonblock(sockfd); return 0; } /* Characters considered whitespace in strsep calls. */ #define WHITESPACE " \t\r\n" #define QUOTE "\"" /* return next token in configuration line */ static char * strdelim_internal(char **s, int split_equals) { char *old; int wspace = 0; if (*s == NULL) return NULL; old = *s; *s = strpbrk(*s, split_equals ? WHITESPACE QUOTE "=" : WHITESPACE QUOTE); if (*s == NULL) return (old); if (*s[0] == '\"') { memmove(*s, *s + 1, strlen(*s)); /* move nul too */ /* Find matching quote */ if ((*s = strpbrk(*s, QUOTE)) == NULL) { return (NULL); /* no matching quote */ } else { *s[0] = '\0'; *s += strspn(*s + 1, WHITESPACE) + 1; return (old); } } /* Allow only one '=' to be skipped */ if (split_equals && *s[0] == '=') wspace = 1; *s[0] = '\0'; /* Skip any extra whitespace after first token */ *s += strspn(*s + 1, WHITESPACE) + 1; if (split_equals && *s[0] == '=' && !wspace) *s += strspn(*s + 1, WHITESPACE) + 1; return (old); } /* * Return next token in configuration line; splts on whitespace or a * single '=' character. */ char * strdelim(char **s) { return strdelim_internal(s, 1); } /* * Return next token in configuration line; splts on whitespace only. */ char * strdelimw(char **s) { return strdelim_internal(s, 0); } struct passwd * pwcopy(struct passwd *pw) { struct passwd *copy = xcalloc(1, sizeof(*copy)); copy->pw_name = xstrdup(pw->pw_name); copy->pw_passwd = xstrdup(pw->pw_passwd == NULL ? "*" : pw->pw_passwd); #ifdef HAVE_STRUCT_PASSWD_PW_GECOS copy->pw_gecos = xstrdup(pw->pw_gecos); #endif copy->pw_uid = pw->pw_uid; copy->pw_gid = pw->pw_gid; #ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE copy->pw_expire = pw->pw_expire; #endif #ifdef HAVE_STRUCT_PASSWD_PW_CHANGE copy->pw_change = pw->pw_change; #endif #ifdef HAVE_STRUCT_PASSWD_PW_CLASS copy->pw_class = xstrdup(pw->pw_class); #endif copy->pw_dir = xstrdup(pw->pw_dir); copy->pw_shell = xstrdup(pw->pw_shell); return copy; } /* * Convert ASCII string to TCP/IP port number. * Port must be >=0 and <=65535. * Return -1 if invalid. */ int a2port(const char *s) { struct servent *se; long long port; const char *errstr; port = strtonum(s, 0, 65535, &errstr); if (errstr == NULL) return (int)port; if ((se = getservbyname(s, "tcp")) != NULL) return ntohs(se->s_port); return -1; } int a2tun(const char *s, int *remote) { const char *errstr = NULL; char *sp, *ep; int tun; if (remote != NULL) { *remote = SSH_TUNID_ANY; sp = xstrdup(s); if ((ep = strchr(sp, ':')) == NULL) { free(sp); return (a2tun(s, NULL)); } ep[0] = '\0'; ep++; *remote = a2tun(ep, NULL); tun = a2tun(sp, NULL); free(sp); return (*remote == SSH_TUNID_ERR ? *remote : tun); } if (strcasecmp(s, "any") == 0) return (SSH_TUNID_ANY); tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr); if (errstr != NULL) return (SSH_TUNID_ERR); return (tun); } #define SECONDS 1 #define MINUTES (SECONDS * 60) #define HOURS (MINUTES * 60) #define DAYS (HOURS * 24) #define WEEKS (DAYS * 7) /* * Convert a time string into seconds; format is * a sequence of: * time[qualifier] * * Valid time qualifiers are: * seconds * s|S seconds * m|M minutes * h|H hours * d|D days * w|W weeks * * Examples: * 90m 90 minutes * 1h30m 90 minutes * 2d 2 days * 1w 1 week * * Return -1 if time string is invalid. */ int convtime(const char *s) { long total, secs, multiplier; const char *p; char *endp; errno = 0; total = 0; p = s; if (p == NULL || *p == '\0') return -1; while (*p) { secs = strtol(p, &endp, 10); if (p == endp || (errno == ERANGE && (secs == INT_MIN || secs == INT_MAX)) || secs < 0) return -1; multiplier = 1; switch (*endp++) { case '\0': endp--; break; case 's': case 'S': break; case 'm': case 'M': multiplier = MINUTES; break; case 'h': case 'H': multiplier = HOURS; break; case 'd': case 'D': multiplier = DAYS; break; case 'w': case 'W': multiplier = WEEKS; break; default: return -1; } if (secs > INT_MAX / multiplier) return -1; secs *= multiplier; if (total > INT_MAX - secs) return -1; total += secs; if (total < 0) return -1; p = endp; } 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. */ char * put_host_port(const char *host, u_short port) { char *hoststr; if (port == 0 || port == SSH_DEFAULT_PORT) return(xstrdup(host)); if (asprintf(&hoststr, "[%s]:%d", host, (int)port) == -1) fatal("put_host_port: asprintf: %s", strerror(errno)); debug3("put_host_port: %s", hoststr); return hoststr; } /* * Search for next delimiter between hostnames/addresses and ports. * Argument may be modified (for termination). * Returns *cp if parsing succeeds. * *cp is set to the start of the next field, if one was found. * The delimiter char, if present, is stored in delim. * If this is the last field, *cp is set to NULL. */ char * hpdelim2(char **cp, char *delim) { char *s, *old; if (cp == NULL || *cp == NULL) return NULL; old = s = *cp; if (*s == '[') { if ((s = strchr(s, ']')) == NULL) return NULL; else s++; } else if ((s = strpbrk(s, ":/")) == NULL) s = *cp + strlen(*cp); /* skip to end (see first case below) */ switch (*s) { case '\0': *cp = NULL; /* no more fields*/ break; case ':': case '/': if (delim != NULL) *delim = *s; *s = '\0'; /* terminate */ *cp = s + 1; break; default: return NULL; } return old; } /* The common case: only accept colon as delimiter. */ char * hpdelim(char **cp) { char *r, delim = '\0'; r = hpdelim2(cp, &delim); if (delim == '/') return NULL; return r; } char * cleanhostname(char *host) { if (*host == '[' && host[strlen(host) - 1] == ']') { host[strlen(host) - 1] = '\0'; return (host + 1); } else return host; } char * colon(char *cp) { int flag = 0; if (*cp == ':') /* Leading colon is part of file name. */ return NULL; if (*cp == '[') flag = 1; for (; *cp; ++cp) { if (*cp == '@' && *(cp+1) == '[') flag = 1; if (*cp == ']' && *(cp+1) == ':' && flag) return (cp+1); if (*cp == ':' && !flag) return (cp); if (*cp == '/') return NULL; } return NULL; } /* * Parse a [user@]host:[path] string. * Caller must free returned user, host and path. * Any of the pointer return arguments may be NULL (useful for syntax checking). * If user was not specified then *userp will be set to NULL. * If host was not specified then *hostp will be set to NULL. * If path was not specified then *pathp will be set to ".". * Returns 0 on success, -1 on failure. */ int parse_user_host_path(const char *s, char **userp, char **hostp, char **pathp) { char *user = NULL, *host = NULL, *path = NULL; char *sdup, *tmp; int ret = -1; if (userp != NULL) *userp = NULL; if (hostp != NULL) *hostp = NULL; if (pathp != NULL) *pathp = NULL; sdup = xstrdup(s); /* Check for remote syntax: [user@]host:[path] */ if ((tmp = colon(sdup)) == NULL) goto out; /* Extract optional path */ *tmp++ = '\0'; if (*tmp == '\0') tmp = "."; path = xstrdup(tmp); /* Extract optional user and mandatory host */ tmp = strrchr(sdup, '@'); if (tmp != NULL) { *tmp++ = '\0'; host = xstrdup(cleanhostname(tmp)); if (*sdup != '\0') user = xstrdup(sdup); } else { host = xstrdup(cleanhostname(sdup)); user = NULL; } /* Success */ if (userp != NULL) { *userp = user; user = NULL; } if (hostp != NULL) { *hostp = host; host = NULL; } if (pathp != NULL) { *pathp = path; path = NULL; } ret = 0; out: free(sdup); free(user); free(host); free(path); return ret; } /* * Parse a [user@]host[:port] string. * Caller must free returned user and host. * Any of the pointer return arguments may be NULL (useful for syntax checking). * If user was not specified then *userp will be set to NULL. * If port was not specified then *portp will be -1. * Returns 0 on success, -1 on failure. */ int parse_user_host_port(const char *s, char **userp, char **hostp, int *portp) { char *sdup, *cp, *tmp; char *user = NULL, *host = NULL; int port = -1, ret = -1; if (userp != NULL) *userp = NULL; if (hostp != NULL) *hostp = NULL; if (portp != NULL) *portp = -1; if ((sdup = tmp = strdup(s)) == NULL) return -1; /* Extract optional username */ if ((cp = strrchr(tmp, '@')) != NULL) { *cp = '\0'; if (*tmp == '\0') goto out; if ((user = strdup(tmp)) == NULL) goto out; tmp = cp + 1; } /* Extract mandatory hostname */ if ((cp = hpdelim(&tmp)) == NULL || *cp == '\0') goto out; host = xstrdup(cleanhostname(cp)); /* Convert and verify optional port */ if (tmp != NULL && *tmp != '\0') { if ((port = a2port(tmp)) <= 0) goto out; } /* Success */ if (userp != NULL) { *userp = user; user = NULL; } if (hostp != NULL) { *hostp = host; host = NULL; } if (portp != NULL) *portp = port; ret = 0; out: free(sdup); free(user); free(host); return ret; } /* * Converts a two-byte hex string to decimal. * Returns the decimal value or -1 for invalid input. */ static int hexchar(const char *s) { unsigned char result[2]; int i; for (i = 0; i < 2; i++) { if (s[i] >= '0' && s[i] <= '9') result[i] = (unsigned char)(s[i] - '0'); else if (s[i] >= 'a' && s[i] <= 'f') result[i] = (unsigned char)(s[i] - 'a') + 10; else if (s[i] >= 'A' && s[i] <= 'F') result[i] = (unsigned char)(s[i] - 'A') + 10; else return -1; } return (result[0] << 4) | result[1]; } /* * Decode an url-encoded string. * Returns a newly allocated string on success or NULL on failure. */ static char * urldecode(const char *src) { char *ret, *dst; int ch; size_t srclen; if ((srclen = strlen(src)) >= SIZE_MAX) fatal_f("input too large"); ret = xmalloc(srclen + 1); for (dst = ret; *src != '\0'; src++) { switch (*src) { case '+': *dst++ = ' '; break; case '%': if (!isxdigit((unsigned char)src[1]) || !isxdigit((unsigned char)src[2]) || (ch = hexchar(src + 1)) == -1) { free(ret); return NULL; } *dst++ = ch; src += 2; break; default: *dst++ = *src; break; } } *dst = '\0'; return ret; } /* * Parse an (scp|ssh|sftp)://[user@]host[:port][/path] URI. * See https://tools.ietf.org/html/draft-ietf-secsh-scp-sftp-ssh-uri-04 * Either user or path may be url-encoded (but not host or port). * Caller must free returned user, host and path. * Any of the pointer return arguments may be NULL (useful for syntax checking) * but the scheme must always be specified. * If user was not specified then *userp will be set to NULL. * If port was not specified then *portp will be -1. * If path was not specified then *pathp will be set to NULL. * Returns 0 on success, 1 if non-uri/wrong scheme, -1 on error/invalid uri. */ int parse_uri(const char *scheme, const char *uri, char **userp, char **hostp, int *portp, char **pathp) { char *uridup, *cp, *tmp, ch; char *user = NULL, *host = NULL, *path = NULL; int port = -1, ret = -1; size_t len; len = strlen(scheme); if (strncmp(uri, scheme, len) != 0 || strncmp(uri + len, "://", 3) != 0) return 1; uri += len + 3; if (userp != NULL) *userp = NULL; if (hostp != NULL) *hostp = NULL; if (portp != NULL) *portp = -1; if (pathp != NULL) *pathp = NULL; uridup = tmp = xstrdup(uri); /* Extract optional ssh-info (username + connection params) */ if ((cp = strchr(tmp, '@')) != NULL) { char *delim; *cp = '\0'; /* Extract username and connection params */ if ((delim = strchr(tmp, ';')) != NULL) { /* Just ignore connection params for now */ *delim = '\0'; } if (*tmp == '\0') { /* Empty username */ goto out; } if ((user = urldecode(tmp)) == NULL) goto out; tmp = cp + 1; } /* Extract mandatory hostname */ if ((cp = hpdelim2(&tmp, &ch)) == NULL || *cp == '\0') goto out; host = xstrdup(cleanhostname(cp)); if (!valid_domain(host, 0, NULL)) goto out; if (tmp != NULL && *tmp != '\0') { if (ch == ':') { /* Convert and verify port. */ if ((cp = strchr(tmp, '/')) != NULL) *cp = '\0'; if ((port = a2port(tmp)) <= 0) goto out; tmp = cp ? cp + 1 : NULL; } if (tmp != NULL && *tmp != '\0') { /* Extract optional path */ if ((path = urldecode(tmp)) == NULL) goto out; } } /* Success */ if (userp != NULL) { *userp = user; user = NULL; } if (hostp != NULL) { *hostp = host; host = NULL; } if (portp != NULL) *portp = port; if (pathp != NULL) { *pathp = path; path = NULL; } ret = 0; out: free(uridup); free(user); free(host); free(path); return ret; } /* function to assist building execv() arguments */ void addargs(arglist *args, char *fmt, ...) { va_list ap; char *cp; u_int nalloc; int r; va_start(ap, fmt); r = vasprintf(&cp, fmt, ap); va_end(ap); if (r == -1) fatal_f("argument too long"); nalloc = args->nalloc; if (args->list == NULL) { nalloc = 32; args->num = 0; } else if (args->num > (256 * 1024)) fatal_f("too many arguments"); else if (args->num >= args->nalloc) fatal_f("arglist corrupt"); else if (args->num+2 >= nalloc) nalloc *= 2; args->list = xrecallocarray(args->list, args->nalloc, nalloc, sizeof(char *)); args->nalloc = nalloc; args->list[args->num++] = cp; args->list[args->num] = NULL; } void replacearg(arglist *args, u_int which, char *fmt, ...) { va_list ap; char *cp; int r; va_start(ap, fmt); r = vasprintf(&cp, fmt, ap); va_end(ap); if (r == -1) fatal_f("argument too long"); if (args->list == NULL || args->num >= args->nalloc) fatal_f("arglist corrupt"); if (which >= args->num) fatal_f("tried to replace invalid arg %d >= %d", which, args->num); free(args->list[which]); args->list[which] = cp; } void freeargs(arglist *args) { u_int i; if (args == NULL) return; if (args->list != NULL && args->num < args->nalloc) { for (i = 0; i < args->num; i++) free(args->list[i]); free(args->list); } args->nalloc = args->num = 0; args->list = NULL; } /* * Expands tildes in the file name. Returns data allocated by xmalloc. * Warning: this calls getpw*. */ int tilde_expand(const char *filename, uid_t uid, char **retp) { char *ocopy = NULL, *copy, *s = NULL; const char *path = NULL, *user = NULL; struct passwd *pw; size_t len; int ret = -1, r, slash; *retp = NULL; if (*filename != '~') { *retp = xstrdup(filename); return 0; } ocopy = copy = xstrdup(filename + 1); if (*copy == '\0') /* ~ */ path = NULL; else if (*copy == '/') { copy += strspn(copy, "/"); if (*copy == '\0') path = NULL; /* ~/ */ else path = copy; /* ~/path */ } else { user = copy; if ((path = strchr(copy, '/')) != NULL) { copy[path - copy] = '\0'; path++; path += strspn(path, "/"); if (*path == '\0') /* ~user/ */ path = NULL; /* else ~user/path */ } /* else ~user */ } if (user != NULL) { if ((pw = getpwnam(user)) == NULL) { error_f("No such user %s", user); goto out; } } else if ((pw = getpwuid(uid)) == NULL) { error_f("No such uid %ld", (long)uid); goto out; } /* Make sure directory has a trailing '/' */ slash = (len = strlen(pw->pw_dir)) == 0 || pw->pw_dir[len - 1] != '/'; if ((r = xasprintf(&s, "%s%s%s", pw->pw_dir, slash ? "/" : "", path != NULL ? path : "")) <= 0) { error_f("xasprintf failed"); goto out; } if (r >= PATH_MAX) { error_f("Path too long"); goto out; } /* success */ ret = 0; *retp = s; s = NULL; out: free(s); free(ocopy); return ret; } char * tilde_expand_filename(const char *filename, uid_t uid) { char *ret; if (tilde_expand(filename, uid, &ret) != 0) cleanup_exit(255); return ret; } /* * 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. */ static char * vdollar_percent_expand(int *parseerror, int dollar, int percent, const char *string, va_list ap) { -#define EXPAND_MAX_KEYS 16 +#define EXPAND_MAX_KEYS 64 u_int num_keys = 0, i; struct { const char *key; const char *repl; } keys[EXPAND_MAX_KEYS]; struct sshbuf *buf; int r, missingvar = 0; char *ret = NULL, *var, *varend, *val; size_t len; if ((buf = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if (parseerror == NULL) fatal_f("null parseerror arg"); *parseerror = 1; /* 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"); } /* Expand string */ for (i = 0; *string != '\0'; string++) { /* 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') { 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_fr(r, "sshbuf_put %%-repl"); break; } } if (i >= num_keys) { error_f("unknown key %%%c", *string); goto out; } } if (!missingvar && (ret = sshbuf_dup_string(buf)) == NULL) fatal_f("sshbuf_dup_string failed"); *parseerror = 0; out: sshbuf_free(buf); 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) { #if defined(CUSTOM_SYS_TUN_OPEN) return (sys_tun_open(tun, mode, ifname)); #elif defined(SSH_TUN_OPENBSD) struct ifreq ifr; char name[100]; int fd = -1, sock; const char *tunbase = "tun"; if (ifname != NULL) *ifname = NULL; if (mode == SSH_TUNMODE_ETHERNET) tunbase = "tap"; /* Open the tunnel device */ if (tun <= SSH_TUNID_MAX) { snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); fd = open(name, O_RDWR); } else if (tun == SSH_TUNID_ANY) { for (tun = 100; tun >= 0; tun--) { snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); if ((fd = open(name, O_RDWR)) >= 0) break; } } else { debug_f("invalid tunnel %u", tun); return -1; } if (fd == -1) { debug_f("%s open: %s", name, strerror(errno)); return -1; } 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); if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) goto failed; if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) { 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_f("activate interface %s: %s", ifr.ifr_name, strerror(errno)); goto failed; } } if (ifname != NULL) *ifname = xstrdup(ifr.ifr_name); close(sock); return fd; failed: if (fd >= 0) close(fd); if (sock >= 0) close(sock); return -1; #else error("Tunnel interfaces are not supported on this platform"); return (-1); #endif } void sanitise_stdfd(void) { int nullfd, dupfd; if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { fprintf(stderr, "Couldn't open /dev/null: %s\n", strerror(errno)); exit(1); } while (++dupfd <= STDERR_FILENO) { /* Only populate closed fds. */ if (fcntl(dupfd, F_GETFL) == -1 && errno == EBADF) { if (dup2(nullfd, dupfd) == -1) { fprintf(stderr, "dup2: %s\n", strerror(errno)); exit(1); } } } if (nullfd > STDERR_FILENO) close(nullfd); } char * tohex(const void *vp, size_t l) { const u_char *p = (const u_char *)vp; char b[3], *r; size_t i, hl; if (l > 65536) return xstrdup("tohex: length > 65536"); hl = l * 2 + 1; r = xcalloc(1, hl); for (i = 0; i < l; i++) { snprintf(b, sizeof(b), "%02x", p[i]); strlcat(r, b, hl); } return (r); } /* * 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) { const u_char *p = (const u_char *)vp; u_int64_t v; v = (u_int64_t)p[0] << 56; v |= (u_int64_t)p[1] << 48; v |= (u_int64_t)p[2] << 40; v |= (u_int64_t)p[3] << 32; v |= (u_int64_t)p[4] << 24; v |= (u_int64_t)p[5] << 16; v |= (u_int64_t)p[6] << 8; v |= (u_int64_t)p[7]; return (v); } u_int32_t get_u32(const void *vp) { const u_char *p = (const u_char *)vp; u_int32_t v; v = (u_int32_t)p[0] << 24; v |= (u_int32_t)p[1] << 16; v |= (u_int32_t)p[2] << 8; v |= (u_int32_t)p[3]; return (v); } u_int32_t get_u32_le(const void *vp) { const u_char *p = (const u_char *)vp; u_int32_t v; v = (u_int32_t)p[0]; v |= (u_int32_t)p[1] << 8; v |= (u_int32_t)p[2] << 16; v |= (u_int32_t)p[3] << 24; return (v); } u_int16_t get_u16(const void *vp) { const u_char *p = (const u_char *)vp; u_int16_t v; v = (u_int16_t)p[0] << 8; v |= (u_int16_t)p[1]; return (v); } void put_u64(void *vp, u_int64_t v) { u_char *p = (u_char *)vp; p[0] = (u_char)(v >> 56) & 0xff; p[1] = (u_char)(v >> 48) & 0xff; p[2] = (u_char)(v >> 40) & 0xff; p[3] = (u_char)(v >> 32) & 0xff; p[4] = (u_char)(v >> 24) & 0xff; p[5] = (u_char)(v >> 16) & 0xff; p[6] = (u_char)(v >> 8) & 0xff; p[7] = (u_char)v & 0xff; } void put_u32(void *vp, u_int32_t v) { u_char *p = (u_char *)vp; p[0] = (u_char)(v >> 24) & 0xff; p[1] = (u_char)(v >> 16) & 0xff; p[2] = (u_char)(v >> 8) & 0xff; p[3] = (u_char)v & 0xff; } void put_u32_le(void *vp, u_int32_t v) { u_char *p = (u_char *)vp; p[0] = (u_char)v & 0xff; p[1] = (u_char)(v >> 8) & 0xff; p[2] = (u_char)(v >> 16) & 0xff; p[3] = (u_char)(v >> 24) & 0xff; } void put_u16(void *vp, u_int16_t v) { u_char *p = (u_char *)vp; p[0] = (u_char)(v >> 8) & 0xff; p[1] = (u_char)v & 0xff; } void ms_subtract_diff(struct timeval *start, int *ms) { struct timeval diff, finish; monotime_tv(&finish); timersub(&finish, start, &diff); *ms -= (diff.tv_sec * 1000) + (diff.tv_usec / 1000); } void ms_to_timespec(struct timespec *ts, int ms) { if (ms < 0) ms = 0; ts->tv_sec = ms / 1000; ts->tv_nsec = (ms % 1000) * 1000 * 1000; } void monotime_ts(struct timespec *ts) { struct timeval tv; #if defined(HAVE_CLOCK_GETTIME) && (defined(CLOCK_BOOTTIME) || \ defined(CLOCK_MONOTONIC) || defined(CLOCK_REALTIME)) static int gettime_failed = 0; if (!gettime_failed) { # ifdef CLOCK_BOOTTIME if (clock_gettime(CLOCK_BOOTTIME, ts) == 0) return; # endif /* CLOCK_BOOTTIME */ # ifdef CLOCK_MONOTONIC if (clock_gettime(CLOCK_MONOTONIC, ts) == 0) return; # endif /* CLOCK_MONOTONIC */ # ifdef CLOCK_REALTIME /* Not monotonic, but we're almost out of options here. */ if (clock_gettime(CLOCK_REALTIME, ts) == 0) return; # endif /* CLOCK_REALTIME */ debug3("clock_gettime: %s", strerror(errno)); gettime_failed = 1; } #endif /* HAVE_CLOCK_GETTIME && (BOOTTIME || MONOTONIC || REALTIME) */ gettimeofday(&tv, NULL); ts->tv_sec = tv.tv_sec; ts->tv_nsec = (long)tv.tv_usec * 1000; } void monotime_tv(struct timeval *tv) { struct timespec ts; monotime_ts(&ts); tv->tv_sec = ts.tv_sec; tv->tv_usec = ts.tv_nsec / 1000; } time_t monotime(void) { struct timespec ts; monotime_ts(&ts); return ts.tv_sec; } double monotime_double(void) { struct timespec ts; monotime_ts(&ts); return ts.tv_sec + ((double)ts.tv_nsec / 1000000000); } void bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen) { bw->buflen = buflen; bw->rate = kbps; bw->thresh = buflen; bw->lamt = 0; timerclear(&bw->bwstart); timerclear(&bw->bwend); } /* Callback from read/write loop to insert bandwidth-limiting delays */ void bandwidth_limit(struct bwlimit *bw, size_t read_len) { u_int64_t waitlen; struct timespec ts, rm; bw->lamt += read_len; if (!timerisset(&bw->bwstart)) { monotime_tv(&bw->bwstart); return; } if (bw->lamt < bw->thresh) return; monotime_tv(&bw->bwend); timersub(&bw->bwend, &bw->bwstart, &bw->bwend); if (!timerisset(&bw->bwend)) return; bw->lamt *= 8; waitlen = (double)1000000L * bw->lamt / bw->rate; bw->bwstart.tv_sec = waitlen / 1000000L; bw->bwstart.tv_usec = waitlen % 1000000L; if (timercmp(&bw->bwstart, &bw->bwend, >)) { timersub(&bw->bwstart, &bw->bwend, &bw->bwend); /* Adjust the wait time */ if (bw->bwend.tv_sec) { bw->thresh /= 2; if (bw->thresh < bw->buflen / 4) bw->thresh = bw->buflen / 4; } else if (bw->bwend.tv_usec < 10000) { bw->thresh *= 2; if (bw->thresh > bw->buflen * 8) bw->thresh = bw->buflen * 8; } TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts); while (nanosleep(&ts, &rm) == -1) { if (errno != EINTR) break; ts = rm; } } bw->lamt = 0; monotime_tv(&bw->bwstart); } /* Make a template filename for mk[sd]temp() */ void mktemp_proto(char *s, size_t len) { const char *tmpdir; int r; if ((tmpdir = getenv("TMPDIR")) != NULL) { r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir); if (r > 0 && (size_t)r < len) return; } r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX"); if (r < 0 || (size_t)r >= len) fatal_f("template string too short"); } static const struct { const char *name; int value; } ipqos[] = { { "none", INT_MAX }, /* can't use 0 here; that's CS0 */ { "af11", IPTOS_DSCP_AF11 }, { "af12", IPTOS_DSCP_AF12 }, { "af13", IPTOS_DSCP_AF13 }, { "af21", IPTOS_DSCP_AF21 }, { "af22", IPTOS_DSCP_AF22 }, { "af23", IPTOS_DSCP_AF23 }, { "af31", IPTOS_DSCP_AF31 }, { "af32", IPTOS_DSCP_AF32 }, { "af33", IPTOS_DSCP_AF33 }, { "af41", IPTOS_DSCP_AF41 }, { "af42", IPTOS_DSCP_AF42 }, { "af43", IPTOS_DSCP_AF43 }, { "cs0", IPTOS_DSCP_CS0 }, { "cs1", IPTOS_DSCP_CS1 }, { "cs2", IPTOS_DSCP_CS2 }, { "cs3", IPTOS_DSCP_CS3 }, { "cs4", IPTOS_DSCP_CS4 }, { "cs5", IPTOS_DSCP_CS5 }, { "cs6", IPTOS_DSCP_CS6 }, { "cs7", IPTOS_DSCP_CS7 }, { "ef", IPTOS_DSCP_EF }, { "le", IPTOS_DSCP_LE }, { "lowdelay", IPTOS_LOWDELAY }, { "throughput", IPTOS_THROUGHPUT }, { "reliability", IPTOS_RELIABILITY }, { NULL, -1 } }; int parse_ipqos(const char *cp) { u_int i; char *ep; long val; if (cp == NULL) return -1; for (i = 0; ipqos[i].name != NULL; i++) { if (strcasecmp(cp, ipqos[i].name) == 0) return ipqos[i].value; } /* Try parsing as an integer */ val = strtol(cp, &ep, 0); if (*cp == '\0' || *ep != '\0' || val < 0 || val > 255) return -1; return val; } const char * iptos2str(int iptos) { int i; static char iptos_str[sizeof "0xff"]; for (i = 0; ipqos[i].name != NULL; i++) { if (ipqos[i].value == iptos) return ipqos[i].name; } snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos); return iptos_str; } void lowercase(char *s) { for (; *s; s++) *s = tolower((u_char)*s); } int unix_listener(const char *path, int backlog, int unlink_first) { struct sockaddr_un sunaddr; int saved_errno, sock; memset(&sunaddr, 0, sizeof(sunaddr)); sunaddr.sun_family = AF_UNIX; if (strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) { error_f("path \"%s\" too long for Unix domain socket", path); errno = ENAMETOOLONG; return -1; } sock = socket(PF_UNIX, SOCK_STREAM, 0); if (sock == -1) { saved_errno = errno; error_f("socket: %.100s", strerror(errno)); errno = saved_errno; return -1; } if (unlink_first == 1) { if (unlink(path) != 0 && errno != ENOENT) error("unlink(%s): %.100s", path, strerror(errno)); } if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { saved_errno = 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_f("cannot listen on path %s: %s", path, strerror(errno)); close(sock); unlink(path); errno = saved_errno; return -1; } return sock; } void sock_set_v6only(int s) { #if defined(IPV6_V6ONLY) && !defined(__OpenBSD__) int on = 1; debug3("%s: set socket %d IPV6_V6ONLY", __func__, s); if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) error("setsockopt IPV6_V6ONLY: %s", strerror(errno)); #endif } /* * Compares two strings that maybe be NULL. Returns non-zero if strings * are both NULL or are identical, returns zero otherwise. */ static int strcmp_maybe_null(const char *a, const char *b) { if ((a == NULL && b != NULL) || (a != NULL && b == NULL)) return 0; if (a != NULL && strcmp(a, b) != 0) return 0; return 1; } /* * Compare two forwards, returning non-zero if they are identical or * zero otherwise. */ int forward_equals(const struct Forward *a, const struct Forward *b) { if (strcmp_maybe_null(a->listen_host, b->listen_host) == 0) return 0; if (a->listen_port != b->listen_port) return 0; if (strcmp_maybe_null(a->listen_path, b->listen_path) == 0) return 0; if (strcmp_maybe_null(a->connect_host, b->connect_host) == 0) return 0; if (a->connect_port != b->connect_port) return 0; if (strcmp_maybe_null(a->connect_path, b->connect_path) == 0) return 0; /* allocated_port and handle are not checked */ return 1; } /* returns 1 if process is already daemonized, 0 otherwise */ int daemonized(void) { int fd; if ((fd = open(_PATH_TTY, O_RDONLY | O_NOCTTY)) >= 0) { close(fd); return 0; /* have controlling terminal */ } if (getppid() != 1) return 0; /* parent is not init */ if (getsid(0) != getpid()) return 0; /* not session leader */ debug3("already daemonized"); return 1; } /* * Splits 's' into an argument vector. Handles quoted string and basic * escape characters (\\, \", \'). Caller must free the argument vector * and its members. */ int argv_split(const char *s, int *argcp, char ***argvp, int terminate_on_comment) { int r = SSH_ERR_INTERNAL_ERROR; int argc = 0, quote, i, j; char *arg, **argv = xcalloc(1, sizeof(*argv)); *argvp = NULL; *argcp = 0; for (i = 0; s[i] != '\0'; i++) { /* Skip leading whitespace */ if (s[i] == ' ' || s[i] == '\t') continue; if (terminate_on_comment && s[i] == '#') break; /* Start of a token */ quote = 0; argv = xreallocarray(argv, (argc + 2), sizeof(*argv)); arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1); argv[argc] = NULL; /* Copy the token in, removing escapes */ for (j = 0; s[i] != '\0'; i++) { if (s[i] == '\\') { if (s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\' || (quote == 0 && s[i + 1] == ' ')) { i++; /* Skip '\' */ arg[j++] = s[i]; } else { /* Unrecognised escape */ arg[j++] = s[i]; } } else if (quote == 0 && (s[i] == ' ' || s[i] == '\t')) break; /* done */ else if (quote == 0 && (s[i] == '\"' || s[i] == '\'')) quote = s[i]; /* quote start */ else if (quote != 0 && s[i] == quote) quote = 0; /* quote end */ else arg[j++] = s[i]; } if (s[i] == '\0') { if (quote != 0) { /* Ran out of string looking for close quote */ r = SSH_ERR_INVALID_FORMAT; goto out; } break; } } /* Success */ *argcp = argc; *argvp = argv; argc = 0; argv = NULL; r = 0; out: if (argc != 0 && argv != NULL) { for (i = 0; i < argc; i++) free(argv[i]); free(argv); } return r; } /* * Reassemble an argument vector into a string, quoting and escaping as * necessary. Caller must free returned string. */ char * argv_assemble(int argc, char **argv) { int i, j, ws, r; char c, *ret; struct sshbuf *buf, *arg; if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); for (i = 0; i < argc; i++) { ws = 0; sshbuf_reset(arg); for (j = 0; argv[i][j] != '\0'; j++) { r = 0; c = argv[i][j]; switch (c) { case ' ': case '\t': ws = 1; r = sshbuf_put_u8(arg, c); break; case '\\': case '\'': case '"': if ((r = sshbuf_put_u8(arg, '\\')) != 0) break; /* FALLTHROUGH */ default: r = sshbuf_put_u8(arg, c); break; } if (r != 0) fatal_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_fr(r, "assemble"); } if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL) fatal_f("malloc failed"); memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf)); ret[sshbuf_len(buf)] = '\0'; sshbuf_free(buf); sshbuf_free(arg); return ret; } char * argv_next(int *argcp, char ***argvp) { char *ret = (*argvp)[0]; if (*argcp > 0 && ret != NULL) { (*argcp)--; (*argvp)++; } return ret; } void argv_consume(int *argcp) { *argcp = 0; } void argv_free(char **av, int ac) { int i; if (av == NULL) return; for (i = 0; i < ac; i++) free(av[i]); free(av); } /* Returns 0 if pid exited cleanly, non-zero otherwise */ int exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet) { int status; while (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) { error("%s waitpid: %s", tag, strerror(errno)); return -1; } } if (WIFSIGNALED(status)) { error("%s %s exited on signal %d", tag, cmd, WTERMSIG(status)); return -1; } else if (WEXITSTATUS(status) != 0) { do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO, "%s %s failed, status %d", tag, cmd, WEXITSTATUS(status)); return -1; } return 0; } /* * Check a given path for security. This is defined as all components * of the path to the file must be owned by either the owner of * of the file or root and no directories must be group or world writable. * * XXX Should any specific check be done for sym links ? * * Takes a file name, its stat information (preferably from fstat() to * avoid races), the uid of the expected owner, their home directory and an * error buffer plus max size as arguments. * * Returns 0 on success and -1 on failure */ int safe_path(const char *name, struct stat *stp, const char *pw_dir, uid_t uid, char *err, size_t errlen) { char buf[PATH_MAX], homedir[PATH_MAX]; char *cp; int comparehome = 0; struct stat st; if (realpath(name, buf) == NULL) { snprintf(err, errlen, "realpath %s failed: %s", name, strerror(errno)); return -1; } if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL) comparehome = 1; if (!S_ISREG(stp->st_mode)) { snprintf(err, errlen, "%s is not a regular file", buf); return -1; } if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || (stp->st_mode & 022) != 0) { snprintf(err, errlen, "bad ownership or modes for file %s", buf); return -1; } /* for each component of the canonical path, walking upwards */ for (;;) { if ((cp = dirname(buf)) == NULL) { snprintf(err, errlen, "dirname() failed"); return -1; } strlcpy(buf, cp, sizeof(buf)); if (stat(buf, &st) == -1 || (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || (st.st_mode & 022) != 0) { snprintf(err, errlen, "bad ownership or modes for directory %s", buf); return -1; } /* If are past the homedir then we can stop */ if (comparehome && strcmp(homedir, buf) == 0) break; /* * dirname should always complete with a "/" path, * but we can be paranoid and check for "." too */ if ((strcmp("/", buf) == 0) || (strcmp(".", buf) == 0)) break; } return 0; } /* * Version of safe_path() that accepts an open file descriptor to * avoid races. * * Returns 0 on success and -1 on failure */ int safe_path_fd(int fd, const char *file, struct passwd *pw, char *err, size_t errlen) { struct stat st; /* check the open file to avoid races */ if (fstat(fd, &st) == -1) { snprintf(err, errlen, "cannot stat file %s: %s", file, strerror(errno)); return -1; } return safe_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen); } /* * Sets the value of the given variable in the environment. If the variable * already exists, its value is overridden. */ void child_set_env(char ***envp, u_int *envsizep, const char *name, const char *value) { char **env; u_int envsize; u_int i, namelen; if (strchr(name, '=') != NULL) { error("Invalid environment variable \"%.100s\"", name); return; } /* * If we're passed an uninitialized list, allocate a single null * entry before continuing. */ if ((*envp == NULL) != (*envsizep == 0)) fatal_f("environment size mismatch"); if (*envp == NULL && *envsizep == 0) { *envp = xmalloc(sizeof(char *)); *envp[0] = NULL; *envsizep = 1; } /* * Find the slot where the value should be stored. If the variable * already exists, we reuse the slot; otherwise we append a new slot * at the end of the array, expanding if necessary. */ env = *envp; namelen = strlen(name); for (i = 0; env[i]; i++) if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=') break; if (env[i]) { /* Reuse the slot. */ free(env[i]); } else { /* New variable. Expand if necessary. */ envsize = *envsizep; if (i >= envsize - 1) { if (envsize >= 1000) fatal("child_set_env: too many env vars"); envsize += 50; env = (*envp) = xreallocarray(env, envsize, sizeof(char *)); *envsizep = envsize; } /* Need to set the NULL pointer at end of array beyond the new slot. */ env[i + 1] = NULL; } /* Allocate space and format the variable in the appropriate slot. */ /* XXX xasprintf */ env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1); snprintf(env[i], strlen(name) + 1 + strlen(value) + 1, "%s=%s", name, value); } /* * Check and optionally lowercase a domain name, also removes trailing '.' * Returns 1 on success and 0 on failure, storing an error message in errstr. */ int valid_domain(char *name, int makelower, const char **errstr) { size_t i, l = strlen(name); u_char c, last = '\0'; static char errbuf[256]; if (l == 0) { strlcpy(errbuf, "empty domain name", sizeof(errbuf)); goto bad; } if (!isalpha((u_char)name[0]) && !isdigit((u_char)name[0])) { snprintf(errbuf, sizeof(errbuf), "domain name \"%.100s\" " "starts with invalid character", name); goto bad; } for (i = 0; i < l; i++) { c = tolower((u_char)name[i]); if (makelower) name[i] = (char)c; if (last == '.' && c == '.') { snprintf(errbuf, sizeof(errbuf), "domain name " "\"%.100s\" contains consecutive separators", name); goto bad; } if (c != '.' && c != '-' && !isalnum(c) && c != '_') /* technically invalid, but common */ { snprintf(errbuf, sizeof(errbuf), "domain name " "\"%.100s\" contains invalid characters", name); goto bad; } last = c; } if (name[l - 1] == '.') name[l - 1] = '\0'; if (errstr != NULL) *errstr = NULL; return 1; bad: if (errstr != NULL) *errstr = errbuf; return 0; } /* * Verify that a environment variable name (not including initial '$') is * valid; consisting of one or more alphanumeric or underscore characters only. * Returns 1 on valid, 0 otherwise. */ int valid_env_name(const char *name) { const char *cp; if (name[0] == '\0') return 0; for (cp = name; *cp != '\0'; cp++) { if (!isalnum((u_char)*cp) && *cp != '_') return 0; } return 1; } const char * atoi_err(const char *nptr, int *val) { const char *errstr = NULL; long long num; if (nptr == NULL || *nptr == '\0') return "missing"; num = strtonum(nptr, 0, INT_MAX, &errstr); if (errstr == NULL) *val = (int)num; return errstr; } int parse_absolute_time(const char *s, uint64_t *tp) { struct tm tm; time_t tt; char buf[32], *fmt; const char *cp; size_t l; int is_utc = 0; *tp = 0; l = strlen(s); if (l > 1 && strcasecmp(s + l - 1, "Z") == 0) { is_utc = 1; l--; } else if (l > 3 && strcasecmp(s + l - 3, "UTC") == 0) { is_utc = 1; l -= 3; } /* * POSIX strptime says "The application shall ensure that there * is white-space or other non-alphanumeric characters between * any two conversion specifications" so arrange things this way. */ switch (l) { case 8: /* YYYYMMDD */ fmt = "%Y-%m-%d"; snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2s", s, s + 4, s + 6); break; case 12: /* YYYYMMDDHHMM */ fmt = "%Y-%m-%dT%H:%M"; snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s", s, s + 4, s + 6, s + 8, s + 10); break; case 14: /* YYYYMMDDHHMMSS */ fmt = "%Y-%m-%dT%H:%M:%S"; snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s", s, s + 4, s + 6, s + 8, s + 10, s + 12); break; default: return SSH_ERR_INVALID_FORMAT; } memset(&tm, 0, sizeof(tm)); if ((cp = strptime(buf, fmt, &tm)) == NULL || *cp != '\0') return SSH_ERR_INVALID_FORMAT; if (is_utc) { if ((tt = timegm(&tm)) < 0) return SSH_ERR_INVALID_FORMAT; } else { if ((tt = mktime(&tm)) < 0) return SSH_ERR_INVALID_FORMAT; } /* success */ *tp = (uint64_t)tt; return 0; } void format_absolute_time(uint64_t t, char *buf, size_t len) { time_t tt = t > SSH_TIME_T_MAX ? SSH_TIME_T_MAX : t; struct tm tm; localtime_r(&tt, &tm); strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm); } +/* + * Parse a "pattern=interval" clause (e.g. a ChannelTimeout). + * Returns 0 on success or non-zero on failure. + * Caller must free *typep. + */ +int +parse_pattern_interval(const char *s, char **typep, int *secsp) +{ + char *cp, *sdup; + int secs; + + if (typep != NULL) + *typep = NULL; + if (secsp != NULL) + *secsp = 0; + if (s == NULL) + return -1; + sdup = xstrdup(s); + + if ((cp = strchr(sdup, '=')) == NULL || cp == sdup) { + free(sdup); + return -1; + } + *cp++ = '\0'; + if ((secs = convtime(cp)) < 0) { + free(sdup); + return -1; + } + /* success */ + if (typep != NULL) + *typep = xstrdup(sdup); + if (secsp != NULL) + *secsp = secs; + free(sdup); + return 0; +} + /* check if path is absolute */ int path_absolute(const char *path) { return (*path == '/') ? 1 : 0; } void skip_space(char **cpp) { char *cp; for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++) ; *cpp = cp; } /* authorized_key-style options parsing helpers */ /* * Match flag 'opt' in *optsp, and if allow_negate is set then also match * 'no-opt'. Returns -1 if option not matched, 1 if option matches or 0 * if negated option matches. * If the option or negated option matches, then *optsp is updated to * point to the first character after the option. */ int opt_flag(const char *opt, int allow_negate, const char **optsp) { size_t opt_len = strlen(opt); const char *opts = *optsp; int negate = 0; if (allow_negate && strncasecmp(opts, "no-", 3) == 0) { opts += 3; negate = 1; } if (strncasecmp(opts, opt, opt_len) == 0) { *optsp = opts + opt_len; return negate ? 0 : 1; } return -1; } char * opt_dequote(const char **sp, const char **errstrp) { const char *s = *sp; char *ret; size_t i; *errstrp = NULL; if (*s != '"') { *errstrp = "missing start quote"; return NULL; } s++; if ((ret = malloc(strlen((s)) + 1)) == NULL) { *errstrp = "memory allocation failed"; return NULL; } for (i = 0; *s != '\0' && *s != '"';) { if (s[0] == '\\' && s[1] == '"') s++; ret[i++] = *s++; } if (*s == '\0') { *errstrp = "missing end quote"; free(ret); return NULL; } ret[i] = '\0'; s++; *sp = s; return ret; } int opt_match(const char **opts, const char *term) { if (strncasecmp((*opts), term, strlen(term)) == 0 && (*opts)[strlen(term)] == '=') { *opts += strlen(term) + 1; return 1; } 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 && safe_path(av[0], &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) { error("Unsafe %s \"%s\": %s", tag, av[0], errmsg); 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(); 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 (geteuid() == 0 && initgroups(pw->pw_name, pw->pw_gid) == -1) { error("%s: initgroups(%s, %u): %s", tag, pw->pw_name, (u_int)pw->pw_gid, strerror(errno)); _exit(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; } 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; } const char * lookup_env_in_list(const char *env, char * const *envs, size_t nenvs) { size_t i, envlen; envlen = strlen(env); for (i = 0; i < nenvs; i++) { if (strncmp(envs[i], env, envlen) == 0 && envs[i][envlen] == '=') { return envs[i] + envlen + 1; } } return NULL; } const char * lookup_setenv_in_list(const char *env, char * const *envs, size_t nenvs) { char *name, *cp; const char *ret; name = xstrdup(env); if ((cp = strchr(name, '=')) == NULL) { free(name); return NULL; /* not env=val */ } *cp = '\0'; ret = lookup_env_in_list(name, envs, nenvs); free(name); return ret; } /* * Helpers for managing poll(2)/ppoll(2) timeouts * Will remember the earliest deadline and return it for use in poll/ppoll. */ /* Initialise a poll/ppoll timeout with an indefinite deadline */ void ptimeout_init(struct timespec *pt) { /* * Deliberately invalid for ppoll(2). * Will be converted to NULL in ptimeout_get_tspec() later. */ pt->tv_sec = -1; pt->tv_nsec = 0; } /* Specify a poll/ppoll deadline of at most 'sec' seconds */ void ptimeout_deadline_sec(struct timespec *pt, long sec) { if (pt->tv_sec == -1 || pt->tv_sec >= sec) { pt->tv_sec = sec; pt->tv_nsec = 0; } } /* Specify a poll/ppoll deadline of at most 'p' (timespec) */ static void ptimeout_deadline_tsp(struct timespec *pt, struct timespec *p) { if (pt->tv_sec == -1 || timespeccmp(pt, p, >=)) *pt = *p; } /* Specify a poll/ppoll deadline of at most 'ms' milliseconds */ void ptimeout_deadline_ms(struct timespec *pt, long ms) { struct timespec p; p.tv_sec = ms / 1000; p.tv_nsec = (ms % 1000) * 1000000; ptimeout_deadline_tsp(pt, &p); } /* Specify a poll/ppoll deadline at wall clock monotime 'when' (timespec) */ void ptimeout_deadline_monotime_tsp(struct timespec *pt, struct timespec *when) { struct timespec now, t; monotime_ts(&now); if (timespeccmp(&now, when, >=)) { /* 'when' is now or in the past. Timeout ASAP */ pt->tv_sec = 0; pt->tv_nsec = 0; } else { timespecsub(when, &now, &t); ptimeout_deadline_tsp(pt, &t); } } /* Specify a poll/ppoll deadline at wall clock monotime 'when' */ void ptimeout_deadline_monotime(struct timespec *pt, time_t when) { struct timespec t; t.tv_sec = when; t.tv_nsec = 0; ptimeout_deadline_monotime_tsp(pt, &t); } /* Get a poll(2) timeout value in milliseconds */ int ptimeout_get_ms(struct timespec *pt) { if (pt->tv_sec == -1) return -1; if (pt->tv_sec >= (INT_MAX - (pt->tv_nsec / 1000000)) / 1000) return INT_MAX; return (pt->tv_sec * 1000) + (pt->tv_nsec / 1000000); } /* Get a ppoll(2) timeout value as a timespec pointer */ struct timespec * ptimeout_get_tsp(struct timespec *pt) { return pt->tv_sec == -1 ? NULL : pt; } /* Returns non-zero if a timeout has been set (i.e. is not indefinite) */ int ptimeout_isset(struct timespec *pt) { return pt->tv_sec != -1; } /* * Returns zero if the library at 'path' contains symbol 's', nonzero * otherwise. */ int lib_contains_symbol(const char *path, const char *s) { #ifdef HAVE_NLIST_H struct nlist nl[2]; int ret = -1, r; memset(nl, 0, sizeof(nl)); nl[0].n_name = xstrdup(s); nl[1].n_name = NULL; if ((r = nlist(path, nl)) == -1) { error_f("nlist failed for %s", path); goto out; } if (r != 0 || nl[0].n_value == 0 || nl[0].n_type == 0) { error_f("library %s does not contain symbol %s", path, s); goto out; } /* success */ ret = 0; out: free(nl[0].n_name); return ret; #else /* HAVE_NLIST_H */ int fd, ret = -1; struct stat st; void *m = NULL; size_t sz = 0; memset(&st, 0, sizeof(st)); if ((fd = open(path, O_RDONLY)) < 0) { error_f("open %s: %s", path, strerror(errno)); return -1; } if (fstat(fd, &st) != 0) { error_f("fstat %s: %s", path, strerror(errno)); goto out; } if (!S_ISREG(st.st_mode)) { error_f("%s is not a regular file", path); goto out; } if (st.st_size < 0 || (size_t)st.st_size < strlen(s) || st.st_size >= INT_MAX/2) { error_f("%s bad size %lld", path, (long long)st.st_size); goto out; } sz = (size_t)st.st_size; if ((m = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED || m == NULL) { error_f("mmap %s: %s", path, strerror(errno)); goto out; } if (memmem(m, sz, s, strlen(s)) == NULL) { error_f("%s does not contain expected string %s", path, s); goto out; } /* success */ ret = 0; out: if (m != NULL && m != MAP_FAILED) munmap(m, sz); close(fd); return ret; #endif /* HAVE_NLIST_H */ } diff --git a/crypto/openssh/misc.h b/crypto/openssh/misc.h index 4f941597e9e3..74c6f832cb19 100644 --- a/crypto/openssh/misc.h +++ b/crypto/openssh/misc.h @@ -1,249 +1,250 @@ -/* $OpenBSD: misc.h,v 1.105 2023/08/28 03:31:16 djm Exp $ */ +/* $OpenBSD: misc.h,v 1.106 2023/10/11 22:42:26 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #ifndef _MISC_H #define _MISC_H #include #include #include #include #include /* Data structure for representing a forwarding request. */ struct Forward { char *listen_host; /* Host (address) to listen on. */ int listen_port; /* Port to forward. */ char *listen_path; /* Path to bind domain socket. */ char *connect_host; /* Host to connect. */ int connect_port; /* Port to connect on connect_host. */ char *connect_path; /* Path to connect domain socket. */ int allocated_port; /* Dynamically allocated listen port */ int handle; /* Handle for dynamic listen ports */ }; int forward_equals(const struct Forward *, const struct Forward *); int daemonized(void); /* Common server and client forwarding options. */ struct ForwardOptions { int gateway_ports; /* Allow remote connects to forwarded ports. */ mode_t streamlocal_bind_mask; /* umask for streamlocal binds */ int streamlocal_bind_unlink; /* unlink socket before bind */ }; /* misc.c */ char *chop(char *); void rtrim(char *); void skip_space(char **); char *strdelim(char **); char *strdelimw(char **); int set_nonblock(int); int unset_nonblock(int); void set_nodelay(int); int set_reuseaddr(int); char *get_rdomain(int); int set_rdomain(int, const char *); int get_sock_af(int); void set_sock_tos(int, int); int waitrfd(int, int *, volatile sig_atomic_t *); int timeout_connect(int, const struct sockaddr *, socklen_t, int *); int a2port(const char *); int a2tun(const char *, int *); char *put_host_port(const char *, u_short); char *hpdelim2(char **, char *); char *hpdelim(char **); char *cleanhostname(char *); char *colon(char *); int parse_user_host_path(const char *, char **, char **, char **); int parse_user_host_port(const char *, char **, char **, int *); int parse_uri(const char *, const char *, char **, char **, int *, char **); int convtime(const char *); const char *fmt_timeframe(time_t t); int tilde_expand(const char *, uid_t, char **); 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_timespec(struct timespec *, int); void monotime_ts(struct timespec *); void monotime_tv(struct timeval *); time_t monotime(void); double monotime_double(void); void lowercase(char *s); int unix_listener(const char *, int, int); int valid_domain(char *, int, const char **); int valid_env_name(const char *); const char *atoi_err(const char *, int *); int parse_absolute_time(const char *, uint64_t *); void format_absolute_time(uint64_t, char *, size_t); +int parse_pattern_interval(const char *, char **, int *); int path_absolute(const char *); int stdfd_devnull(int, int, int); int lib_contains_symbol(const char *, const char *); 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; u_int num; u_int nalloc; }; void addargs(arglist *, char *, ...) __attribute__((format(printf, 2, 3))); void replacearg(arglist *, u_int, char *, ...) __attribute__((format(printf, 3, 4))); void freeargs(arglist *); int tun_open(int, int, char **); /* Common definitions for ssh tunnel device forwarding */ #define SSH_TUNMODE_NO 0x00 #define SSH_TUNMODE_POINTOPOINT 0x01 #define SSH_TUNMODE_ETHERNET 0x02 #define SSH_TUNMODE_DEFAULT SSH_TUNMODE_POINTOPOINT #define SSH_TUNMODE_YES (SSH_TUNMODE_POINTOPOINT|SSH_TUNMODE_ETHERNET) #define SSH_TUNID_ANY 0x7fffffff #define SSH_TUNID_ERR (SSH_TUNID_ANY - 1) #define SSH_TUNID_MAX (SSH_TUNID_ANY - 2) /* Fake port to indicate that host field is really a path. */ #define PORT_STREAMLOCAL -2 /* Functions to extract or store big-endian words of various sizes */ u_int64_t get_u64(const void *) __attribute__((__bounded__( __minbytes__, 1, 8))); u_int32_t get_u32(const void *) __attribute__((__bounded__( __minbytes__, 1, 4))); u_int16_t get_u16(const void *) __attribute__((__bounded__( __minbytes__, 1, 2))); void put_u64(void *, u_int64_t) __attribute__((__bounded__( __minbytes__, 1, 8))); void put_u32(void *, u_int32_t) __attribute__((__bounded__( __minbytes__, 1, 4))); void put_u16(void *, u_int16_t) __attribute__((__bounded__( __minbytes__, 1, 2))); /* Little-endian store/load, used by umac.c */ u_int32_t get_u32_le(const void *) __attribute__((__bounded__(__minbytes__, 1, 4))); void put_u32_le(void *, u_int32_t) __attribute__((__bounded__(__minbytes__, 1, 4))); struct bwlimit { size_t buflen; u_int64_t rate; /* desired rate in kbit/s */ u_int64_t thresh; /* threshold after which we'll check timers */ u_int64_t lamt; /* amount written in last timer interval */ struct timeval bwstart, bwend; }; void bandwidth_limit_init(struct bwlimit *, u_int64_t, size_t); void bandwidth_limit(struct bwlimit *, size_t); int parse_ipqos(const char *); const char *iptos2str(int); void mktemp_proto(char *, size_t); void child_set_env(char ***envp, u_int *envsizep, const char *name, const char *value); const char *lookup_env_in_list(const char *env, char * const *envs, size_t nenvs); const char *lookup_setenv_in_list(const char *env, char * const *envs, size_t nenvs); int argv_split(const char *, int *, char ***, int); char *argv_assemble(int, char **argv); char *argv_next(int *, char ***); void argv_consume(int *); void argv_free(char **, int); int exited_cleanly(pid_t, const char *, const char *, int); struct stat; int safe_path(const char *, struct stat *, const char *, uid_t, char *, size_t); int safe_path_fd(int, const char *, struct passwd *, char *err, size_t errlen); /* authorized_key-style options parsing helpers */ 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); struct timespec; void ptimeout_init(struct timespec *pt); void ptimeout_deadline_sec(struct timespec *pt, long sec); void ptimeout_deadline_ms(struct timespec *pt, long ms); void ptimeout_deadline_monotime_tsp(struct timespec *pt, struct timespec *when); void ptimeout_deadline_monotime(struct timespec *pt, time_t when); int ptimeout_get_ms(struct timespec *pt); struct timespec *ptimeout_get_tsp(struct timespec *pt); int ptimeout_isset(struct timespec *pt); /* readpass.c */ #define RP_ECHO 0x0001 #define RP_ALLOW_STDIN 0x0002 #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); /* On OpenBSD time_t is int64_t which is long long. */ /* #define SSH_TIME_T_MAX LLONG_MAX */ #endif /* _MISC_H */ diff --git a/crypto/openssh/moduli b/crypto/openssh/moduli index e7bff9328451..00d293e72cf6 100644 --- a/crypto/openssh/moduli +++ b/crypto/openssh/moduli @@ -1,445 +1,455 @@ -# $OpenBSD: moduli,v 1.34 2023/05/01 08:57:29 dtucker Exp $ +# $OpenBSD: moduli,v 1.35 2023/10/25 05:38:08 dtucker Exp $ # Time Type Tests Tries Size Generator Modulus -20230417120124 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C943E0383 -20230417120129 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C9462F9B3 -20230417120132 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C94818443 -20230417120135 2 6 100 2047 5 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C949B755F -20230417120155 2 6 100 2047 5 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C954A83D7 -20230417120158 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C95657A3B -20230417120201 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C957B51F3 -20230417120201 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C957EB6BB -20230417120206 2 6 100 2047 5 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C95AF6707 -20230417120209 2 6 100 2047 5 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C95C36207 -20230417120211 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C95D89093 -20230417120214 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C95F024C3 -20230417120220 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C962642AB -20230417120225 2 6 100 2047 5 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C96584C87 -20230417120238 2 6 100 2047 5 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C96CE8FAF -20230417120304 2 6 100 2047 5 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C97B17897 -20230417120306 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C97C2F6B3 -20230417120317 2 6 100 2047 5 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C9827CC27 -20230417120345 2 6 100 2047 5 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C9922340F -20230417120401 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C99B05AC3 -20230417120406 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C99DFACAB -20230417120409 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C99F8E8CB -20230417120414 2 6 100 2047 5 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C9A202DEF -20230417120414 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C9A2503C3 -20230417120441 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C9B0A324B -20230417120445 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C9B33D5C3 -20230417120447 2 6 100 2047 5 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C9B411987 -20230417120448 2 6 100 2047 5 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C9B494607 -20230417120456 2 6 100 2047 2 ED2A924913C58F89692C7C19D5075DA18DAC087CF012163C5646F4794A5082F4C9484C4D5691813AFD61BC001A8406A5D574BFF03BE23BC6D47E847E2BCEE71529CC26026D0A1171DAFC8D0CB4827E195260AA6B14FCF7DACC02CD3A8AA5892CB166D75219DB8A739D4DCB04CE626180EDC992DA4F8A6A71362F15EF700EE98DF93904085D7FFC6433C88DE5AF7F2887A55362F963BDCB229D72A6920A363AD76ABD3BE7321BB07DD8C69AA3B824B2C52D0C9CE9F362A4E73452CD0CA3D95BBDDB01B8EB1AECEBF563A4BB36B7957EBB5BB814FC51BE58CC474035CCDC7C753984A530EB565E1A7DE1EFE84B33BD42FA8856BCAAF6F6A937896B931C9B8CC7AB -20230417120528 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A6455043 -20230417120532 2 6 100 2047 5 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A66D5957 -20230417120533 2 6 100 2047 5 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A6717F0F -20230417120546 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A6E2BA9B -20230417120547 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A6EAA9CB -20230417120607 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A79FC72B -20230417120608 2 6 100 2047 5 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A7A811FF -20230417120614 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A7DE27B3 -20230417120616 2 6 100 2047 5 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A7EEE8FF -20230417120628 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A85E5CA3 -20230417120637 2 6 100 2047 5 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A8AD9E57 -20230417120643 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A8DEAEA3 -20230417120649 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A9129123 -20230417120659 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A972661B -20230417120700 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A979D6A3 -20230417120703 2 6 100 2047 5 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A998550F -20230417120704 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3A9A1128B -20230417120715 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3AA04DA23 -20230417120716 2 6 100 2047 5 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3AA119F0F -20230417120717 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3AA15B76B -20230417120732 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3AA9F9413 -20230417120736 2 6 100 2047 5 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3AABFACEF -20230417120754 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3AB62E753 -20230417120807 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3ABD48FAB -20230417120809 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3ABE6D223 -20230417120818 2 6 100 2047 5 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3AC33888F -20230417120822 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3AC57C9AB -20230417120823 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3AC62FF5B -20230417120828 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3AC887DDB -20230417120838 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3ACDD94C3 -20230417120846 2 6 100 2047 5 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3AD2B9D3F -20230417120847 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3AD344873 -20230417120850 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3AD46FA4B -20230417120900 2 6 100 2047 2 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3ADA332FB -20230417120904 2 6 100 2047 5 EEBE899F650DF44524FF30ED346D3194D97BB10C569F8893CF14E8C1F69BAD0AB49C38EB947AACA1AB0C4F69B4E4DFBCA29AB2BC4722D5D5A335BA06EEF733A5C348CA1D536F91BA3DBCA0E5FD00412E4206BF93E7C055BF7CC9EE38082E21F4A0B8F61DDB684F41215E676A268CA8D49ED432CB778CF91B6FEBD8FC652E042A7E949169A6AAA15A74B905C5EF5E0B81D7524725D207CCAD05E2B255E91470E114AE4ED55C9B592BCD6AB64FB65623D9DB57934F12F3AED693BC152F3EB08F445760049378C584973A4FF4CC404C9BC9B638CD2E27FE21F8AB925BCF874DFCB0D915DC6BF1BD482FBC861CEFEAFCA437B3669CB60B5F7E47DEC9CBF3ADC084EF -20230417121744 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2D99166AB -20230417121754 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2D9B0872F -20230417121757 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2D9B900E3 -20230417121800 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2D9C2B1E3 -20230417121825 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DA1F5717 -20230417121847 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DA6B2143 -20230417121944 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DB3ACBB3 -20230417122011 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DB9C216B -20230417122021 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DBBDFA2B -20230417122056 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DC38C803 -20230417122127 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DCA602F7 -20230417122129 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DCACFFF3 -20230417122132 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DCB4B893 -20230417122219 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DD5A5A03 -20230417122219 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DD5CD153 -20230417122238 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DD9E09A3 -20230417122247 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DDBD243F -20230417122408 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DED32707 -20230417122430 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DF223A83 -20230417122433 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DF2B9D83 -20230417122440 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DF426847 -20230417122457 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2DF7BCFA3 -20230417122624 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E0B497FB -20230417122658 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E12D46AF -20230417122710 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E159181B -20230417122711 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E15E6583 -20230417122714 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E1654A4F -20230417122733 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E1AA366F -20230417122739 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E1BE2C5F -20230417122922 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E32EE927 -20230417122925 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E337B273 -20230417123014 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E3DFEA5F -20230417123028 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E40E1737 -20230417123047 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E4515123 -20230417123056 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E4701B43 -20230417123056 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E470F5FB -20230417123120 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E4C3CB4B -20230417123255 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E6107DB7 -20230417123326 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E67ED8B7 -20230417123345 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E6C1920F -20230417123354 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E6DFA043 -20230417123440 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E77B3AA3 -20230417123609 2 6 100 3071 5 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2E8C255DF -20230417123747 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2EA2B40F3 -20230417123841 2 6 100 3071 2 D721E9FFB0F42262EBE068B02546B1857649EC8D8172C9EFB33A5C244FC57C5C0A5208035FE2DA4C342C9E9F7503D8FE89B39B3AA1244E30BEDD885598832B4574846A1594EFFCDB86E91A62343F0E37DACCC022595BDAA2A06EDC553174928C0EB8BC8D223F49AE5F43F0D10090C825050C4C301E9C02AC5F0353D83F0EC0FD2B5A147CDE7635D93E77461FFBB34F7DCB7AC51C79876859C75A04E1BA8A0851F5DBCA3C317452641359B3D9F53D60011979ACCA30F1919867B605FBC775B4C7DE2E76F2B468F232D914AD6D0893708F3882D7098CCB612DD1CEDDAE43DBE1486B530C13D5CB01EE3F962388C7A0B7182DFB76C4AF1A0ED17843AA78F76EDA5B58F730A43299CA7FDDC5D972EA9AF01A36BC9739E3933A3291F6AE0A171F172A6A527147CE08132739A198C9D086FFB0B84878CD3BAE644EC2FF8133A5DB391D0ABD4ED732F674DF45D0C3BCC98D11A0C962BE01DD573A8B7DBEEE81E8866FDDB94877C2552E4E232B7D12DC71A3A30C22C6D504B53A9FE4BDCE1CD2EAEAE16B -20230417123920 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3A5E1FC7 -20230417123928 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3A7A8353 -20230417123939 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3AA10DE7 -20230417123945 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3AB25DCB -20230417123953 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3ACEB053 -20230417124009 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3B05AD5B -20230417124024 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3B39B303 -20230417124029 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3B4BDF1F -20230417124109 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3BD5489B -20230417124127 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3C1470EB -20230417124227 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3CE4EBC3 -20230417124244 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3D22B88B -20230417124306 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3D6CF783 -20230417124307 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3D715E4B -20230417124326 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3DAC5AB3 -20230417124406 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3E2FBD0F -20230417124407 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3E3504B3 -20230417124415 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3E516D97 -20230417124450 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3ECEC67B -20230417124508 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3F0E9FFB -20230417124601 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A3FD1B78F -20230417124628 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A40357A17 -20230417124639 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A405C53B3 -20230417124805 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A4191A5DF -20230417124913 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A427B559F -20230417124937 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A42CEE57F -20230417124938 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A42D34AF7 -20230417125003 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A4329C5A7 -20230417125012 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A4347143B -20230417125021 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A436AB003 -20230417125142 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A448A9A43 -20230417125152 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A44AB761F -20230417125204 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A44D48BCB -20230417125224 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A45197863 -20230417125302 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A459B79F7 -20230417125312 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A45BFF7BB -20230417125323 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A45E659C3 -20230417125407 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A467F9F2F -20230417125506 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A474AE883 -20230417125516 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A476DD73B -20230417125557 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A47F974F3 -20230417125610 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A4827BA43 -20230417125801 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A49B5D97F -20230417125803 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A49BC1273 -20230417125827 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A4A0F4523 -20230417125933 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A4AF059AB -20230417130019 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A4B913D0B -20230417130025 2 6 100 3071 5 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A4BA8802F -20230417130030 2 6 100 3071 2 C4747DFF05D355ABFB6E5F6FDAE3BCBE31EAEE34C49ABBAF89CC8E6309CEA65B6B417DC3760DAC07D51C759168CE9225D1CD9C97EA230DDC793E4AD05C72063DB2A49CD27B57CC287D26FAE461817464B84A3EBA3D517574D5E6ECE37053776F3009150444AF274DDD85D9EAACACB6A0EA99E3292A7238EDE2AFA0B9EB39D7C170E6909AC7F14E402F7708759345F542F8EC91A0F1AD12D6F5449F0C140C694DB136CFA002BE3C1C0F21531A8EF2AF85BF85B3B176EFB022718319101EE4AB208BC7BC4D5BB7536DE84934F783761CF7DE217DAC95239199146395CD1EDFFE586C8558FB73277ED6A432EAD6634AE0D35708BBADC335A3666E101508438C5269EEEF13FF0316C4B497E7B2D838AC51B2CE40A90FF6D01EB980FEB9E7F5FDBC94A2107AC0F9AA91A821C05C77624C4F0EBD956919C02DB43B457CC0416DD4170BA2005ACDC929E796D94D96A54CC3102E41D00276D2E540C917ED72AB1C6579E3DDDEC6ED7719A89EEF2A1D49F457B756A573A4BD1AF5F95E26EF1F3A4BB8247B -20230417131219 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E27BDE22FB -20230417131442 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E27CD43153 -20230417131501 2 6 100 4095 5 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E27CF4BFD7 -20230417131650 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E27DB2B14B -20230417131657 2 6 100 4095 5 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E27DBF71FF -20230417131955 2 6 100 4095 5 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E27EF8AE1F -20230417132223 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E27FFCB94B -20230417132225 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E27FFEA3B3 -20230417132516 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E281200CD3 -20230417133132 2 6 100 4095 5 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E283AC7167 -20230417133149 2 6 100 4095 5 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E283CBB837 -20230417133526 2 6 100 4095 5 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E28539A7E7 -20230417134301 2 6 100 4095 5 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E28842D85F -20230417134528 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E2892BF3C3 -20230417134857 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E28A9390AB -20230417135216 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E28BECDCB3 -20230417140717 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E291FB0063 -20230417140828 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E29272AC03 -20230417140936 2 6 100 4095 5 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E292E18A4F -20230417141154 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E293CF26BB -20230417141515 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E2951E8503 -20230417141826 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E29669544B -20230417142656 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E299CE52F3 -20230417142717 2 6 100 4095 5 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E299F07077 -20230417142807 2 6 100 4095 5 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E29A3EFCFF -20230417143013 2 6 100 4095 2 F276C2B5EA33827576113DA1557DAAF34337A5AA948EAF20BE835D94FB8F1A619106EE29BB65F72D1E1D87180BE08FEBCD6D34961C28414AE1DEB661034334579171972DE85073678980212D6147D692D6DF5C2FE83EEBAC6AF4291A9609B6D2C32A532687DEF60553A17F4DB82C8CF6FCFF7BDC54CDACCA94DD6B9C6EF8D5C6142DA36609E8D910EF4CC974DDFC28C152CC2F6C3B8EB9694F47B16EFB925F94C2CE8D36E69E3C6A15D0903E4F8251010FE3BB625D717E61B789F347829A6B0BEDE369F9BD0608529E9554A20B384AE6017C4DCD888CA536AC537F1BE49EDB99BD3DA550C2C42F1C0D9200541E7788D0FDF63855C4E8730CBEEF1069104D28F3E02E4B9B43127B7E030DF609ECA801A031FA508434B94B9D4CC495A14DD36BDD73534A987EC3278AA3B65C41C788963D98F9384B7598C2A4A5C82570156E57691D9232E312D211B6EE4BE6B21184F17808C85A00D31439D0586521F4E81AFBEB31CF45A78F8780CBD305ADC2058FA46C7D07752C680A7D6607111D4CCD14151B58B57AF3F1A75C9DE0C3C9E2130ABC0E99176B16F2008C05A6179C6880A3C50E16F8C46DAC4D9AC828C6F535E7E2123BFCB5F8B7F818865B943C045F0386B2E630391B52E7D4BDA5B68B95E42A274215A21EFDC76A604A54F403A465135CA3C479BCADEE0B88273824A73177BCE9AE84D870B76EC5E9A90C58D875E29B0F6BFB -20230417143250 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3A2E74663 -20230417143303 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3A2FA9DFB -20230417143423 2 6 100 4095 5 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3A383862F -20230417143748 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3A4E1E6F3 -20230417143924 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3A5885103 -20230417143934 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3A5996373 -20230417144442 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3A7976643 -20230417144545 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3A800917B -20230417144731 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3A8B4AEA3 -20230417144803 2 6 100 4095 5 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3A8E81D07 -20230417145101 2 6 100 4095 5 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3AA116A2F -20230417145423 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3AB6705BB -20230417145750 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3ACC23463 -20230417150019 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3ADB5D94B -20230417150211 2 6 100 4095 5 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3AE71770F -20230417150325 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3AEEBBF5B -20230417150603 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3AFF73B4B -20230417150807 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3B0C44DCB -20230417150816 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3B0D1394B -20230417150849 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3B106812B -20230417151239 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3B27ED09B -20230417151347 2 6 100 4095 5 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3B2F2550F -20230417151425 2 6 100 4095 5 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3B332B547 -20230417151611 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3B3EA8AB3 -20230417151713 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3B4513E53 -20230417151925 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3B52DCCC3 -20230417152202 2 6 100 4095 5 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3B637CD3F -20230417152609 2 6 100 4095 5 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3B7DC96B7 -20230417152728 2 6 100 4095 5 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3B8629C67 -20230417152827 2 6 100 4095 5 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3B8CADF07 -20230417153140 2 6 100 4095 5 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3BA074D97 -20230417153158 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3BA24F59B -20230417153250 2 6 100 4095 5 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3BA7AE117 -20230417153439 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3BB3840C3 -20230417153801 2 6 100 4095 5 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3BC88A33F -20230417153940 2 6 100 4095 5 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3BD2FAC67 -20230417154048 2 6 100 4095 5 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3BDA47277 -20230417154515 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3BF5CCBEB -20230417154742 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3C0541E73 -20230417154853 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3C0CD2823 -20230417154902 2 6 100 4095 2 DD51C971A271D216F492E589C7321ADE786218DC52E48C0014AD0C8463D97D684EFDAF651BB95E2F66938587A96FD8F21C9438D3C6C8FFE1FE615DADF90227BA15FF8BA4124074AEB8553A747DEA8726F53CD2301A4A23E6A1185F25F79A11694B6221CA88C33AF35FF542870577070F669EBA8CE673D772133F6A2BED84B841B57C433D4A2EC542C39CF9FB2E3770BF8AF5929B14064513857F0CE6C0E21A867EFCAB0C8244DB1E3A4256F1480DBFD5E66E7E7D44A0AE5021E6F932241D2209F5525B0798EA2C4190A429AD5B5CACFC7EDBC39B1B123E6414BC54AE2FCE4D14BC9BF13CDD4D6D18FADE09E520B8E243BF3C404BD4FBC506924FEA7E18B826AEF83E478672F43E84F1137526F15BAF86BEF8A3CDB41210CAEB4BFC1C0D929A9ED23E37C179FEE8DCF225A73F0A85F3FC3182AC6F4C9C956ECBD5EC9F6DC5E37A3207C37F21E911E970939F1BEE07D09BADE42EF4A6B379473B1E18A069D1A4B606075200D8FD0A1494F10C86916E0772A422FC4EF74BA4471DBBD8347C5550625FC462ACBA0718514F07852B7AA5AAD4147C665E6FBE01BA6860B74D6CFA733E61EB3BB1CA7C8025FF0EFE2B62197074F630A1A947EE208B39CE7B6C096D9C73A0507367CF0E2E7C5BCADBF50FA89CE31173FCAF98D02DBFD7AE226237461EF97074C893EF6539F67E298CF1E8F2EECD5C5A7D38F5635365C32771F3C0DB5AEB -20230417160813 2 6 100 6143 5 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E09E6043C37 -20230417160955 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E09E63E5ECB -20230417161116 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E09E66D0C13 -20230417173223 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E09F118B56B -20230417174435 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E09F2AC221B -20230417175622 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E09F431B3AB -20230417175805 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E09F466880B -20230417183350 2 6 100 6143 5 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E09F91A3D7F -20230417184313 2 6 100 6143 5 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E09FA5788BF -20230417185829 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E09FC599A13 -20230417190440 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E09FD2A3E43 -20230417190730 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E09FD87730B -20230417191209 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E09FE2497BB -20230417194348 2 6 100 6143 5 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A0251ABDF -20230417195254 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A0382A6EB -20230417201258 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A0626800B -20230417202628 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A07E2F2B3 -20230417203654 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A09425B53 -20230417204838 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A0ACBF40B -20230417205653 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A0BE7263B -20230417212057 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A0F16EC4B -20230417213120 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A1077CDCB -20230417214744 2 6 100 6143 5 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A129A10AF -20230417221328 2 6 100 6143 5 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A15F72EDF -20230417222735 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A17CA8523 -20230417224212 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A19B5D243 -20230417224454 2 6 100 6143 5 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A1A0C1567 -20230417225206 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A1AFC257B -20230417225753 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A1BBA535B -20230417231103 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A1D71EBBB -20230417233302 2 6 100 6143 5 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A204E454F -20230417234117 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A2161C2F3 -20230417235538 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A233C6313 -20230418001249 2 6 100 6143 5 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A25743D17 -20230418001609 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A25E2D033 -20230418001631 2 6 100 6143 5 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A25EEEE27 -20230418002758 2 6 100 6143 5 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A276810B7 -20230418005715 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A2B4072A3 -20230418010752 2 6 100 6143 2 E46F881BE5C8A93A760C690AEBB76537B0B760CEF7E185FFC5AAEA0A2CDD1421E824F043E03614B5A628A80227CCF49F4E0234CB7A1DC3FB0919CF408BA43315FA3383CC9933EE3F177DDD127F680CAD5B701B1BD4D275420EB426175A3F2AB4D8793AF82737C7443ECE98B6C9A54989BC857F6F71E0528D07F8701ABD4FE58992C0D3A106068AB3FB08D3055C647E692A7B43D675CC821EEAE2B51106B9473DF2F4D2069EE1FDB832F741C751F54318419FEC81A5EC3DF257176652B329279D8BF310D0F54568DE5D9D079114EE6597FB320DE0DCD72F10AD51D65722BCFCDF61BBA1F08D6BA05B9AA367D4CB1DB8E050222057FFA5B9678B18DBABE66A022EF78447D7181D4658AF75466E1CA5458852DE729D5AE7E21D4720A2DBF648714C0FBB797C0C3D2CDB2C153B3573C6C483EB905ED338BC7141D779115E746A9BA67DDE0A8690CF0AAE64576F5AA58BD5945FC3A9C7A6527A658EFDEE7E4180F761D7CF1222E6280BFB503047A6E4DE2FB273C31532BDFA1D73E6CDA027E03F63EA237597AE56258EB12181B96AB931709C688BF4770E71A5FC83495131C79AC32EE5C04BCFB23D1414D2DFC21B713F65EE5B9AAF208A2B993B27C2DEEC1C1F334C4305D6EB95C4DF54C8ECB40DC7CDAECBA98F8A48D89D1E1F2F29212FC6A3BD022358D2797E359187FC69332D78C8185BCB0FB45DA3D89128405C30F36B25AE7FA1887ED26B188E67C61BB2799179F8429E2821ACEB946F05FEFDBDDCD34B94B11D8290881B38DC4896B0393494F79DA78CA3871A95820C6E12189C4BB12CEE21A83B01990F52A94B360D33701958332BD600B1EB0547CB6E6ABB89E8CDC20EF346BEB032DE096E17C5C40BFF40EADDF81EF428E0D0873E2630A833AE2C353209C4322366D745ED93A51550A284FC67448E373D843300ED3B2EB094897B7B1318A544CB17A399FFF4F0E9C7B681245245B84D87898C49E6D3CD514CE7489BA76584CA9FE216D3F5C69BB332B50B8FFC153421848B5BE0F3FA25624BB9415D947F46C16ED7B6541D8BF642D6407CADD18702A3642CA6B4281091F28E0A2C9EFD13 -20230418012058 2 6 100 6143 5 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375B6CD63D7 -20230418012826 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375B7C73CEB -20230418021312 2 6 100 6143 5 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375BDAC84F7 -20230418024639 2 6 100 6143 5 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375C1F8860F -20230418024643 2 6 100 6143 5 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375C1FA3B4F -20230418025309 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375C2CE464B -20230418030814 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375C4C3707B -20230418031522 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375C5B95BDB -20230418033054 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375C7B41ED3 -20230418034725 2 6 100 6143 5 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375C9D253E7 -20230418035159 2 6 100 6143 5 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375CA67420F -20230418040206 2 6 100 6143 5 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375CBBA3E37 -20230418041509 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375CD6CC14B -20230418041639 2 6 100 6143 5 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375CD9FAC87 -20230418043135 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375CF9403A3 -20230418043522 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375D012B66B -20230418045745 2 6 100 6143 5 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375D2FD7267 -20230418052031 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375D6045D63 -20230418052723 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375D6E70C73 -20230418053117 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375D766A2F3 -20230418053137 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375D771B1BB -20230418054951 2 6 100 6143 5 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375D9D7E09F -20230418055013 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375D9E3AA03 -20230418055054 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375D9FBD5B3 -20230418073313 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375E77882EB -20230418074130 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375E888520B -20230418080153 2 6 100 6143 5 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375EB2BC2C7 -20230418080336 2 6 100 6143 5 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375EB640357 -20230418090623 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375F38F9E2B -20230418091211 2 6 100 6143 5 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375F450FA1F -20230418094003 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375F7EF9113 -20230418100906 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375FBCE0373 -20230418101337 2 6 100 6143 2 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375FC615953 -20230418102743 2 6 100 6143 5 D87B312D2FDDD6A6859E8AFC18BA9BD5277D8512257428F787213E185E899E0F6522D5BF15826D513286CE011C3075457ADE549AF31D0B119B6042318589A00E271ACE924C8345AB9417EF02AB0A4DFFB421B386A1366E64AD4D533600C56C62130EE0F5460D919972E95120C54924CB6773DC35AB41169829AB673F2A865DA93FF23867E8260C186D12345BA8F7B0123C14D0065F07698AADD8E18381E3CB9F00C22D13F28FFBC01A2D068BBB31DA6C94B5253061A5C008FBE4E546E6C743E0A902145ECA71CA698A1789D4E223C065D03980E07D07E1829D46FFF04BD620BE6C06C2916BD3B2DE59513E2582DAEFA8C80333D2D5393109B151D33246D82AD26D31968FBA185975FE72146E767BE6900D39A0D41F290DAAE8FC0BF1696538CE7EB20A60CE6BF7089C137E392A0DCAF26B0C29D57F07C06E619BCB8A1CC2D40839791CF5A2AECCDB219F78B01FA32110F95BB2A020DA3E4434DFE37DEF5DBFAFF9811C4DC09E7AC5E8B4D185A1CF5B60B80DE34891E75819EC6FF2AB5B6B8D822B5B20D431805D0AE8FAF0A2254B4B661A1A3C7D0E9666A7C4841B894C796FC4218246357F57FD12B0284B90645C9EBF382EEE1565FD5AF51BE53CC6104C849A50B969A4A7136D38126658FACFEF7A04FA57D21D20A1D50E791E5E4900252D72E2340C12DFCD51A63D63B0ADFA040AD2580F3CC3098E75B82F488496E59664B5B90C712447F5C797BF94C8222B03727ED63E4C12BAB974C2B4AB5F4D626BC03772D993AB441E55676189E13E47BD43C4E5BCBF6ACA579199E6743D555ACEE8D451450D0930A550C7BBA5678BCB66C55ED5F1E1C1A23230F5760AC019CBC7316C3DA7DEFB469A891BE37FEC8B198F5DA123E1DB77662E639A6D6C7530CD7F13B0C204C442363349CAD4B1BBCA422FB96896CE6DFF68DE0D52806975F67759F87CDF1E343ACA3AEFFEC5F6E14F82D5628DE5108E3245CE5370802DB35CFC5FE3E57759515BDA3E3A26DE95F6A1E06E72C2FF24E7C9C83FD8691BC7E510A3E3F90403D0E7A979B59A1FA356FEFDE5DF79A540A65C4F54159BB34D7E7375FE3AB57F -20230418104554 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A8EED2781B -20230418120300 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A8F42A6567 -20230418133631 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A8FAB96A33 -20230418134401 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A8FB3C693B -20230418135304 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A8FBE1FDF7 -20230418140347 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A8FCA2EF8F -20230418140739 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A8FCE86483 -20230418143257 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A8FEA8B8EB -20230418143741 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A8FEFCF0EF -20230418145224 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A9000357FF -20230418150943 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A9013DFCAF -20230418160126 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A904D89E1B -20230418161313 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A905ACEFEB -20230418180127 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A90D3AA387 -20230418182846 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A90F1CD427 -20230418202701 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A9174E9CF7 -20230418204312 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A918741C57 -20230418204839 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A918D3DC5B -20230418211022 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A91A55DFBF -20230418212613 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A91B73EC93 -20230418221337 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A91EBBED5F -20230418225747 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A921D917E7 -20230419002050 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A92785525B -20230419004356 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A9292AACFF -20230419022901 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A9308E1103 -20230419023745 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A9312D894B -20230419030420 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A933069573 -20230419031318 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A933A41003 -20230419033911 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A93567E59B -20230419042004 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A93840906F -20230419061114 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A93FF67383 -20230419071818 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A9449D35D3 -20230419074500 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A94676D117 -20230419120028 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A9581F62B3 -20230419120616 2 6 100 7679 5 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A95884E00F -20230419121044 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A958D6B5F3 -20230419123026 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A95A32A0C3 -20230419123300 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A95A5F992B -20230419134253 2 6 100 7679 2 E6328EAAA3BE5DE7BC6DF1162500D0156A4EAB04554C56D34676E60C43C89A1F8E27529EF3EC83D92452B5643F31BE9E2E8739F8FF94F1ABAD41FFFBC12BE470E1E7C00F03202514C1C7E529D812382488E8C3255F0C8172587FE308C2B628DDE448F2F304AB7B8423341E094D5284250535298A938097C4BFAFE2F4F86003DB7220BDAE8FBEE421A77B4F657E3614E8A2E921C80622A91B56B18B597BBAF44537B9114CAAB58A858808079845327240322CEC27D2A3B779E60ABF0939A8BA547608BCE19255161850CEAF0FB1AB7F8FD9235B4821AC5D307220BE3C27FF12880194B3062FFAF52AC118092FCCFFA1CBC1EAA9BD2C07CA4EB2E2766AD27D65F7F6B3C23F18410D079142808E6311E381F2EA13C4980B1EEA01A9225875D979E807C8F69EF5B75A8ABA1ED8279978AC653E910BA02EF0C3478618570AEDF059D314BF3BDA7B827F41542EA7FD62A705C9F5B68F25CF5470BE09E0C0D324738D479D8AF107CD2F8141C2E086F4D5F207FA28EB8F84F0A006ED5F4A9D2FC54D41064EEB71EA9322296A69606C3330873C74C9EC71A2752DEA3A9A50730910013B3B1BD18108B7B19AC3C728D79BD12C5B42DA4C4D68575BE63872E07972878EE9014BFFEE2B10641B1F55FFC344DECBB2C51E72FCA9BDD60FEBDCB206C53D2598D35EA6F19CC29077C6975D6D03E5BF66EF6A681A2F1CB8586588B205D10FD92738F87E613374FF334DE27D8DB2CFDBD54093464FF9C965268FB9F237FD2DD11CBED0C29C919577722F7038F1D66B18BEC3730FCAB90065610C1835655EB37A93C8E126AA68C4ABC1F3035A3A9A8D7AF1FBA8891CBACFC4579551287AA6631345DBF4D15B8E2FB5C6FCE0A13D02F9FF6A378D46E95A6441F658BCE43E0852CC38B6EB2F3FF22918C7183AC9C599A4769D5DBC015731C346945913240DC338E31FBCF336C25CE3E23313EDA94FFE0046242F7A58ED59920B3C1A54B9AD0F7606B955422A22AC0598BCC0EEEEBD12E9B90647D9D9A6E26C875C7A25DC002812A6C6765872FAFE3DEBD75B09FCED45A358E6E5DDFC76C2A4230740C67DA9F0EB1D270F5742236D231FA14BD72C361BBB42D795624FF32BA6F68C9BA4762DC366C9AA41CC6453AD4D33F2972DD18D4A8EBCE2A0B9DC708BF37A5419F12B746F6A16A352CDDD7EEDC57E74762C98D388F8C7462DE48D87FC8E5BBAEC758D8C641F5666E4E5F9D09634247B0267C13F620F0B08B97D792F718665E14B0B04B9EA56CAF0DB6791621CC130EB9FEB08AF04F8E0C42B25254548236CA04808E527174D8323B6B548E5EC4E5201F29166E9822A52416B873B22E65A3CA8CFCC1508A95F419D8B -20230419140355 2 6 100 7679 5 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275B6DAF6E7 -20230419164053 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275C1BD51F3 -20230419164703 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275C22B54BB -20230419184237 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275CA289983 -20230419184441 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275CA4ABA5B -20230419191659 2 6 100 7679 5 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275CC85EF37 -20230419203722 2 6 100 7679 5 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275D2235D8F -20230419204226 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275D27D56C3 -20230419210337 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275D3F789AB -20230419212914 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275D5C166C3 -20230419223024 2 6 100 7679 5 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275D9E7621F -20230419225541 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275DBB85733 -20230420003433 2 6 100 7679 5 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275E281C87F -20230420020414 2 6 100 7679 5 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275E8AA20A7 -20230420020944 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275E90CEC1B -20230420033320 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275EEE545FB -20230420040742 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275F1541A43 -20230420051608 2 6 100 7679 5 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275F60EA9DF -20230420054435 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275F807287B -20230420065254 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275FCB923C3 -20230420070106 2 6 100 7679 5 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40275FD48EA57 -20230420075138 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F4027600C3C693 -20230420080219 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F4027601848A23 -20230420082952 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F4027603750093 -20230420085330 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F402760517E16B -20230420101848 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F402760B1F3F33 -20230420111601 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F402760F23C613 -20230420125724 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40276162D7A03 -20230420130717 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F4027616DD043B -20230420132347 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40276180015AB -20230420140830 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F402761B14F4DB -20230420145219 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F402761E29C17B -20230420145940 2 6 100 7679 5 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F402761EAD5A67 -20230420150934 2 6 100 7679 2 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F402761F5F3F03 -20230420163440 2 6 100 7679 5 ED95B1E8982BC7E5DD6FE4F09F3C276F55F746A034CC2F3F0D6D9D15F57C5912D649A6949A697F938BCB3B6F36A34106627F30FBB938F7BFB8EF66FE2986897300E55A2446E0FC196FDFB0B058C5810F1F86BCA99FBF8640C922DB18BA48C357F750757F4FBCDD5EC841D41113F273269B03745636A6BBCBDB59BBF7D0B96BA6DE2AF01A50E63E3A4AB683A491787509991AC0989506489C3AAFDDEB90096AB3D0D75805BDD30C8C3CFC214B02DD42201D46FBDE4CB61B5C249F7FF268149DD6624C8763C1DBFCC4BB132C84C06821B69C2DC60518A6F48743CADD638C5952562F98205473D526EA658DD2D94A0BE537771CF38C11A7C2B30BD3F4F8CB260BA3F74CD86FB12A553E869710C87B9125E3E09C84BA77DCE75C8EBCD4B5F3213C128AD00C4FB1F3461B638DF8BA435B57A69D728C7F749BE7D99F33975EA0A1B9E244422770C6448AF7C4FD9C6354B6BDBAA9537FBFFC026A60F2A537C1DE8A0241B26AF08D69266E6BA90FEBC78E6B4D1047C006293040E8639BBFB85A3C1719DCE255B098512811E73A4DE11CEB7D6313400AA282470FC79E392ABFFC6268C257805BEB6BDD870C967E7C38E2F4BFDB67B4FDAB05B4FCA1135163C7F4F23E78BB83BB9021246D97D5EE3B99CF8E02060A08B5B3A111D4C5C065ACC3A9D767CF612B124317F9561BED7135A7A65C6718C65B0E63A0A05E819546B14BE5AEB5157C5F7A91125E523B1A154F3EE998B8FB120ED1E647BA6742FCF0648998EC2A8A28E97386C25AD5D0C30AB634747B7082CD1FAC7B6146262BE4F74C1C84BDC5DCCFD70601E3895ED04EC59C7A67E12D607EE8F121BC3A2BB34767C47269B604ECE063CCB5E2E32444D5D2CBD0680467EB0AE70C7B22D4ACE868D12F7ABBC42FFA210AB2124073E8312C778057ABD78E38EAF7D929F4FEE09EA8C754281D8D3C05377909F7FA0F37615E3B6BCF8497FBD62C357B8D5D019F589A767B76B2E99A6EDFED1A69178B5E634CB97DE7CA4E087D58BC62CB902251DC212B6B4B43FABA537E2D961C45174F648AC43CBF4C7EA00012AB68B1020A007972E57FA7119E40E44EB68EF6A7BE7BFB3DEED0FC4FBC5D54B0FD440D586EE8768092616F415EF079BB7D707A2F3D8DD622AEB12EED0BDC92356E20A2775EFEE512F93DCE561EC4DC86DBE1B2D98BE130E41F966AC2B28BD89921E1CCB79F90BC1E638F26C1AD2288A74AFE4D317DE4202BF05401F36E8B4F768090C99214AAF63FCFCBE016463462F6EECB5DA4F28F6420E67B05557AA57D29F8CE3AC8BEC44336F5B2ED9705714770D3D481FABF3601A10EBADFDA1B03DF30483025E9E0918CE305F40276254852AF -20230420182032 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B71FBDC11B -20230420195640 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B72538E3F3 -20230420200923 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B725F3E50F -20230420202526 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B726E264AF -20230420210905 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B72964F467 -20230420225631 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B72F962103 -20230421020353 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B73A554953 -20230421025019 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B73D03C6F7 -20230421025402 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B73D3934DB -20230421025900 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B73D81E4AF -20230421033101 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B73F5DFB7B -20230421041148 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B741AAA7E3 -20230421042239 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B7424B0683 -20230421052746 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B7460F6067 -20230421070426 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B74B975CE3 -20230421071911 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B74C702073 -20230421074756 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B74E1061CF -20230421085630 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B751F35FFF -20230421090204 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B752462FAF -20230421102319 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B75705B853 -20230421105111 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B758A7AC97 -20230421131420 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B760DF7513 -20230421131956 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B76132615B -20230421135550 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B763472133 -20230421153558 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B7690B048F -20230421153757 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B76927A217 -20230421155746 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B76A4781CB -20230421165514 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B76D95D9DF -20230421173555 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B76FF163BB -20230421174847 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B770AE85DB -20230421185652 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B774A0D307 -20230421210430 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B77BEE92CB -20230421213116 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B77D820F3B -20230421213341 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B77DA622A3 -20230421215327 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B77ED1585F -20230421220349 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B77F6C72EB -20230421223656 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B78152125B -20230421235028 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B7858BD2E7 -20230421235413 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B785C13573 -20230422011230 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B78A3A0403 -20230422025702 2 6 100 8191 2 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B79042A373 -20230422042255 2 6 100 8191 5 FCF60CA27F941D57B38FB9E34C2D72C459D16DEBD084FB56A6579FC062494A8CDEFCFFBBA6D8B7C811C515C1A1234A95529620DF53CE8FB9BADD3971575C3F31B44F2B37CFFB7733B83FA3927F430A809C5942D23DD7F05445AA3B9D81DB2D65ED91B9E3D0F03E96C30CC3B5D23509B34DD52C49FFB0C720FB8D94C006BC8819CCF3B09712B7B598FEC791C4568F0B276E42247708129B21964866ACFDEF1D4BD1A3162417A41F8992F2B8DA2AFDE571F4F15E58CA7395B0D05C2AE0E5570BC91451E3F1EF50188D6F089BA88E767FA5C8CA926B66BF95BBDE24EDAB82E359581681AFBD7CE2B7E5B318476324DA6C6B2CA8F5B723A4FA40308F83FE05C187EB65B0FCE3C88A8B0EE903E0775570EA99CBF9BE0F5EEFCA1C87BF496206EB584FA37D59176787C224BE6FC7928883D3750C51B7D3A23B411030FF1AF81F258D5F65E0D859E9C50FAD039F6B1BDED73BA469F9139B9F7B1F2373C52320FAA2C9ACE24AC5AA27DC755D6D1C18A85E26CF851722FCF40A0BA06BC39FCF3D41E5269F6815A677AA69B11E7FE1C15B49E9BF2D16CAA4D80AC84D0087F36A91344DCE44BAE7458899C51EE511B81A06DD529B7BF1AB6BAEDF2DE3299F9E53CE8F8045EFA06A2BB0A4746A8F304D376F3AE9993639BEBEB7BB8A7D4D9FE72110CE657D4F1421EE2E13CBB6D771BDA0DC191755A11B7FEC7E5E0F401D9E87787E1B931A75491802547E79C30DFEBB4072B8055BFAAB1F73F488B8C1A57B9DFFD9FB663B823EED77A3D0A36014FD7077BB0BC7EBD5C16584F4A2400AC37945511A9F71847BB7426A18D332833B51AAB4839FD844714A4A5655B73ABFB1217980E45E85398B7CC4F00E89281279BEC2335AF713EAE4C3178333DA014EB0A19DADDB29B4416396FE250FD086A58D898E98BB44F98BFD17415780681536C5496626BD88DA34E4F2651E68E8D7BC952779B9945CEA3947B9F556344178A67BE2D23403F58B87EFB5CC079910F267469BBABA49D2DA01AC3D0E21252602FF132A0B12359D41878CC42DEBF7E25C27816AB1ADAB9508E2AD4DB493040D8671AC70D4045B366D3553082191A46E0BC9649BA4F9F58506314314C971033AEDBF9BDF17A6FF2451EB53326C6745A7BF8007AEFBDE26BD9F880FAB74EF249A8155547BD72EEC5F7DDD1EABA445CEDB920A4AD0BC6E3430976DF2BCB6360ED8B83A3F21A322DB1BF1CC6E99A84D4ABA51694A1BAEFBFED72459EA0807E854D4E97D00FC9272FDFA3101B1A93A73E6E445A83B155646DF89100A8A4806D1FD0B6050240B188C51FE1E595F80DDBF4724549981F7117617261EBF9512E2A4D655C5C388901E87C906DE0B17B2F1FEADDB25E12FB71E9FFE73785B82DCE66D1974438477DE725FEE06A45C945EC6E20FF2D15E9430D186110F0D9376238401043517F73D0D4FA7B7953A1A87 -20230422062516 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054AFDE2F2B -20230422072256 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054B339C3FB -20230422073338 2 6 100 8191 5 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054B3D7B997 -20230422075019 2 6 100 8191 5 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054B4D1179F -20230422114740 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054C29B898B -20230422143218 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054CC21806B -20230422150241 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054CDDFDF13 -20230422151148 2 6 100 8191 5 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054CE67D36F -20230422153713 2 6 100 8191 5 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054CFDA4817 -20230422154815 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054D0758A03 -20230422162135 2 6 100 8191 5 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054D2640177 -20230422165112 2 6 100 8191 5 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054D412F29F -20230422174106 2 6 100 8191 5 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054D6FF9DEF -20230422202834 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054E0C09CCB -20230422224100 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054E879D08B -20230422231400 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054EA62450B -20230422234622 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054EC3EFCC3 -20230423001926 2 6 100 8191 5 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054EE2C1057 -20230423032142 2 6 100 8191 5 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C054F8AFB6D7 -20230423075205 2 6 100 8191 5 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C055085ED347 -20230423082125 2 6 100 8191 5 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C0550A098AA7 -20230423083106 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C0550A963F6B -20230423093228 2 6 100 8191 5 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C0550E1B6ACF -20230423101913 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C05510CD28C3 -20230423105846 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C05513146EBB -20230423160506 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C05524BA0BD3 -20230423164733 2 6 100 8191 5 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C055272D6F0F -20230423165317 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C055277E91B3 -20230423182230 2 6 100 8191 2 CCFD66A378B8DEC3500EA03607592E16716277D5268BE0BE77506C2B5223A2641DF17C236A81DC0DD126CC3AC0E1B02B0452D0368DFABE38A88C74A8C78355187EAFEE839F4D3D954040958AF21AC4E1E71AC775479EC3259ECE7C076AB20FA5D5ED85DCBF426F19ABDE5FCC8E69B7A6103CB8CC16EFEEA6E239BF08C840DEB6A56A18A8C52F098E55FB8FAE71060A48A2328A33BF53D095446FF8A1ECC841E2E935A25C70ED02D455089B0B0098A2D93C60E8E8241FC7A929F807085AA837AD0BC9624F822A687FF1AF49C57B89FA23BD8369B1379C57CDB407FFD60CB71CEDB2C025C6348BF3252DFBD76B6BD815CE914897D025FFA0F723E2BC8B28EC5AE63E9D7289F5A2649EB3A74977C0E09350A49625AA41437A32F05BE39548CAD706F5BC3260FB9CA9BE11CE1CFFCE374CBF6EE9C73D5D3F41862A0033A645DD3270E7F46FE6237C5CA71C18EBEAD327EBF05B60AA6FEE024EDDA47A4A9922424F17F3E5772B429C49D32856AEBD978C4C3D65FDEBD6DF21783F1680B106A7E6D4F087A4B02AD2D928EC41C6F61F9E10BB48BDDEA799A478B0250A11008582ECBC21BE859FD2C71810FAF252507C039019FB2B1BC4FCFF8BCF382D466D7A534C2185E9F8D4D73A63CD055062E7D207AC780C5EB174F673060AA6BBE11B469B760A249048B2B55958AAEEF5F3CDC8AD43E9703A9B930071A5EDB8DD704B796C5868B11DF538AD7C49F34294B3DFD9525F4E84ED61D30040566F3182E42E5F1F048693B64D1B85B84A829FAE30FA042E551E4A375639D47FEF4B3CE13A32BC3F351EE304C124F4D42B4474407A7691B2CA2F0BA6AF2EAA12641DE19585577F32004F472B5CB28F28EE1DAB8B823DB079661BF13CFE0104B33DC5C41E6A68D79F0459CA68C8B766E5F3C7396DD552666EABA420987DAB2B62146D540148D89A5DA040F681D9D3A9BCA677E674070CE29087E8F19E3F662ACF60DF27C23BE4E217D43FB6D7CFC9558C4D0D8BA7125D10455DB549048CF506A9B1A1CDA601833072F9644F09DD91599963C3842F193EA09CD5C629005B699AEA2325DD09A4555E62583D3AF91946353D183D6E61123FCFFE0606E5BD6E5B85199701F03F233E6412323BD6A776593540AC7EB11F85341DB138CD8C1D89872B04BA89420FDAC51D652F104C999C6EED071EBAC30DA247695E1985291BEDCE929DFD35D0C3A159578565F7020322647A7B90F6722109D3EA233944E700A8BE3E6C62AA4B916C3BB64BE584E1E1055328CA42A83E3A04A3D7CDBD3EC390D24A32F49F6A61AAF22C61C01E4F383551E6F9226133D4EDB8FFF166282846CF3655CCA31C7F5664257636E1E7683D64EED64A96FC763C2A0E86ACC3400D8E5F327F1DE9C3199FC9B2BDF83046410355746826CABDC6605728CE9EAB826DAC32FF41BD9FC996B8CC65C0552CAB0673 +20231002030805 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EB8660D47 +20231002030808 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EB87B625B +20231002030813 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EB899E127 +20231002030815 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EB8A5B277 +20231002030836 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EB93E67BF +20231002030904 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBA18CD33 +20231002030905 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBA1F43E3 +20231002030909 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBA35A643 +20231002030914 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBA5AD7D7 +20231002030917 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBA688543 +20231002030922 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBA8BC207 +20231002030930 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBAC6C757 +20231002030932 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBACF1123 +20231002030937 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBAEED413 +20231002030945 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBB278463 +20231002030948 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBB360C03 +20231002030953 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBB5351EB +20231002030957 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBB718EB7 +20231002031014 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBBF2439F +20231002031016 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBBFCAB93 +20231002031017 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBBFF4D43 +20231002031018 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBC02091B +20231002031024 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBC293BBB +20231002031030 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBC539E1F +20231002031041 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBC9F21FB +20231002031046 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBCC001EB +20231002031055 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBD054ECB +20231002031101 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBD2BEB8F +20231002031105 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBD4264E7 +20231002031111 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBD725953 +20231002031137 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBE30F30F +20231002031141 2 6 100 2047 2 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBE4B5583 +20231002031201 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBEE6277F +20231002031226 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBFA54AFF +20231002031228 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EBFAF829F +20231002031240 2 6 100 2047 5 C9221A14AD5A6D21D700B002E8DAD042C817FAAAB8D0456A14E7A99010D8C877B4838CDCFA265C3E3675B0DA35547737F9A6913F6CF3F43EC7EEC9336B620D3B4203847DDCB679BD72B32F6D2E8949E23B86EB2BA4A05C622A33C8050F0CC6868B2A0D6C813FDAE12CF6D1288B689F454C605DC5443B75B887460A05B4D0674982D714E02D579BAA26A1B044193755164E1DDB9E06281D7D59BE4289D4F0E5255896903A5164903B1B27BD10B7F2E8DAFE1257DBE4F0B7AF918229C71803CB48226B4A4B7269D1482E67F8AF49AA7B866264F5659F4069AC49ADDB799707C3BB50A3CB15109EBEAAA522FDDBE7A04CC957D507952B1AB7C8433CCE9EC0092F8F +20231002031252 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BCF330043 +20231002031302 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BCF7CB2A7 +20231002031315 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BCFD54D3B +20231002031324 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD019867B +20231002031330 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD048E5CB +20231002031333 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD058783B +20231002031336 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD06951E7 +20231002031345 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD0B15DDB +20231002031352 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD0DF392F +20231002031353 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD0E1DA4F +20231002031358 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD1024ECF +20231002031422 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD1AD9CCF +20231002031443 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD246DEB7 +20231002031446 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD25B82D7 +20231002031501 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD2BDB3B3 +20231002031503 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD2CA2913 +20231002031507 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD2DDA103 +20231002031510 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD2EE864F +20231002031512 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD2FD7593 +20231002031524 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD34B987F +20231002031529 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD36CFB43 +20231002031554 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD42296D3 +20231002031557 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD4325F13 +20231002031558 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD435523B +20231002031559 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD4378F23 +20231002031606 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD46B0D8F +20231002031609 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD47838DB +20231002031614 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD49B4D97 +20231002031616 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD4A79F1B +20231002031627 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD4F13DE7 +20231002031640 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD54C80A3 +20231002031647 2 6 100 2047 2 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD57CEE9B +20231002031657 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD5C336DF +20231002031722 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD67708D7 +20231002031726 2 6 100 2047 5 C6D9FD71BDE795C2EE4F7D579076A77F9B3890B702B6DFB925953742C053CCFB301FCA857CD81F06B3CF899EBE78D6D73BBAB02268E886B2A87D92B4F633852675AC105C0E82CE802614E36A7F390E18D4F0F78682E9695A949E8C127B82164EF1FC6F5859D66EDACDD23B9FE330B26B6D468A0A50E4C14F70F66F970895A3EE007AA67635FADEA461D164CE6D79F4DFC13EAFBE05D68275D8383AB0A4D6A658D7A1AE0202787F53F0F8D330A1D1E8BAA0B6FD51C5D694BA3790B2A80E2C7B070CA5BCD04637244CA32D64B3F07268E57F506826A8DFA31A9554168C0A9DB5FEBFBF8F9F69F654037386E0E5E256F29F68A2591707D9039231137F3BD691BEF7 +20231002032547 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12D8CBB46B +20231002032805 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12DA7EE34B +20231002032822 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12DAAEC6FB +20231002032842 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12DAEA6C23 +20231002032914 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12DB4D999B +20231002033000 2 6 100 3071 5 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12DBDC876F +20231002033013 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12DBFF1573 +20231002033053 2 6 100 3071 5 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12DC7C299F +20231002033112 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12DCB88C93 +20231002033119 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12DCC509A3 +20231002033850 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12DCD76FEB +20231002034205 2 6 100 3071 5 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12DF47D2AF +20231002034230 2 6 100 3071 5 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12DF8EE537 +20231002034248 2 6 100 3071 5 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12DFC506C7 +20231002034330 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E0404E13 +20231002034333 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E0446EA3 +20231002034515 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E1834B9B +20231002034639 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E290DF83 +20231002034740 2 6 100 3071 5 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E34F7147 +20231002034840 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E40DCBEB +20231002035011 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E532191B +20231002035040 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E58DBAF3 +20231002035054 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E5B2B7B3 +20231002035152 2 6 100 3071 5 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E664D9B7 +20231002035246 2 6 100 3071 5 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E7118207 +20231002035321 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E77B3B6B +20231002035417 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E82BC0B3 +20231002035425 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E840D433 +20231002035503 2 6 100 3071 5 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E8B63EEF +20231002035546 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12E9486AEB +20231002035730 2 6 100 3071 2 D435B9DA29C6441FE8C9693F4276E0DF5FC91028EBCB2FE2DC0EC03A9F7BF53BB1B447DC71B517B5CB363A71FE199CF790CC42C21692526421D200C39C2B41EA8E9DBF0FE4366B1B372C69B33D6381A38E1213F317D0D792C826510E72F70F2B198DDB768D19FB28E5FC20D678044D67BC6DAF6B7496AE902BB7C07BE6D2671A284A226179B73C43DA4902313D03A601BE81267B9A7D0064E386FC1B1DD31D7146BB837B5D0CED5CC5D834BC0E25F4C2EF181A881B4F5B96C34324758D5FEAF5659098F445871B6593AD4F6E2BC5CC01BF7DA5827BFEED605C26B0C50B6B308EE376528A933E01DA445D5902DCF4C937B2D575EDD33ECE07EA6738167858430515AF1B160E301ED1C4096871F2248CD83019FA381449723D2F220D94F4CE3C2E6A789D6748B0BDADE26ED2B445AE04B421342393804D7F0EBF6A53AE289FA16A0366F419EF5BA2690690836055833140A8EA541F6329E12C6C094667CE2E744DE08B6ADB36E944EE9E8721E0D7E6D6953B9C0AFB033EC9A1E229CB12EA982A83 +20231002040037 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B030938951705C3 +20231002040109 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B030938957A0E7B +20231002040120 2 6 100 3071 5 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B0309389599ED67 +20231002040253 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B03093896C6D78B +20231002040333 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B03093897424DDB +20231002040358 2 6 100 3071 5 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B03093897902357 +20231002040616 2 6 100 3071 5 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B0309389948105F +20231002040624 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B030938995C6133 +20231002040627 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B030938995FC8B3 +20231002040642 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B03093899896D03 +20231002040758 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B0309389A758183 +20231002040835 2 6 100 3071 5 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B0309389AE5E05F +20231002040911 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B0309389B52D353 +20231002041010 2 6 100 3071 5 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B0309389C013C77 +20231002041047 2 6 100 3071 5 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B0309389C71BDC7 +20231002041152 2 6 100 3071 5 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B0309389D3D79CF +20231002041202 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B0309389D565883 +20231002041216 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B0309389D7D082B +20231002041326 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B0309389E56387B +20231002041453 2 6 100 3071 5 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B0309389F70C107 +20231002041513 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B0309389FAACA93 +20231002041815 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B030938A1ECB753 +20231002041833 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B030938A222270B +20231002041942 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B030938A2FDDF13 +20231002041950 2 6 100 3071 5 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B030938A3105EB7 +20231002041955 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B030938A31AC273 +20231002042039 2 6 100 3071 5 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B030938A3A1B25F +20231002042113 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B030938A405A9EB +20231002042201 2 6 100 3071 2 CFA8C0FEA9FA30086B87B145CE1B10C850BED7B0E48D74F4104D54A0587078F777489F278BDD390E108E3535FA8DBE332D3C22F5EEEF08BF54017590B7182E3A2C0F955D437957004A29177CBD8549716E8159BD84160EF1369DC35DD34B286F9364DD5CEFB4D32DEAB497D2F80AE9C943DD623B7D064EF87EF53EC9E60512C8511B0F26C46E0A1BC9AA62B80675C3C17D28C13BDD8B40CC9C3647F4C72333CF2710F4C0319F26C2D030B77838012F58815DCC36E887ED5121B80819BFD12F127C43A839190115036D3F1075AF79D189A9F4E64DD0E811FBF4FF29D57665DE4D6FA07BF0724D829FF003079279299C2126105F084677DCB09911041CBE2B551FDAED06905986B219FC807A529BF392C8F73DFE1C57EC6E4AC3C14643813849A1F9EE1BC522C7C073817C980404116116E4A04945396190A640D2F7B1D255473470EA22A4D53D438656BDE67F95C83D00E1F184C956D7546F7D8954E6ABA6187B315BA05FF68D55CBA76E166D05D5932A3A6830CA2A2633B55B030938A4A09C1B +20231002043546 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150F97BB7733 +20231002043733 2 6 100 4095 5 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150F9861D57F +20231002043843 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150F98C8A233 +20231002044121 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150F99BD3D4B +20231002044301 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150F9A5765BB +20231002044414 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150F9ABFFEB3 +20231002044437 2 6 100 4095 5 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150F9ADDE5FF +20231002044444 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150F9AE21BFB +20231002044502 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150F9AF4897B +20231002044715 2 6 100 4095 5 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150F9BC8783F +20231002045021 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150F9CF269E3 +20231002045030 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150F9CF82FF3 +20231002045222 2 6 100 4095 5 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150F9DA5D437 +20231002045350 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150F9E2AF5C3 +20231002045917 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FA034D613 +20231002050316 2 6 100 4095 5 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FA1A8EC27 +20231002050449 2 6 100 4095 5 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FA231F75F +20231002050518 2 6 100 4095 5 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FA2566FD7 +20231002050704 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FA2F8012B +20231002051424 2 6 100 4095 5 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FA5AB0EEF +20231002051430 2 6 100 4095 5 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FA5AC9567 +20231002051505 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FA5DBE54B +20231002051743 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FA6CA6C3B +20231002051905 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FA7475D7B +20231002052700 2 6 100 4095 5 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FAA2FD977 +20231002052843 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FAACE8103 +20231002053332 2 6 100 4095 5 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FAC9088BF +20231002053348 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FACA13883 +20231002053427 2 6 100 4095 5 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FACD80957 +20231002053619 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FAD8747C3 +20231002053638 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FADA116CB +20231002054016 2 6 100 4095 5 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FAEF247E7 +20231002054332 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FB01C491B +20231002055042 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FB2C6574B +20231002055303 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FB3A696EB +20231002055356 2 6 100 4095 2 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FB3F0234B +20231002055921 2 6 100 4095 5 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FB5E7DD1F +20231002060022 2 6 100 4095 5 C333C378E10FC8C3708C149CF7D706B80DAAA93FE362B5EB5E8AF660111D8D65BF44AC08C0393E17B84456EA4D7397E1AA57E6273381A401F425E96DD3B920B49FF097DAA659A2AC0C33F40EA13C8390BEE8BD1C3C9351076C4E114B117148246665CB5F314AF2054C69C6C9E13BB5CF6471FCE69C62DCC98D69ECDC9E9A92AAC2DF217F08CC4ED2FD87B513AA2315B1B9D23ACFEBFA8F333DABCA10A1F0A4ABC0C4A67B238D8E6D0AB68FE704A026F6EF933EE8D65B9BC314E3C3DD7B7FA6D2F964AB1B515A8A59CB5494DE98BDA70F6EC165BB541B00A1DF8A1B36BA4DA1503CD030C446D0443CB27AFC732C8136E53B69CFA21213C23B98DE5F5B513339427885AEE13B4578F8D53E03DD61AAF34FE8EB0979E29289A3661EED1954AC61CD61118AE5E4F9957198521F730D252A2B5FA51B3ECD0CBD48B1C4A2ACD8BB8131449E896C11E23F41C96BF044AADCC0DB1EEB57E3CFBE9042B06C772AB665A8FA630A2D0217E536E4538F2AE51E44161CF1FD2FA42D26C049C406AEE8D9F1B5BD01A5161E47906F3733F2EAE03F38697DDA9241C1722E5A73B229B0A270B0161208F7A1E4BE65E00B7713E38BFE7D806206D87B55D8E81F2F35F8871611DE73A47BFCA3EE2FE77EC71E20A262A3C02220A026D1E8819608D4EAE37ECFA36D9E9126033C64C4DFE951E6807E14F5B3F870EA3FA19EA754C87435A8150FB6418067 +20231002060252 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C9744E5413 +20231002060407 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C974C3A0E7 +20231002060612 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C9758246AF +20231002060651 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C975B74527 +20231002061114 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C9774C8B23 +20231002061217 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C977A83D87 +20231002061542 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C978E6F5CB +20231002061844 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C97A0144F7 +20231002061946 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C97A6011B3 +20231002062202 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C97B334B7B +20231002062312 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C97B9ED387 +20231002062659 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C97D0167CB +20231002062852 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C97DB1C8BF +20231002063237 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C97F124ADB +20231002063513 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C98005B663 +20231002063540 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C9802AD0C3 +20231002063556 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C9803CF883 +20231002063708 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C980A85467 +20231002063741 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C980D5E6E3 +20231002064635 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C984192C6F +20231002064848 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C984DE3F33 +20231002065019 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C98566002F +20231002065353 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C986B1C91F +20231002065445 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C986FBEF63 +20231002065538 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C9874B543F +20231002065545 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C9874E6C33 +20231002065701 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C987BBE79B +20231002065747 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C987FA3B4B +20231002065946 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C988B42243 +20231002070008 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C988CE62DF +20231002070120 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C98938A307 +20231002070247 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C989BCF6BF +20231002070501 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C98A8905A7 +20231002070514 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C98A959DB7 +20231002070804 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C98B9DB8B7 +20231002070841 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C98BD43657 +20231002071314 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C98D7FB3C3 +20231002071325 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C98D88E8EB +20231002071745 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C98F149D2B +20231002072004 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C98FEA9D3F +20231002072030 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C9901007BB +20231002072226 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C990C0B8B3 +20231002072853 2 6 100 4095 2 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C993192063 +20231002072941 2 6 100 4095 5 E10CECA5887CEBC483A29080A2665F35F0CA7AD441F1451C2549272D35936D1324CA62500733CA6F11AEC477CAEAA7FBB60520F6A84C052238F72F22488739C6D6A14A96A7CEBBB293123CBA3845C0EE6B4D6B5305B2FD642B339BF418BC410A3FC054C07017656805C573C065EF62661B2B638AB5B65EF9C6F90A60FA2DCC60DF4004BF0E9F8B01FD7CD71D73AFE50CCC276652E2198FF628842A84BF4BBF8B8DBCA7E609FEB204610F9D179D28FBE60F84D3E31DBCA604F14388E698B9613EFA6CD699B7AFBEEC7876691838FE7DC40803BAF56B6B96D9A975B1512B64ABECE3B1DA48E4EE3414B935B458482AD23938D4878EC3205C6570145C02753F81D2EFF8D466B09CAD48CFFD3296B963958584DE48060708B00436CDF38A23A2C6B87740CFEC4F83A706F04C0C5F21670AAC91DBB5A5AE739767BB27C60B981E7E14EF74B191FA1532BD002BBEC37FA81F9497AB3620C259A8BF7E9271BC275B2BDBE3E64485551EC9D8D2E0A35B6CF7337840A1591B7693ED5F1F2EEB16ADFE9946DB2FCDCF1A1DF8ACB4AA6E84E821269ED19AF829985AC9185ED3A320C62D0562DAC68F6C4E6A6D0924030D6721226A7985CC7086AA6B02ABF22BF80878A69415D1ED7E0FEEF5D97DC3598CF2528185137B2A3401F07BDE1B8E3883D6BDC6E9A9329D764E8861F40FA27BEDCB2B1B04908503C8A30BF19AA4564DB7C9935E137F +20231002081041 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76B0333397 +20231002082147 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76B18E4283 +20231002083104 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76B2B4F773 +20231002083134 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76B2BD2843 +20231002084350 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76B44B71D3 +20231002141344 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76B0333397 +20231002142442 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76B18E4283 +20231002143348 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76B2B4F773 +20231002143419 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76B2BD2843 +20231002144651 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76B44B71D3 +20231002150103 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76B612B503 +20231002150136 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76B61C3BEB +20231002151801 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76B82F193B +20231002152637 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76B9420B8F +20231002153456 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76BA45EDCF +20231002153746 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76BA97B48F +20231002160531 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76BE29EAC3 +20231002162342 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76C078F093 +20231002163511 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76C1E48843 +20231002170308 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76C57F3C33 +20231002170614 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76C5DBDF1B +20231002172548 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76C855E547 +20231002172639 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76C86B2807 +20231002175342 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76CBE853A3 +20231002180217 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76CCFBD417 +20231002184225 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76D20A9DF7 +20231002185958 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76D43A135F +20231002192316 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76D72F8AEF +20231002192445 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76D7559777 +20231002195410 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76DB15D467 +20231002200603 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76DC94115F +20231002201042 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76DD1AA643 +20231002201544 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76DDB77B67 +20231002204234 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76E11C2123 +20231002211226 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76E4DC58EB +20231002211356 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76E50579B3 +20231002213652 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76E7E66133 +20231002214032 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76E854A163 +20231002215638 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76EA552477 +20231002221259 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76EC52B343 +20231002222832 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76EE45CBAB +20231002222905 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76EE4E0293 +20231002224654 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76F081244B +20231002225640 2 6 100 6143 2 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76F1A84B23 +20231002230658 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76F2F06967 +20231002232045 2 6 100 6143 5 CFDC18EEBE159970EEDBE80A11E47B1A8BE485032522B106574399D90EC4F423A1328A4BDCFC7622AA2CC6E350C364FFBFE243DE26176C0CF4937AA4358BF4B1D83FC4A6ADD821604FBD9523C52C108BD658BC9DAAF471040A6ACA8BA818F84F784AC48F5EA6619C156F1B24246C2C35CF91C7560CB09CF96C53B2431B5292461048F66E36902B86D9352DF48E8B2D37FECB3B76A84A2BE0A419DC7D163926F15101D626A44F13C5AE5EFFD2992E49C6BC91A4AEFF174A980270F4CA8399D5B1AC018914F086C459BEDE80C02B798F580CCB22968C9C5EF85FD28D92D18AC6F39B8B0DA06B7116095C6EABC0B836B67DD741FF5D8E4561FB952DD1069018C9EC658DFF6CA7A0135B0822806A4BBFCA0F05A16756723066675D452014BFF4C40D80BD511C8CB04442A5FB4E50EAED4E9416D7332F7673E74D7A51E0AFE293881F6B8189B8A6A6092425FB7734B5D793523C3F2F2F6C6F40C8E00BA743261D8E0A4F5D2A3823C4362689C8F1249A8EDAB713A56DFCC95401F34844D51E5A43C5A2D973A01D9147323A551813F203F13C3FD16E21106332CF76CFF77AFE496A4230E1DC309F37A7FB7533301AD98B6B85D5F3D0FAF67E07538C58FDF91A610E12499B4D02FE5E94960AA8523232CDC302DD3BDBAE3633A887A4FBBCDCBEA355C54DF03F525FA519209FDF545E278592E787DB253EFCD80EE378A1575674DD389EBC3C80D1BEA7E42A0CA77EB84D278CE20F762B9838823B134311CBA91E1A3C0A71C4F59DDDB9F1465C406E1064DD1034F26EB3387F45A6C02787F73CB3D5244930EAF20096797ABCC2B02D32030C35FEA1DD34C7FD5ABC9282A6C7B8DEA0654728ABE170DA23A7CA27629B115C0D35120E29C278CA8F7B367F7D2D76745630D8ACC3FA1F8ACAE2E033B0D5944C33193AFDF44CC221099E5AE2C25C8796F7E1A71FE1D60936A2A4096D95B173E141CC0222ECEF1B41C96F3A30FFEDABAA1BC36642504E8B8AF30BDD54D12F70F3CD6A307727A55213C33AE4DF3BE726174FDFA1CC2BA74460E0C1F119374290191476F7116353A4E1AF9A48E33D1E8B76F4A69E2F +20231002234558 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49A810F69E7 +20231002234915 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49A817337BB +20231002235010 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49A81889047 +20231002235237 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49A81CC51AB +20231003001041 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49A83FF7FCF +20231003001507 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49A8487F873 +20231003003839 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49A877676D3 +20231003004439 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49A882FB0BB +20231003013638 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49A8EC44FDB +20231003020602 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49A92680F23 +20231003022233 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49A94729617 +20231003022838 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49A9533C427 +20231003030014 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49A99255993 +20231003030947 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49A9A55F43F +20231003033759 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49A9DDBBF27 +20231003042143 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AA34E398F +20231003042540 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AA3C73223 +20231003051219 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AA9B54CC3 +20231003051253 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AA9BFC61B +20231003051513 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AAA026323 +20231003052052 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AAAAEAB1F +20231003053941 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AAD067F87 +20231003054545 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AADC1B5EF +20231003055211 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AAE8576D3 +20231003060848 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AB094C2F7 +20231003061146 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AB0EDC1DB +20231003061445 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AB14AF5EF +20231003062126 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AB2207DD3 +20231003062948 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AB32671FF +20231003065951 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AB6F4703B +20231003071814 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AB9393AC3 +20231003071838 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AB93E6CBF +20231003073040 2 6 100 6143 5 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49ABABC23A7 +20231003081738 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AC09DE603 +20231003082407 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AC1617963 +20231003085747 2 6 100 6143 2 E66EC740BCD486B24BA43649320948C64050E6C92B464AFE6928BCA87FA1C070DD66DC0701751137EC1E54BF664BE2E2413FC0F8E50E750818F15D3653B10F52D3F70E8BC30AA5F98A9958A73CAAB3D6EA71004E3A45FF48D7941330A6E0737EA76EBC51FD1285D843F7690CBA7C2685E747DA987A4BAAF6D13D1581C900C05AAABE5AA9E2AB2FE4D5ED2E1C1EDEA3AB0BC6158D77EA2C77D3565AB3BB83639E1E2712AEBC580CE892108F1C5D392CE075E4BFC9F98A94B341333B65CCB6010EDCE294956ED236360320912525D079609779796E11F549A893B29FC6118699EDA544D0570B91985C952A9DBE05E7EFBD8859BD1B217D24C429287F78464619B843DFC537BB96829A6C98B7C48CB2A233C48F98C853DABF495FE81A796E24FB5AE643504CEB40BB45468578433E6F5545B7939CF834857B33FE32B39ECA28C8D1E4C1EC020BFFB68CC3CB8547B9F6BB867826288D13F37F613F273373CD8742E3F2822133CEEAD8ECF136EDB0EEB06C84AA5225A389B489B4693C0BC0F4FC5B0023A06809CC4A83E0B6C8B0E72915B742396FF3F422137F73A6D399AF4E32B577E79B0F624ECD040F04C10C25AB94379FAE65036069AAF84549533C6589BE6935FBFB0FC9AFFA325C0F9972D5D5B4F8B271281ABB54597CE4D6E52F9D19824E2813D86FF6FE2ADE81B401569BD36F0D3D33FD44661AC6A0371469D731D6B0D2541E8A03638420FA4AAD41DF127FAA90E2C7C8560593E6B3C6D5895F95B7336FCD91E34CE18EF912103FBA1CDE7BC5B1C4AA81CE0FFCE0386F1AAF3555A6E5832A22CE96C0CA9D5E47BED9984F1D4E1C53B60020FE25B5083AAE62ADADBCA1F37CE843B63B8F7190CF6DACBF6690E398C26C3FA2D90439DD73E7340775AE6A83A73447B624C299720DCA85FEB67C85061BEA7A296C4CCF7342AFCC1B284D6AFE6D25273F38B44F1938205927FA1E5163A8EE8411D68A5DA3DD0ADE75A60B14C842B954117CC4A55CAC0BE44A396DC24B4BBE558C208210A3621D4914ED87674301AAFA923D7E9897A6AFFCB32BA80AB214AE2B2DD13D50FBB73E1AA49AC5927A1B +20231016131900 2 6 100 7679 5 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA00EACECF +20231016132859 2 6 100 7679 5 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA019290D7 +20231016142904 2 6 100 7679 5 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA059B4417 +20231016152750 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA0999EB13 +20231016155325 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA0B553BF3 +20231016172849 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA11CB2E4B +20231016180042 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA13ECF3CB +20231016180126 2 6 100 7679 5 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA13F1687F +20231016180748 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA14552213 +20231016195614 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA1BAD2973 +20231016201150 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA1CBAEDBB +20231016224251 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA271BE9F3 +20231016230521 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA28A3337B +20231016235753 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA2C38DA3B +20231017004035 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA2F2C3553 +20231017011243 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA314D420B +20231017011549 2 6 100 7679 5 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA317A2D5F +20231017032411 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA3A4E69EB +20231017035035 2 6 100 7679 5 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA3C0F1B77 +20231017040535 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA3D0B2F7B +20231017053244 2 6 100 7679 5 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA42FECF0F +20231017061754 2 6 100 7679 5 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA46082F6F +20231017062414 2 6 100 7679 5 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA46692FEF +20231017064457 2 6 100 7679 5 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA47CD78D7 +20231017080259 2 6 100 7679 5 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA4D1F422F +20231017081616 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA4E000C6B +20231017090950 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA51A428FB +20231017100646 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA55892F1B +20231017101201 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA55DC859B +20231017114805 2 6 100 7679 5 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA5C5D2C7F +20231017130334 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA6177B58B +20231017144733 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA686F3603 +20231017150532 2 6 100 7679 5 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA699ED29F +20231017155907 2 6 100 7679 2 EE7B7F77179CAE64DB89ACE5368617513DF050B0CBB10C2E59A189C487BA454C7576B7BEAA078CA60539C649C10086BC0B045CA609A4EC64C5DF5E4F2453B5D0691E16F17DEA71E80E00926E84D57A812BC2E23187228963F0E55C49F2676806A99BF0B482EEABAA0865954ADF181C0093376004938999A95404A56E869C3B4AD36B6F3B60846F236272DE29D8BFE6298857B7DFA5309E2724E60A87076195A480F402A0029A3D67839705EDA6F3963A995863A07A0E775236CFB6EA8658658CBD65F014FDAC4B4D504AFAB91E3E1C9CD4EA842404641153D33BA95F7D7F8285511878F6ADF344921256C07CF06112F1548542EB6BF0FF78AB8FFFA35D238216D52CA7D4FF5B43C62FEF5FF3BA7CEFBD7BC9EAB09292EE409868450E5B6A37BD52999774065131C7FAA305E81A93D086549946BB5EE3EAD0D319E724DC2646DD7F31E928BCF8FF816B9D0FB27DEB691834DC8B56FFCEEC8BC33095734363A01E493F17E6B7D692C10F951A5EE98DA6B428144C4031D089458807A8B3425E80E8D42E9D8F504B9BF9198FE13C371F2ED23C39BD6AF99C1C4D4FDC3E726B0227D8F195AFBB7B70FCB8789473CD7B46FDAE7B3FD63FF89116DB318CD3EE340371AB6F8C4CB88909DCC42B6B9D1AC5C917247E6C27DAD51D7AC998EFAE905C8D8B1381A3C2D8B7F37166AA24762E5C9C347F73AC8EC2DAFC40608221C664E85EE218D3A950B4DA358CCFB4E1B56471095E49A0BEB276A7F6CA7527EC2A80D106943E00B3977F393278C4A6AD01435C1AD72E019B4B2B43D2C9222D3C2A63D5EEA69B1442F4FBA285504F4218323C8C226246398C8059117CB36F96A312F6F8B4C442F2C8213BF4FDEED2C5D0342D9F82B492D74679F5DAFDB79BD57EEE2969471F320D3887EEF552D0548F467D24FA26CBC7FFE4684890DEC965A48689FBD713BDE3146E612B91CB10CD6AA0A3C222ADB01FFB74B4603116421BCA02BCD35992700FA954D4BEBBAF64C19E373715283ABC185C57653974A159F080939AC7BC3F385F406D9086B2B03A9B69CDBF725CC9CF8CF74A9F65753EEB48036D13413CBA8FDFC43FCF640EDB5654A44D7EE0585081B740A1481E877EA4E43C318645A61532E6E8668219AA37E2A467761D50A622599AF55D99C3FE763319F0307496F1E99664A4FEF3FC6860D68F80A07E8C259A1D2C85895D7B8E07368C052CB7C17FF2DBD6B0AD3824B2DF89C23805B42C21DA29B39FB25C6D94D8AF318AF790A59FB4B08E7430856CE11694B34156E7E4634D241D5EA5632E87F53EA0ED552C6F89C3D03C0A725BAFF8133DA9755C7499AF96A7709BB82A61F6FB42203B50B3AA6D3AFB8B +20231017181544 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E175059BF743 +20231017190547 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17508FC9613 +20231017192033 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17509F702C3 +20231017200530 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1750CFB1AD7 +20231017201043 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1750D4F4543 +20231017203134 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1750EBB8757 +20231017205507 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17510485E5B +20231017224217 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E175179CEF9B +20231017232528 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1751A835A53 +20231017232941 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1751AC3F17B +20231018003956 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1751F836183 +20231018005815 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17520BD845B +20231018011203 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17521AE2577 +20231018012138 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1752253381F +20231018031440 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1752A0C708F +20231018031950 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1752A5914A7 +20231018033845 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1752B977FCF +20231018040441 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1752D5365D7 +20231018041121 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1752DC38AAB +20231018054013 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17533C80607 +20231018054825 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1753451216B +20231018071952 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1753A752783 +20231018083252 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1753F72808B +20231018090047 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17541479E9F +20231018093100 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E175434FCD7B +20231018100316 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E175457635C3 +20231018101033 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17545EBDD63 +20231018110847 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17549CE2733 +20231018113805 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1754BBD7BE7 +20231018122625 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1754EE7384F +20231018123413 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1754F632783 +20231018125726 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17550E83927 +20231018135301 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17554AA25B7 +20231018140418 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17555636167 +20231018141949 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E175565EE997 +20231018142439 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17556A866DF +20231018144725 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17558217B9B +20231018160133 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1755D0F69FF +20231018172124 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E175626A63C3 +20231018173327 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1756332AFAB +20231018174338 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17563DEEBA7 +20231018182026 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1756663AE4B +20231018184456 2 6 100 7679 2 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E17568173BF3 +20231018202029 2 6 100 7679 5 FEC5FA301DA99770B0001C6661792A17D47495458B6FC55BF33FB1CD1E8CD5675550AEDED89217D8945CA01F1F68EF0F543E6E3BEADF0053FC7D706FE59F390E7758CC227C1CC6AEB6AEE82BD92CAA8DB32CD80B57E3DED4C5D5F029FA776D439EF2E069271AE4A2ED1F05C94ED9216E07DB8E0488B3E422D9F3E91618BFDFEB004ACB899A99AB89107FC3888337778FBE3D597FBD40FA4F791C96E175A163D22CDA2D84D049198083CD68D731740D4437B79383B36A33DF6650A42D497B7D7796BB3FFE02FCB5B5CB890EBE4BE4DFFB2AAA0D4134ECE4BF31AB678B16EA621A1598827179BF77A0290D34902352BEB99F92B244A402E431C47414E96A9D6EECC402B6A1CDA088E34D22D25804F3FE4C3B382AEB0DC530C6BF9C70B042256B5BE7B30896B05C5B4CBD88512B0A8B3D13A3D6BDC14670031381EC66DA8AB6C5645A79B1081EC58A0882D8FB17E0C083720C9B119CF52A88833D5600E43CD5C48C524F1643F515B30474A64118EACC834A272351048A1727438913B8F369BBF3E7A1628B3D40E77DD980BA8A1CF545CE7EAEB5B17301AB9A80A19C64227B645291AAD618D2805FAF39AF48ED5035EF23ED7FB734D929C8D0028A46162FC17302C5DB50F5E696EE451CD4C0899DB3E907185FCA1C53EB60E0131D6A199B0517A300BF136FE3BC236C884171ED76F79ADEB64DF1A50A76F8B26C7AD72AC0E2C1104566DB81C50BA607BFB379BB8FB142355D6A3D0D034E5697665FA31403241B806ED8A427DC437EBAC54DDC408DA022C4C2F8BF4AD59DD43C7BC7A4C4E5BF24D812719FFDFB03B797B366B2DA35AA280893EA813A5BD9E1E91B280299BB7A02A3FFBCE1F52219D43B308C723D0B0F25B8CE12C110491B33713E5F2C5C7E946322B28500480DB234515B5DB5370788D9DCB6D460281E91EE343B5BEE12CD367B83EFAEB4964B3051CEB8CD2E54E7ABCF0E4AF3D18D9A6B5D58B09B58DC97287BFB058DDBA94BC376BAEE117C2AB9E6CF0B13553AE4F8B91A247FD24C0D70C090E16B152CDE92456A95E5BBE98F939BBD5083EAABA538A675C3DFBB25D001D2E5A3B3811E7C6E982A7C58C3399E05C0FDBD31F80A623E6C83356D3E65BE34C6DF5445D10C27551F4D5697B9FEDCFB3A0BE6F209754A7364DE364FCC11BBF70366A2C61864F65FF203DDAB2C693C82BD35AD6C0EB9D001DD4FA520F439BFBC9E15EB6E186A59CDA292D1D9512CC67B25471F5557659228C0E663586D7E09D0FF8E6B97102A020DA9673B5BCB92800F72E36505766FAE603C886BF950A3A1C08798B9E9555A3A4E39B6DD20B1B4336C09F99D7182DBE4D1DAE287653C63E1756E9EF4F7 +20231018213032 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE63834379427FF +20231018232202 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE638343DD5A117 +20231019004844 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE63834429F64F7 +20231019010247 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE6383443605C17 +20231019022342 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE6383447F1B393 +20231019031710 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE638344AF828FF +20231019043555 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE638344F5C458F +20231019044032 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE638344F983EAB +20231019053824 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE6383452D8631F +20231019063745 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE63834562930F7 +20231019081055 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE638345B642C07 +20231019100522 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE6383461BD232F +20231019100852 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE6383461E6DF8B +20231019105326 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE63834645F1673 +20231019111044 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE6383465527463 +20231019111309 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE63834656D78B3 +20231019115348 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE6383467A7C8F3 +20231019131104 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE638346C0D8BDB +20231019142914 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE638347067646B +20231019173223 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE638347A9DF68F +20231019175446 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE638347BD81D27 +20231019191611 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE63834806DF947 +20231019193510 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE638348179CB5F +20231019211306 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE6383486F90F9F +20231019231750 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE638348DF30017 +20231020001735 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE63834914CAE7B +20231020012141 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE6383494D94DBB +20231020014803 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE63834964F5923 +20231020021214 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE6383497A3C3B7 +20231020034933 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE638349D0D7D8B +20231020044258 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE63834A0069007 +20231020045617 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE63834A0BEE89B +20231020064548 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE63834A6D2ACC3 +20231020071102 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE63834A83942A7 +20231020083119 2 6 100 8191 2 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE63834ACC3A13B +20231020092435 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE63834AFB5EA3F +20231020102437 2 6 100 8191 5 FD04CC30F7BF7D987760BE4FEA189E499B09DC2781A9AA9BB317A3C7D8BF99E3CDFAC9B6CCC12703EDC9EBF48F4917314723298E5F8A43920F2098EF0CCD7A09B7841411EF6F075575B375025F228A4DF56355DDFADE746FA4A9303924B871C442B3F341C809C37A498823B276982BD02A58268F5D7DA88859801A464C41CD725B23C0E52515657B9CC4B377DCE9CBBCDAD24D411745450CC9EA6DA349E5CDAE9D5870817286B4E4AD7D152EE3200CB9A4DF18321E1A8D36560DCE6BB1C2D398594A7A907723C1BB72E40473EEF91998649FCEE5DEA29353BBEDE80A22C0904355536471CAAEDC3A9F1D1B9AAA485AD6F562865483A90A699B96ABBEC4223AD2A4B398458D63278AEB887EB433DE5EEA6D6654DB597F6C557558191A05130FB3E113E50515DD07007754FF905E55AC92E3147EC319017759A7B84D81BDB5A0EF2B9BAB184BB5B52ECE2C0C15C33B9305A41811F6E661F7C0AE6ED1F101ABEDE4EDD3EFFB81AF98C666D1EE3532C3917349ED6FE12F2D9BB0BA0C81BC0F100B5E44D2C79FA8AFD161F37C913798DD6B85CBFED8ED1109AB19E505ED9BCF2F30F3DEFD9EEE2FF67B07F2D189F7C84B941A9F2C9E81E77E1F4A92B70EB630A7BE64C3FD2C0881E42DFF118E3FE627771A1FD7F65C6480156E88D3F80E7A58939A44023B25184E53F9702096E22FDBCE23C8995A8D058117EB8F1B92DB232D74308204C394FD2DEF237BE4FA0870267BFE7F3B0A279D51C80D434669DCE6153038D653F1A55BFAFA79D68F740DD35E827475DECC6F9B55A635DFDCEE9E48252D2B0312711A32995B2F9325A4B9D7406A1A50387FDD2CF9BC9763108C2E9660935B159371387BC23599C94D68FD4BC1AE88ADCB30FABD1E8C369B13E857EC001F7D2E1746DD4F208766BB321BD5CA996E27051B83A482140D58496A54C49D584397E618E8611012F0B8070B58393B658FD365A11E76A7991AAB691B8FCE882F67FD2C7456C96EC91AFD9C7821ECC0470097F135ACBCE8AE4880C78C3DFE968D0066731EAFA5C411A6E17E4BB1A2C54F26F3AA9E900676182E218766CED65B212F7893C32990BC3C034E53216D349A3BBA4A9E94E2AB6F6D023FD9E8DB61F3D6AF9C4010BEBB06B12332DBADBEFEE8C0209B8AEC80E87AD0B4FF48E499F0722674862FA974470700F0E51D9C78CEDEB51BF06A8642BAAC990B0A0B8C44B7BAA4634E4B90788C3C6633AA14B859B743C1986435933EA19D01DEFC36ECCBCC04325B1662D9873FA24BEC87560C3E059AA491E960A5977BA569FC780744D54020C3CF3C539A629A7C8475574EF4EEA4B7BA6EE1764D95369654953938E51CBB5FA442B8517FFFA77E42269EC4270D1B2148CBA1546E4E04CE3C0CC956D10D799F9D1CF5F111D06323E08BDD8FE1C1420ADD181D4D6165C0329E3EEC0F4BE63834B2F88B67 +20231020120924 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E53BA038B +20231020135128 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E5963D87F +20231020141837 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E5ADDB3BF +20231020144225 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E5C23DA93 +20231020150405 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E5D53167B +20231020155408 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E6012AFBF +20231020161645 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E6155F8BF +20231020201740 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E6EE62BF7 +20231020212403 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E729EE083 +20231020213051 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E72F5F79F +20231020222529 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E7604BE3F +20231021020659 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E826C9DAF +20231021024826 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E84B7FDA7 +20231021060900 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E90033123 +20231021070156 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E92F5819B +20231021074615 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E95655CC3 +20231021075426 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E95D1FF3B +20231021080049 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E9624A203 +20231021094905 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E9C2D4FFB +20231021101528 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E9DA4B553 +20231021105156 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15E9FAA5047 +20231021112242 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EA159B54F +20231021121606 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EA462327B +20231021123502 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EA566E22F +20231021140626 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EAA7D27A7 +20231021144911 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EACD5272F +20231021161127 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EB1713BE3 +20231021162002 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EB1DFAA87 +20231021162540 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EB22A3C83 +20231021174652 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EB6ADB0DB +20231021190654 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EBB224183 +20231021192557 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EBC2D1F93 +20231021193213 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EBC7ECAAB +20231021194107 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EBCF4C693 +20231021195056 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EBD7953DB +20231021201746 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EBEF4D117 +20231021203518 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EBFE78F6B +20231021222354 2 6 100 8191 5 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EC60AEBDF +20231021223151 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EC674EB1B +20231021225247 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EC79E5D1B +20231021231628 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15EC8ECAA63 +20231022001025 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15ECBF5D973 +20231022005100 2 6 100 8191 2 E01A60D3325645E3E0DD9D0BD00BEB9715262052AA5A04F3232BE563EFD025CFE05B0A86B07BCC4CB70A1D115E3DD0E1D5B5C394B491144DF417E29A1FBE336AECCA9E68BEACD5979103B7FD2923A58AB05E3195A5AFA717AE1F5F4B19C6616CCDA2FC597B3C92CB2EA57C10580C488638BF1261AA552DB9B4BDAFA45BBA4D7BF0A3A2B066F797F1B444AB990D9797A445D752647EE9ED870002A04DCA5DB1D65F3AA9620DCC4547A640BA30B27B09B48DC3BB06C9F714A9ECA54F09AD37BD57557E5EAD0B64C5CCCD2E2592A04E009BE169B079E3DED7161AB33474304BC70861BBCB2C05776EF82E2B32F0939E1C271187713632C6F624BD13C9C714FAFB99C4D5A36C1A7EF2DE6A18D5BC2FD2DAE7450B78494FC94ED842476B5DF567D47F066A1D168483B1A693A87E831B8DA20B48A05D13A688E30E7FDCB8AAE34A46FCC6A5642BCCF1D2FBC1804789E2D1D7098BA9AF2C94C889D58F949F6B97338879A45D26A3875D8C2098E41AD429F3B7AC9DA8B6C3D714CD477049487B778E553EBB1BAF2403FFDECCB38D691F3E31A7DB9729F1651E42972284802C5C14C76CACE52F1BAD053769C9ED3052A5370B9363F0A87273CE4ED2521F41320E0BD053CB2C79F79B708F72745E2B63D0894ACF06EDF0E612CAA81B38CFBBA421A61924C6794F0B321823C411330703F0291CDEB0FE71A3D3459413933E4C6D681A765848809F787EBA5E14EFF0A52FA57003589A7039776DA11F21B12F14424F694AB810D5C8271C8A108659B190A029666F77357AFD28DCE2BC93EC38104FA250E29610F477265622BDBEE96A933D503A7F820B3B4DB8929A43B3BD2167BC1DCE61708C1D599D7A584DA5A2DD6EAE2D5D6428E8A0912CF18D9FBA71ABDD0F975B43B50056315F76148739D3FAFEA4094EC3E25A3EDC9F0133E0C435C1070B2F7C073EC33D5B7DE096DCC490D82CE8B053F24009F73450C49369B91AD381581BEDB402909A2C95CE0AFFCC64A51C5B824666A26E1C40F2A2EC104DA1F481ACB967068E6A0E4A5CEC1A37730D7A93761C6BE3F745FC245FE16B841444DF177B2F779A8D22FE67EC92166BAA7ACC6ADB84565369D0B174686783775F79C5ABF65E726911833385457DC896E150D3440504D9F7FDC087698F69B82052FE4F2B577CDA4262A7B26FA7F38CD3471AC7E433CABD3470B309A96585FF7C3889B6537ACADE1E79F7B605387BDCCC5ED8445DB923B98D11F29EFCB413FF2E09E9E543263309C87E8C7FC22F13E9BDFF2F04CD36DD2FFF425EEE50C1460C676A804CED5319C0D68B60251494EBD97C73EE0E7803B4B8414D4503954F40147885299B8EE19ECA8F2CC2FA48230781F788D9FF1AA7A9D1F23E54357EDE3DEE548C80DBD0F0DA070ED149A34EE08FB3FB01895C5D2ED1E68A5508A5BFBB7D2DBFA4C46830D15ECE33665B diff --git a/crypto/openssh/monitor_wrap.c b/crypto/openssh/monitor_wrap.c index 3533cf0692c0..6270d1398f53 100644 --- a/crypto/openssh/monitor_wrap.c +++ b/crypto/openssh/monitor_wrap.c @@ -1,1020 +1,1020 @@ -/* $OpenBSD: monitor_wrap.c,v 1.128 2023/03/31 00:44:29 dtucker Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.129 2023/12/18 14:45:49 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #ifdef WITH_OPENSSL #include #include #include #endif #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #ifdef WITH_OPENSSL #include "dh.h" #endif #include "sshbuf.h" #include "sshkey.h" #include "cipher.h" #include "kex.h" #include "hostfile.h" #include "auth.h" #include "auth-options.h" #include "packet.h" #include "mac.h" #include "log.h" #include "auth-pam.h" #include "monitor.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "monitor_wrap.h" #include "atomicio.h" #include "monitor_fdpass.h" #include "misc.h" #include "channels.h" #include "session.h" #include "servconf.h" #include "ssherr.h" /* Imports */ extern struct monitor *pmonitor; extern struct sshbuf *loginmsg; extern ServerOptions options; void mm_log_handler(LogLevel level, int forced, const char *msg, void *ctx) { struct sshbuf *log_msg; struct monitor *mon = (struct monitor *)ctx; int r; size_t len; if (mon->m_log_sendfd == -1) fatal_f("no log channel"); if ((log_msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u32(log_msg, 0)) != 0 || /* length; filled below */ (r = sshbuf_put_u32(log_msg, level)) != 0 || (r = sshbuf_put_u32(log_msg, forced)) != 0 || (r = sshbuf_put_cstring(log_msg, msg)) != 0) fatal_fr(r, "assemble"); if ((len = sshbuf_len(log_msg)) < 4 || len > 0xffffffff) 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_f("write: %s", strerror(errno)); sshbuf_free(log_msg); } int mm_is_monitor(void) { /* * m_pid is only set in the privileged part, and * points to the unprivileged child. */ return (pmonitor && pmonitor->m_pid > 0); } void mm_request_send(int sock, enum monitor_reqtype type, struct sshbuf *m) { size_t mlen = sshbuf_len(m); u_char buf[5]; debug3_f("entering, type %d", type); if (mlen >= 0xffffffff) 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_f("write: %s", strerror(errno)); if (atomicio(vwrite, sock, sshbuf_mutable_ptr(m), mlen) != mlen) fatal_f("write: %s", strerror(errno)); } void mm_request_receive(int sock, struct sshbuf *m) { u_char buf[4], *p = NULL; u_int msg_len; int r; debug3_f("entering"); if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) { if (errno == EPIPE) cleanup_exit(255); fatal_f("read: %s", strerror(errno)); } msg_len = PEEK_U32(buf); if (msg_len > 256 * 1024) fatal_f("read: bad msg_len %d", msg_len); sshbuf_reset(m); if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) fatal_fr(r, "reserve"); if (atomicio(read, sock, p, msg_len) != msg_len) fatal_f("read: %s", strerror(errno)); } void mm_request_receive_expect(int sock, enum monitor_reqtype type, struct sshbuf *m) { u_char rtype; int r; debug3_f("entering, type %d", type); mm_request_receive(sock, m); if ((r = sshbuf_get_u8(m, &rtype)) != 0) fatal_fr(r, "parse"); if (rtype != type) fatal_f("read: rtype %d != type %d", rtype, type); } #ifdef WITH_OPENSSL DH * mm_choose_dh(int min, int nbits, int max) { BIGNUM *p, *g; int r; u_char success = 0; struct sshbuf *m; if ((m = sshbuf_new()) == NULL) fatal_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_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, m); 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_fr(r, "parse success"); if (success == 0) fatal_f("MONITOR_ANS_MODULI failed"); if ((r = sshbuf_get_bignum2(m, &p)) != 0 || (r = sshbuf_get_bignum2(m, &g)) != 0) fatal_fr(r, "parse group"); debug3_f("remaining %zu", sshbuf_len(m)); sshbuf_free(m); return (dh_new_group(g, p)); } #endif 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, 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_f("entering"); if ((m = sshbuf_new()) == NULL) 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_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, m); 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_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) { struct sshbuf *m; struct passwd *pw; size_t len; u_int i; ServerOptions *newopts; int r; u_char ok; const u_char *p; debug3_f("entering"); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, username)) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, m); 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_fr(r, "parse success"); if (ok == 0) { pw = NULL; goto out; } /* XXX don't like passing struct passwd like this */ pw = xcalloc(sizeof(*pw), 1); 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 (r = sshbuf_get_cstring(m, &pw->pw_gecos, NULL)) != 0 || #endif #ifdef HAVE_STRUCT_PASSWD_PW_CLASS (r = sshbuf_get_cstring(m, &pw->pw_class, NULL)) != 0 || #endif (r = sshbuf_get_cstring(m, &pw->pw_dir, NULL)) != 0 || (r = sshbuf_get_cstring(m, &pw->pw_shell, NULL)) != 0) fatal_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_fr(r, "parse opts"); if (len != sizeof(*newopts)) 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 && \ (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 ? \ NULL : xcalloc(newopts->nx, sizeof(*newopts->x)); \ for (i = 0; i < newopts->nx; i++) { \ if ((r = sshbuf_get_cstring(m, \ &newopts->x[i], NULL)) != 0) \ fatal_fr(r, "parse %s", #x); \ } \ } while (0) /* See comment in servconf.h */ COPY_MATCH_STRING_OPTS(); #undef M_CP_STROPT #undef M_CP_STRARRAYOPT copy_set_server_options(&options, newopts, 1); log_change_level(options.log_level); log_verbose_reset(); for (i = 0; i < options.num_log_verbose; i++) log_verbose_add(options.log_verbose[i]); process_permitopen(ssh, &options); process_channel_timeouts(ssh, &options); + kex_set_server_sig_algs(ssh, options.pubkey_accepted_algos); free(newopts); - sshbuf_free(m); return (pw); } char * mm_auth2_read_banner(void) { struct sshbuf *m; char *banner; int r; debug3_f("entering"); if ((m = sshbuf_new()) == NULL) 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_fr(r, "parse"); sshbuf_free(m); /* treat empty banner as missing banner */ if (strlen(banner) == 0) { free(banner); banner = NULL; } return (banner); } /* Inform the privileged process about service and style */ void mm_inform_authserv(char *service, char *style) { struct sshbuf *m; int r; debug3_f("entering"); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, service)) != 0 || (r = sshbuf_put_cstring(m, style ? style : "")) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m); sshbuf_free(m); } /* Do the password authentication */ int mm_auth_password(struct ssh *ssh, char *password) { struct sshbuf *m; int r, authenticated = 0; #ifdef USE_PAM u_int maxtries = 0; #endif debug3_f("entering"); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, password)) != 0) fatal_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, m); 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_fr(r, "parse"); #ifdef USE_PAM if ((r = sshbuf_get_u32(m, &maxtries)) != 0) fatal_fr(r, "parse PAM"); if (maxtries > INT_MAX) fatal_fr(r, "bad maxtries"); sshpam_set_maxtries_reached(maxtries); #endif sshbuf_free(m); debug3_f("user %sauthenticated", authenticated ? "" : "not "); return (authenticated); } int mm_user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key, int pubkey_auth_attempt, struct sshauthopt **authoptp) { return (mm_key_allowed(MM_USERKEY, NULL, NULL, key, pubkey_auth_attempt, authoptp)); } int mm_hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, const char *user, const char *host, struct sshkey *key) { return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0, NULL)); } int mm_key_allowed(enum mm_keytype type, const char *user, const char *host, struct sshkey *key, int pubkey_auth_attempt, struct sshauthopt **authoptp) { struct sshbuf *m; int r, allowed = 0; struct sshauthopt *opts = NULL; debug3_f("entering"); if (authoptp != NULL) *authoptp = NULL; if ((m = sshbuf_new()) == NULL) 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_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, m); 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_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) { *authoptp = opts; opts = NULL; } sshauthopt_free(opts); return allowed; } /* * This key verify needs to send the key type along, because the * privileged parent makes the decision if the key is allowed * for authentication. */ int mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, const u_char *data, size_t datalen, const char *sigalg, u_int compat, struct 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_f("entering"); if (sig_detailsp != NULL) *sig_detailsp = NULL; if ((m = sshbuf_new()) == NULL) 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_fr(r, "assemble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, m); 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 || (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); if (encoded_ret != 0) return SSH_ERR_SIGNATURE_INVALID; return 0; } void mm_send_keystate(struct ssh *ssh, struct monitor *monitor) { struct sshbuf *m; int r; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = ssh_packet_get_state(ssh, m)) != 0) fatal_fr(r, "ssh_packet_get_state"); mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m); debug3_f("Finished sending state"); sshbuf_free(m); } int mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen) { struct sshbuf *m; char *p, *msg; int success = 0, tmp1 = -1, tmp2 = -1, r; /* Kludge: ensure there are fds free to receive the pty/tty */ if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 || (tmp2 = dup(pmonitor->m_recvfd)) == -1) { error_f("cannot allocate fds for pty"); if (tmp1 >= 0) close(tmp1); return 0; } close(tmp1); close(tmp2); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, m); 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_fr(r, "parse success"); if (success == 0) { 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_fr(r, "parse"); sshbuf_free(m); strlcpy(namebuf, p, namebuflen); /* Possible truncation */ free(p); if ((r = sshbuf_put(loginmsg, msg, strlen(msg))) != 0) 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_f("receive fds failed"); /* Success */ return (1); } void mm_session_pty_cleanup2(Session *s) { struct sshbuf *m; int r; if (s->ttyfd == -1) return; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, s->tty)) != 0) fatal_fr(r, "assmble"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, m); sshbuf_free(m); /* closed dup'ed master */ if (s->ptymaster != -1 && close(s->ptymaster) == -1) error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno)); /* unlink pty from session */ s->ttyfd = -1; } #ifdef USE_PAM void mm_start_pam(struct ssh *ssh) { struct sshbuf *m; debug3("%s entering", __func__); if (!options.use_pam) fatal("UsePAM=no, but ended up in %s anyway", __func__); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, m); sshbuf_free(m); } u_int mm_do_pam_account(void) { struct sshbuf *m; u_int ret; char *msg; size_t msglen; int r; debug3("%s entering", __func__); if (!options.use_pam) fatal("UsePAM=no, but ended up in %s anyway", __func__); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, m); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_ACCOUNT, m); if ((r = sshbuf_get_u32(m, &ret)) != 0 || (r = sshbuf_get_cstring(m, &msg, &msglen)) != 0 || (r = sshbuf_put(loginmsg, msg, msglen)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); free(msg); sshbuf_free(m); debug3("%s returning %d", __func__, ret); return (ret); } void * mm_sshpam_init_ctx(Authctxt *authctxt) { struct sshbuf *m; int r, success; debug3("%s", __func__); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, m); debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_INIT_CTX, m); if ((r = sshbuf_get_u32(m, &success)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); if (success == 0) { debug3("%s: pam_init_ctx failed", __func__); sshbuf_free(m); return (NULL); } sshbuf_free(m); return (authctxt); } int mm_sshpam_query(void *ctx, char **name, char **info, u_int *num, char ***prompts, u_int **echo_on) { struct sshbuf *m; u_int i, n; int r, ret; debug3("%s", __func__); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, m); debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_QUERY, m); if ((r = sshbuf_get_u32(m, &ret)) != 0 || (r = sshbuf_get_cstring(m, name, NULL)) != 0 || (r = sshbuf_get_cstring(m, info, NULL)) != 0 || (r = sshbuf_get_u32(m, &n)) != 0 || (r = sshbuf_get_u32(m, num)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); debug3("%s: pam_query returned %d", __func__, ret); sshpam_set_maxtries_reached(n); if (*num > PAM_MAX_NUM_MSG) fatal("%s: received %u PAM messages, expected <= %u", __func__, *num, PAM_MAX_NUM_MSG); *prompts = xcalloc((*num + 1), sizeof(char *)); *echo_on = xcalloc((*num + 1), sizeof(u_int)); for (i = 0; i < *num; ++i) { if ((r = sshbuf_get_cstring(m, &((*prompts)[i]), NULL)) != 0 || (r = sshbuf_get_u32(m, &((*echo_on)[i]))) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); } sshbuf_free(m); return (ret); } int mm_sshpam_respond(void *ctx, u_int num, char **resp) { struct sshbuf *m; u_int n, i; int r, ret; debug3("%s", __func__); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_u32(m, num)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); for (i = 0; i < num; ++i) { if ((r = sshbuf_put_cstring(m, resp[i])) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); } mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, m); debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_RESPOND, m); if ((r = sshbuf_get_u32(m, &n)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); ret = (int)n; /* XXX */ debug3("%s: pam_respond returned %d", __func__, ret); sshbuf_free(m); return (ret); } void mm_sshpam_free_ctx(void *ctxtp) { struct sshbuf *m; debug3("%s", __func__); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, m); debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, m); sshbuf_free(m); } #endif /* USE_PAM */ /* Request process termination */ void mm_terminate(void) { struct sshbuf *m; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, m); sshbuf_free(m); } static void mm_chall_setup(char **name, char **infotxt, u_int *numprompts, char ***prompts, u_int **echo_on) { *name = xstrdup(""); *infotxt = xstrdup(""); *numprompts = 1; *prompts = xcalloc(*numprompts, sizeof(char *)); *echo_on = xcalloc(*numprompts, sizeof(u_int)); (*echo_on)[0] = 0; } int mm_bsdauth_query(void *ctx, char **name, char **infotxt, u_int *numprompts, char ***prompts, u_int **echo_on) { struct sshbuf *m; u_int success; char *challenge; int r; debug3_f("entering"); if ((m = sshbuf_new()) == NULL) 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_fr(r, "parse success"); if (success == 0) { 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_fr(r, "parse challenge"); sshbuf_free(m); mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); (*prompts)[0] = challenge; debug3_f("received challenge: %s", challenge); return (0); } int mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses) { struct sshbuf *m; int r, authok; debug3_f("entering"); if (numresponses != 1) return (-1); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, responses[0])) != 0) 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_fr(r, "parse"); sshbuf_free(m); return ((authok == 0) ? -1 : 0); } #ifdef SSH_AUDIT_EVENTS void mm_audit_event(struct ssh *ssh, ssh_audit_event_t event) { struct sshbuf *m; int r; debug3("%s entering", __func__); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_u32(m, event)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, m); sshbuf_free(m); } void mm_audit_run_command(const char *command) { struct sshbuf *m; int r; debug3("%s entering command %s", __func__, command); if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); if ((r = sshbuf_put_cstring(m, command)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, m); sshbuf_free(m); } #endif /* SSH_AUDIT_EVENTS */ #ifdef GSSAPI OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid) { struct sshbuf *m; OM_uint32 major; int r; /* Client doesn't get to see the context */ *ctx = NULL; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_string(m, goid->elements, goid->length)) != 0) 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_fr(r, "parse"); sshbuf_free(m); return (major); } OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in, gss_buffer_desc *out, OM_uint32 *flagsp) { struct sshbuf *m; OM_uint32 major; u_int flags; int r; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_string(m, in->value, in->length)) != 0) 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_fr(r, "parse"); if (flagsp != NULL) { if ((r = sshbuf_get_u32(m, &flags)) != 0) fatal_fr(r, "parse flags"); *flagsp = flags; } sshbuf_free(m); return (major); } OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) { struct sshbuf *m; OM_uint32 major; int r; if ((m = sshbuf_new()) == NULL) fatal_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_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_fr(r, "parse"); sshbuf_free(m); return(major); } int mm_ssh_gssapi_userok(char *user) { struct sshbuf *m; int r, authenticated = 0; if ((m = sshbuf_new()) == NULL) fatal_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_fr(r, "parse"); sshbuf_free(m); debug3_f("user %sauthenticated", authenticated ? "" : "not "); return (authenticated); } #endif /* GSSAPI */ diff --git a/crypto/openssh/mux.c b/crypto/openssh/mux.c index d9d5e7d994ca..d598a17e2da5 100644 --- a/crypto/openssh/mux.c +++ b/crypto/openssh/mux.c @@ -1,2374 +1,2374 @@ -/* $OpenBSD: mux.c,v 1.100 2023/08/18 01:37:41 djm Exp $ */ +/* $OpenBSD: mux.c,v 1.101 2023/11/23 03:37:05 dtucker Exp $ */ /* * Copyright (c) 2002-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. */ /* ssh session multiplexing support */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_PATHS_H #include #endif #ifdef HAVE_POLL_H #include #else # ifdef HAVE_SYS_POLL_H # include # endif #endif #ifdef HAVE_UTIL_H # include #endif #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "log.h" #include "ssh.h" #include "ssh2.h" #include "pathnames.h" #include "misc.h" #include "match.h" #include "sshbuf.h" #include "channels.h" #include "msg.h" #include "packet.h" #include "monitor_fdpass.h" #include "sshpty.h" #include "sshkey.h" #include "readconf.h" #include "clientloop.h" #include "ssherr.h" #include "misc.h" /* from ssh.c */ extern int tty_flag; extern Options options; extern char *host; extern struct sshbuf *command; extern volatile sig_atomic_t quit_pending; /* Context for session open confirmation callback */ struct mux_session_confirm_ctx { u_int want_tty; u_int want_subsys; u_int want_x_fwd; u_int want_agent_fwd; struct sshbuf *cmd; char *term; struct termios tio; char **env; u_int rid; }; /* Context for stdio fwd open confirmation callback */ struct mux_stdio_confirm_ctx { u_int rid; }; /* Context for global channel callback */ struct mux_channel_confirm_ctx { u_int cid; /* channel id */ u_int rid; /* request id */ int fid; /* forward id */ }; /* fd to control socket */ int muxserver_sock = -1; /* client request id */ u_int muxclient_request_id = 0; /* Multiplexing control command */ u_int muxclient_command = 0; /* Set when signalled. */ static volatile sig_atomic_t muxclient_terminate = 0; /* PID of multiplex server */ static u_int muxserver_pid = 0; static Channel *mux_listener_channel = NULL; struct mux_master_state { int hello_rcvd; }; /* mux protocol messages */ #define MUX_MSG_HELLO 0x00000001 #define MUX_C_NEW_SESSION 0x10000002 #define MUX_C_ALIVE_CHECK 0x10000004 #define MUX_C_TERMINATE 0x10000005 #define MUX_C_OPEN_FWD 0x10000006 #define MUX_C_CLOSE_FWD 0x10000007 #define MUX_C_NEW_STDIO_FWD 0x10000008 #define MUX_C_STOP_LISTENING 0x10000009 #define MUX_C_PROXY 0x1000000f #define MUX_S_OK 0x80000001 #define MUX_S_PERMISSION_DENIED 0x80000002 #define MUX_S_FAILURE 0x80000003 #define MUX_S_EXIT_MESSAGE 0x80000004 #define MUX_S_ALIVE 0x80000005 #define MUX_S_SESSION_OPENED 0x80000006 #define MUX_S_REMOTE_PORT 0x80000007 #define MUX_S_TTY_ALLOC_FAIL 0x80000008 #define MUX_S_PROXY 0x8000000f /* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */ #define MUX_FWD_LOCAL 1 #define MUX_FWD_REMOTE 2 #define MUX_FWD_DYNAMIC 3 static void mux_session_confirm(struct ssh *, int, int, void *); static void mux_stdio_confirm(struct ssh *, int, int, void *); static int mux_master_process_hello(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_new_session(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_alive_check(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_terminate(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_open_fwd(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_close_fwd(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_stdio_fwd(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_stop_listening(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static int mux_master_process_proxy(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); static const struct { u_int type; int (*handler)(struct ssh *, u_int, Channel *, struct sshbuf *, struct sshbuf *); } mux_master_handlers[] = { { MUX_MSG_HELLO, mux_master_process_hello }, { MUX_C_NEW_SESSION, mux_master_process_new_session }, { MUX_C_ALIVE_CHECK, mux_master_process_alive_check }, { MUX_C_TERMINATE, mux_master_process_terminate }, { MUX_C_OPEN_FWD, mux_master_process_open_fwd }, { MUX_C_CLOSE_FWD, mux_master_process_close_fwd }, { MUX_C_NEW_STDIO_FWD, mux_master_process_stdio_fwd }, { MUX_C_STOP_LISTENING, mux_master_process_stop_listening }, { MUX_C_PROXY, mux_master_process_proxy }, { 0, NULL } }; /* Cleanup callback fired on closure of mux client _session_ channel */ static void mux_master_session_cleanup_cb(struct ssh *ssh, int cid, int force, void *unused) { Channel *cc, *c = channel_by_id(ssh, cid); debug3_f("entering for channel %d", cid); if (c == NULL) fatal_f("channel_by_id(%i) == NULL", cid); if (c->ctl_chan != -1) { if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) 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; chan_rcvd_oclose(ssh, cc); } channel_cancel_cleanup(ssh, c->self); } /* Cleanup callback fired on closure of mux client _control_ channel */ static void mux_master_control_cleanup_cb(struct ssh *ssh, int cid, int force, void *unused) { Channel *sc, *c = channel_by_id(ssh, cid); debug3_f("entering for channel %d", cid); if (c == NULL) fatal_f("channel_by_id(%i) == NULL", cid); if (c->have_remote_id) { if ((sc = channel_by_id(ssh, c->remote_id)) == NULL) 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_f("channel %d: not open", sc->self); chan_mark_dead(ssh, sc); } else { if (sc->istate == CHAN_INPUT_OPEN) chan_read_failed(ssh, sc); if (sc->ostate == CHAN_OUTPUT_OPEN) chan_write_failed(ssh, sc); } } channel_cancel_cleanup(ssh, c->self); } /* Check mux client environment variables before passing them to mux master. */ static int env_permitted(const char *env) { u_int i; int ret; char name[1024], *cp; if ((cp = strchr(env, '=')) == NULL || cp == env) return 0; ret = snprintf(name, sizeof(name), "%.*s", (int)(cp - env), env); if (ret <= 0 || (size_t)ret >= sizeof(name)) { error_f("name '%.100s...' too long", env); return 0; } for (i = 0; i < options.num_send_env; i++) if (match_pattern(name, options.send_env[i])) return 1; return 0; } /* Mux master protocol message handlers */ static int mux_master_process_hello(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { u_int ver; struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; int r; if (state == NULL) fatal_f("channel %d: c->mux_ctx == NULL", c->self); if (state->hello_rcvd) { error_f("HELLO received twice"); return -1; } if ((r = sshbuf_get_u32(m, &ver)) != 0) { error_fr(r, "parse"); return -1; } if (ver != SSHMUX_VER) { error_f("unsupported multiplexing protocol version %u " "(expected %u)", ver, SSHMUX_VER); return -1; } debug2_f("channel %d client version %u", c->self, ver); /* No extensions are presently defined */ while (sshbuf_len(m) > 0) { char *name = NULL; size_t value_len = 0; if ((r = sshbuf_get_cstring(m, &name, NULL)) != 0 || (r = sshbuf_get_string_direct(m, NULL, &value_len)) != 0) { error_fr(r, "parse extension"); return -1; } debug2_f("Unrecognised extension \"%s\" length %zu", name, value_len); free(name); } state->hello_rcvd = 1; return 0; } /* Enqueue a "ok" response to the reply buffer */ static void reply_ok(struct sshbuf *reply, u_int rid) { int r; if ((r = sshbuf_put_u32(reply, MUX_S_OK)) != 0 || (r = sshbuf_put_u32(reply, rid)) != 0) fatal_fr(r, "reply"); } /* Enqueue an error response to the reply buffer */ static void reply_error(struct sshbuf *reply, u_int type, u_int rid, const char *msg) { int r; if ((r = sshbuf_put_u32(reply, type)) != 0 || (r = sshbuf_put_u32(reply, rid)) != 0 || (r = sshbuf_put_cstring(reply, msg)) != 0) fatal_fr(r, "reply"); } static int mux_master_process_new_session(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { Channel *nc; struct mux_session_confirm_ctx *cctx; char *cmd, *cp; u_int i, j, env_len, escape_char, window, packetmax; int r, new_fd[3]; /* Reply for SSHMUX_COMMAND_OPEN */ cctx = xcalloc(1, sizeof(*cctx)); cctx->term = NULL; cctx->rid = rid; cmd = NULL; cctx->env = NULL; env_len = 0; if ((r = sshbuf_skip_string(m)) != 0 || /* reserved */ (r = sshbuf_get_u32(m, &cctx->want_tty)) != 0 || (r = sshbuf_get_u32(m, &cctx->want_x_fwd)) != 0 || (r = sshbuf_get_u32(m, &cctx->want_agent_fwd)) != 0 || (r = sshbuf_get_u32(m, &cctx->want_subsys)) != 0 || (r = sshbuf_get_u32(m, &escape_char)) != 0 || (r = sshbuf_get_cstring(m, &cctx->term, NULL)) != 0 || (r = sshbuf_get_cstring(m, &cmd, NULL)) != 0) { malf: free(cmd); for (j = 0; j < env_len; j++) free(cctx->env[j]); free(cctx->env); free(cctx->term); free(cctx); error_f("malformed message"); return -1; } #define MUX_MAX_ENV_VARS 4096 while (sshbuf_len(m) > 0) { if ((r = sshbuf_get_cstring(m, &cp, NULL)) != 0) goto malf; if (!env_permitted(cp)) { free(cp); continue; } cctx->env = xreallocarray(cctx->env, env_len + 2, sizeof(*cctx->env)); cctx->env[env_len++] = cp; cctx->env[env_len] = NULL; if (env_len > MUX_MAX_ENV_VARS) { error_f(">%d environment variables received, " "ignoring additional", MUX_MAX_ENV_VARS); break; } } 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_f("sshbuf_new"); if ((r = sshbuf_put(cctx->cmd, cmd, strlen(cmd))) != 0) 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_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++) free(cctx->env[j]); free(cctx->env); free(cctx->term); sshbuf_free(cctx->cmd); free(cctx); reply_error(reply, MUX_S_FAILURE, rid, "did not receive file descriptors"); return -1; } } debug3_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_f("session already open"); reply_error(reply, MUX_S_FAILURE, rid, "Multiple sessions not supported"); cleanup: close(new_fd[0]); close(new_fd[1]); close(new_fd[2]); free(cctx->term); if (env_len != 0) { for (i = 0; i < env_len; i++) free(cctx->env[i]); free(cctx->env); } sshbuf_free(cctx->cmd); free(cctx); return 0; } if (options.control_master == SSHCTL_MASTER_ASK || options.control_master == SSHCTL_MASTER_AUTO_ASK) { if (!ask_permission("Allow shared connection to %s? ", host)) { debug2_f("session refused by user"); reply_error(reply, MUX_S_PERMISSION_DENIED, rid, "Permission denied"); goto cleanup; } } /* Try to pick up ttymodes from client before it goes raw */ if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1) error_f("tcgetattr: %s", strerror(errno)); window = CHAN_SES_WINDOW_DEFAULT; packetmax = CHAN_SES_PACKET_DEFAULT; if (cctx->want_tty) { window >>= 1; packetmax >>= 1; } nc = channel_new(ssh, "session", SSH_CHANNEL_OPENING, new_fd[0], new_fd[1], new_fd[2], window, packetmax, CHAN_EXTENDED_WRITE, "client-session", CHANNEL_NONBLOCK_STDIO); nc->ctl_chan = c->self; /* link session -> control channel */ c->remote_id = nc->self; /* link control -> session channel */ c->have_remote_id = 1; if (cctx->want_tty && escape_char != 0xffffffff) { channel_register_filter(ssh, nc->self, client_simple_escape_filter, NULL, client_filter_cleanup, client_new_escape_filter_ctx((int)escape_char)); } debug2_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); c->mux_pause = 1; /* stop handling messages until open_confirm done */ channel_register_cleanup(ssh, nc->self, mux_master_session_cleanup_cb, 1); /* reply is deferred, sent by mux_session_confirm */ return 0; } static int mux_master_process_alive_check(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { int r; debug2_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_fr(r, "reply"); return 0; } static int mux_master_process_terminate(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { 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_f("termination refused by user"); reply_error(reply, MUX_S_PERMISSION_DENIED, rid, "Permission denied"); return 0; } } quit_pending = 1; reply_ok(reply, rid); /* XXX exit happens too soon - message never makes it to client */ return 0; } static char * format_forward(u_int ftype, struct Forward *fwd) { char *ret; switch (ftype) { case MUX_FWD_LOCAL: xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d", (fwd->listen_path != NULL) ? fwd->listen_path : (fwd->listen_host == NULL) ? (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : fwd->listen_host, fwd->listen_port, (fwd->connect_path != NULL) ? fwd->connect_path : fwd->connect_host, fwd->connect_port); break; case MUX_FWD_DYNAMIC: xasprintf(&ret, "dynamic forward %.200s:%d -> *", (fwd->listen_host == NULL) ? (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : fwd->listen_host, fwd->listen_port); break; case MUX_FWD_REMOTE: xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d", (fwd->listen_path != NULL) ? fwd->listen_path : (fwd->listen_host == NULL) ? "LOCALHOST" : fwd->listen_host, fwd->listen_port, (fwd->connect_path != NULL) ? fwd->connect_path : fwd->connect_host, fwd->connect_port); break; default: fatal_f("unknown forward type %u", ftype); } return ret; } static int compare_host(const char *a, const char *b) { if (a == NULL && b == NULL) return 1; if (a == NULL || b == NULL) return 0; return strcmp(a, b) == 0; } static int compare_forward(struct Forward *a, struct Forward *b) { if (!compare_host(a->listen_host, b->listen_host)) return 0; if (!compare_host(a->listen_path, b->listen_path)) return 0; if (a->listen_port != b->listen_port) return 0; if (!compare_host(a->connect_host, b->connect_host)) return 0; if (!compare_host(a->connect_path, b->connect_path)) return 0; if (a->connect_port != b->connect_port) return 0; return 1; } static void mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) { struct mux_channel_confirm_ctx *fctx = ctxt; char *failmsg = NULL; struct Forward *rfwd; Channel *c; struct sshbuf *out; u_int port; int r; if ((c = channel_by_id(ssh, fctx->cid)) == NULL) { /* no channel for reply */ error_f("unknown channel"); return; } if ((out = sshbuf_new()) == NULL) 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)) { xasprintf(&failmsg, "unknown forwarding id %d", fctx->fid); goto fail; } rfwd = &options.remote_forwards[fctx->fid]; 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_fr(r, "parse port"); if (port > 65535) { fatal("Invalid allocated port %u for " "mux remote forward to %s:%d", port, rfwd->connect_host, rfwd->connect_port); } rfwd->allocated_port = (int)port; debug("Allocated port %u for mux remote forward" " to %s:%d", rfwd->allocated_port, rfwd->connect_host, rfwd->connect_port); if ((r = sshbuf_put_u32(out, MUX_S_REMOTE_PORT)) != 0 || (r = sshbuf_put_u32(out, fctx->rid)) != 0 || (r = sshbuf_put_u32(out, rfwd->allocated_port)) != 0) fatal_fr(r, "reply"); channel_update_permission(ssh, rfwd->handle, rfwd->allocated_port); } else { reply_ok(out, fctx->rid); } goto out; } else { if (rfwd->listen_port == 0) channel_update_permission(ssh, rfwd->handle, -1); if (rfwd->listen_path != NULL) xasprintf(&failmsg, "remote port forwarding failed for " "listen path %s", rfwd->listen_path); else xasprintf(&failmsg, "remote port forwarding failed for " "listen port %d", rfwd->listen_port); debug2_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); free(rfwd->listen_host); free(rfwd->listen_path); free(rfwd->connect_host); free(rfwd->connect_path); memset(rfwd, 0, sizeof(*rfwd)); } fail: 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_fr(r, "enqueue"); sshbuf_free(out); if (c->mux_pause <= 0) fatal_f("mux_pause %d", c->mux_pause); c->mux_pause = 0; /* start processing messages again */ } static int mux_master_process_open_fwd(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { struct Forward fwd; char *fwd_desc = NULL; char *listen_addr, *connect_addr; u_int ftype; u_int lport, cport; int r, i, ret = 0, freefwd = 1; memset(&fwd, 0, sizeof(fwd)); /* XXX - lport/cport check redundant */ if ((r = sshbuf_get_u32(m, &ftype)) != 0 || (r = sshbuf_get_cstring(m, &listen_addr, NULL)) != 0 || (r = sshbuf_get_u32(m, &lport)) != 0 || (r = sshbuf_get_cstring(m, &connect_addr, NULL)) != 0 || (r = sshbuf_get_u32(m, &cport)) != 0 || (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { error_f("malformed message"); ret = -1; goto out; } if (*listen_addr == '\0') { free(listen_addr); listen_addr = NULL; } if (*connect_addr == '\0') { free(connect_addr); connect_addr = NULL; } memset(&fwd, 0, sizeof(fwd)); fwd.listen_port = lport; if (fwd.listen_port == PORT_STREAMLOCAL) fwd.listen_path = listen_addr; else fwd.listen_host = listen_addr; fwd.connect_port = cport; if (fwd.connect_port == PORT_STREAMLOCAL) fwd.connect_path = connect_addr; else fwd.connect_host = connect_addr; debug2_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_f("invalid forwarding type %u", ftype); invalid: free(listen_addr); free(connect_addr); reply_error(reply, MUX_S_FAILURE, rid, "Invalid forwarding request"); return 0; } if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) { logit_f("streamlocal and dynamic forwards " "are mutually exclusive"); goto invalid; } if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) { 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_f("invalid connect port %u", fwd.connect_port); goto invalid; } if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) { logit_f("missing connect host"); goto invalid; } /* Skip forwards that have already been requested */ switch (ftype) { case MUX_FWD_LOCAL: case MUX_FWD_DYNAMIC: for (i = 0; i < options.num_local_forwards; i++) { if (compare_forward(&fwd, options.local_forwards + i)) { exists: debug2_f("found existing forwarding"); reply_ok(reply, rid); goto out; } } break; case MUX_FWD_REMOTE: for (i = 0; i < options.num_remote_forwards; i++) { if (!compare_forward(&fwd, options.remote_forwards + i)) continue; if (fwd.listen_port != 0) goto exists; debug2_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_fr(r, "reply FWD_REMOTE"); goto out; } break; } if (options.control_master == SSHCTL_MASTER_ASK || options.control_master == SSHCTL_MASTER_AUTO_ASK) { if (!ask_permission("Open %s on %s?", fwd_desc, host)) { debug2_f("forwarding refused by user"); reply_error(reply, MUX_S_PERMISSION_DENIED, rid, "Permission denied"); goto out; } } if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { if (!channel_setup_local_fwd_listener(ssh, &fwd, &options.fwd_opts)) { fail: logit_f("requested %s failed", fwd_desc); reply_error(reply, MUX_S_FAILURE, rid, "Port forwarding failed"); goto out; } add_local_forward(&options, &fwd); freefwd = 0; } else { struct mux_channel_confirm_ctx *fctx; fwd.handle = channel_request_remote_forwarding(ssh, &fwd); if (fwd.handle < 0) goto fail; add_remote_forward(&options, &fwd); fctx = xcalloc(1, sizeof(*fctx)); fctx->cid = c->self; fctx->rid = rid; fctx->fid = options.num_remote_forwards - 1; client_register_global_confirm(mux_confirm_remote_forward, fctx); freefwd = 0; c->mux_pause = 1; /* wait for mux_confirm_remote_forward */ /* delayed reply in mux_confirm_remote_forward */ goto out; } reply_ok(reply, rid); out: free(fwd_desc); if (freefwd) { free(fwd.listen_host); free(fwd.listen_path); free(fwd.connect_host); free(fwd.connect_path); } return ret; } static int mux_master_process_close_fwd(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { struct Forward fwd, *found_fwd; char *fwd_desc = NULL; const char *error_reason = NULL; char *listen_addr = NULL, *connect_addr = NULL; u_int ftype; int r, i, ret = 0; u_int lport, cport; memset(&fwd, 0, sizeof(fwd)); if ((r = sshbuf_get_u32(m, &ftype)) != 0 || (r = sshbuf_get_cstring(m, &listen_addr, NULL)) != 0 || (r = sshbuf_get_u32(m, &lport)) != 0 || (r = sshbuf_get_cstring(m, &connect_addr, NULL)) != 0 || (r = sshbuf_get_u32(m, &cport)) != 0 || (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) || (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) { error_f("malformed message"); ret = -1; goto out; } if (*listen_addr == '\0') { free(listen_addr); listen_addr = NULL; } if (*connect_addr == '\0') { free(connect_addr); connect_addr = NULL; } memset(&fwd, 0, sizeof(fwd)); fwd.listen_port = lport; if (fwd.listen_port == PORT_STREAMLOCAL) fwd.listen_path = listen_addr; else fwd.listen_host = listen_addr; fwd.connect_port = cport; if (fwd.connect_port == PORT_STREAMLOCAL) fwd.connect_path = connect_addr; else fwd.connect_host = connect_addr; debug2_f("channel %d: request cancel %s", c->self, (fwd_desc = format_forward(ftype, &fwd))); /* make sure this has been requested */ found_fwd = NULL; switch (ftype) { case MUX_FWD_LOCAL: case MUX_FWD_DYNAMIC: for (i = 0; i < options.num_local_forwards; i++) { if (compare_forward(&fwd, options.local_forwards + i)) { found_fwd = options.local_forwards + i; break; } } break; case MUX_FWD_REMOTE: for (i = 0; i < options.num_remote_forwards; i++) { if (compare_forward(&fwd, options.remote_forwards + i)) { found_fwd = options.remote_forwards + i; break; } } break; } if (found_fwd == NULL) error_reason = "port not forwarded"; else if (ftype == MUX_FWD_REMOTE) { /* * This shouldn't fail unless we confused the host/port * between options.remote_forwards and permitted_opens. * However, for dynamic allocated listen ports we need * to use the actual listen port. */ if (channel_request_rforward_cancel(ssh, found_fwd) == -1) error_reason = "port not in permitted opens"; } else { /* local and dynamic forwards */ /* Ditto */ if (channel_cancel_lport_listener(ssh, &fwd, fwd.connect_port, &options.fwd_opts) == -1) error_reason = "port not found"; } if (error_reason != NULL) reply_error(reply, MUX_S_FAILURE, rid, error_reason); else { reply_ok(reply, rid); free(found_fwd->listen_host); free(found_fwd->listen_path); free(found_fwd->connect_host); free(found_fwd->connect_path); found_fwd->listen_host = found_fwd->connect_host = NULL; found_fwd->listen_path = found_fwd->connect_path = NULL; found_fwd->listen_port = found_fwd->connect_port = 0; } out: free(fwd_desc); free(listen_addr); free(connect_addr); return ret; } static int mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { Channel *nc; char *chost = NULL; u_int _cport, i, j; int ok = 0, cport, r, new_fd[2]; struct mux_stdio_confirm_ctx *cctx; if ((r = sshbuf_skip_string(m)) != 0 || /* reserved */ (r = sshbuf_get_cstring(m, &chost, NULL)) != 0 || (r = sshbuf_get_u32(m, &_cport)) != 0) { free(chost); error_f("malformed message"); return -1; } if (_cport == (u_int)PORT_STREAMLOCAL) cport = PORT_STREAMLOCAL; else if (_cport <= INT_MAX) cport = (int)_cport; else { free(chost); error_f("invalid port 0x%x", _cport); return -1; } debug2_f("channel %d: stdio fwd to %s:%d", 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_f("failed to receive fd %d from client", i); for (j = 0; j < i; j++) close(new_fd[j]); free(chost); /* prepare reply */ reply_error(reply, MUX_S_FAILURE, rid, "did not receive file descriptors"); return -1; } } debug3_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_f("session already open"); reply_error(reply, MUX_S_FAILURE, rid, "Multiple sessions not supported"); cleanup: close(new_fd[0]); close(new_fd[1]); free(chost); return 0; } if (options.control_master == SSHCTL_MASTER_ASK || options.control_master == SSHCTL_MASTER_AUTO_ASK) { if (cport == PORT_STREAMLOCAL) { ok = ask_permission("Allow forward to path %s", chost); } else { ok = ask_permission("Allow forward to [%s]:%d? ", chost, cport); } if (!ok) { debug2_f("stdio fwd refused by user"); reply_error(reply, MUX_S_PERMISSION_DENIED, rid, "Permission denied"); goto cleanup; } } nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1], CHANNEL_NONBLOCK_STDIO); free(chost); nc->ctl_chan = c->self; /* link session -> control channel */ c->remote_id = nc->self; /* link control -> session channel */ c->have_remote_id = 1; debug2_f("channel_new: %d control %d", nc->self, nc->ctl_chan); channel_register_cleanup(ssh, nc->self, mux_master_session_cleanup_cb, 1); cctx = xcalloc(1, sizeof(*cctx)); cctx->rid = rid; channel_register_open_confirm(ssh, nc->self, mux_stdio_confirm, cctx); c->mux_pause = 1; /* stop handling messages until open_confirm done */ /* reply is deferred, sent by mux_session_confirm */ return 0; } /* Callback on open confirmation in mux master for a mux stdio fwd session. */ static void mux_stdio_confirm(struct ssh *ssh, int id, int success, void *arg) { struct mux_stdio_confirm_ctx *cctx = arg; Channel *c, *cc; struct sshbuf *reply; int r; if (cctx == NULL) fatal_f("cctx == NULL"); if ((c = channel_by_id(ssh, id)) == NULL) fatal_f("no channel for id %d", id); if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) fatal_f("channel %d lacks control channel %d", id, c->ctl_chan); if ((reply = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if (!success) { debug3_f("sending failure reply"); reply_error(reply, MUX_S_FAILURE, cctx->rid, "Session open refused by peer"); /* prepare reply */ goto done; } 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_fr(r, "reply"); done: /* Send reply */ if ((r = sshbuf_put_stringb(cc->output, reply)) != 0) fatal_fr(r, "enqueue"); sshbuf_free(reply); if (cc->mux_pause <= 0) fatal_f("mux_pause %d", cc->mux_pause); cc->mux_pause = 0; /* start processing messages again */ c->open_confirm_ctx = NULL; free(cctx); } static int mux_master_process_stop_listening(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { debug_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_f("stop listen refused by user"); reply_error(reply, MUX_S_PERMISSION_DENIED, rid, "Permission denied"); return 0; } } if (mux_listener_channel != NULL) { channel_free(ssh, mux_listener_channel); client_stop_mux(); free(options.control_path); options.control_path = NULL; mux_listener_channel = NULL; muxserver_sock = -1; } reply_ok(reply, rid); return 0; } static int mux_master_process_proxy(struct ssh *ssh, u_int rid, Channel *c, struct sshbuf *m, struct sshbuf *reply) { int r; debug_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_fr(r, "reply"); return 0; } /* Channel callbacks fired on read/write from mux client fd */ static int mux_master_read_cb(struct ssh *ssh, Channel *c) { struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; struct sshbuf *in = NULL, *out = NULL; u_int type, rid, i; int r, ret = -1; if ((out = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); /* Setup ctx and */ if (c->mux_ctx == NULL) { state = xcalloc(1, sizeof(*state)); c->mux_ctx = state; channel_register_cleanup(ssh, c->self, mux_master_control_cleanup_cb, 0); /* Send hello */ if ((r = sshbuf_put_u32(out, MUX_MSG_HELLO)) != 0 || (r = sshbuf_put_u32(out, SSHMUX_VER)) != 0) fatal_fr(r, "reply"); /* no extensions */ if ((r = sshbuf_put_stringb(c->output, out)) != 0) fatal_fr(r, "enqueue"); debug3_f("channel %d: hello sent", c->self); ret = 0; goto out; } /* Channel code ensures that we receive whole packets */ if ((r = sshbuf_froms(c->input, &in)) != 0) { malf: error_f("malformed message"); goto out; } if ((r = sshbuf_get_u32(in, &type)) != 0) goto malf; 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_f("expected MUX_MSG_HELLO(0x%08x), " "received 0x%08x", MUX_MSG_HELLO, type); goto out; } if ((r = sshbuf_get_u32(in, &rid)) != 0) goto malf; } for (i = 0; mux_master_handlers[i].handler != NULL; i++) { if (type == mux_master_handlers[i].type) { ret = mux_master_handlers[i].handler(ssh, rid, c, in, out); break; } } if (mux_master_handlers[i].handler == NULL) { error_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 && (r = sshbuf_put_stringb(c->output, out)) != 0) fatal_fr(r, "enqueue"); out: sshbuf_free(in); sshbuf_free(out); return ret; } void mux_exit_message(struct ssh *ssh, Channel *c, int exitval) { struct sshbuf *m; Channel *mux_chan; int r; debug3_f("channel %d: exit message, exitval %d", c->self, exitval); if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL) 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_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_fr(r, "reply"); sshbuf_free(m); } void mux_tty_alloc_failed(struct ssh *ssh, Channel *c) { struct sshbuf *m; Channel *mux_chan; int r; debug3_f("channel %d: TTY alloc failed", c->self); if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL) 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_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_fr(r, "reply"); sshbuf_free(m); } /* Prepare a mux master to listen on a Unix domain socket. */ void muxserver_listen(struct ssh *ssh) { mode_t old_umask; char *orig_control_path = options.control_path; char rbuf[16+1]; u_int i, r; int oerrno; if (options.control_path == NULL || options.control_master == SSHCTL_MASTER_NO) return; debug("setting up multiplex master socket"); /* * Use a temporary path before listen so we can pseudo-atomically * establish the listening socket in its final location to avoid * other processes racing in between bind() and listen() and hitting * an unready socket. */ for (i = 0; i < sizeof(rbuf) - 1; i++) { r = arc4random_uniform(26+26+10); rbuf[i] = (r < 26) ? 'a' + r : (r < 26*2) ? 'A' + r - 26 : '0' + r - 26 - 26; } rbuf[sizeof(rbuf) - 1] = '\0'; options.control_path = NULL; xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf); debug3_f("temporary control path %s", options.control_path); old_umask = umask(0177); muxserver_sock = unix_listener(options.control_path, 64, 0); oerrno = errno; umask(old_umask); if (muxserver_sock < 0) { if (oerrno == EINVAL || oerrno == EADDRINUSE) { error("ControlSocket %s already exists, " "disabling multiplexing", options.control_path); disable_mux_master: if (muxserver_sock != -1) { close(muxserver_sock); muxserver_sock = -1; } free(orig_control_path); free(options.control_path); options.control_path = NULL; options.control_master = SSHCTL_MASTER_NO; return; } else { /* unix_listener() logs the error */ cleanup_exit(255); } } /* Now atomically "move" the mux socket into position */ if (link(options.control_path, orig_control_path) != 0) { if (errno != EEXIST) { fatal_f("link mux listener %s => %s: %s", options.control_path, orig_control_path, strerror(errno)); } error("ControlSocket %s already exists, disabling multiplexing", orig_control_path); unlink(options.control_path); goto disable_mux_master; } unlink(options.control_path); free(options.control_path); options.control_path = orig_control_path; set_nonblock(muxserver_sock); mux_listener_channel = channel_new(ssh, "mux listener", SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, options.control_path, 1); mux_listener_channel->mux_rcb = mux_master_read_cb; debug3_f("mux listener channel %d fd %d", mux_listener_channel->self, mux_listener_channel->sock); } /* Callback on open confirmation in mux master for a mux client session. */ static void mux_session_confirm(struct ssh *ssh, int id, int success, void *arg) { struct mux_session_confirm_ctx *cctx = arg; const char *display; Channel *c, *cc; int i, r; struct sshbuf *reply; if (cctx == NULL) fatal_f("cctx == NULL"); if ((c = channel_by_id(ssh, id)) == NULL) fatal_f("no channel for id %d", id); if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) fatal_f("channel %d lacks control channel %d", id, c->ctl_chan); if ((reply = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if (!success) { debug3_f("sending failure reply"); reply_error(reply, MUX_S_FAILURE, cctx->rid, "Session open refused by peer"); goto done; } display = getenv("DISPLAY"); if (cctx->want_x_fwd && options.forward_x11 && display != NULL) { char *proto, *data; /* Get reasonable local authentication information. */ if (client_x11_get_proto(ssh, display, options.xauth_location, options.forward_x11_trusted, options.forward_x11_timeout, &proto, &data) == 0) { /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication " "spoofing."); x11_request_forwarding_with_spoofing(ssh, id, display, proto, data, 1); /* XXX exit_on_forward_failure */ client_expect_confirm(ssh, id, "X11 forwarding", CONFIRM_WARN); } } if (cctx->want_agent_fwd && options.forward_agent) { debug("Requesting authentication agent forwarding."); channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0); if ((r = sshpkt_send(ssh)) != 0) 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_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_fr(r, "reply"); done: /* Send reply */ if ((r = sshbuf_put_stringb(cc->output, reply)) != 0) fatal_fr(r, "enqueue"); sshbuf_free(reply); if (cc->mux_pause <= 0) 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); free(cctx->term); if (cctx->env != NULL) { for (i = 0; cctx->env[i] != NULL; i++) free(cctx->env[i]); free(cctx->env); } free(cctx); } /* ** Multiplexing client support */ /* Exit signal handler */ static void control_client_sighandler(int signo) { muxclient_terminate = signo; } /* * Relay signal handler - used to pass some signals from mux client to * mux master. */ static void control_client_sigrelay(int signo) { int save_errno = errno; if (muxserver_pid > 1) kill(muxserver_pid, signo); errno = save_errno; } static int mux_client_read(int fd, struct sshbuf *b, size_t need, int timeout_ms) { size_t have; ssize_t len; u_char *p; int r; if ((r = sshbuf_reserve(b, need, &p)) != 0) fatal_fr(r, "reserve"); for (have = 0; have < need; ) { if (muxclient_terminate) { errno = EINTR; return -1; } len = read(fd, p + have, need - have); if (len == -1) { switch (errno) { #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) case EWOULDBLOCK: #endif case EAGAIN: if (waitrfd(fd, &timeout_ms, &muxclient_terminate) == -1 && errno != EINTR) return -1; /* timeout */ /* FALLTHROUGH */ case EINTR: continue; default: return -1; } } if (len == 0) { errno = EPIPE; return -1; } have += (size_t)len; } return 0; } static int mux_client_write_packet(int fd, struct sshbuf *m) { struct sshbuf *queue; u_int have, need; int r, oerrno, len; const u_char *ptr; struct pollfd pfd; pfd.fd = fd; pfd.events = POLLOUT; if ((queue = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_stringb(queue, m)) != 0) fatal_fr(r, "enqueue"); need = sshbuf_len(queue); ptr = sshbuf_ptr(queue); for (have = 0; have < need; ) { if (muxclient_terminate) { sshbuf_free(queue); errno = EINTR; return -1; } len = write(fd, ptr + have, need - have); if (len == -1) { switch (errno) { #if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) case EWOULDBLOCK: #endif case EAGAIN: (void)poll(&pfd, 1, -1); /* FALLTHROUGH */ case EINTR: continue; default: oerrno = errno; sshbuf_free(queue); errno = oerrno; return -1; } } if (len == 0) { sshbuf_free(queue); errno = EPIPE; return -1; } have += (u_int)len; } sshbuf_free(queue); return 0; } static int mux_client_read_packet_timeout(int fd, struct sshbuf *m, int timeout_ms) { struct sshbuf *queue; size_t need, have; const u_char *ptr; int r, oerrno; if ((queue = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if (mux_client_read(fd, queue, 4, timeout_ms) != 0) { if ((oerrno = errno) == EPIPE) debug3_f("read header failed: %s", strerror(errno)); sshbuf_free(queue); errno = oerrno; return -1; } need = PEEK_U32(sshbuf_ptr(queue)); if (mux_client_read(fd, queue, need, timeout_ms) != 0) { oerrno = 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_fr(r, "dequeue"); sshbuf_free(queue); return 0; } static int mux_client_read_packet(int fd, struct sshbuf *m) { return mux_client_read_packet_timeout(fd, m, -1); } static int mux_client_hello_exchange(int fd, int timeout_ms) { struct sshbuf *m; u_int type, ver; int r, ret = -1; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_u32(m, MUX_MSG_HELLO)) != 0 || (r = sshbuf_put_u32(m, SSHMUX_VER)) != 0) fatal_fr(r, "assemble hello"); /* no extensions */ if (mux_client_write_packet(fd, m) != 0) { debug_f("write packet: %s", strerror(errno)); goto out; } sshbuf_reset(m); /* Read their HELLO */ if (mux_client_read_packet_timeout(fd, m, timeout_ms) != 0) { debug_f("read packet failed"); goto out; } if ((r = sshbuf_get_u32(m, &type)) != 0) fatal_fr(r, "parse type"); if (type != MUX_MSG_HELLO) { error_f("expected HELLO (%u) got %u", MUX_MSG_HELLO, type); goto out; } if ((r = sshbuf_get_u32(m, &ver)) != 0) fatal_fr(r, "parse version"); if (ver != SSHMUX_VER) { error("Unsupported multiplexing protocol version %d " "(expected %d)", ver, SSHMUX_VER); goto out; } 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_fr(r, "parse extension"); goto out; } debug2("Unrecognised master extension \"%s\"", name); free(name); } /* success */ ret = 0; out: sshbuf_free(m); return ret; } static u_int mux_client_request_alive(int fd) { struct sshbuf *m; char *e; u_int pid, type, rid; int r; debug3_f("entering"); if ((m = sshbuf_new()) == NULL) 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_fr(r, "assemble"); if (mux_client_write_packet(fd, m) != 0) fatal_f("write packet: %s", strerror(errno)); sshbuf_reset(m); /* Read their reply */ if (mux_client_read_packet(fd, m) != 0) { sshbuf_free(m); return 0; } if ((r = sshbuf_get_u32(m, &type)) != 0) fatal_fr(r, "parse type"); if (type != MUX_S_ALIVE) { if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); fatal_f("master returned error: %s", e); } if ((r = sshbuf_get_u32(m, &rid)) != 0) fatal_fr(r, "parse remote ID"); if (rid != muxclient_request_id) fatal_f("out of sequence reply: my id %u theirs %u", muxclient_request_id, rid); if ((r = sshbuf_get_u32(m, &pid)) != 0) fatal_fr(r, "parse PID"); sshbuf_free(m); debug3_f("done pid = %u", pid); muxclient_request_id++; return pid; } static void mux_client_request_terminate(int fd) { struct sshbuf *m; char *e; u_int type, rid; int r; debug3_f("entering"); if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_u32(m, MUX_C_TERMINATE)) != 0 || (r = sshbuf_put_u32(m, muxclient_request_id)) != 0) fatal_fr(r, "request"); if (mux_client_write_packet(fd, m) != 0) fatal_f("write packet: %s", strerror(errno)); sshbuf_reset(m); /* Read their reply */ if (mux_client_read_packet(fd, m) != 0) { /* Remote end exited already */ if (errno == EPIPE) { sshbuf_free(m); return; } fatal_f("read from master failed: %s", strerror(errno)); } if ((r = sshbuf_get_u32(m, &type)) != 0 || (r = sshbuf_get_u32(m, &rid)) != 0) fatal_fr(r, "parse"); if (rid != muxclient_request_id) 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_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_fr(r, "parse error message"); fatal_f("termination request failed: %s", e); default: fatal_f("unexpected response from master 0x%08x", type); } sshbuf_free(m); muxclient_request_id++; } static int mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd) { struct sshbuf *m; char *e, *fwd_desc; const char *lhost, *chost; u_int type, rid; int r; fwd_desc = format_forward(ftype, fwd); debug("Requesting %s %s", cancel_flag ? "cancellation of" : "forwarding of", fwd_desc); free(fwd_desc); type = cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD; if (fwd->listen_path != NULL) lhost = fwd->listen_path; else if (fwd->listen_host == NULL) lhost = ""; else if (*fwd->listen_host == '\0') lhost = "*"; else lhost = fwd->listen_host; if (fwd->connect_path != NULL) chost = fwd->connect_path; else if (fwd->connect_host == NULL) chost = ""; else chost = fwd->connect_host; if ((m = sshbuf_new()) == NULL) fatal_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 || (r = sshbuf_put_cstring(m, lhost)) != 0 || (r = sshbuf_put_u32(m, fwd->listen_port)) != 0 || (r = sshbuf_put_cstring(m, chost)) != 0 || (r = sshbuf_put_u32(m, fwd->connect_port)) != 0) fatal_fr(r, "request"); if (mux_client_write_packet(fd, m) != 0) fatal_f("write packet: %s", strerror(errno)); sshbuf_reset(m); /* Read their reply */ if (mux_client_read_packet(fd, m) != 0) { sshbuf_free(m); return -1; } if ((r = sshbuf_get_u32(m, &type)) != 0 || (r = sshbuf_get_u32(m, &rid)) != 0) fatal_fr(r, "parse"); if (rid != muxclient_request_id) 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_f("got MUX_S_REMOTE_PORT for cancel"); if ((r = sshbuf_get_u32(m, &fwd->allocated_port)) != 0) fatal_fr(r, "parse port"); verbose("Allocated port %u for remote forward to %s:%d", fwd->allocated_port, fwd->connect_host ? fwd->connect_host : "", fwd->connect_port); if (muxclient_command == SSHMUX_COMMAND_FORWARD) fprintf(stdout, "%i\n", fwd->allocated_port); break; case MUX_S_PERMISSION_DENIED: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_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_fr(r, "parse error message"); sshbuf_free(m); error_f("forwarding request failed: %s", e); return -1; default: fatal_f("unexpected response from master 0x%08x", type); } sshbuf_free(m); muxclient_request_id++; return 0; } static int mux_client_forwards(int fd, int cancel_flag) { int i, ret = 0; debug3_f("%s forwardings: %d local, %d remote", cancel_flag ? "cancel" : "request", options.num_local_forwards, options.num_remote_forwards); /* XXX ExitOnForwardingFailure */ for (i = 0; i < options.num_local_forwards; i++) { if (mux_client_forward(fd, cancel_flag, options.local_forwards[i].connect_port == 0 ? MUX_FWD_DYNAMIC : MUX_FWD_LOCAL, options.local_forwards + i) != 0) ret = -1; } for (i = 0; i < options.num_remote_forwards; i++) { if (mux_client_forward(fd, cancel_flag, MUX_FWD_REMOTE, options.remote_forwards + i) != 0) ret = -1; } return ret; } static int mux_client_request_session(int fd) { struct sshbuf *m; char *e; const char *term = NULL; u_int i, echar, rid, sid, esid, exitval, type, exitval_seen; extern char **environ; int r, rawmode = 0; debug3_f("entering"); if ((muxserver_pid = mux_client_request_alive(fd)) == 0) { error_f("master alive request failed"); return -1; } ssh_signal(SIGPIPE, SIG_IGN); if (options.stdin_null && stdfd_devnull(1, 0, 0) == -1) fatal_f("stdfd_devnull failed"); if ((term = lookup_env_in_list("TERM", options.setenv, options.num_setenv)) == NULL || *term == '\0') term = getenv("TERM"); echar = 0xffffffff; if (options.escape_char != SSH_ESCAPECHAR_NONE) echar = (u_int)options.escape_char; if ((m = sshbuf_new()) == NULL) 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 */ (r = sshbuf_put_u32(m, tty_flag)) != 0 || (r = sshbuf_put_u32(m, options.forward_x11)) != 0 || (r = sshbuf_put_u32(m, options.forward_agent)) != 0 || (r = sshbuf_put_u32(m, options.session_type == SESSION_TYPE_SUBSYSTEM)) != 0 || (r = sshbuf_put_u32(m, echar)) != 0 || (r = sshbuf_put_cstring(m, term == NULL ? "" : term)) != 0 || (r = sshbuf_put_stringb(m, command)) != 0) fatal_fr(r, "request"); /* Pass environment */ if (options.num_send_env > 0 && environ != NULL) { for (i = 0; environ[i] != NULL; i++) { if (!env_permitted(environ[i])) continue; if ((r = sshbuf_put_cstring(m, environ[i])) != 0) fatal_fr(r, "request sendenv"); } } for (i = 0; i < options.num_setenv; i++) { if ((r = sshbuf_put_cstring(m, options.setenv[i])) != 0) fatal_fr(r, "request setenv"); } if (mux_client_write_packet(fd, m) != 0) 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_f("send fds failed"); debug3_f("session request sent"); /* Read their reply */ sshbuf_reset(m); if (mux_client_read_packet(fd, m) != 0) { 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_fr(r, "parse"); if (rid != muxclient_request_id) 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_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_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_fr(r, "parse error message"); error_f("session request failed: %s", e); sshbuf_free(m); return -1; default: sshbuf_free(m); error_f("unexpected response from master 0x%08x", type); return -1; } muxclient_request_id++; if (pledge("stdio proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); platform_pledge_mux(); ssh_signal(SIGHUP, control_client_sighandler); ssh_signal(SIGINT, control_client_sighandler); ssh_signal(SIGTERM, control_client_sighandler); ssh_signal(SIGWINCH, control_client_sigrelay); if (options.fork_after_authentication) daemon(1, 1); else { rawmode = tty_flag; if (tty_flag) { enter_raw_mode( options.request_tty == REQUEST_TTY_FORCE); } } /* * Stick around until the controlee closes the client_fd. * Before it does, it is expected to write an exit message. * This process must read the value and wait for the closure of * the client_fd; if this one closes early, the multiplex master will * terminate early too (possibly losing data). */ for (exitval = 255, exitval_seen = 0;;) { sshbuf_reset(m); if (mux_client_read_packet(fd, m) != 0) break; if ((r = sshbuf_get_u32(m, &type)) != 0) fatal_fr(r, "parse type"); switch (type) { case MUX_S_TTY_ALLOC_FAIL: if ((r = sshbuf_get_u32(m, &esid)) != 0) fatal_fr(r, "parse session ID"); if (esid != sid) 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_fr(r, "parse session ID"); if (esid != sid) fatal_f("exit on unknown session: " "my id %u theirs %u", sid, esid); if (exitval_seen) fatal_f("exitval sent twice"); if ((r = sshbuf_get_u32(m, &exitval)) != 0) fatal_fr(r, "parse exitval"); exitval_seen = 1; continue; default: if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0) fatal_fr(r, "parse error message"); fatal_f("master returned error: %s", e); } } close(fd); if (rawmode) leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); if (muxclient_terminate) { debug2("Exiting on signal: %s", strsignal(muxclient_terminate)); exitval = 255; } else if (!exitval_seen) { debug2("Control master terminated unexpectedly"); exitval = 255; } else debug2("Received exit status from master %d", exitval); if (tty_flag && options.log_level >= SYSLOG_LEVEL_INFO) fprintf(stderr, "Shared connection to %s closed.\r\n", host); exit(exitval); } static int mux_client_proxy(int fd) { struct sshbuf *m; char *e; u_int type, rid; int r; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_put_u32(m, MUX_C_PROXY)) != 0 || (r = sshbuf_put_u32(m, muxclient_request_id)) != 0) fatal_fr(r, "request"); if (mux_client_write_packet(fd, m) != 0) fatal_f("write packet: %s", strerror(errno)); sshbuf_reset(m); /* Read their reply */ if (mux_client_read_packet(fd, m) != 0) { sshbuf_free(m); return 0; } if ((r = sshbuf_get_u32(m, &type)) != 0 || (r = sshbuf_get_u32(m, &rid)) != 0) fatal_fr(r, "parse"); if (rid != muxclient_request_id) 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_fr(r, "parse error message"); fatal_f("master returned error: %s", e); } sshbuf_free(m); debug3_f("done"); muxclient_request_id++; return 0; } static int mux_client_request_stdio_fwd(int fd) { struct sshbuf *m; char *e; u_int type, rid, sid; int r; debug3_f("entering"); if ((muxserver_pid = mux_client_request_alive(fd)) == 0) { error_f("master alive request failed"); return -1; } ssh_signal(SIGPIPE, SIG_IGN); if (options.stdin_null && stdfd_devnull(1, 0, 0) == -1) fatal_f("stdfd_devnull failed"); if ((m = sshbuf_new()) == NULL) 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_fr(r, "request"); if (mux_client_write_packet(fd, m) != 0) 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_f("send fds failed"); if (pledge("stdio proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); platform_pledge_mux(); debug3_f("stdio forward request sent"); /* Read their reply */ sshbuf_reset(m); if (mux_client_read_packet(fd, m) != 0) { 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_fr(r, "parse"); if (rid != muxclient_request_id) 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_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_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_fr(r, "parse error message"); sshbuf_free(m); fatal("Stdio forwarding request failed: %s", e); default: sshbuf_free(m); error_f("unexpected response from master 0x%08x", type); return -1; } muxclient_request_id++; 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. */ sshbuf_reset(m); if (mux_client_read_packet(fd, m) != 0) { if (errno == EPIPE || (errno == EINTR && muxclient_terminate != 0)) return 0; fatal_f("mux_client_read_packet: %s", strerror(errno)); } fatal_f("master returned unexpected message %u", type); } static void mux_client_request_stop_listening(int fd) { struct sshbuf *m; char *e; u_int type, rid; int r; debug3_f("entering"); if ((m = sshbuf_new()) == NULL) 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_fr(r, "request"); if (mux_client_write_packet(fd, m) != 0) fatal_f("write packet: %s", strerror(errno)); sshbuf_reset(m); /* Read their reply */ if (mux_client_read_packet(fd, m) != 0) 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_fr(r, "parse"); if (rid != muxclient_request_id) 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_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_fr(r, "parse error message"); fatal_f("stop listening request failed: %s", e); default: fatal_f("unexpected response from master 0x%08x", type); } sshbuf_free(m); muxclient_request_id++; } /* Multiplex client main loop. */ int muxclient(const char *path) { struct sockaddr_un addr; int sock, timeout = options.connection_timeout, timeout_ms = -1; u_int pid; if (muxclient_command == 0) { if (options.stdio_forward_host != NULL) muxclient_command = SSHMUX_COMMAND_STDIO_FWD; else muxclient_command = SSHMUX_COMMAND_OPEN; } switch (options.control_master) { case SSHCTL_MASTER_AUTO: case SSHCTL_MASTER_AUTO_ASK: - debug("auto-mux: Trying existing master"); + debug("auto-mux: Trying existing master at '%s'", path); /* FALLTHROUGH */ case SSHCTL_MASTER_NO: break; default: return -1; } memset(&addr, '\0', sizeof(addr)); addr.sun_family = AF_UNIX; if (strlcpy(addr.sun_path, path, sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) fatal("ControlPath too long ('%s' >= %u bytes)", path, (unsigned int)sizeof(addr.sun_path)); if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) fatal_f("socket(): %s", strerror(errno)); if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { switch (muxclient_command) { case SSHMUX_COMMAND_OPEN: case SSHMUX_COMMAND_STDIO_FWD: break; default: fatal("Control socket connect(%.100s): %s", path, strerror(errno)); } if (errno == ECONNREFUSED && options.control_master != SSHCTL_MASTER_NO) { debug("Stale control socket %.100s, unlinking", path); unlink(path); } else if (errno == ENOENT) { debug("Control socket \"%.100s\" does not exist", path); } else { error("Control socket connect(%.100s): %s", path, strerror(errno)); } close(sock); return -1; } set_nonblock(sock); /* Timeout on initial connection only. */ if (timeout > 0 && timeout < INT_MAX / 1000) timeout_ms = timeout * 1000; if (mux_client_hello_exchange(sock, timeout_ms) != 0) { error_f("master hello exchange failed"); close(sock); return -1; } switch (muxclient_command) { case SSHMUX_COMMAND_ALIVE_CHECK: if ((pid = mux_client_request_alive(sock)) == 0) fatal_f("master alive check failed"); fprintf(stderr, "Master running (pid=%u)\r\n", pid); exit(0); case SSHMUX_COMMAND_TERMINATE: mux_client_request_terminate(sock); if (options.log_level != SYSLOG_LEVEL_QUIET) fprintf(stderr, "Exit request sent.\r\n"); exit(0); case SSHMUX_COMMAND_FORWARD: if (mux_client_forwards(sock, 0) != 0) fatal_f("master forward request failed"); exit(0); case SSHMUX_COMMAND_OPEN: if (mux_client_forwards(sock, 0) != 0) { error_f("master forward request failed"); return -1; } mux_client_request_session(sock); return -1; case SSHMUX_COMMAND_STDIO_FWD: mux_client_request_stdio_fwd(sock); exit(0); case SSHMUX_COMMAND_STOP: mux_client_request_stop_listening(sock); if (options.log_level != SYSLOG_LEVEL_QUIET) fprintf(stderr, "Stop listening request sent.\r\n"); exit(0); case SSHMUX_COMMAND_CANCEL_FWD: if (mux_client_forwards(sock, 1) != 0) error_f("master cancel forward request failed"); exit(0); case SSHMUX_COMMAND_PROXY: mux_client_proxy(sock); return (sock); default: fatal("unrecognised muxclient_command %d", muxclient_command); } } diff --git a/crypto/openssh/openbsd-compat/port-solaris.c b/crypto/openssh/openbsd-compat/port-solaris.c index 10c2d6b7fa5a..05aa1f76b829 100644 --- a/crypto/openssh/openbsd-compat/port-solaris.c +++ b/crypto/openssh/openbsd-compat/port-solaris.c @@ -1,360 +1,382 @@ /* * Copyright (c) 2006 Chad Mynhier. * * 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 "config.h" #include "includes.h" #include #include #include #ifdef HAVE_FCNTL_H # include #endif #include #include #include #include "log.h" #ifdef USE_SOLARIS_PROCESS_CONTRACTS #include #include #include #define CT_TEMPLATE CTFS_ROOT "/process/template" #define CT_LATEST CTFS_ROOT "/process/latest" static int tmpl_fd = -1; /* Lookup the latest process contract */ static ctid_t get_active_process_contract_id(void) { int stat_fd; ctid_t ctid = -1; ct_stathdl_t stathdl; if ((stat_fd = open64(CT_LATEST, O_RDONLY)) == -1) { error("%s: Error opening 'latest' process " "contract: %s", __func__, strerror(errno)); return -1; } if (ct_status_read(stat_fd, CTD_COMMON, &stathdl) != 0) { error("%s: Error reading process contract " "status: %s", __func__, strerror(errno)); goto out; } if ((ctid = ct_status_get_id(stathdl)) < 0) { error("%s: Error getting process contract id: %s", __func__, strerror(errno)); goto out; } ct_status_free(stathdl); out: close(stat_fd); return ctid; } void solaris_contract_pre_fork(void) { if ((tmpl_fd = open64(CT_TEMPLATE, O_RDWR)) == -1) { error("%s: open %s: %s", __func__, CT_TEMPLATE, strerror(errno)); return; } debug2("%s: setting up process contract template on fd %d", __func__, tmpl_fd); /* First we set the template parameters and event sets. */ if (ct_pr_tmpl_set_param(tmpl_fd, CT_PR_PGRPONLY) != 0) { error("%s: Error setting process contract parameter set " "(pgrponly): %s", __func__, strerror(errno)); goto fail; } if (ct_pr_tmpl_set_fatal(tmpl_fd, CT_PR_EV_HWERR) != 0) { error("%s: Error setting process contract template " "fatal events: %s", __func__, strerror(errno)); goto fail; } if (ct_tmpl_set_critical(tmpl_fd, 0) != 0) { error("%s: Error setting process contract template " "critical events: %s", __func__, strerror(errno)); goto fail; } if (ct_tmpl_set_informative(tmpl_fd, CT_PR_EV_HWERR) != 0) { error("%s: Error setting process contract template " "informative events: %s", __func__, strerror(errno)); goto fail; } /* Now make this the active template for this process. */ if (ct_tmpl_activate(tmpl_fd) != 0) { error("%s: Error activating process contract " "template: %s", __func__, strerror(errno)); goto fail; } return; fail: if (tmpl_fd != -1) { close(tmpl_fd); tmpl_fd = -1; } } void solaris_contract_post_fork_child() { debug2("%s: clearing process contract template on fd %d", __func__, tmpl_fd); /* Clear the active template. */ if (ct_tmpl_clear(tmpl_fd) != 0) error("%s: Error clearing active process contract " "template: %s", __func__, strerror(errno)); close(tmpl_fd); tmpl_fd = -1; } void solaris_contract_post_fork_parent(pid_t pid) { ctid_t ctid; char ctl_path[256]; int r, ctl_fd = -1, stat_fd = -1; debug2("%s: clearing template (fd %d)", __func__, tmpl_fd); if (tmpl_fd == -1) return; /* First clear the active template. */ if ((r = ct_tmpl_clear(tmpl_fd)) != 0) error("%s: Error clearing active process contract " "template: %s", __func__, strerror(errno)); close(tmpl_fd); tmpl_fd = -1; /* * If either the fork didn't succeed (pid < 0), or clearing * th active contract failed (r != 0), then we have nothing * more do. */ if (r != 0 || pid <= 0) return; /* Now lookup and abandon the contract we've created. */ ctid = get_active_process_contract_id(); debug2("%s: abandoning contract id %ld", __func__, ctid); snprintf(ctl_path, sizeof(ctl_path), CTFS_ROOT "/process/%ld/ctl", ctid); if ((ctl_fd = open64(ctl_path, O_WRONLY)) < 0) { error("%s: Error opening process contract " "ctl file: %s", __func__, strerror(errno)); goto fail; } if (ct_ctl_abandon(ctl_fd) < 0) { error("%s: Error abandoning process contract: %s", __func__, strerror(errno)); goto fail; } close(ctl_fd); return; fail: if (tmpl_fd != -1) { close(tmpl_fd); tmpl_fd = -1; } if (stat_fd != -1) close(stat_fd); if (ctl_fd != -1) close(ctl_fd); } #endif #ifdef USE_SOLARIS_PROJECTS #include #include /* * Get/set solaris default project. * If we fail, just run along gracefully. */ void solaris_set_default_project(struct passwd *pw) { struct project *defaultproject; struct project tempproject; char buf[1024]; /* get default project, if we fail just return gracefully */ if ((defaultproject = getdefaultproj(pw->pw_name, &tempproject, &buf, sizeof(buf))) != NULL) { /* set default project */ if (setproject(defaultproject->pj_name, pw->pw_name, TASK_NORMAL) != 0) debug("setproject(%s): %s", defaultproject->pj_name, strerror(errno)); } else { /* debug on getdefaultproj() error */ debug("getdefaultproj(%s): %s", pw->pw_name, strerror(errno)); } } #endif /* USE_SOLARIS_PROJECTS */ #ifdef USE_SOLARIS_PRIVS # ifdef HAVE_PRIV_H # include # endif priv_set_t * solaris_basic_privset(void) { priv_set_t *pset; #ifdef HAVE_PRIV_BASICSET if ((pset = priv_allocset()) == NULL) { error("priv_allocset: %s", strerror(errno)); return NULL; } priv_basicset(pset); #else if ((pset = priv_str_to_set("basic", ",", NULL)) == NULL) { error("priv_str_to_set: %s", strerror(errno)); return NULL; } #endif return pset; } void solaris_drop_privs_pinfo_net_fork_exec(void) { priv_set_t *pset = NULL, *npset = NULL; /* * Note: this variant avoids dropping DAC filesystem rights, in case * the process calling it is running as root and should have the * ability to read/write/chown any file on the system. * * We start with the basic set, then *add* the DAC rights to it while * taking away other parts of BASIC we don't need. Then we intersect * this with our existing PERMITTED set. In this way we keep any * DAC rights we had before, while otherwise reducing ourselves to * the minimum set of privileges we need to proceed. * * This also means we drop any other parts of "root" that we don't * need (e.g. the ability to kill any process, create new device nodes * etc etc). */ if ((pset = priv_allocset()) == NULL) fatal("priv_allocset: %s", strerror(errno)); if ((npset = solaris_basic_privset()) == NULL) fatal("solaris_basic_privset: %s", strerror(errno)); if (priv_addset(npset, PRIV_FILE_CHOWN) != 0 || priv_addset(npset, PRIV_FILE_DAC_READ) != 0 || priv_addset(npset, PRIV_FILE_DAC_SEARCH) != 0 || priv_addset(npset, PRIV_FILE_DAC_WRITE) != 0 || priv_addset(npset, PRIV_FILE_OWNER) != 0) fatal("priv_addset: %s", strerror(errno)); if (priv_delset(npset, PRIV_PROC_EXEC) != 0 || #ifdef PRIV_NET_ACCESS priv_delset(npset, PRIV_NET_ACCESS) != 0 || #endif priv_delset(npset, PRIV_PROC_FORK) != 0 || priv_delset(npset, PRIV_PROC_INFO) != 0 || priv_delset(npset, PRIV_PROC_SESSION) != 0) fatal("priv_delset: %s", strerror(errno)); +#ifdef PRIV_XPOLICY + /* + * It is possible that the user has an extended policy + * in place; the LIMIT set restricts the extended policy + * and so should not be restricted. + * PRIV_XPOLICY is newly defined in Solaris 11 though the extended + * policy was not implemented until Solaris 11.1. + */ + if (getpflags(PRIV_XPOLICY) == 1) { + if (getppriv(PRIV_LIMIT, pset) != 0) + fatal("getppriv: %s", strerror(errno)); + priv_intersect(pset, npset); + if (setppriv(PRIV_SET, PRIV_LIMIT, npset) != 0) + fatal("setppriv: %s", strerror(errno)); + } else +#endif + { + /* Cannot exec, so we can kill the limit set. */ + priv_emptyset(pset); + if (setppriv(PRIV_SET, PRIV_LIMIT, pset) != 0) + fatal("setppriv: %s", strerror(errno)); + } + if (getppriv(PRIV_PERMITTED, pset) != 0) fatal("getppriv: %s", strerror(errno)); priv_intersect(pset, npset); if (setppriv(PRIV_SET, PRIV_PERMITTED, npset) != 0 || - setppriv(PRIV_SET, PRIV_LIMIT, npset) != 0 || setppriv(PRIV_SET, PRIV_INHERITABLE, npset) != 0) fatal("setppriv: %s", strerror(errno)); priv_freeset(pset); priv_freeset(npset); } void solaris_drop_privs_root_pinfo_net(void) { priv_set_t *pset = NULL; /* Start with "basic" and drop everything we don't need. */ if ((pset = solaris_basic_privset()) == NULL) fatal("solaris_basic_privset: %s", strerror(errno)); if (priv_delset(pset, PRIV_FILE_LINK_ANY) != 0 || #ifdef PRIV_NET_ACCESS priv_delset(pset, PRIV_NET_ACCESS) != 0 || #endif priv_delset(pset, PRIV_PROC_INFO) != 0 || priv_delset(pset, PRIV_PROC_SESSION) != 0) fatal("priv_delset: %s", strerror(errno)); if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) != 0 || setppriv(PRIV_SET, PRIV_LIMIT, pset) != 0 || setppriv(PRIV_SET, PRIV_INHERITABLE, pset) != 0) fatal("setppriv: %s", strerror(errno)); priv_freeset(pset); } void solaris_drop_privs_root_pinfo_net_exec(void) { priv_set_t *pset = NULL; /* Start with "basic" and drop everything we don't need. */ if ((pset = solaris_basic_privset()) == NULL) fatal("solaris_basic_privset: %s", strerror(errno)); if (priv_delset(pset, PRIV_FILE_LINK_ANY) != 0 || #ifdef PRIV_NET_ACCESS priv_delset(pset, PRIV_NET_ACCESS) != 0 || #endif priv_delset(pset, PRIV_PROC_EXEC) != 0 || priv_delset(pset, PRIV_PROC_INFO) != 0) fatal("priv_delset: %s", strerror(errno)); if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) != 0 || setppriv(PRIV_SET, PRIV_LIMIT, pset) != 0 || setppriv(PRIV_SET, PRIV_INHERITABLE, pset) != 0) fatal("setppriv: %s", strerror(errno)); priv_freeset(pset); } #endif diff --git a/crypto/openssh/readconf.c b/crypto/openssh/readconf.c index 2ff8f68b6fb3..39e38ec88cc8 100644 --- a/crypto/openssh/readconf.c +++ b/crypto/openssh/readconf.c @@ -1,3640 +1,3687 @@ -/* $OpenBSD: readconf.c,v 1.381 2023/08/28 03:31:16 djm Exp $ */ +/* $OpenBSD: readconf.c,v 1.383 2023/10/12 02:18:18 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Functions for reading the configuration files. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_IFADDRS_H # include #endif #include #include #ifdef HAVE_PATHS_H # include #endif #include #include #include #include #include #include #ifdef USE_SYSTEM_GLOB # include #else # include "openbsd-compat/glob.h" #endif #ifdef HAVE_UTIL_H #include #endif #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) # include #endif #include "xmalloc.h" #include "ssh.h" #include "ssherr.h" #include "cipher.h" #include "pathnames.h" #include "log.h" #include "sshkey.h" #include "misc.h" #include "readconf.h" #include "match.h" #include "kex.h" #include "mac.h" #include "uidswap.h" #include "myproposal.h" #include "digest.h" /* Format of the configuration file: # Configuration data is parsed as follows: # 1. command line options # 2. user-specific file # 3. system-wide file # Any configuration value is only changed the first time it is set. # Thus, host-specific definitions should be at the beginning of the # configuration file, and defaults at the end. # Host-specific declarations. These may override anything above. A single # host may match multiple declarations; these are processed in the order # that they are given in. Host *.ngs.fi ngs.fi User foo Host fake.com Hostname another.host.name.real.org User blaah Port 34289 ForwardX11 no ForwardAgent no Host books.com RemoteForward 9999 shadows.cs.hut.fi:9999 Ciphers 3des-cbc Host fascist.blob.com Port 23123 User tylonen PasswordAuthentication no Host puukko.hut.fi User t35124p ProxyCommand ssh-proxy %h %p Host *.fr PublicKeyAuthentication no Host *.su Ciphers aes128-ctr PasswordAuthentication no Host vpn.fake.com Tunnel yes TunnelDevice 3 # Defaults for various options Host * ForwardAgent no ForwardX11 no PasswordAuthentication yes StrictHostKeyChecking yes TcpKeepAlive no IdentityFile ~/.ssh/identity Port 22 EscapeChar ~ */ static int read_config_file_depth(const char *filename, struct passwd *pw, const char *host, const char *original_host, Options *options, int flags, int *activep, int *want_final_pass, int depth); static int process_config_line_depth(Options *options, struct passwd *pw, const char *host, const char *original_host, char *line, const char *filename, int linenum, int *activep, int flags, int *want_final_pass, int depth); /* Keyword tokens. */ typedef enum { oBadOption, oHost, oMatch, oInclude, oTag, oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, oGatewayPorts, oExitOnForwardFailure, oPasswordAuthentication, oXAuthLocation, oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward, oPermitRemoteOpen, oCertificateFile, oAddKeysToAgent, oIdentityAgent, oUser, oEscapeChar, oProxyCommand, oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression, oTCPKeepAlive, oNumberOfPasswordPrompts, oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs, oPubkeyAuthentication, oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider, oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, oRemoteCommand, oVisualHostKey, oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull, oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass, oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms, oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump, oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize, - oEnableEscapeCommandline, oObscureKeystrokeTiming, + oEnableEscapeCommandline, oObscureKeystrokeTiming, oChannelTimeout, oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported } OpCodes; /* Textual representations of the tokens. */ static struct { const char *name; OpCodes opcode; } keywords[] = { /* Deprecated options */ { "protocol", oIgnore }, /* NB. silently ignored */ { "cipher", oDeprecated }, { "fallbacktorsh", oDeprecated }, { "globalknownhostsfile2", oDeprecated }, { "rhostsauthentication", oDeprecated }, { "userknownhostsfile2", oDeprecated }, { "useroaming", oDeprecated }, { "usersh", oDeprecated }, { "useprivilegedport", oDeprecated }, /* Unsupported options */ { "afstokenpassing", oUnsupported }, { "kerberosauthentication", oUnsupported }, { "kerberostgtpassing", oUnsupported }, { "rsaauthentication", oUnsupported }, { "rhostsrsaauthentication", oUnsupported }, { "compressionlevel", oUnsupported }, /* Sometimes-unsupported options */ #if defined(GSSAPI) { "gssapiauthentication", oGssAuthentication }, { "gssapidelegatecredentials", oGssDelegateCreds }, # else { "gssapiauthentication", oUnsupported }, { "gssapidelegatecredentials", oUnsupported }, #endif #ifdef ENABLE_PKCS11 { "pkcs11provider", oPKCS11Provider }, { "smartcarddevice", oPKCS11Provider }, # else { "smartcarddevice", oUnsupported }, { "pkcs11provider", oUnsupported }, #endif { "forwardagent", oForwardAgent }, { "forwardx11", oForwardX11 }, { "forwardx11trusted", oForwardX11Trusted }, { "forwardx11timeout", oForwardX11Timeout }, { "exitonforwardfailure", oExitOnForwardFailure }, { "xauthlocation", oXAuthLocation }, { "gatewayports", oGatewayPorts }, { "passwordauthentication", oPasswordAuthentication }, { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, { "kbdinteractivedevices", oKbdInteractiveDevices }, { "challengeresponseauthentication", oKbdInteractiveAuthentication }, /* alias */ { "skeyauthentication", oKbdInteractiveAuthentication }, /* alias */ { "tisauthentication", oKbdInteractiveAuthentication }, /* alias */ { "pubkeyauthentication", oPubkeyAuthentication }, { "dsaauthentication", oPubkeyAuthentication }, /* alias */ { "hostbasedauthentication", oHostbasedAuthentication }, { "identityfile", oIdentityFile }, { "identityfile2", oIdentityFile }, /* obsolete */ { "identitiesonly", oIdentitiesOnly }, { "certificatefile", oCertificateFile }, { "addkeystoagent", oAddKeysToAgent }, { "identityagent", oIdentityAgent }, { "hostname", oHostname }, { "hostkeyalias", oHostKeyAlias }, { "proxycommand", oProxyCommand }, { "port", oPort }, { "ciphers", oCiphers }, { "macs", oMacs }, { "remoteforward", oRemoteForward }, { "localforward", oLocalForward }, { "permitremoteopen", oPermitRemoteOpen }, { "user", oUser }, { "host", oHost }, { "match", oMatch }, { "tag", oTag }, { "escapechar", oEscapeChar }, { "globalknownhostsfile", oGlobalKnownHostsFile }, { "userknownhostsfile", oUserKnownHostsFile }, { "connectionattempts", oConnectionAttempts }, { "batchmode", oBatchMode }, { "checkhostip", oCheckHostIP }, { "stricthostkeychecking", oStrictHostKeyChecking }, { "compression", oCompression }, { "tcpkeepalive", oTCPKeepAlive }, { "keepalive", oTCPKeepAlive }, /* obsolete */ { "numberofpasswordprompts", oNumberOfPasswordPrompts }, { "syslogfacility", oLogFacility }, { "loglevel", oLogLevel }, { "logverbose", oLogVerbose }, { "dynamicforward", oDynamicForward }, { "preferredauthentications", oPreferredAuthentications }, { "hostkeyalgorithms", oHostKeyAlgorithms }, { "casignaturealgorithms", oCASignatureAlgorithms }, { "bindaddress", oBindAddress }, { "bindinterface", oBindInterface }, { "clearallforwardings", oClearAllForwardings }, { "enablesshkeysign", oEnableSSHKeysign }, { "verifyhostkeydns", oVerifyHostKeyDNS }, { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, { "rekeylimit", oRekeyLimit }, { "connecttimeout", oConnectTimeout }, { "addressfamily", oAddressFamily }, { "serveraliveinterval", oServerAliveInterval }, { "serveralivecountmax", oServerAliveCountMax }, { "sendenv", oSendEnv }, { "setenv", oSetEnv }, { "controlpath", oControlPath }, { "controlmaster", oControlMaster }, { "controlpersist", oControlPersist }, { "hashknownhosts", oHashKnownHosts }, { "include", oInclude }, { "tunnel", oTunnel }, { "tunneldevice", oTunnelDevice }, { "localcommand", oLocalCommand }, { "permitlocalcommand", oPermitLocalCommand }, { "remotecommand", oRemoteCommand }, { "visualhostkey", oVisualHostKey }, { "kexalgorithms", oKexAlgorithms }, { "ipqos", oIPQoS }, { "requesttty", oRequestTTY }, { "sessiontype", oSessionType }, { "stdinnull", oStdinNull }, { "forkafterauthentication", oForkAfterAuthentication }, { "proxyusefdpass", oProxyUseFdpass }, { "canonicaldomains", oCanonicalDomains }, { "canonicalizefallbacklocal", oCanonicalizeFallbackLocal }, { "canonicalizehostname", oCanonicalizeHostname }, { "canonicalizemaxdots", oCanonicalizeMaxDots }, { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, { "streamlocalbindmask", oStreamLocalBindMask }, { "streamlocalbindunlink", oStreamLocalBindUnlink }, { "revokedhostkeys", oRevokedHostKeys }, { "fingerprinthash", oFingerprintHash }, { "updatehostkeys", oUpdateHostkeys }, { "hostbasedacceptedalgorithms", oHostbasedAcceptedAlgorithms }, { "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */ { "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms }, { "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */ { "ignoreunknown", oIgnoreUnknown }, { "proxyjump", oProxyJump }, { "securitykeyprovider", oSecurityKeyProvider }, { "knownhostscommand", oKnownHostsCommand }, { "requiredrsasize", oRequiredRSASize }, { "enableescapecommandline", oEnableEscapeCommandline }, { "obscurekeystroketiming", oObscureKeystrokeTiming }, + { "channeltimeout", oChannelTimeout }, /* Client VersionAddendum - retired in bffe60ead024 */ { "versionaddendum", oDeprecated }, { 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) + const char *user, const char *jumphost) { 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_update(md, jumphost, strlen(jumphost)) < 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. */ void add_local_forward(Options *options, const struct Forward *newfwd) { struct Forward *fwd; int i; /* Don't add duplicates */ for (i = 0; i < options->num_local_forwards; i++) { if (forward_equals(newfwd, options->local_forwards + i)) return; } options->local_forwards = xreallocarray(options->local_forwards, options->num_local_forwards + 1, sizeof(*options->local_forwards)); fwd = &options->local_forwards[options->num_local_forwards++]; fwd->listen_host = newfwd->listen_host; fwd->listen_port = newfwd->listen_port; fwd->listen_path = newfwd->listen_path; fwd->connect_host = newfwd->connect_host; fwd->connect_port = newfwd->connect_port; fwd->connect_path = newfwd->connect_path; } /* * Adds a remote TCP/IP port forward to options. Never returns if there is * an error. */ void add_remote_forward(Options *options, const struct Forward *newfwd) { struct Forward *fwd; int i; /* Don't add duplicates */ for (i = 0; i < options->num_remote_forwards; i++) { if (forward_equals(newfwd, options->remote_forwards + i)) return; } options->remote_forwards = xreallocarray(options->remote_forwards, options->num_remote_forwards + 1, sizeof(*options->remote_forwards)); fwd = &options->remote_forwards[options->num_remote_forwards++]; fwd->listen_host = newfwd->listen_host; fwd->listen_port = newfwd->listen_port; fwd->listen_path = newfwd->listen_path; fwd->connect_host = newfwd->connect_host; fwd->connect_port = newfwd->connect_port; fwd->connect_path = newfwd->connect_path; fwd->handle = newfwd->handle; fwd->allocated_port = 0; } static void clear_forwardings(Options *options) { int i; for (i = 0; i < options->num_local_forwards; i++) { free(options->local_forwards[i].listen_host); free(options->local_forwards[i].listen_path); free(options->local_forwards[i].connect_host); free(options->local_forwards[i].connect_path); } if (options->num_local_forwards > 0) { free(options->local_forwards); options->local_forwards = NULL; } options->num_local_forwards = 0; for (i = 0; i < options->num_remote_forwards; i++) { free(options->remote_forwards[i].listen_host); free(options->remote_forwards[i].listen_path); free(options->remote_forwards[i].connect_host); free(options->remote_forwards[i].connect_path); } if (options->num_remote_forwards > 0) { free(options->remote_forwards); options->remote_forwards = NULL; } options->num_remote_forwards = 0; options->tun_open = SSH_TUNMODE_NO; } void add_certificate_file(Options *options, const char *path, int userprovided) { int i; if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES) fatal("Too many certificate files specified (max %d)", SSH_MAX_CERTIFICATE_FILES); /* Avoid registering duplicates */ for (i = 0; i < options->num_certificate_files; i++) { if (options->certificate_file_userprovided[i] == userprovided && strcmp(options->certificate_files[i], path) == 0) { debug2_f("ignoring duplicate key %s", path); return; } } options->certificate_file_userprovided[options->num_certificate_files] = userprovided; options->certificate_files[options->num_certificate_files++] = xstrdup(path); } void add_identity_file(Options *options, const char *dir, const char *filename, int userprovided) { char *path; int i; if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) fatal("Too many identity files specified (max %d)", SSH_MAX_IDENTITY_FILES); if (dir == NULL) /* no dir, filename is absolute */ path = xstrdup(filename); else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX) fatal("Identity file path %s too long", path); /* Avoid registering duplicates */ for (i = 0; i < options->num_identity_files; i++) { if (options->identity_file_userprovided[i] == userprovided && strcmp(options->identity_files[i], path) == 0) { debug2_f("ignoring duplicate key %s", path); free(path); return; } } options->identity_file_userprovided[options->num_identity_files] = userprovided; options->identity_files[options->num_identity_files++] = path; } int default_ssh_port(void) { static int port; struct servent *sp; if (port == 0) { sp = getservbyname(SSH_SERVICE_NAME, "tcp"); port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT; } return port; } /* * Execute a command in a shell. * Return its exit status or -1 on abnormal exit. */ static int execute_in_shell(const char *cmd) { char *shell; pid_t pid; int status; if ((shell = getenv("SHELL")) == NULL) shell = _PATH_BSHELL; if (access(shell, X_OK) == -1) { fatal("Shell \"%s\" is not executable: %s", shell, strerror(errno)); } debug("Executing command: '%.500s'", cmd); /* Fork and execute the command. */ if ((pid = fork()) == 0) { char *argv[4]; if (stdfd_devnull(1, 1, 0) == -1) fatal_f("stdfd_devnull failed"); closefrom(STDERR_FILENO + 1); argv[0] = shell; argv[1] = "-c"; argv[2] = xstrdup(cmd); argv[3] = NULL; execv(argv[0], argv); error("Unable to execute '%.100s': %s", cmd, strerror(errno)); /* Die with signal to make this error apparent to parent. */ ssh_signal(SIGTERM, SIG_DFL); kill(getpid(), SIGTERM); _exit(1); } /* Parent. */ if (pid == -1) fatal_f("fork: %.100s", strerror(errno)); while (waitpid(pid, &status, 0) == -1) { if (errno != EINTR && errno != EAGAIN) fatal_f("waitpid: %s", strerror(errno)); } if (!WIFEXITED(status)) { error("command '%.100s' exited abnormally", cmd); return -1; } debug3("command returned status %d", WEXITSTATUS(status)); return WEXITSTATUS(status); } /* * Check whether a local network interface address appears in CIDR pattern- * list 'addrlist'. Returns 1 if matched or 0 otherwise. */ static int check_match_ifaddrs(const char *addrlist) { #ifdef HAVE_IFADDRS_H struct ifaddrs *ifa, *ifaddrs = NULL; int r, found = 0; char addr[NI_MAXHOST]; socklen_t salen; if (getifaddrs(&ifaddrs) != 0) { error("match localnetwork: getifaddrs failed: %s", strerror(errno)); return 0; } for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL || (ifa->ifa_flags & IFF_UP) == 0) continue; switch (ifa->ifa_addr->sa_family) { case AF_INET: salen = sizeof(struct sockaddr_in); break; case AF_INET6: salen = sizeof(struct sockaddr_in6); break; #ifdef AF_LINK case AF_LINK: /* ignore */ continue; #endif /* AF_LINK */ default: debug2_f("interface %s: unsupported address family %d", ifa->ifa_name, ifa->ifa_addr->sa_family); continue; } if ((r = getnameinfo(ifa->ifa_addr, salen, addr, sizeof(addr), NULL, 0, NI_NUMERICHOST)) != 0) { debug2_f("interface %s getnameinfo failed: %s", ifa->ifa_name, gai_strerror(r)); continue; } debug3_f("interface %s addr %s", ifa->ifa_name, addr); if (addr_match_cidr_list(addr, addrlist) == 1) { debug3_f("matched interface %s: address %s in %s", ifa->ifa_name, addr, addrlist); found = 1; break; } } freeifaddrs(ifaddrs); return found; #else /* HAVE_IFADDRS_H */ error("match localnetwork: not supported on this platform"); return 0; #endif /* HAVE_IFADDRS_H */ } /* * Parse and execute a Match directive. */ static int match_cfg_line(Options *options, char **condition, struct passwd *pw, const char *host_arg, const char *original_host, int final_pass, int *want_final_pass, const char *filename, int linenum) { char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria; const char *ruser; int r, port, this_result, result = 1, attributes = 0, negate; char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; char uidstr[32]; /* * Configuration is likely to be incomplete at this point so we * must be prepared to use default values. */ port = options->port <= 0 ? default_ssh_port() : options->port; ruser = options->user == NULL ? pw->pw_name : options->user; if (final_pass) { host = xstrdup(options->hostname); } else if (options->hostname != NULL) { /* NB. Please keep in sync with ssh.c:main() */ host = percent_expand(options->hostname, "h", host_arg, (char *)NULL); } else { host = xstrdup(host_arg); } debug2("checking match for '%s' host %s originally %s", cp, host, original_host); while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') { /* Terminate on comment */ if (*attrib == '#') { cp = NULL; /* mark all arguments consumed */ break; } arg = criteria = NULL; this_result = 1; if ((negate = (attrib[0] == '!'))) attrib++; /* Criterion "all" has no argument and must appear alone */ if (strcasecmp(attrib, "all") == 0) { if (attributes > 1 || ((arg = strdelim(&cp)) != NULL && *arg != '\0' && *arg != '#')) { error("%.200s line %d: '%s' cannot be combined " "with other Match attributes", filename, linenum, oattrib); result = -1; goto out; } if (arg != NULL && *arg == '#') cp = NULL; /* mark all arguments consumed */ if (result) result = negate ? 0 : 1; goto out; } attributes++; /* criteria "final" and "canonical" have no argument */ if (strcasecmp(attrib, "canonical") == 0 || strcasecmp(attrib, "final") == 0) { /* * If the config requests "Match final" then remember * this so we can perform a second pass later. */ if (strcasecmp(attrib, "final") == 0 && want_final_pass != NULL) *want_final_pass = 1; r = !!final_pass; /* force bitmask member to boolean */ if (r == (negate ? 1 : 0)) this_result = result = 0; debug3("%.200s line %d: %smatched '%s'", filename, linenum, this_result ? "" : "not ", oattrib); continue; } /* All other criteria require an argument */ if ((arg = strdelim(&cp)) == NULL || *arg == '\0' || *arg == '#') { error("Missing Match criteria for %s", attrib); result = -1; goto out; } if (strcasecmp(attrib, "host") == 0) { criteria = xstrdup(host); r = match_hostname(host, arg) == 1; if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "originalhost") == 0) { criteria = xstrdup(original_host); r = match_hostname(original_host, arg) == 1; if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "user") == 0) { criteria = xstrdup(ruser); r = match_pattern_list(ruser, arg, 0) == 1; if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "localuser") == 0) { criteria = xstrdup(pw->pw_name); r = match_pattern_list(pw->pw_name, arg, 0) == 1; if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "localnetwork") == 0) { if (addr_match_cidr_list(NULL, arg) == -1) { /* Error already printed */ result = -1; goto out; } r = check_match_ifaddrs(arg) == 1; if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "tagged") == 0) { criteria = xstrdup(options->tag == NULL ? "" : options->tag); r = match_pattern_list(criteria, arg, 0) == 1; if (r == (negate ? 1 : 0)) this_result = result = 0; } else if (strcasecmp(attrib, "exec") == 0) { - char *conn_hash_hex, *keyalias; + char *conn_hash_hex, *keyalias, *jmphost; if (gethostname(thishost, sizeof(thishost)) == -1) fatal("gethostname: %s", strerror(errno)); + jmphost = option_clear_or_none(options->jump_host) ? + "" : options->jump_host; strlcpy(shorthost, thishost, sizeof(shorthost)); shorthost[strcspn(thishost, ".")] = '\0'; snprintf(portstr, sizeof(portstr), "%d", port); snprintf(uidstr, sizeof(uidstr), "%llu", (unsigned long long)pw->pw_uid); conn_hash_hex = ssh_connection_hash(thishost, host, - portstr, ruser); + portstr, ruser, jmphost); 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, "r", ruser, "u", pw->pw_name, "i", uidstr, + "j", jmphost, (char *)NULL); free(conn_hash_hex); if (result != 1) { /* skip execution if prior predicate failed */ debug3("%.200s line %d: skipped exec " "\"%.100s\"", filename, linenum, cmd); free(cmd); continue; } r = execute_in_shell(cmd); if (r == -1) { fatal("%.200s line %d: match exec " "'%.100s' error", filename, linenum, cmd); } criteria = xstrdup(cmd); free(cmd); /* Force exit status to boolean */ r = r == 0; if (r == (negate ? 1 : 0)) this_result = result = 0; } else { error("Unsupported Match attribute %s", attrib); result = -1; goto out; } debug3("%.200s line %d: %smatched '%s%s%.100s%s' ", filename, linenum, this_result ? "": "not ", oattrib, criteria == NULL ? "" : " \"", criteria == NULL ? "" : criteria, criteria == NULL ? "" : "\""); free(criteria); } if (attributes == 0) { error("One or more attributes required for Match"); result = -1; goto out; } out: if (result != -1) debug2("match %sfound", result ? "" : "not "); *condition = cp; free(host); return result; } /* Remove environment variable by pattern */ static void rm_env(Options *options, const char *arg, const char *filename, int linenum) { u_int i, j, onum_send_env = options->num_send_env; /* Remove an environment variable */ for (i = 0; i < options->num_send_env; ) { if (!match_pattern(options->send_env[i], arg + 1)) { i++; continue; } debug3("%s line %d: removing environment %s", filename, linenum, options->send_env[i]); free(options->send_env[i]); options->send_env[i] = NULL; for (j = i; j < options->num_send_env - 1; j++) { options->send_env[j] = options->send_env[j + 1]; options->send_env[j + 1] = NULL; } options->num_send_env--; /* NB. don't increment i */ } 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)); } } /* * Returns the number of the token pointed to by cp or oBadOption. */ static OpCodes parse_token(const char *cp, const char *filename, int linenum, const char *ignored_unknown) { int i; for (i = 0; keywords[i].name; i++) if (strcmp(cp, keywords[i].name) == 0) return keywords[i].opcode; if (ignored_unknown != NULL && match_pattern_list(cp, ignored_unknown, 1) == 1) return oIgnoredUnknownOption; error("%s: line %d: Bad configuration option: %s", filename, linenum, cp); return oBadOption; } /* Multistate option parsing */ struct multistate { char *key; int value; }; static const struct multistate multistate_flag[] = { { "true", 1 }, { "false", 0 }, { "yes", 1 }, { "no", 0 }, { NULL, -1 } }; static const struct multistate multistate_yesnoask[] = { { "true", 1 }, { "false", 0 }, { "yes", 1 }, { "no", 0 }, { "ask", 2 }, { NULL, -1 } }; static const struct multistate multistate_strict_hostkey[] = { { "true", SSH_STRICT_HOSTKEY_YES }, { "false", SSH_STRICT_HOSTKEY_OFF }, { "yes", SSH_STRICT_HOSTKEY_YES }, { "no", SSH_STRICT_HOSTKEY_OFF }, { "ask", SSH_STRICT_HOSTKEY_ASK }, { "off", SSH_STRICT_HOSTKEY_OFF }, { "accept-new", SSH_STRICT_HOSTKEY_NEW }, { NULL, -1 } }; static const struct multistate multistate_yesnoaskconfirm[] = { { "true", 1 }, { "false", 0 }, { "yes", 1 }, { "no", 0 }, { "ask", 2 }, { "confirm", 3 }, { NULL, -1 } }; static const struct multistate multistate_addressfamily[] = { { "inet", AF_INET }, { "inet6", AF_INET6 }, { "any", AF_UNSPEC }, { NULL, -1 } }; static const struct multistate multistate_controlmaster[] = { { "true", SSHCTL_MASTER_YES }, { "yes", SSHCTL_MASTER_YES }, { "false", SSHCTL_MASTER_NO }, { "no", SSHCTL_MASTER_NO }, { "auto", SSHCTL_MASTER_AUTO }, { "ask", SSHCTL_MASTER_ASK }, { "autoask", SSHCTL_MASTER_AUTO_ASK }, { NULL, -1 } }; static const struct multistate multistate_tunnel[] = { { "ethernet", SSH_TUNMODE_ETHERNET }, { "point-to-point", SSH_TUNMODE_POINTOPOINT }, { "true", SSH_TUNMODE_DEFAULT }, { "yes", SSH_TUNMODE_DEFAULT }, { "false", SSH_TUNMODE_NO }, { "no", SSH_TUNMODE_NO }, { NULL, -1 } }; static const struct multistate multistate_requesttty[] = { { "true", REQUEST_TTY_YES }, { "yes", REQUEST_TTY_YES }, { "false", REQUEST_TTY_NO }, { "no", REQUEST_TTY_NO }, { "force", REQUEST_TTY_FORCE }, { "auto", REQUEST_TTY_AUTO }, { NULL, -1 } }; static const struct multistate multistate_sessiontype[] = { { "none", SESSION_TYPE_NONE }, { "subsystem", SESSION_TYPE_SUBSYSTEM }, { "default", SESSION_TYPE_DEFAULT }, { NULL, -1 } }; static const struct multistate multistate_canonicalizehostname[] = { { "true", SSH_CANONICALISE_YES }, { "false", SSH_CANONICALISE_NO }, { "yes", SSH_CANONICALISE_YES }, { "no", SSH_CANONICALISE_NO }, { "always", SSH_CANONICALISE_ALWAYS }, { NULL, -1 } }; static const struct multistate multistate_pubkey_auth[] = { { "true", SSH_PUBKEY_AUTH_ALL }, { "false", SSH_PUBKEY_AUTH_NO }, { "yes", SSH_PUBKEY_AUTH_ALL }, { "no", SSH_PUBKEY_AUTH_NO }, { "unbound", SSH_PUBKEY_AUTH_UNBOUND }, { "host-bound", SSH_PUBKEY_AUTH_HBOUND }, { 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 * only sets those values that have not already been set. */ int process_config_line(Options *options, struct passwd *pw, const char *host, const char *original_host, char *line, const char *filename, int linenum, int *activep, int flags) { return process_config_line_depth(options, pw, host, original_host, line, filename, linenum, activep, flags, NULL, 0); } #define WHITESPACE " \t\r\n" static int process_config_line_depth(Options *options, struct passwd *pw, const char *host, const char *original_host, char *line, const char *filename, int linenum, int *activep, int flags, int *want_final_pass, int depth) { char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p; 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, ca_only = 0; LogLevel *log_level_ptr; SyslogFacility *log_facility_ptr; long long val64; size_t len; struct Forward fwd; const struct multistate *multistate_ptr; struct allowed_cname *cname; glob_t gl; const char *errstr; char **oav = NULL, **av; int oac = 0, ac; int ret = -1; if (activep == NULL) { /* We are processing a command line directive */ cmdline = 1; activep = &cmdline; } /* Strip trailing whitespace. Allow \f (form feed) at EOL only */ if ((len = strlen(line)) == 0) return 0; for (len--; len > 0; len--) { if (strchr(WHITESPACE "\f", line[len]) == NULL) break; line[len] = '\0'; } str = line; /* Get the keyword. (Each line is supposed to begin with a keyword). */ if ((keyword = strdelim(&str)) == NULL) return 0; /* Ignore leading whitespace. */ if (*keyword == '\0') keyword = strdelim(&str); if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#') return 0; /* Match lowercase keyword */ lowercase(keyword); /* Prepare to parse remainder of line */ if (str != NULL) str += strspn(str, WHITESPACE); if (str == NULL || *str == '\0') { error("%s line %d: no argument after keyword \"%s\"", filename, linenum, keyword); return -1; } opcode = parse_token(keyword, filename, linenum, options->ignored_unknown); if (argv_split(str, &oac, &oav, 1) != 0) { error("%s line %d: invalid quotes", filename, linenum); return -1; } ac = oac; av = oav; switch (opcode) { case oBadOption: /* don't panic, but count bad options */ goto out; case oIgnore: argv_consume(&ac); break; case oIgnoredUnknownOption: debug("%s line %d: Ignored unknown option \"%s\"", filename, linenum, keyword); argv_consume(&ac); break; case oConnectTimeout: intptr = &options->connection_timeout; parse_time: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%s line %d: missing time value.", filename, linenum); goto out; } if (strcmp(arg, "none") == 0) value = -1; else if ((value = convtime(arg)) == -1) { error("%s line %d: invalid time value.", filename, linenum); goto out; } if (*activep && *intptr == -1) *intptr = value; break; case oForwardAgent: intptr = &options->forward_agent; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%s line %d: missing argument.", filename, linenum); goto out; } 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) { if (*activep && *intptr == -1) *intptr = value; break; } /* ForwardAgent wasn't 'yes' or 'no', assume a path */ if (*activep && *intptr == -1) *intptr = 1; charptr = &options->forward_agent_sock_path; goto parse_agent_path; case oForwardX11: intptr = &options->forward_x11; parse_flag: multistate_ptr = multistate_flag; parse_multistate: arg = argv_next(&ac, &av); if ((value = parse_multistate_value(arg, filename, linenum, multistate_ptr)) == -1) { error("%s line %d: unsupported option \"%s\".", filename, linenum, arg); goto out; } if (*activep && *intptr == -1) *intptr = value; break; case oForwardX11Trusted: intptr = &options->forward_x11_trusted; goto parse_flag; case oForwardX11Timeout: intptr = &options->forward_x11_timeout; goto parse_time; case oGatewayPorts: intptr = &options->fwd_opts.gateway_ports; goto parse_flag; case oExitOnForwardFailure: intptr = &options->exit_on_forward_failure; goto parse_flag; case oPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; case oKbdInteractiveAuthentication: intptr = &options->kbd_interactive_authentication; goto parse_flag; case oKbdInteractiveDevices: charptr = &options->kbd_interactive_devices; goto parse_string; case oPubkeyAuthentication: multistate_ptr = multistate_pubkey_auth; intptr = &options->pubkey_authentication; goto parse_multistate; case oHostbasedAuthentication: intptr = &options->hostbased_authentication; goto parse_flag; case oGssAuthentication: intptr = &options->gss_authentication; goto parse_flag; case oGssDelegateCreds: intptr = &options->gss_deleg_creds; goto parse_flag; case oBatchMode: intptr = &options->batch_mode; goto parse_flag; case oCheckHostIP: intptr = &options->check_host_ip; goto parse_flag; case oVerifyHostKeyDNS: intptr = &options->verify_host_key_dns; multistate_ptr = multistate_yesnoask; goto parse_multistate; case oStrictHostKeyChecking: intptr = &options->strict_host_key_checking; multistate_ptr = multistate_strict_hostkey; goto parse_multistate; case oCompression: intptr = &options->compression; multistate_ptr = multistate_compression; goto parse_multistate; case oTCPKeepAlive: intptr = &options->tcp_keep_alive; goto parse_flag; case oNoHostAuthenticationForLocalhost: intptr = &options->no_host_authentication_for_localhost; goto parse_flag; case oNumberOfPasswordPrompts: intptr = &options->number_of_password_prompts; goto parse_int; case oRekeyLimit: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (strcmp(arg, "default") == 0) { val64 = 0; } else { if (scan_scaled(arg, &val64) == -1) { error("%.200s line %d: Bad number '%s': %s", filename, linenum, arg, strerror(errno)); goto out; } if (val64 != 0 && val64 < 16) { error("%.200s line %d: RekeyLimit too small", filename, linenum); goto out; } } if (*activep && options->rekey_limit == -1) options->rekey_limit = val64; if (ac != 0) { /* optional rekey interval present */ if (strcmp(av[0], "none") == 0) { (void)argv_next(&ac, &av); /* discard */ break; } intptr = &options->rekey_interval; goto parse_time; } break; case oIdentityFile: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (*activep) { intptr = &options->num_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); goto out; } add_identity_file(options, NULL, arg, flags & SSHCONF_USERCONF); } break; case oCertificateFile: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (*activep) { intptr = &options->num_certificate_files; if (*intptr >= SSH_MAX_CERTIFICATE_FILES) { error("%.200s line %d: Too many certificate " "files specified (max %d).", filename, linenum, SSH_MAX_CERTIFICATE_FILES); goto out; } add_certificate_file(options, arg, flags & SSHCONF_USERCONF); } break; case oXAuthLocation: charptr=&options->xauth_location; goto parse_string; case oUser: charptr = &options->user; parse_string: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case oGlobalKnownHostsFile: cpptr = (char **)&options->system_hostfiles; uintptr = &options->num_system_hostfiles; max_entries = SSH_MAX_HOSTS_FILES; parse_char_array: i = 0; value = *uintptr == 0; /* was array empty when we started? */ while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { error("%s line %d: keyword %s empty argument", filename, linenum, keyword); goto out; } /* Allow "none" only in first position */ if (strcasecmp(arg, "none") == 0) { if (i > 0 || ac > 0) { error("%s line %d: keyword %s \"none\" " "argument must appear alone.", filename, linenum, keyword); goto out; } } i++; if (*activep && value) { if ((*uintptr) >= max_entries) { error("%s line %d: too many %s " "entries.", filename, linenum, keyword); goto out; } cpptr[(*uintptr)++] = xstrdup(arg); } } break; case oUserKnownHostsFile: cpptr = (char **)&options->user_hostfiles; uintptr = &options->num_user_hostfiles; max_entries = SSH_MAX_HOSTS_FILES; goto parse_char_array; case oHostname: charptr = &options->hostname; goto parse_string; case oTag: charptr = &options->tag; goto parse_string; case oHostKeyAlias: charptr = &options->host_key_alias; goto parse_string; case oPreferredAuthentications: charptr = &options->preferred_authentications; goto parse_string; case oBindAddress: charptr = &options->bind_address; goto parse_string; case oBindInterface: charptr = &options->bind_interface; goto parse_string; case oPKCS11Provider: charptr = &options->pkcs11_provider; goto parse_string; case 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 (str == NULL) { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } len = strspn(str, WHITESPACE "="); if (*activep && *charptr == NULL) *charptr = xstrdup(str + len); argv_consume(&ac); break; case oProxyJump: if (str == NULL) { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } len = strspn(str, WHITESPACE "="); /* XXX use argv? */ if (parse_jump(str + len, options, *activep) == -1) { error("%.200s line %d: Invalid ProxyJump \"%s\"", filename, linenum, str + len); goto out; } argv_consume(&ac); break; case oPort: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } value = a2port(arg); if (value <= 0) { error("%.200s line %d: Bad port '%s'.", filename, linenum, arg); goto out; } if (*activep && options->port == -1) options->port = value; break; case oConnectionAttempts: intptr = &options->connection_attempts; parse_int: arg = argv_next(&ac, &av); if ((errstr = atoi_err(arg, &value)) != NULL) { error("%s line %d: integer value %s.", filename, linenum, errstr); goto out; } if (*activep && *intptr == -1) *intptr = value; break; case oCiphers: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (*arg != '-' && !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){ error("%.200s line %d: Bad SSH2 cipher spec '%s'.", filename, linenum, arg ? arg : ""); goto out; } if (*activep && options->ciphers == NULL) options->ciphers = xstrdup(arg); break; case oMacs: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (*arg != '-' && !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) { error("%.200s line %d: Bad SSH2 MAC spec '%s'.", filename, linenum, arg ? arg : ""); goto out; } if (*activep && options->macs == NULL) options->macs = xstrdup(arg); break; case oKexAlgorithms: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (*arg != '-' && !kex_names_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) { error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.", filename, linenum, arg ? arg : ""); goto out; } if (*activep && options->kex_algorithms == NULL) options->kex_algorithms = xstrdup(arg); break; case oHostKeyAlgorithms: charptr = &options->hostkeyalgorithms; ca_only = 0; parse_pubkey_algos: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (*arg != '-' && !sshkey_names_valid2(*arg == '+' || *arg == '^' ? arg + 1 : arg, 1, ca_only)) { error("%s line %d: Bad key types '%s'.", filename, linenum, arg ? arg : ""); goto out; } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case oCASignatureAlgorithms: charptr = &options->ca_sign_algorithms; ca_only = 1; goto parse_pubkey_algos; case oLogLevel: log_level_ptr = &options->log_level; arg = argv_next(&ac, &av); value = log_level_number(arg); if (value == SYSLOG_LEVEL_NOT_SET) { error("%.200s line %d: unsupported log level '%s'", filename, linenum, arg ? arg : ""); goto out; } if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET) *log_level_ptr = (LogLevel) value; break; case oLogFacility: log_facility_ptr = &options->log_facility; arg = argv_next(&ac, &av); value = log_facility_number(arg); if (value == SYSLOG_FACILITY_NOT_SET) { error("%.200s line %d: unsupported log facility '%s'", filename, linenum, arg ? arg : ""); goto out; } if (*log_facility_ptr == -1) *log_facility_ptr = (SyslogFacility) value; break; case oLogVerbose: cppptr = &options->log_verbose; uintptr = &options->num_log_verbose; i = 0; while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { error("%s line %d: keyword %s empty argument", filename, linenum, keyword); goto out; } /* Allow "none" only in first position */ if (strcasecmp(arg, "none") == 0) { if (i > 0 || ac > 0) { error("%s line %d: keyword %s \"none\" " "argument must appear alone.", filename, linenum, keyword); goto out; } } i++; if (*activep && *uintptr == 0) { *cppptr = xrecallocarray(*cppptr, *uintptr, *uintptr + 1, sizeof(**cppptr)); (*cppptr)[(*uintptr)++] = xstrdup(arg); } } break; case oLocalForward: case oRemoteForward: case oDynamicForward: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } remotefwd = (opcode == oRemoteForward); dynamicfwd = (opcode == oDynamicForward); if (!dynamicfwd) { arg2 = argv_next(&ac, &av); if (arg2 == NULL || *arg2 == '\0') { if (remotefwd) dynamicfwd = 1; else { error("%.200s line %d: Missing target " "argument.", filename, linenum); goto out; } } else { /* construct a string for parse_forward */ snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); } } if (dynamicfwd) strlcpy(fwdarg, arg, sizeof(fwdarg)); if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) { error("%.200s line %d: Bad forwarding specification.", filename, linenum); goto out; } if (*activep) { if (remotefwd) { add_remote_forward(options, &fwd); } else { add_local_forward(options, &fwd); } } break; case oPermitRemoteOpen: uintptr = &options->num_permitted_remote_opens; cppptr = &options->permitted_remote_opens; uvalue = *uintptr; /* modified later */ i = 0; while ((arg = argv_next(&ac, &av)) != NULL) { arg2 = xstrdup(arg); /* Allow any/none only in first position */ if (strcasecmp(arg, "none") == 0 || strcasecmp(arg, "any") == 0) { if (i > 0 || ac > 0) { error("%s line %d: keyword %s \"%s\" " "argument must appear alone.", filename, linenum, keyword, arg); free(arg2); goto out; } } else { p = hpdelim(&arg); if (p == NULL) { 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); i++; } if (i == 0) fatal("%s line %d: missing %s specification", filename, linenum, lookup_opcode_name(opcode)); break; case oClearAllForwardings: intptr = &options->clear_forwardings; goto parse_flag; case oHost: if (cmdline) { error("Host directive not supported as a command-line " "option"); goto out; } *activep = 0; arg2 = NULL; while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { error("%s line %d: keyword %s empty argument", filename, linenum, keyword); goto out; } if ((flags & SSHCONF_NEVERMATCH) != 0) { argv_consume(&ac); break; } negated = *arg == '!'; if (negated) arg++; if (match_pattern(host, arg)) { if (negated) { debug("%.200s line %d: Skipping Host " "block because of negated match " "for %.100s", filename, linenum, arg); *activep = 0; argv_consume(&ac); break; } if (!*activep) arg2 = arg; /* logged below */ *activep = 1; } } if (*activep) debug("%.200s line %d: Applying options for %.100s", filename, linenum, arg2); break; case oMatch: if (cmdline) { error("Host directive not supported as a command-line " "option"); goto out; } value = match_cfg_line(options, &str, pw, host, original_host, flags & SSHCONF_FINAL, want_final_pass, filename, linenum); if (value < 0) { error("%.200s line %d: Bad Match condition", filename, linenum); goto out; } *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value; /* * If match_cfg_line() didn't consume all its arguments then * arrange for the extra arguments check below to fail. */ if (str == NULL || *str == '\0') argv_consume(&ac); break; case oEscapeChar: intptr = &options->escape_char; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if (strcmp(arg, "none") == 0) value = SSH_ESCAPECHAR_NONE; else if (arg[1] == '\0') value = (u_char) arg[0]; else if (arg[0] == '^' && arg[2] == 0 && (u_char) arg[1] >= 64 && (u_char) arg[1] < 128) value = (u_char) arg[1] & 31; else { error("%.200s line %d: Bad escape character.", filename, linenum); goto out; } if (*activep && *intptr == -1) *intptr = value; break; case oAddressFamily: intptr = &options->address_family; multistate_ptr = multistate_addressfamily; goto parse_multistate; case oEnableSSHKeysign: intptr = &options->enable_ssh_keysign; goto parse_flag; case oIdentitiesOnly: intptr = &options->identities_only; goto parse_flag; case oServerAliveInterval: intptr = &options->server_alive_interval; goto parse_time; case oServerAliveCountMax: intptr = &options->server_alive_count_max; goto parse_int; case oSendEnv: while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0' || strchr(arg, '=') != NULL) { error("%s line %d: Invalid environment name.", filename, linenum); goto out; } if (!*activep) continue; if (*arg == '-') { /* Removing an env var */ rm_env(options, arg, filename, linenum); continue; } opt_array_append(filename, linenum, lookup_opcode_name(opcode), &options->send_env, &options->num_send_env, arg); } break; case oSetEnv: value = options->num_setenv; while ((arg = argv_next(&ac, &av)) != NULL) { if (strchr(arg, '=') == NULL) { error("%s line %d: Invalid SetEnv.", filename, linenum); goto out; } if (!*activep || value != 0) continue; if (lookup_setenv_in_list(arg, options->setenv, options->num_setenv) != NULL) { debug2("%s line %d: ignoring duplicate env " "name \"%.64s\"", filename, linenum, arg); continue; } opt_array_append(filename, linenum, lookup_opcode_name(opcode), &options->setenv, &options->num_setenv, arg); } break; case oControlPath: charptr = &options->control_path; goto parse_string; case oControlMaster: intptr = &options->control_master; multistate_ptr = multistate_controlmaster; goto parse_multistate; case oControlPersist: /* no/false/yes/true, or a time spec */ intptr = &options->control_persist; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing ControlPersist" " argument.", filename, linenum); goto out; } value = 0; value2 = 0; /* timeout */ if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) value = 0; else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) value = 1; else if ((value2 = convtime(arg)) >= 0) value = 1; else { error("%.200s line %d: Bad ControlPersist argument.", filename, linenum); goto out; } if (*activep && *intptr == -1) { *intptr = value; options->control_persist_timeout = value2; } break; case oHashKnownHosts: intptr = &options->hash_known_hosts; goto parse_flag; case oTunnel: intptr = &options->tun_open; multistate_ptr = multistate_tunnel; goto parse_multistate; case oTunnelDevice: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } value = a2tun(arg, &value2); if (value == SSH_TUNID_ERR) { error("%.200s line %d: Bad tun device.", filename, linenum); goto out; } if (*activep && options->tun_local == -1) { options->tun_local = value; options->tun_remote = value2; } break; case oLocalCommand: charptr = &options->local_command; goto parse_command; case oPermitLocalCommand: intptr = &options->permit_local_command; goto parse_flag; case oRemoteCommand: charptr = &options->remote_command; goto parse_command; case oVisualHostKey: intptr = &options->visual_host_key; goto parse_flag; case oInclude: if (cmdline) { error("Include directive not supported as a " "command-line option"); goto out; } value = 0; while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { error("%s line %d: keyword %s empty argument", filename, linenum, keyword); goto out; } /* * Ensure all paths are anchored. User configuration * files may begin with '~/' but system configurations * must not. If the path is relative, then treat it * as living in ~/.ssh for user configurations or * /etc/ssh for system ones. */ if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) { error("%.200s line %d: bad include path %s.", filename, linenum, arg); goto out; } if (!path_absolute(arg) && *arg != '~') { xasprintf(&arg2, "%s/%s", (flags & SSHCONF_USERCONF) ? "~/" _PATH_SSH_USER_DIR : SSHDIR, arg); } else arg2 = xstrdup(arg); memset(&gl, 0, sizeof(gl)); r = glob(arg2, GLOB_TILDE, NULL, &gl); if (r == GLOB_NOMATCH) { debug("%.200s line %d: include %s matched no " "files",filename, linenum, arg2); free(arg2); continue; } else if (r != 0) { error("%.200s line %d: glob failed for %s.", filename, linenum, arg2); goto out; } free(arg2); oactive = *activep; 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, oactive ? "" : " (parse only)"); r = read_config_file_depth(gl.gl_pathv[i], pw, host, original_host, options, flags | SSHCONF_CHECKPERM | (oactive ? 0 : SSHCONF_NEVERMATCH), activep, want_final_pass, depth + 1); if (r != 1 && errno != ENOENT) { error("Can't open user config file " "%.100s: %.100s", gl.gl_pathv[i], strerror(errno)); globfree(&gl); goto out; } /* * don't let Match in includes clobber the * containing file's Match state. */ *activep = oactive; if (r != 1) value = -1; } globfree(&gl); } if (value != 0) ret = value; break; case oIPQoS: arg = argv_next(&ac, &av); if ((value = parse_ipqos(arg)) == -1) { error("%s line %d: Bad IPQoS value: %s", filename, linenum, arg); goto out; } arg = argv_next(&ac, &av); if (arg == NULL) value2 = value; else if ((value2 = parse_ipqos(arg)) == -1) { error("%s line %d: Bad IPQoS value: %s", filename, linenum, arg); goto out; } if (*activep && options->ip_qos_interactive == -1) { options->ip_qos_interactive = value; options->ip_qos_bulk = value2; } break; case oRequestTTY: intptr = &options->request_tty; multistate_ptr = multistate_requesttty; goto parse_multistate; case oSessionType: intptr = &options->session_type; multistate_ptr = multistate_sessiontype; goto parse_multistate; case oStdinNull: intptr = &options->stdin_null; goto parse_flag; case oForkAfterAuthentication: intptr = &options->fork_after_authentication; goto parse_flag; case oIgnoreUnknown: charptr = &options->ignored_unknown; goto parse_string; case oProxyUseFdpass: intptr = &options->proxy_use_fdpass; goto parse_flag; case oCanonicalDomains: value = options->num_canonical_domains != 0; i = 0; while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { error("%s line %d: keyword %s empty argument", filename, linenum, keyword); goto out; } /* Allow "none" only in first position */ if (strcasecmp(arg, "none") == 0) { if (i > 0 || ac > 0) { error("%s line %d: keyword %s \"none\" " "argument must appear alone.", filename, linenum, keyword); goto out; } } i++; if (!valid_domain(arg, 1, &errstr)) { error("%s line %d: %s", filename, linenum, errstr); goto out; } if (!*activep || value) continue; if (options->num_canonical_domains >= MAX_CANON_DOMAINS) { error("%s line %d: too many hostname suffixes.", filename, linenum); goto out; } options->canonical_domains[ options->num_canonical_domains++] = xstrdup(arg); } break; case oCanonicalizePermittedCNAMEs: value = options->num_permitted_cnames != 0; i = 0; while ((arg = argv_next(&ac, &av)) != NULL) { /* * Either 'none' (only in first position), '*' for * everything or 'list:list' */ if (strcasecmp(arg, "none") == 0) { if (i > 0 || ac > 0) { error("%s line %d: keyword %s \"none\" " "argument must appear alone.", filename, linenum, keyword); goto out; } arg2 = ""; } else if (strcmp(arg, "*") == 0) { arg2 = arg; } else { lowercase(arg); if ((arg2 = strchr(arg, ':')) == NULL || arg2[1] == '\0') { error("%s line %d: " "Invalid permitted CNAME \"%s\"", filename, linenum, arg); goto out; } *arg2 = '\0'; arg2++; } i++; if (!*activep || value) continue; if (options->num_permitted_cnames >= MAX_CANON_DOMAINS) { error("%s line %d: too many permitted CNAMEs.", filename, linenum); goto out; } cname = options->permitted_cnames + options->num_permitted_cnames++; cname->source_list = xstrdup(arg); cname->target_list = xstrdup(arg2); } break; case oCanonicalizeHostname: intptr = &options->canonicalize_hostname; multistate_ptr = multistate_canonicalizehostname; goto parse_multistate; case oCanonicalizeMaxDots: intptr = &options->canonicalize_max_dots; goto parse_int; case oCanonicalizeFallbackLocal: intptr = &options->canonicalize_fallback_local; goto parse_flag; case oStreamLocalBindMask: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing StreamLocalBindMask " "argument.", filename, linenum); goto out; } /* Parse mode in octal format */ value = strtol(arg, &endofnumber, 8); if (arg == endofnumber || value < 0 || value > 0777) { error("%.200s line %d: Bad mask.", filename, linenum); goto out; } options->fwd_opts.streamlocal_bind_mask = (mode_t)value; break; case oStreamLocalBindUnlink: intptr = &options->fwd_opts.streamlocal_bind_unlink; goto parse_flag; case oRevokedHostKeys: charptr = &options->revoked_host_keys; goto parse_string; case oFingerprintHash: intptr = &options->fingerprint_hash; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } if ((value = ssh_digest_alg_by_name(arg)) == -1) { error("%.200s line %d: Invalid hash algorithm \"%s\".", filename, linenum, arg); goto out; } if (*activep && *intptr == -1) *intptr = value; break; case oUpdateHostkeys: intptr = &options->update_hostkeys; multistate_ptr = multistate_yesnoask; goto parse_multistate; case oHostbasedAcceptedAlgorithms: charptr = &options->hostbased_accepted_algos; ca_only = 0; goto parse_pubkey_algos; case oPubkeyAcceptedAlgorithms: charptr = &options->pubkey_accepted_algos; ca_only = 0; goto parse_pubkey_algos; case oAddKeysToAgent: arg = argv_next(&ac, &av); arg2 = argv_next(&ac, &av); 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) { error("%s line %d: invalid time value.", filename, linenum); goto out; } } else if (value == -1 && arg2 == NULL) { if ((value2 = convtime(arg)) == -1) { error("%s line %d: unsupported option", filename, linenum); goto out; } value = 1; /* yes */ } else if (value == -1 || arg2 != NULL) { error("%s line %d: unsupported option", filename, linenum); goto out; } 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 = argv_next(&ac, &av); if (!arg || *arg == '\0') { error("%.200s line %d: Missing argument.", filename, linenum); goto out; } parse_agent_path: /* Extra validation if the string represents an env var. */ if ((arg2 = dollar_expand(&r, arg)) == NULL || r) { error("%.200s line %d: Invalid environment expansion " "%s.", filename, linenum, arg); goto out; } 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); goto out; } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case oEnableEscapeCommandline: intptr = &options->enable_escape_commandline; goto parse_flag; case oRequiredRSASize: intptr = &options->required_rsa_size; goto parse_int; case oObscureKeystrokeTiming: value = -1; while ((arg = argv_next(&ac, &av)) != NULL) { if (value != -1) { error("%s line %d: invalid arguments", filename, linenum); goto out; } if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) value = SSH_KEYSTROKE_DEFAULT_INTERVAL_MS; else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) value = 0; else if (strncmp(arg, "interval:", 9) == 0) { if ((errstr = atoi_err(arg + 9, &value)) != NULL) { error("%s line %d: integer value %s.", filename, linenum, errstr); goto out; } if (value <= 0 || value > 1000) { error("%s line %d: value out of range.", filename, linenum); goto out; } } else { error("%s line %d: unsupported argument \"%s\"", filename, linenum, arg); goto out; } } if (value == -1) { error("%s line %d: missing argument", filename, linenum); goto out; } intptr = &options->obscure_keystroke_timing_interval; if (*activep && *intptr == -1) *intptr = value; break; + case oChannelTimeout: + uvalue = options->num_channel_timeouts; + i = 0; + while ((arg = argv_next(&ac, &av)) != NULL) { + /* Allow "none" only in first position */ + if (strcasecmp(arg, "none") == 0) { + if (i > 0 || ac > 0) { + error("%s line %d: keyword %s \"none\" " + "argument must appear alone.", + filename, linenum, keyword); + goto out; + } + } else if (parse_pattern_interval(arg, + NULL, NULL) != 0) { + fatal("%s line %d: invalid channel timeout %s", + filename, linenum, arg); + } + if (!*activep || uvalue != 0) + continue; + opt_array_append(filename, linenum, keyword, + &options->channel_timeouts, + &options->num_channel_timeouts, arg); + } + break; + case oDeprecated: debug("%s line %d: Deprecated option \"%s\"", filename, linenum, keyword); argv_consume(&ac); break; case oUnsupported: error("%s line %d: Unsupported option \"%s\"", filename, linenum, keyword); argv_consume(&ac); break; default: error("%s line %d: Unimplemented opcode %d", filename, linenum, opcode); goto out; } /* Check that there is no garbage at end of line. */ if (ac > 0) { error("%.200s line %d: keyword %s extra arguments " "at end of line", filename, linenum, keyword); goto out; } /* success */ ret = 0; out: argv_free(oav, oac); return ret; } /* * Reads the config file and modifies the options accordingly. Options * should already be initialized before this call. This never returns if * there is an error. If the file does not exist, this returns 0. */ int read_config_file(const char *filename, struct passwd *pw, const char *host, const char *original_host, Options *options, int flags, int *want_final_pass) { int active = 1; return read_config_file_depth(filename, pw, host, original_host, options, flags, &active, want_final_pass, 0); } #define READCONF_MAX_DEPTH 16 static int read_config_file_depth(const char *filename, struct passwd *pw, const char *host, const char *original_host, Options *options, int flags, int *activep, int *want_final_pass, int depth) { FILE *f; char *line = NULL; size_t linesize = 0; int linenum; int bad_options = 0; if (depth < 0 || depth > READCONF_MAX_DEPTH) fatal("Too many recursive configuration includes"); if ((f = fopen(filename, "r")) == NULL) return 0; if (flags & SSHCONF_CHECKPERM) { struct stat sb; if (fstat(fileno(f), &sb) == -1) fatal("fstat %s: %s", filename, strerror(errno)); if (((sb.st_uid != 0 && sb.st_uid != getuid()) || (sb.st_mode & 022) != 0)) fatal("Bad owner or permissions on %s", filename); } debug("Reading configuration data %.200s", filename); /* * Mark that we are now processing the options. This flag is turned * on/off by Host specifications. */ linenum = 0; while (getline(&line, &linesize, f) != -1) { /* Update line number counter. */ linenum++; /* * Trim out comments and strip whitespace. * NB - preserve newlines, they are needed to reproduce * line numbers later for error messages. */ if (process_config_line_depth(options, pw, host, original_host, line, filename, linenum, activep, flags, want_final_pass, depth) != 0) bad_options++; } free(line); fclose(f); if (bad_options > 0) fatal("%s: terminating, %d bad configuration options", filename, bad_options); return 1; } /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ int option_clear_or_none(const char *o) { return o == NULL || strcasecmp(o, "none") == 0; } /* * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise. * Allowed to be called on non-final configuration. */ int config_has_permitted_cnames(Options *options) { if (options->num_permitted_cnames == 1 && strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 && strcmp(options->permitted_cnames[0].target_list, "") == 0) return 0; return options->num_permitted_cnames > 0; } /* * Initializes options to special values that indicate that they have not yet * been set. Read_config_file will only set options with this value. Options * are processed in the following order: command line, user config file, * system config file. Last, fill_default_options is called. */ void initialize_options(Options * options) { memset(options, 'X', sizeof(*options)); options->host_arg = NULL; options->forward_agent = -1; options->forward_agent_sock_path = NULL; options->forward_x11 = -1; options->forward_x11_trusted = -1; options->forward_x11_timeout = -1; options->stdio_forward_host = NULL; options->stdio_forward_port = 0; options->clear_forwardings = -1; options->exit_on_forward_failure = -1; options->xauth_location = NULL; options->fwd_opts.gateway_ports = -1; options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; options->fwd_opts.streamlocal_bind_unlink = -1; options->pubkey_authentication = -1; options->gss_authentication = -1; options->gss_deleg_creds = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; options->hostbased_authentication = -1; options->batch_mode = -1; options->check_host_ip = -1; options->strict_host_key_checking = -1; options->compression = -1; options->tcp_keep_alive = -1; options->port = -1; options->address_family = -1; options->connection_attempts = -1; options->connection_timeout = -1; options->number_of_password_prompts = -1; options->ciphers = NULL; options->macs = NULL; options->kex_algorithms = NULL; options->hostkeyalgorithms = NULL; options->ca_sign_algorithms = NULL; options->num_identity_files = 0; 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; options->jump_user = NULL; options->jump_host = NULL; options->jump_port = -1; options->jump_extra = NULL; options->user = NULL; options->escape_char = -1; options->num_system_hostfiles = 0; options->num_user_hostfiles = 0; options->local_forwards = NULL; options->num_local_forwards = 0; options->remote_forwards = NULL; options->num_remote_forwards = 0; options->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; options->rekey_limit = - 1; options->rekey_interval = -1; options->verify_host_key_dns = -1; options->server_alive_interval = -1; options->server_alive_count_max = -1; options->send_env = NULL; options->num_send_env = 0; options->setenv = NULL; options->num_setenv = 0; options->control_path = NULL; options->control_master = -1; options->control_persist = -1; options->control_persist_timeout = 0; options->hash_known_hosts = -1; options->tun_open = -1; options->tun_local = -1; options->tun_remote = -1; options->local_command = NULL; options->permit_local_command = -1; options->remote_command = NULL; options->add_keys_to_agent = -1; options->add_keys_to_agent_lifespan = -1; options->identity_agent = NULL; options->visual_host_key = -1; options->ip_qos_interactive = -1; options->ip_qos_bulk = -1; options->request_tty = -1; options->session_type = -1; options->stdin_null = -1; options->fork_after_authentication = -1; options->proxy_use_fdpass = -1; options->ignored_unknown = NULL; options->num_canonical_domains = 0; options->num_permitted_cnames = 0; options->canonicalize_max_dots = -1; options->canonicalize_fallback_local = -1; options->canonicalize_hostname = -1; options->revoked_host_keys = NULL; options->fingerprint_hash = -1; options->update_hostkeys = -1; options->hostbased_accepted_algos = NULL; options->pubkey_accepted_algos = NULL; options->known_hosts_command = NULL; options->required_rsa_size = -1; options->enable_escape_commandline = -1; options->obscure_keystroke_timing_interval = -1; options->tag = NULL; + options->channel_timeouts = NULL; + options->num_channel_timeouts = 0; } /* * A petite version of fill_default_options() that just fills the options * needed for hostname canonicalization to proceed. */ void fill_default_options_for_canonicalization(Options *options) { if (options->canonicalize_max_dots == -1) options->canonicalize_max_dots = 1; if (options->canonicalize_fallback_local == -1) options->canonicalize_fallback_local = 1; if (options->canonicalize_hostname == -1) options->canonicalize_hostname = SSH_CANONICALISE_NO; } /* * Called after processing other sources of option data, this fills those * options for which no value has been specified with their default values. */ int fill_default_options(Options * options) { char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; int ret = 0, r; if (options->forward_agent == -1) options->forward_agent = 0; if (options->forward_x11 == -1) options->forward_x11 = 0; if (options->forward_x11_trusted == -1) options->forward_x11_trusted = 0; if (options->forward_x11_timeout == -1) options->forward_x11_timeout = 1200; /* * stdio forwarding (-W) changes the default for these but we defer * setting the values so they can be overridden. */ if (options->exit_on_forward_failure == -1) options->exit_on_forward_failure = options->stdio_forward_host != NULL ? 1 : 0; if (options->clear_forwardings == -1) options->clear_forwardings = options->stdio_forward_host != NULL ? 1 : 0; if (options->clear_forwardings == 1) clear_forwardings(options); if (options->xauth_location == NULL) options->xauth_location = 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) options->fwd_opts.streamlocal_bind_mask = 0177; if (options->fwd_opts.streamlocal_bind_unlink == -1) options->fwd_opts.streamlocal_bind_unlink = 0; if (options->pubkey_authentication == -1) options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL; if (options->gss_authentication == -1) options->gss_authentication = 0; if (options->gss_deleg_creds == -1) options->gss_deleg_creds = 0; if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) options->kbd_interactive_authentication = 1; if (options->hostbased_authentication == -1) options->hostbased_authentication = 0; if (options->batch_mode == -1) options->batch_mode = 0; if (options->check_host_ip == -1) options->check_host_ip = 0; if (options->strict_host_key_checking == -1) options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK; if (options->compression == -1) options->compression = 0; if (options->tcp_keep_alive == -1) options->tcp_keep_alive = 1; if (options->port == -1) options->port = 0; /* Filled in ssh_connect. */ if (options->address_family == -1) options->address_family = AF_UNSPEC; if (options->connection_attempts == -1) options->connection_attempts = 1; if (options->number_of_password_prompts == -1) options->number_of_password_prompts = 3; /* options->hostkeyalgorithms, default set in myproposals.h */ if (options->add_keys_to_agent == -1) { options->add_keys_to_agent = 0; options->add_keys_to_agent_lifespan = 0; } if (options->num_identity_files == 0) { add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 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); add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); } if (options->escape_char == -1) options->escape_char = '~'; if (options->num_system_hostfiles == 0) { options->system_hostfiles[options->num_system_hostfiles++] = xstrdup(_PATH_SSH_SYSTEM_HOSTFILE); options->system_hostfiles[options->num_system_hostfiles++] = xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2); } if (options->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); options->user_hostfiles[options->num_user_hostfiles++] = xstrdup(_PATH_SSH_USER_HOSTFILE2); } if (options->log_level == SYSLOG_LEVEL_NOT_SET) options->log_level = SYSLOG_LEVEL_INFO; if (options->log_facility == SYSLOG_FACILITY_NOT_SET) options->log_facility = SYSLOG_FACILITY_USER; if (options->no_host_authentication_for_localhost == - 1) options->no_host_authentication_for_localhost = 0; if (options->identities_only == -1) options->identities_only = 0; if (options->enable_ssh_keysign == -1) options->enable_ssh_keysign = 0; if (options->rekey_limit == -1) options->rekey_limit = 0; if (options->rekey_interval == -1) options->rekey_interval = 0; if (options->verify_host_key_dns == -1) options->verify_host_key_dns = 0; if (options->server_alive_interval == -1) options->server_alive_interval = 0; if (options->server_alive_count_max == -1) options->server_alive_count_max = 3; if (options->control_master == -1) options->control_master = 0; if (options->control_persist == -1) { options->control_persist = 0; options->control_persist_timeout = 0; } if (options->hash_known_hosts == -1) options->hash_known_hosts = 0; if (options->tun_open == -1) options->tun_open = SSH_TUNMODE_NO; if (options->tun_local == -1) options->tun_local = SSH_TUNID_ANY; if (options->tun_remote == -1) options->tun_remote = SSH_TUNID_ANY; if (options->permit_local_command == -1) options->permit_local_command = 0; if (options->visual_host_key == -1) options->visual_host_key = 0; if (options->ip_qos_interactive == -1) options->ip_qos_interactive = IPTOS_DSCP_AF21; if (options->ip_qos_bulk == -1) options->ip_qos_bulk = IPTOS_DSCP_CS1; if (options->request_tty == -1) options->request_tty = REQUEST_TTY_AUTO; if (options->session_type == -1) options->session_type = SESSION_TYPE_DEFAULT; if (options->stdin_null == -1) options->stdin_null = 0; if (options->fork_after_authentication == -1) options->fork_after_authentication = 0; if (options->proxy_use_fdpass == -1) options->proxy_use_fdpass = 0; if (options->canonicalize_max_dots == -1) options->canonicalize_max_dots = 1; if (options->canonicalize_fallback_local == -1) options->canonicalize_fallback_local = 1; if (options->canonicalize_hostname == -1) options->canonicalize_hostname = SSH_CANONICALISE_NO; if (options->fingerprint_hash == -1) options->fingerprint_hash = SSH_FP_HASH_DEFAULT; #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 if (options->required_rsa_size == -1) options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; if (options->enable_escape_commandline == -1) options->enable_escape_commandline = 0; if (options->obscure_keystroke_timing_interval == -1) { options->obscure_keystroke_timing_interval = SSH_KEYSTROKE_DEFAULT_INTERVAL_MS; } /* Expand KEX name lists */ all_cipher = cipher_alg_list(',', 0); all_mac = mac_alg_list(','); all_kex = kex_alg_list(','); all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); /* 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) { \ error_fr(r, "%s", #what); \ goto fail; \ } \ } while (0) 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 #define CLEAR_ON_NONE(v) \ do { \ if (option_clear_or_none(v)) { \ free(v); \ v = NULL; \ } \ } while(0) +#define CLEAR_ON_NONE_ARRAY(v, nv, none) \ + do { \ + if (options->nv == 1 && \ + strcasecmp(options->v[0], none) == 0) { \ + free(options->v[0]); \ + free(options->v); \ + options->v = NULL; \ + options->nv = 0; \ + } \ + } while (0) CLEAR_ON_NONE(options->local_command); CLEAR_ON_NONE(options->remote_command); CLEAR_ON_NONE(options->proxy_command); CLEAR_ON_NONE(options->control_path); CLEAR_ON_NONE(options->revoked_host_keys); CLEAR_ON_NONE(options->pkcs11_provider); CLEAR_ON_NONE(options->sk_provider); CLEAR_ON_NONE(options->known_hosts_command); + CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none"); +#undef CLEAR_ON_NONE +#undef CLEAR_ON_NONE_ARRAY if (options->jump_host != NULL && strcmp(options->jump_host, "none") == 0 && options->jump_port == 0 && options->jump_user == NULL) { free(options->jump_host); options->jump_host = NULL; } if (options->num_permitted_cnames == 1 && !config_has_permitted_cnames(options)) { /* clean up CanonicalizePermittedCNAMEs=none */ free(options->permitted_cnames[0].source_list); free(options->permitted_cnames[0].target_list); memset(options->permitted_cnames, '\0', sizeof(*options->permitted_cnames)); options->num_permitted_cnames = 0; } /* options->identity_agent distinguishes NULL from 'none' */ /* options->user will be set in the main program if appropriate */ /* options->hostname will be set in the main program if appropriate */ /* options->host_key_alias should not be set by default */ /* options->preferred_authentications will be set in ssh */ /* 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(u_int, o->num_send_env, o->send_env); free(o->send_env); FREE_ARRAY(u_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 { char *arg; int ispath; }; /* * parse_fwd_field * parses the next field in a port forwarding specification. * sets fwd to the parsed field and advances p past the colon * or sets it to NULL at end of string. * returns 0 on success, else non-zero. */ static int parse_fwd_field(char **p, struct fwdarg *fwd) { char *ep, *cp = *p; int ispath = 0; if (*cp == '\0') { *p = NULL; return -1; /* end of string */ } /* * A field escaped with square brackets is used literally. * XXX - allow ']' to be escaped via backslash? */ if (*cp == '[') { /* find matching ']' */ for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) { if (*ep == '/') ispath = 1; } /* no matching ']' or not at end of field. */ if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0')) return -1; /* NUL terminate the field and advance p past the colon */ *ep++ = '\0'; if (*ep != '\0') *ep++ = '\0'; fwd->arg = cp + 1; fwd->ispath = ispath; *p = ep; return 0; } for (cp = *p; *cp != '\0'; cp++) { switch (*cp) { case '\\': memmove(cp, cp + 1, strlen(cp + 1) + 1); if (*cp == '\0') return -1; break; case '/': ispath = 1; break; case ':': *cp++ = '\0'; goto done; } } done: fwd->arg = *p; fwd->ispath = ispath; *p = cp; return 0; } /* * parse_forward * parses a string containing a port forwarding specification of the form: * dynamicfwd == 0 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath * listenpath:connectpath * dynamicfwd == 1 * [listenhost:]listenport * returns number of arguments parsed or zero on error */ int parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) { struct fwdarg fwdargs[4]; char *p, *cp; int i, err; memset(fwd, 0, sizeof(*fwd)); memset(fwdargs, 0, sizeof(fwdargs)); /* * 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)) cp++; for (i = 0; i < 4; ++i) { if (parse_fwd_field(&cp, &fwdargs[i]) != 0) break; } /* Check for trailing garbage */ if (cp != NULL && *cp != '\0') { i = 0; /* failure */ } switch (i) { case 1: if (fwdargs[0].ispath) { fwd->listen_path = xstrdup(fwdargs[0].arg); fwd->listen_port = PORT_STREAMLOCAL; } else { fwd->listen_host = NULL; fwd->listen_port = a2port(fwdargs[0].arg); } fwd->connect_host = xstrdup("socks"); break; case 2: if (fwdargs[0].ispath && fwdargs[1].ispath) { fwd->listen_path = xstrdup(fwdargs[0].arg); fwd->listen_port = PORT_STREAMLOCAL; fwd->connect_path = xstrdup(fwdargs[1].arg); fwd->connect_port = PORT_STREAMLOCAL; } else if (fwdargs[1].ispath) { fwd->listen_host = NULL; fwd->listen_port = a2port(fwdargs[0].arg); fwd->connect_path = xstrdup(fwdargs[1].arg); fwd->connect_port = PORT_STREAMLOCAL; } else { fwd->listen_host = xstrdup(fwdargs[0].arg); fwd->listen_port = a2port(fwdargs[1].arg); fwd->connect_host = xstrdup("socks"); } break; case 3: if (fwdargs[0].ispath) { fwd->listen_path = xstrdup(fwdargs[0].arg); fwd->listen_port = PORT_STREAMLOCAL; fwd->connect_host = xstrdup(fwdargs[1].arg); fwd->connect_port = a2port(fwdargs[2].arg); } else if (fwdargs[2].ispath) { fwd->listen_host = xstrdup(fwdargs[0].arg); fwd->listen_port = a2port(fwdargs[1].arg); fwd->connect_path = xstrdup(fwdargs[2].arg); fwd->connect_port = PORT_STREAMLOCAL; } else { fwd->listen_host = NULL; fwd->listen_port = a2port(fwdargs[0].arg); fwd->connect_host = xstrdup(fwdargs[1].arg); fwd->connect_port = a2port(fwdargs[2].arg); } break; case 4: fwd->listen_host = xstrdup(fwdargs[0].arg); fwd->listen_port = a2port(fwdargs[1].arg); fwd->connect_host = xstrdup(fwdargs[2].arg); fwd->connect_port = a2port(fwdargs[3].arg); break; default: i = 0; /* failure */ } free(p); if (dynamicfwd) { if (!(i == 1 || i == 2)) goto fail_free; } else { if (!(i == 3 || i == 4)) { if (fwd->connect_path == NULL && fwd->listen_path == NULL) goto fail_free; } if (fwd->connect_port <= 0 && fwd->connect_path == NULL) goto fail_free; } if ((fwd->listen_port < 0 && fwd->listen_path == NULL) || (!remotefwd && fwd->listen_port == 0)) goto fail_free; if (fwd->connect_host != NULL && strlen(fwd->connect_host) >= NI_MAXHOST) goto fail_free; /* * XXX - if connecting to a remote socket, max sun len may not * match this host */ if (fwd->connect_path != NULL && strlen(fwd->connect_path) >= PATH_MAX_SUN) goto fail_free; if (fwd->listen_host != NULL && strlen(fwd->listen_host) >= NI_MAXHOST) goto fail_free; if (fwd->listen_path != NULL && strlen(fwd->listen_path) >= PATH_MAX_SUN) goto fail_free; return (i); fail_free: free(fwd->connect_host); fwd->connect_host = NULL; free(fwd->connect_path); fwd->connect_path = NULL; free(fwd->listen_host); fwd->listen_host = NULL; free(fwd->listen_path); fwd->listen_path = NULL; return (0); } int parse_jump(const char *s, Options *o, int active) { char *orig, *sdup, *cp; char *host = NULL, *user = NULL; int r, ret = -1, port = -1, first; active &= o->proxy_command == NULL && o->jump_host == NULL; orig = sdup = xstrdup(s); /* Remove comment and trailing whitespace */ if ((cp = strchr(orig, '#')) != NULL) *cp = '\0'; rtrim(orig); first = active; do { if (strcasecmp(s, "none") == 0) break; if ((cp = strrchr(sdup, ',')) == NULL) cp = sdup; /* last */ else *cp++ = '\0'; if (first) { /* First argument and configuration is active */ 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 */ 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 */ } while (cp != sdup); /* success */ if (active) { if (strcasecmp(s, "none") == 0) { o->jump_host = xstrdup("none"); o->jump_port = 0; } else { o->jump_user = user; o->jump_host = host; o->jump_port = port; o->proxy_command = xstrdup("none"); user = host = NULL; if ((cp = strrchr(s, ',')) != NULL && cp != s) { o->jump_extra = xstrdup(s); o->jump_extra[cp - s] = '\0'; } } } ret = 0; out: free(orig); free(user); free(host); return ret; } int parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp) { char *user = NULL, *host = NULL, *path = NULL; int r, port; 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; } /* XXX the following is a near-vebatim copy from servconf.c; refactor */ static const char * fmt_multistate_int(int val, const struct multistate *m) { u_int i; for (i = 0; m[i].key != NULL; i++) { if (m[i].value == val) return m[i].key; } return "UNKNOWN"; } static const char * fmt_intarg(OpCodes code, int val) { if (val == -1) return "unset"; switch (code) { case oAddressFamily: return fmt_multistate_int(val, multistate_addressfamily); case oVerifyHostKeyDNS: case oUpdateHostkeys: return fmt_multistate_int(val, multistate_yesnoask); case oStrictHostKeyChecking: return fmt_multistate_int(val, multistate_strict_hostkey); case oControlMaster: return fmt_multistate_int(val, multistate_controlmaster); case oTunnel: return fmt_multistate_int(val, multistate_tunnel); case oRequestTTY: return fmt_multistate_int(val, multistate_requesttty); case oSessionType: return fmt_multistate_int(val, multistate_sessiontype); case oCanonicalizeHostname: return fmt_multistate_int(val, multistate_canonicalizehostname); case oAddKeysToAgent: return fmt_multistate_int(val, multistate_yesnoaskconfirm); case oPubkeyAuthentication: return fmt_multistate_int(val, multistate_pubkey_auth); case oFingerprintHash: return ssh_digest_alg_name(val); default: switch (val) { case 0: return "no"; case 1: return "yes"; default: return "UNKNOWN"; } } } static const char * lookup_opcode_name(OpCodes code) { u_int i; for (i = 0; keywords[i].name != NULL; i++) if (keywords[i].opcode == code) return(keywords[i].name); return "UNKNOWN"; } static void dump_cfg_int(OpCodes code, int val) { if (code == oObscureKeystrokeTiming) { if (val == 0) { printf("%s no\n", lookup_opcode_name(code)); return; } else if (val == SSH_KEYSTROKE_DEFAULT_INTERVAL_MS) { printf("%s yes\n", lookup_opcode_name(code)); return; } /* FALLTHROUGH */ } printf("%s %d\n", lookup_opcode_name(code), val); } static void dump_cfg_fmtint(OpCodes code, int val) { printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); } static void dump_cfg_string(OpCodes code, const char *val) { if (val == NULL) return; printf("%s %s\n", lookup_opcode_name(code), val); } static void dump_cfg_strarray(OpCodes code, u_int count, char **vals) { u_int i; for (i = 0; i < count; i++) printf("%s %s\n", lookup_opcode_name(code), vals[i]); } static void dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals) { u_int i; printf("%s", lookup_opcode_name(code)); if (count == 0) printf(" none"); for (i = 0; i < count; i++) printf(" %s", vals[i]); printf("\n"); } static void dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds) { const struct Forward *fwd; u_int i; /* oDynamicForward */ for (i = 0; i < count; i++) { fwd = &fwds[i]; if (code == oDynamicForward && fwd->connect_host != NULL && strcmp(fwd->connect_host, "socks") != 0) continue; if (code == oLocalForward && fwd->connect_host != NULL && strcmp(fwd->connect_host, "socks") == 0) continue; printf("%s", lookup_opcode_name(code)); if (fwd->listen_port == PORT_STREAMLOCAL) printf(" %s", fwd->listen_path); else if (fwd->listen_host == NULL) printf(" %d", fwd->listen_port); else { printf(" [%s]:%d", fwd->listen_host, fwd->listen_port); } if (code != oDynamicForward) { if (fwd->connect_port == PORT_STREAMLOCAL) printf(" %s", fwd->connect_path); else if (fwd->connect_host == NULL) printf(" %d", fwd->connect_port); else { printf(" [%s]:%d", fwd->connect_host, fwd->connect_port); } } printf("\n"); } } void dump_client_config(Options *o, const char *host) { int i, r; char buf[8], *all_key; /* * 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 ((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 */ dump_cfg_string(oHost, o->host_arg); dump_cfg_string(oUser, o->user); dump_cfg_string(oHostname, host); dump_cfg_int(oPort, o->port); /* Flag options */ dump_cfg_fmtint(oAddressFamily, o->address_family); dump_cfg_fmtint(oBatchMode, o->batch_mode); dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local); dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname); dump_cfg_fmtint(oCheckHostIP, o->check_host_ip); dump_cfg_fmtint(oCompression, o->compression); dump_cfg_fmtint(oControlMaster, o->control_master); dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign); dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); dump_cfg_fmtint(oForwardX11, o->forward_x11); dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); #ifdef GSSAPI dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); #endif /* GSSAPI */ dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); dump_cfg_fmtint(oIdentitiesOnly, o->identities_only); dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication); dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost); dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command); dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass); dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication); dump_cfg_fmtint(oRequestTTY, o->request_tty); dump_cfg_fmtint(oSessionType, o->session_type); dump_cfg_fmtint(oStdinNull, o->stdin_null); dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication); dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking); dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive); dump_cfg_fmtint(oTunnel, o->tun_open); dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns); dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline); /* Integer options */ dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); dump_cfg_int(oConnectionAttempts, o->connection_attempts); dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout); dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); dump_cfg_int(oServerAliveInterval, o->server_alive_interval); dump_cfg_int(oRequiredRSASize, o->required_rsa_size); dump_cfg_int(oObscureKeystrokeTiming, o->obscure_keystroke_timing_interval); /* String options */ dump_cfg_string(oBindAddress, o->bind_address); dump_cfg_string(oBindInterface, o->bind_interface); 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(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); 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); #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(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); dump_cfg_string(oTag, o->tag); /* Forwards */ dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards); dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards); dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards); /* String array options */ dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files); dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains); dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files); dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles); dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles); dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env); dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv); dump_cfg_strarray_oneline(oLogVerbose, o->num_log_verbose, o->log_verbose); + dump_cfg_strarray_oneline(oChannelTimeout, + o->num_channel_timeouts, o->channel_timeouts); /* 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"); else dump_cfg_int(oConnectTimeout, o->connection_timeout); /* oTunnelDevice */ printf("tunneldevice"); if (o->tun_local == SSH_TUNID_ANY) printf(" any"); else printf(" %d", o->tun_local); if (o->tun_remote == SSH_TUNID_ANY) printf(":any"); else printf(":%d", o->tun_remote); printf("\n"); /* oCanonicalizePermittedCNAMEs */ printf("canonicalizePermittedcnames"); if (o->num_permitted_cnames == 0) printf(" none"); for (i = 0; i < o->num_permitted_cnames; i++) { printf(" %s:%s", o->permitted_cnames[i].source_list, o->permitted_cnames[i].target_list); } printf("\n"); /* oControlPersist */ if (o->control_persist == 0 || o->control_persist_timeout == 0) dump_cfg_fmtint(oControlPersist, o->control_persist); else dump_cfg_int(oControlPersist, o->control_persist_timeout); /* oEscapeChar */ if (o->escape_char == SSH_ESCAPECHAR_NONE) printf("escapechar none\n"); else { vis(buf, o->escape_char, VIS_WHITE, 0); printf("escapechar %s\n", buf); } /* oIPQoS */ printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); printf("%s\n", iptos2str(o->ip_qos_bulk)); /* oRekeyLimit */ printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit, o->rekey_interval); /* oStreamLocalBindMask */ printf("streamlocalbindmask 0%o\n", o->fwd_opts.streamlocal_bind_mask); /* oLogFacility */ printf("syslogfacility %s\n", log_facility_name(o->log_facility)); /* oProxyCommand / oProxyJump */ if (o->jump_host == NULL) dump_cfg_string(oProxyCommand, o->proxy_command); else { /* Check for numeric addresses */ i = strchr(o->jump_host, ':') != NULL || strspn(o->jump_host, "1234567890.") == strlen(o->jump_host); snprintf(buf, sizeof(buf), "%d", o->jump_port); printf("proxyjump %s%s%s%s%s%s%s%s%s\n", /* optional additional jump spec */ o->jump_extra == NULL ? "" : o->jump_extra, o->jump_extra == NULL ? "" : ",", /* optional user */ o->jump_user == NULL ? "" : o->jump_user, o->jump_user == NULL ? "" : "@", /* opening [ if hostname is numeric */ i ? "[" : "", /* mandatory hostname */ o->jump_host, /* closing ] if hostname is numeric */ i ? "]" : "", /* optional port number */ o->jump_port <= 0 ? "" : ":", o->jump_port <= 0 ? "" : buf); } } diff --git a/crypto/openssh/readconf.h b/crypto/openssh/readconf.h index ce261bd63642..ff7180cd0c6c 100644 --- a/crypto/openssh/readconf.h +++ b/crypto/openssh/readconf.h @@ -1,255 +1,258 @@ -/* $OpenBSD: readconf.h,v 1.152 2023/08/28 03:31:16 djm Exp $ */ +/* $OpenBSD: readconf.h,v 1.154 2023/10/12 02:18:18 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Functions for reading the configuration file. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #ifndef READCONF_H #define READCONF_H /* Data structure for representing option data. */ #define SSH_MAX_HOSTS_FILES 32 #define MAX_CANON_DOMAINS 32 #define PATH_MAX_SUN (sizeof((struct sockaddr_un *)0)->sun_path) struct allowed_cname { char *source_list; char *target_list; }; typedef struct { char *host_arg; /* Host arg as specified on command line. */ 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. */ int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */ char *xauth_location; /* Location for xauth program */ struct ForwardOptions fwd_opts; /* forwarding options */ int pubkey_authentication; /* Try ssh2 pubkey authentication. */ int hostbased_authentication; /* ssh2's rhosts_rsa */ int gss_authentication; /* Try GSS authentication */ int gss_deleg_creds; /* Delegate GSS credentials */ int password_authentication; /* Try password * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */ int batch_mode; /* Batch mode: do not ask for passwords. */ int check_host_ip; /* Also keep track of keys for IP address */ int strict_host_key_checking; /* Strict host key checking. */ int compression; /* Compress packets in both directions. */ int tcp_keep_alive; /* Set SO_KEEPALIVE. */ int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */ int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */ SyslogFacility log_facility; /* Facility for system logging. */ LogLevel log_level; /* Level for logging. */ 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 * giving up */ int connection_timeout; /* Max time (seconds) before * aborting connection attempt */ int number_of_password_prompts; /* Max number of password * prompts. */ char *ciphers; /* SSH2 ciphers in order of preference. */ char *macs; /* SSH2 macs in order of preference. */ char *hostkeyalgorithms; /* SSH2 server key types in order of preference. */ char *kex_algorithms; /* SSH2 kex methods in order of preference. */ char *ca_sign_algorithms; /* Allowed CA signature algorithms */ char *hostname; /* Real host to connect. */ char *tag; /* Configuration tag name. */ char *host_key_alias; /* hostname alias for .ssh/known_hosts */ char *proxy_command; /* Proxy command for connecting the host. */ char *user; /* User to log in as. */ int escape_char; /* Escape character; -2 = none */ u_int num_system_hostfiles; /* Paths for /etc/ssh/ssh_known_hosts */ char *system_hostfiles[SSH_MAX_HOSTS_FILES]; u_int num_user_hostfiles; /* Path for $HOME/.ssh/known_hosts */ char *user_hostfiles[SSH_MAX_HOSTS_FILES]; char *preferred_authentications; char *bind_address; /* local socket address for connection to sshd */ char *bind_interface; /* local interface for bind address */ char *pkcs11_provider; /* PKCS#11 provider */ 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. */ char *identity_files[SSH_MAX_IDENTITY_FILES]; int identity_file_userprovided[SSH_MAX_IDENTITY_FILES]; struct sshkey *identity_keys[SSH_MAX_IDENTITY_FILES]; int num_certificate_files; /* Number of extra certificates for ssh. */ char *certificate_files[SSH_MAX_CERTIFICATE_FILES]; int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; int add_keys_to_agent; int add_keys_to_agent_lifespan; char *identity_agent; /* Optional path to ssh-agent socket */ /* Local TCP/IP forward requests. */ int num_local_forwards; struct Forward *local_forwards; /* Remote TCP/IP forward requests. */ int num_remote_forwards; struct Forward *remote_forwards; int clear_forwardings; /* 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; int enable_ssh_keysign; int64_t rekey_limit; int rekey_interval; int no_host_authentication_for_localhost; int identities_only; int server_alive_interval; int server_alive_count_max; u_int num_send_env; char **send_env; u_int num_setenv; char **setenv; char *control_path; int control_master; int control_persist; /* ControlPersist flag */ int control_persist_timeout; /* ControlPersist timeout (seconds) */ int hash_known_hosts; int tun_open; /* tun(4) */ int tun_local; /* force tun device (optional) */ int tun_remote; /* force tun device (optional) */ char *local_command; int permit_local_command; char *remote_command; int visual_host_key; int request_tty; int session_type; int stdin_null; int fork_after_authentication; int proxy_use_fdpass; int num_canonical_domains; char *canonical_domains[MAX_CANON_DOMAINS]; int canonicalize_hostname; int canonicalize_max_dots; int canonicalize_fallback_local; int num_permitted_cnames; struct allowed_cname permitted_cnames[MAX_CANON_DOMAINS]; char *revoked_host_keys; int fingerprint_hash; int update_hostkeys; /* one of SSH_UPDATE_HOSTKEYS_* */ char *hostbased_accepted_algos; char *pubkey_accepted_algos; char *jump_user; char *jump_host; int jump_port; char *jump_extra; char *known_hosts_command; int required_rsa_size; /* minimum size of RSA keys */ int enable_escape_commandline; /* ~C commandline */ int obscure_keystroke_timing_interval; + char **channel_timeouts; /* inactivity timeout by channel type */ + u_int num_channel_timeouts; + char *ignored_unknown; /* Pattern list of unknown tokens to ignore */ } Options; #define SSH_PUBKEY_AUTH_NO 0x00 #define SSH_PUBKEY_AUTH_UNBOUND 0x01 #define SSH_PUBKEY_AUTH_HBOUND 0x02 #define SSH_PUBKEY_AUTH_ALL 0x03 #define SSH_CANONICALISE_NO 0 #define SSH_CANONICALISE_YES 1 #define SSH_CANONICALISE_ALWAYS 2 #define SSHCTL_MASTER_NO 0 #define SSHCTL_MASTER_YES 1 #define SSHCTL_MASTER_AUTO 2 #define SSHCTL_MASTER_ASK 3 #define SSHCTL_MASTER_AUTO_ASK 4 #define REQUEST_TTY_AUTO 0 #define REQUEST_TTY_NO 1 #define REQUEST_TTY_YES 2 #define REQUEST_TTY_FORCE 3 #define SESSION_TYPE_NONE 0 #define SESSION_TYPE_SUBSYSTEM 1 #define SESSION_TYPE_DEFAULT 2 #define SSHCONF_CHECKPERM 1 /* check permissions on config file */ #define SSHCONF_USERCONF 2 /* user provided config file not system */ #define SSHCONF_FINAL 4 /* Final pass over config, after canon. */ #define SSHCONF_NEVERMATCH 8 /* Match/Host never matches; internal only */ #define SSH_UPDATE_HOSTKEYS_NO 0 #define SSH_UPDATE_HOSTKEYS_YES 1 #define SSH_UPDATE_HOSTKEYS_ASK 2 #define SSH_STRICT_HOSTKEY_OFF 0 #define SSH_STRICT_HOSTKEY_NEW 1 #define SSH_STRICT_HOSTKEY_YES 2 #define SSH_STRICT_HOSTKEY_ASK 3 /* ObscureKeystrokes parameters */ #define SSH_KEYSTROKE_DEFAULT_INTERVAL_MS 20 #define SSH_KEYSTROKE_CHAFF_MIN_MS 1024 #define SSH_KEYSTROKE_CHAFF_RNG_MS 2048 const char *kex_default_pk_alg(void); char *ssh_connection_hash(const char *thishost, const char *host, - const char *portstr, const char *user); + const char *portstr, const char *user, const char *jump_host); void initialize_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 *, const char *, Options *, int, int *); int parse_forward(struct Forward *, const char *, int, int); int parse_jump(const char *, Options *, int); int parse_ssh_uri(const char *, char **, char **, int *); int default_ssh_port(void); int option_clear_or_none(const char *); int config_has_permitted_cnames(Options *); void dump_client_config(Options *o, const char *host); void add_local_forward(Options *, const struct Forward *); void add_remote_forward(Options *, const struct Forward *); void add_identity_file(Options *, const char *, const char *, int); void add_certificate_file(Options *, const char *, int); #endif /* READCONF_H */ diff --git a/crypto/openssh/regress/Makefile b/crypto/openssh/regress/Makefile index c21b0215a8cd..f5cb9bd4779d 100644 --- a/crypto/openssh/regress/Makefile +++ b/crypto/openssh/regress/Makefile @@ -1,287 +1,293 @@ -# $OpenBSD: Makefile,v 1.126 2023/09/06 23:36:09 djm Exp $ +# $OpenBSD: Makefile,v 1.131 2023/12/18 14:50:08 djm Exp $ tests: prep file-tests t-exec unit REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 # File based tests file-tests: $(REGRESS_TARGETS) # Interop tests are not run by default interop interop-tests: t-exec-interop +extra extra-tests: t-extra + prep: test "x${USE_VALGRIND}" = "x" || mkdir -p $(OBJ)/valgrind-out clean: for F in $(CLEANFILES); do rm -f $(OBJ)$$F; done rm -rf $(OBJ).putty + rm -rf $(OBJ).dropbear distclean: clean LTESTS= connect \ proxy-connect \ sshfp-connect \ connect-privsep \ connect-uri \ proto-version \ proto-mismatch \ exit-status \ exit-status-signal \ envpass \ transfer \ banner \ rekey \ dhgex \ stderr-data \ stderr-after-eof \ broken-pipe \ try-ciphers \ yes-head \ login-timeout \ agent \ agent-getpeereid \ agent-timeout \ agent-ptrace \ agent-subprocess \ keyscan \ keygen-change \ keygen-comment \ keygen-convert \ keygen-knownhosts \ keygen-moduli \ keygen-sshfp \ key-options \ scp \ scp3 \ scp-uri \ sftp \ sftp-chroot \ sftp-cmds \ sftp-badcmds \ sftp-batch \ sftp-glob \ sftp-perm \ sftp-uri \ reconfigure \ dynamic-forward \ forwarding \ multiplex \ reexec \ brokenkeys \ sshcfgparse \ cfgparse \ cfgmatch \ cfgmatchlisten \ percent \ addrmatch \ localcommand \ forcecommand \ portnum \ keytype \ kextype \ cert-hostkey \ cert-userkey \ host-expand \ keys-command \ forward-control \ integrity \ krl \ multipubkey \ limit-keytype \ hostkey-agent \ hostkey-rotate \ principals-command \ cert-file \ cfginclude \ servcfginclude \ allow-deny-users \ authinfo \ sshsig \ knownhosts \ knownhosts-command \ agent-restrict \ hostbased \ channel-timeout \ connection-timeout \ - match-subsystem + match-subsystem \ + agent-pkcs11-restrict \ + agent-pkcs11-cert INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers +INTEROP_TESTS+= dropbear-ciphers dropbear-kex #INTEROP_TESTS+=ssh-com ssh-com-client ssh-com-keygen ssh-com-sftp EXTRA_TESTS= agent-pkcs11 #EXTRA_TESTS+= cipher-speed USERNAME= ${LOGNAME} CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \ authorized_keys_${USERNAME}.* \ authorized_principals_${USERNAME} \ banner.in banner.out cert_host_key* cert_user_key* \ copy.1 copy.2 data ed25519-agent ed25519-agent* \ ed25519-agent.pub ed25519 ed25519.pub empty.in \ expect failed-regress.log failed-ssh.log failed-sshd.log \ hkr.* host.ecdsa-sha2-nistp256 host.ecdsa-sha2-nistp384 \ host.ecdsa-sha2-nistp521 host.ssh-dss host.ssh-ed25519 \ host.ssh-rsa host_ca_key* host_krl_* host_revoked_* key.* \ key.dsa-* key.ecdsa-* key.ed25519-512 \ key.ed25519-512.pub key.rsa-* keys-command-args kh.* askpass \ known_hosts known_hosts-cert known_hosts.* krl-* ls.copy \ modpipe netcat no_identity_config \ pidfile putty.rsa2 ready regress.log remote_pid \ revoked-* rsa rsa-agent rsa-agent.pub rsa.pub rsa_ssh2_cr.prv \ rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \ scp-ssh-wrapper.scp setuid-allowed sftp-server.log \ sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \ ssh-agent.log ssh-add.log slow-sftp-server.sh \ ssh-rsa_oldfmt knownhosts_command \ ssh_config ssh_config.* ssh_proxy ssh_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 \ timestamp testdata user_*key* user_ca* user_key* # Enable all malloc(3) randomisations and checks TEST_ENV= "MALLOC_OPTIONS=CFGJRSUX" TEST_SSH_SSHKEYGEN?=ssh-keygen CPPFLAGS=-I.. t1: ${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/rsa_ssh2.prv | diff - ${.CURDIR}/rsa_openssh.prv tr '\n' '\r' <${.CURDIR}/rsa_ssh2.prv > ${.OBJDIR}/rsa_ssh2_cr.prv ${TEST_SSH_SSHKEYGEN} -if ${.OBJDIR}/rsa_ssh2_cr.prv | diff - ${.CURDIR}/rsa_openssh.prv awk '{print $$0 "\r"}' ${.CURDIR}/rsa_ssh2.prv > ${.OBJDIR}/rsa_ssh2_crnl.prv ${TEST_SSH_SSHKEYGEN} -if ${.OBJDIR}/rsa_ssh2_crnl.prv | diff - ${.CURDIR}/rsa_openssh.prv t2: cat ${.CURDIR}/rsa_openssh.prv > $(OBJ)/t2.out chmod 600 $(OBJ)/t2.out ${TEST_SSH_SSHKEYGEN} -yf $(OBJ)/t2.out | diff - ${.CURDIR}/rsa_openssh.pub t3: ${TEST_SSH_SSHKEYGEN} -ef ${.CURDIR}/rsa_openssh.pub >$(OBJ)/t3.out ${TEST_SSH_SSHKEYGEN} -if $(OBJ)/t3.out | diff - ${.CURDIR}/rsa_openssh.pub t4: ${TEST_SSH_SSHKEYGEN} -E md5 -lf ${.CURDIR}/rsa_openssh.pub |\ awk '{print $$2}' | diff - ${.CURDIR}/t4.ok t5: ${TEST_SSH_SSHKEYGEN} -Bf ${.CURDIR}/rsa_openssh.pub |\ awk '{print $$2}' | diff - ${.CURDIR}/t5.ok t6: ${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/dsa_ssh2.prv > $(OBJ)/t6.out1 ${TEST_SSH_SSHKEYGEN} -if ${.CURDIR}/dsa_ssh2.pub > $(OBJ)/t6.out2 chmod 600 $(OBJ)/t6.out1 ${TEST_SSH_SSHKEYGEN} -yf $(OBJ)/t6.out1 | diff - $(OBJ)/t6.out2 $(OBJ)/t7.out: ${TEST_SSH_SSHKEYGEN} -q -t rsa -N '' -f $@ t7: $(OBJ)/t7.out ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t7.out > /dev/null ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t7.out > /dev/null $(OBJ)/t8.out: ${TEST_SSH_SSHKEYGEN} -q -t dsa -N '' -f $@ t8: $(OBJ)/t8.out ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t8.out > /dev/null ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t8.out > /dev/null $(OBJ)/t9.out: ! ${TEST_SSH_SSH} -Q key-plain | grep ecdsa >/dev/null || \ ${TEST_SSH_SSHKEYGEN} -q -t ecdsa -N '' -f $@ t9: $(OBJ)/t9.out ! ${TEST_SSH_SSH} -Q key-plain | grep ecdsa >/dev/null || \ ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t9.out > /dev/null ! ${TEST_SSH_SSH} -Q key-plain | grep ecdsa >/dev/null || \ ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t9.out > /dev/null $(OBJ)/t10.out: ${TEST_SSH_SSHKEYGEN} -q -t ed25519 -N '' -f $@ t10: $(OBJ)/t10.out ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t10.out > /dev/null ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t10.out > /dev/null t11: ${TEST_SSH_SSHKEYGEN} -E sha256 -lf ${.CURDIR}/rsa_openssh.pub |\ awk '{print $$2}' | diff - ${.CURDIR}/t11.ok $(OBJ)/t12.out: ${TEST_SSH_SSHKEYGEN} -q -t ed25519 -N '' -C 'test-comment-1234' -f $@ t12: $(OBJ)/t12.out ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t12.out.pub | grep test-comment-1234 >/dev/null t-exec: ${LTESTS:=.sh} @if [ "x$?" = "x" ]; then exit 0; fi; \ _started=""; test -z "${LTESTS_FROM}" && _started=1 ;\ for TEST in ""$?; do \ if [ -z "$$_started" ] ; then \ if [ "x$$TEST" = "x${LTESTS_FROM}.sh" ]; then \ _started=1; \ else \ continue; \ fi ; \ fi ; \ skip=no; \ for t in ""$${SKIP_LTESTS}; do \ if [ "x$${t}.sh" = "x$${TEST}" ]; then skip=yes; fi; \ done; \ if [ "x$${skip}" = "xno" ]; then \ echo "run test $${TEST}" ... 1>&2; \ (env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \ else \ echo skip test $${TEST} 1>&2; \ fi; \ done t-exec-interop: ${INTEROP_TESTS:=.sh} @if [ "x$?" = "x" ]; then exit 0; fi; \ for TEST in ""$?; do \ echo "run test $${TEST}" ... 1>&2; \ (env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \ done t-extra: ${EXTRA_TESTS:=.sh} @if [ "x$?" = "x" ]; then exit 0; fi; \ for TEST in ""$?; do \ echo "run test $${TEST}" ... 1>&2; \ (env SUDO="${SUDO}" TEST_ENV=${TEST_ENV} ${TEST_SHELL} ${.CURDIR}/test-exec.sh ${.OBJDIR} ${.CURDIR}/$${TEST}) || exit $$?; \ done # Not run by default interop: ${INTEROP_TARGETS} # Unit tests, built by top-level Makefile unit: set -e ; if test -z "${SKIP_UNIT}" ; then \ V="" ; \ test "x${USE_VALGRIND}" = "x" || \ V=${.CURDIR}/valgrind-unit.sh ; \ $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ -d ${.CURDIR}/unittests/sshkey/testdata ; \ $$V ${.OBJDIR}/unittests/sshsig/test_sshsig \ -d ${.CURDIR}/unittests/sshsig/testdata ; \ $$V ${.OBJDIR}/unittests/authopt/test_authopt \ -d ${.CURDIR}/unittests/authopt/testdata ; \ $$V ${.OBJDIR}/unittests/bitmap/test_bitmap ; \ $$V ${.OBJDIR}/unittests/conversion/test_conversion ; \ $$V ${.OBJDIR}/unittests/kex/test_kex ; \ $$V ${.OBJDIR}/unittests/hostkeys/test_hostkeys \ -d ${.CURDIR}/unittests/hostkeys/testdata ; \ $$V ${.OBJDIR}/unittests/match/test_match ; \ $$V ${.OBJDIR}/unittests/misc/test_misc ; \ if test "x${TEST_SSH_UTF8}" = "xyes" ; then \ $$V ${.OBJDIR}/unittests/utf8/test_utf8 ; \ fi \ fi diff --git a/crypto/openssh/regress/agent-pkcs11-cert.sh b/crypto/openssh/regress/agent-pkcs11-cert.sh new file mode 100644 index 000000000000..4e8f748465a3 --- /dev/null +++ b/crypto/openssh/regress/agent-pkcs11-cert.sh @@ -0,0 +1,92 @@ +# $OpenBSD: agent-pkcs11-cert.sh,v 1.1 2023/12/18 14:50:08 djm Exp $ +# Placed in the Public Domain. + +tid="pkcs11 agent certificate test" + +SSH_AUTH_SOCK="$OBJ/agent.sock" +export SSH_AUTH_SOCK +LC_ALL=C +export LC_ALL +p11_setup || skip "No PKCS#11 library found" + +rm -f $SSH_AUTH_SOCK $OBJ/agent.log +rm -f $OBJ/output_* $OBJ/expect_* +rm -f $OBJ/ca* + +trace "generate CA key and certify keys" +$SSHKEYGEN -q -t ed25519 -C ca -N '' -f $OBJ/ca || fatal "ssh-keygen CA failed" +$SSHKEYGEN -qs $OBJ/ca -I "ecdsa_key" -n $USER -z 1 ${SSH_SOFTHSM_DIR}/EC.pub || + fatal "certify ECDSA key failed" +$SSHKEYGEN -qs $OBJ/ca -I "rsa_key" -n $USER -z 2 ${SSH_SOFTHSM_DIR}/RSA.pub || + fatal "certify RSA key failed" +$SSHKEYGEN -qs $OBJ/ca -I "ca_ca" -n $USER -z 3 $OBJ/ca.pub || + fatal "certify CA key failed" + +rm -f $SSH_AUTH_SOCK +trace "start agent" +${SSHAGENT} ${EXTRA_AGENT_ARGS} -d -a $SSH_AUTH_SOCK > $OBJ/agent.log 2>&1 & +AGENT_PID=$! +trap "kill $AGENT_PID" EXIT +for x in 0 1 2 3 4 ; do + # Give it a chance to start + ${SSHADD} -l > /dev/null 2>&1 + r=$? + test $r -eq 1 && break + sleep 1 +done +if [ $r -ne 1 ]; then + fatal "ssh-add -l did not fail with exit code 1 (got $r)" +fi + +trace "load pkcs11 keys and certs" +# Note: deliberately contains non-cert keys and non-matching cert on commandline +p11_ssh_add -qs ${TEST_SSH_PKCS11} \ + $OBJ/ca.pub \ + ${SSH_SOFTHSM_DIR}/EC.pub \ + ${SSH_SOFTHSM_DIR}/EC-cert.pub \ + ${SSH_SOFTHSM_DIR}/RSA.pub \ + ${SSH_SOFTHSM_DIR}/RSA-cert.pub || + fatal "failed to add keys" +# Verify their presence +cut -d' ' -f1-2 \ + ${SSH_SOFTHSM_DIR}/EC.pub \ + ${SSH_SOFTHSM_DIR}/RSA.pub \ + ${SSH_SOFTHSM_DIR}/EC-cert.pub \ + ${SSH_SOFTHSM_DIR}/RSA-cert.pub | sort > $OBJ/expect_list +$SSHADD -L | cut -d' ' -f1-2 | sort > $OBJ/output_list +diff $OBJ/expect_list $OBJ/output_list + +# Verify that all can perform signatures. +for x in ${SSH_SOFTHSM_DIR}/EC.pub ${SSH_SOFTHSM_DIR}/RSA.pub \ + ${SSH_SOFTHSM_DIR}/EC-cert.pub ${SSH_SOFTHSM_DIR}/RSA-cert.pub ; do + $SSHADD -T $x || fail "Signing failed for $x" +done + +# Delete plain keys. +$SSHADD -qd ${SSH_SOFTHSM_DIR}/EC.pub ${SSH_SOFTHSM_DIR}/RSA.pub +# Verify that certs can still perform signatures. +for x in ${SSH_SOFTHSM_DIR}/EC-cert.pub ${SSH_SOFTHSM_DIR}/RSA-cert.pub ; do + $SSHADD -T $x || fail "Signing failed for $x" +done + +$SSHADD -qD >/dev/null || fatal "clear agent failed" + +trace "load pkcs11 certs only" +p11_ssh_add -qCs ${TEST_SSH_PKCS11} \ + $OBJ/ca.pub \ + ${SSH_SOFTHSM_DIR}/EC.pub \ + ${SSH_SOFTHSM_DIR}/EC-cert.pub \ + ${SSH_SOFTHSM_DIR}/RSA.pub \ + ${SSH_SOFTHSM_DIR}/RSA-cert.pub || + fatal "failed to add keys" +# Verify their presence +cut -d' ' -f1-2 \ + ${SSH_SOFTHSM_DIR}/EC-cert.pub \ + ${SSH_SOFTHSM_DIR}/RSA-cert.pub | sort > $OBJ/expect_list +$SSHADD -L | cut -d' ' -f1-2 | sort > $OBJ/output_list +diff $OBJ/expect_list $OBJ/output_list + +# Verify that certs can perform signatures. +for x in ${SSH_SOFTHSM_DIR}/EC-cert.pub ${SSH_SOFTHSM_DIR}/RSA-cert.pub ; do + $SSHADD -T $x || fail "Signing failed for $x" +done diff --git a/crypto/openssh/regress/agent-pkcs11-restrict.sh b/crypto/openssh/regress/agent-pkcs11-restrict.sh new file mode 100644 index 000000000000..867253211714 --- /dev/null +++ b/crypto/openssh/regress/agent-pkcs11-restrict.sh @@ -0,0 +1,193 @@ +# $OpenBSD: agent-pkcs11-restrict.sh,v 1.1 2023/12/18 14:49:39 djm Exp $ +# Placed in the Public Domain. + +tid="pkcs11 agent constraint test" + +p11_setup || skip "No PKCS#11 library found" + +rm -f $SSH_AUTH_SOCK $OBJ/agent.log $OBJ/host_[abcx]* $OBJ/user_[abcx]* +rm -f $OBJ/sshd_proxy_host* $OBJ/ssh_output* $OBJ/expect_* +rm -f $OBJ/ssh_proxy[._]* $OBJ/command $OBJ/authorized_keys_* + +trace "generate host keys" +for h in a b x ca ; do + $SSHKEYGEN -q -t ed25519 -C host_$h -N '' -f $OBJ/host_$h || \ + fatal "ssh-keygen hostkey failed" +done + +# XXX test CA hostcerts too. + +key_for() { + case $h in + a) K="${SSH_SOFTHSM_DIR}/RSA.pub" ;; + b) K="${SSH_SOFTHSM_DIR}/EC.pub" ;; + *) K="" ;; + esac + export K +} + +SSH_AUTH_SOCK="$OBJ/agent.sock" +export SSH_AUTH_SOCK +rm -f $SSH_AUTH_SOCK +trace "start agent" +${SSHAGENT} ${EXTRA_AGENT_ARGS} -d -a $SSH_AUTH_SOCK > $OBJ/agent.log 2>&1 & +AGENT_PID=$! +trap "kill $AGENT_PID" EXIT +for x in 0 1 2 3 4 ; do + # Give it a chance to start + ${SSHADD} -l > /dev/null 2>&1 + r=$? + test $r -eq 1 && break + sleep 1 +done +if [ $r -ne 1 ]; then + fatal "ssh-add -l did not fail with exit code 1 (got $r)" +fi + +# XXX a lot of this is a copy of agent-restrict.sh, but I couldn't see a nice +# way to factor it out -djm + +trace "prepare client config" +egrep -vi '(identityfile|hostname|hostkeyalias|proxycommand)' \ + $OBJ/ssh_proxy > $OBJ/ssh_proxy.bak +cat << _EOF > $OBJ/ssh_proxy +IdentitiesOnly yes +ForwardAgent yes +ExitOnForwardFailure yes +_EOF +cp $OBJ/ssh_proxy $OBJ/ssh_proxy_noid +for h in a b ; do + key_for $h + cat << _EOF >> $OBJ/ssh_proxy +Host host_$h + Hostname host_$h + HostkeyAlias host_$h + IdentityFile $K + ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h +_EOF + # Variant with no specified keys. + cat << _EOF >> $OBJ/ssh_proxy_noid +Host host_$h + Hostname host_$h + HostkeyAlias host_$h + ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h +_EOF +done +cat $OBJ/ssh_proxy.bak >> $OBJ/ssh_proxy +cat $OBJ/ssh_proxy.bak >> $OBJ/ssh_proxy_noid + +LC_ALL=C +export LC_ALL +echo "SetEnv LC_ALL=${LC_ALL}" >> sshd_proxy + +trace "prepare known_hosts" +rm -f $OBJ/known_hosts +for h in a b x ; do + (printf "host_$h " ; cat $OBJ/host_${h}.pub) >> $OBJ/known_hosts +done + +trace "prepare server configs" +egrep -vi '(hostkey|pidfile)' $OBJ/sshd_proxy \ + > $OBJ/sshd_proxy.bak +for h in a b ; do + cp $OBJ/sshd_proxy.bak $OBJ/sshd_proxy_host_$h + cat << _EOF >> $OBJ/sshd_proxy_host_$h +ExposeAuthInfo yes +Hostkey $OBJ/host_$h +_EOF + cp $OBJ/sshd_proxy_host_$h $OBJ/sshd_proxy_host_${h}.bak +done + +trace "prepare authorized_keys" +cat >> $OBJ/command << EOF +#!/bin/sh +echo USERAUTH +cat \$SSH_USER_AUTH +echo AGENT +if $SSHADD -ql >/dev/null 2>&1 ; then + $SSHADD -L | cut -d' ' -f1-2 | sort +else + echo NONE +fi +EOF +chmod a+x $OBJ/command +>$OBJ/authorized_keys_$USER +for h in a b ; do + key_for $h + (printf "%s" "restrict,agent-forwarding,command=\"$OBJ/command\" "; + cat $K) >> $OBJ/authorized_keys_$USER +done + +trace "unrestricted keys" +$SSHADD -qD >/dev/null || fatal "clear agent failed" +p11_ssh_add -qs ${TEST_SSH_PKCS11} || + fatal "failed to add keys" +for h in a b ; do + key_for $h + echo USERAUTH > $OBJ/expect_$h + printf "publickey " >> $OBJ/expect_$h + cat $K >> $OBJ/expect_$h + echo AGENT >> $OBJ/expect_$h + $SSHADD -L | cut -d' ' -f1-2 | sort >> $OBJ/expect_$h + ${SSH} -F $OBJ/ssh_proxy -oIdentityFile=$K \ + host_$h true > $OBJ/ssh_output || fatal "test ssh $h failed" + cmp $OBJ/expect_$h $OBJ/ssh_output || fatal "unexpected output" +done + +trace "restricted to different host" +$SSHADD -qD >/dev/null || fatal "clear agent failed" +p11_ssh_add -q -h host_x -s ${TEST_SSH_PKCS11} -H $OBJ/known_hosts || + fatal "failed to add keys" +for h in a b ; do + key_for $h + ${SSH} -F $OBJ/ssh_proxy -oIdentityFile=$K \ + host_$h true > $OBJ/ssh_output && fatal "test ssh $h succeeded" +done + +trace "restricted to destination host" +$SSHADD -qD >/dev/null || fatal "clear agent failed" +p11_ssh_add -q -h host_a -h host_b -s ${TEST_SSH_PKCS11} -H $OBJ/known_hosts || + fatal "failed to add keys" +for h in a b ; do + key_for $h + echo USERAUTH > $OBJ/expect_$h + printf "publickey " >> $OBJ/expect_$h + cat $K >> $OBJ/expect_$h + echo AGENT >> $OBJ/expect_$h + echo NONE >> $OBJ/expect_$h + ${SSH} -F $OBJ/ssh_proxy -oIdentityFile=$K \ + host_$h true > $OBJ/ssh_output || fatal "test ssh $h failed" + cmp $OBJ/expect_$h $OBJ/ssh_output || fatal "unexpected output" +done + +trace "restricted multihop" +$SSHADD -qD >/dev/null || fatal "clear agent failed" +p11_ssh_add -q -h host_a -h "host_a>host_b" \ + -s ${TEST_SSH_PKCS11} -H $OBJ/known_hosts || fatal "failed to add keys" +key_for a +AK=$K +key_for b +BK=$K +# Prepare authorized_keys file to additionally ssh to host_b +_command="echo LOCAL ; ${OBJ}/command ; echo REMOTE; ${SSH} -AF $OBJ/ssh_proxy -oIdentityFile=$BK host_b" +(printf "%s" "restrict,agent-forwarding,command=\"$_command\" "; + cat $BK) > $OBJ/authorized_keys_a +grep -vi AuthorizedKeysFile $OBJ/sshd_proxy_host_a.bak > $OBJ/sshd_proxy_host_a +echo "AuthorizedKeysFile $OBJ/authorized_keys_a" >> $OBJ/sshd_proxy_host_a +# Prepare expected output from both hosts. +echo LOCAL > $OBJ/expect_a +echo USERAUTH >> $OBJ/expect_a +printf "publickey " >> $OBJ/expect_a +cat $AK >> $OBJ/expect_a +echo AGENT >> $OBJ/expect_a +$SSHADD -L | cut -d' ' -f1-2 | sort >> $OBJ/expect_a +echo REMOTE >> $OBJ/expect_a +echo USERAUTH >> $OBJ/expect_a +printf "publickey " >> $OBJ/expect_a +cat $BK >> $OBJ/expect_a +echo AGENT >> $OBJ/expect_a +echo NONE >> $OBJ/expect_a +${SSH} -AF $OBJ/ssh_proxy -oIdentityFile=$AK \ + host_a whatever > $OBJ/ssh_output || fatal "test ssh $h failed" +cmp $OBJ/expect_a $OBJ/ssh_output || fatal "unexpected output" + diff --git a/crypto/openssh/regress/agent-pkcs11.sh b/crypto/openssh/regress/agent-pkcs11.sh index 268a70de8885..304734f4b484 100644 --- a/crypto/openssh/regress/agent-pkcs11.sh +++ b/crypto/openssh/regress/agent-pkcs11.sh @@ -1,124 +1,54 @@ -# $OpenBSD: agent-pkcs11.sh,v 1.9 2021/07/25 12:13:03 dtucker Exp $ +# $OpenBSD: agent-pkcs11.sh,v 1.13 2023/10/30 23:00:25 djm Exp $ # Placed in the Public Domain. tid="pkcs11 agent test" -try_token_libs() { - for _lib in "$@" ; do - if test -f "$_lib" ; then - verbose "Using token library $_lib" - TEST_SSH_PKCS11="$_lib" - return - fi - done - echo "skipped: Unable to find PKCS#11 token library" - exit 0 -} - -try_token_libs \ - /usr/local/lib/softhsm/libsofthsm2.so \ - /usr/lib64/pkcs11/libsofthsm2.so \ - /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so - -TEST_SSH_PIN=1234 -TEST_SSH_SOPIN=12345678 -if [ "x$TEST_SSH_SSHPKCS11HELPER" != "x" ]; then - SSH_PKCS11_HELPER="${TEST_SSH_SSHPKCS11HELPER}" - export SSH_PKCS11_HELPER -fi - -test -f "$TEST_SSH_PKCS11" || fatal "$TEST_SSH_PKCS11 does not exist" - -# setup environment for softhsm2 token -DIR=$OBJ/SOFTHSM -rm -rf $DIR -TOKEN=$DIR/tokendir -mkdir -p $TOKEN -SOFTHSM2_CONF=$DIR/softhsm2.conf -export SOFTHSM2_CONF -cat > $SOFTHSM2_CONF << EOF -# SoftHSM v2 configuration file -directories.tokendir = ${TOKEN} -objectstore.backend = file -# ERROR, WARNING, INFO, DEBUG -log.level = DEBUG -# If CKF_REMOVABLE_DEVICE flag should be set -slots.removable = false -EOF -out=$(softhsm2-util --init-token --free --label token-slot-0 --pin "$TEST_SSH_PIN" --so-pin "$TEST_SSH_SOPIN") -slot=$(echo -- $out | sed 's/.* //') - -# prevent ssh-agent from calling ssh-askpass -SSH_ASKPASS=/usr/bin/true -export SSH_ASKPASS -unset DISPLAY - -# start command w/o tty, so ssh-add accepts pin from stdin -notty() { - perl -e 'use POSIX; POSIX::setsid(); - if (fork) { wait; exit($? >> 8); } else { exec(@ARGV) }' "$@" -} - -trace "generating keys" -RSA=${DIR}/RSA -EC=${DIR}/EC -$OPENSSL_BIN genpkey -algorithm rsa > $RSA -$OPENSSL_BIN pkcs8 -nocrypt -in $RSA |\ - softhsm2-util --slot "$slot" --label 01 --id 01 --pin "$TEST_SSH_PIN" --import /dev/stdin -$OPENSSL_BIN genpkey \ - -genparam \ - -algorithm ec \ - -pkeyopt ec_paramgen_curve:prime256v1 |\ - $OPENSSL_BIN genpkey \ - -paramfile /dev/stdin > $EC -$OPENSSL_BIN pkcs8 -nocrypt -in $EC |\ - softhsm2-util --slot "$slot" --label 02 --id 02 --pin "$TEST_SSH_PIN" --import /dev/stdin +p11_setup || skip "No PKCS#11 library found" trace "start agent" eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null r=$? if [ $r -ne 0 ]; then fail "could not start ssh-agent: exit code $r" else trace "add pkcs11 key to agent" - echo ${TEST_SSH_PIN} | notty ${SSHADD} -s ${TEST_SSH_PKCS11} > /dev/null 2>&1 + p11_ssh_add -s ${TEST_SSH_PKCS11} > /dev/null 2>&1 r=$? if [ $r -ne 0 ]; then fail "ssh-add -s failed: exit code $r" fi trace "pkcs11 list via agent" ${SSHADD} -l > /dev/null 2>&1 r=$? if [ $r -ne 0 ]; then fail "ssh-add -l failed: exit code $r" fi for k in $RSA $EC; do trace "testing $k" - chmod 600 $k - ssh-keygen -y -f $k > $k.pub pub=$(cat $k.pub) - ${SSHADD} -L | grep -q "$pub" || fail "key $k missing in ssh-add -L" + ${SSHADD} -L | grep -q "$pub" || \ + fail "key $k missing in ssh-add -L" ${SSHADD} -T $k.pub || fail "ssh-add -T with $k failed" # add to authorized keys cat $k.pub > $OBJ/authorized_keys_$USER trace "pkcs11 connect via agent ($k)" ${SSH} -F $OBJ/ssh_proxy somehost exit 5 r=$? if [ $r -ne 5 ]; then fail "ssh connect failed (exit code $r)" fi done trace "remove pkcs11 keys" - echo ${TEST_SSH_PIN} | notty ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1 + p11_ssh_add -e ${TEST_SSH_PKCS11} > /dev/null 2>&1 r=$? if [ $r -ne 0 ]; then fail "ssh-add -e failed: exit code $r" fi trace "kill agent" ${SSHAGENT} -k > /dev/null fi diff --git a/crypto/openssh/regress/conch-ciphers.sh b/crypto/openssh/regress/conch-ciphers.sh index 6678813a2bdb..26b606d653b2 100644 --- a/crypto/openssh/regress/conch-ciphers.sh +++ b/crypto/openssh/regress/conch-ciphers.sh @@ -1,28 +1,31 @@ -# $OpenBSD: conch-ciphers.sh,v 1.4 2019/07/05 04:12:46 dtucker Exp $ +# $OpenBSD: conch-ciphers.sh,v 1.7 2023/10/26 12:44:07 dtucker Exp $ # Placed in the Public Domain. tid="conch ciphers" if test "x$REGRESS_INTEROP_CONCH" != "xyes" ; then - echo "conch interop tests not enabled" - exit 0 + skip "conch interop tests not enabled" +fi + +if ! [ -t 0 ]; then + skip "conch interop tests requires a controlling terminal" fi start_sshd for c in aes256-ctr aes256-cbc aes192-ctr aes192-cbc aes128-ctr aes128-cbc \ cast128-cbc blowfish 3des-cbc ; do verbose "$tid: cipher $c" rm -f ${COPY} # XXX the 2nd "cat" seems to be needed because of buggy FD handling # in conch - ${CONCH} --identity $OBJ/ssh-rsa --port $PORT --user $USER -e none \ + ${CONCH} --identity $OBJ/ssh-ed25519 --port $PORT --user $USER -e none \ --known-hosts $OBJ/known_hosts --notty --noagent --nox11 -n \ 127.0.0.1 "cat ${DATA}" 2>/dev/null | cat > ${COPY} if [ $? -ne 0 ]; then fail "ssh cat $DATA failed" fi cmp ${DATA} ${COPY} || fail "corrupted copy" done rm -f ${COPY} diff --git a/crypto/openssh/regress/dropbear-ciphers.sh b/crypto/openssh/regress/dropbear-ciphers.sh new file mode 100644 index 000000000000..2e0f9a1d337f --- /dev/null +++ b/crypto/openssh/regress/dropbear-ciphers.sh @@ -0,0 +1,33 @@ +# $OpenBSD: dropbear-ciphers.sh,v 1.1 2023/10/20 06:56:45 dtucker Exp $ +# Placed in the Public Domain. + +tid="dropbear ciphers" + +if test "x$REGRESS_INTEROP_DROPBEAR" != "xyes" ; then + skip "dropbear interop tests not enabled" +fi + +cat >>$OBJ/sshd_proxy <&1 | awk '/ ciphers: /{print $4}' | tr ',' ' '` +macs=`$DBCLIENT -m help 2>&1 | awk '/ MACs: /{print $4}' | tr ',' ' '` +keytype=`(cd $OBJ/.dropbear && ls id_*)` + +for c in $ciphers ; do + for m in $macs; do + for kt in $keytype; do + verbose "$tid: cipher $c mac $m kt $kt" + rm -f ${COPY} + env HOME=$OBJ dbclient -y -i $OBJ/.dropbear/$kt 2>$OBJ/dbclient.log \ + -c $c -m $m -J "$OBJ/ssh_proxy.sh" somehost cat ${DATA} > ${COPY} + if [ $? -ne 0 ]; then + fail "ssh cat $DATA failed" + fi + cmp ${DATA} ${COPY} || fail "corrupted copy" + done + done +done +rm -f ${COPY} diff --git a/crypto/openssh/regress/dropbear-kex.sh b/crypto/openssh/regress/dropbear-kex.sh new file mode 100644 index 000000000000..a25de3eddb7c --- /dev/null +++ b/crypto/openssh/regress/dropbear-kex.sh @@ -0,0 +1,31 @@ +# $OpenBSD: dropbear-kex.sh,v 1.1 2023/10/20 06:56:45 dtucker Exp $ +# Placed in the Public Domain. + +tid="dropbear kex" + +if test "x$REGRESS_INTEROP_DROPBEAR" != "xyes" ; then + skip "dropbear interop tests not enabled" +fi + +cat >>$OBJ/sshd_proxy <$OBJ/sshd_proxy + env HOME=$OBJ dbclient -y -i $OBJ/.dropbear/id_rsa 2>$OBJ/dbclient.log \ + -J "$OBJ/ssh_proxy.sh" somehost cat ${DATA} > ${COPY} + if [ $? -ne 0 ]; then + fail "ssh cat $DATA failed" + fi + cmp ${DATA} ${COPY} || fail "corrupted copy" +done +rm -f ${COPY} diff --git a/crypto/openssh/regress/forcecommand.sh b/crypto/openssh/regress/forcecommand.sh index e756600a6f9d..825ab25a0648 100644 --- a/crypto/openssh/regress/forcecommand.sh +++ b/crypto/openssh/regress/forcecommand.sh @@ -1,35 +1,67 @@ -# $OpenBSD: forcecommand.sh,v 1.5 2023/05/12 06:36:27 djm Exp $ +# $OpenBSD: forcecommand.sh,v 1.7 2023/11/01 02:08:38 dtucker Exp $ # Placed in the Public Domain. tid="forced command" cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak -cp /dev/null $OBJ/authorized_keys_$USER -for t in ${SSH_KEYTYPES}; do - printf 'command="true" ' >>$OBJ/authorized_keys_$USER - cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER -done +authorized_keys() { + cmd=$1 + cp /dev/null $OBJ/authorized_keys_$USER + for t in ${SSH_KEYTYPES}; do + test -z "$cmd" || \ + printf "command=\"$cmd\" " >>$OBJ/authorized_keys_$USER + cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER + done +} + +trace "test config with sftp" +authorized_keys +rm -f $OBJ/ssh_proxy.tmp +echo "@get $OBJ/ssh_proxy $OBJ/ssh_proxy.tmp" | \ + ${SFTP} -S ${SSH} -b - -qF $OBJ/ssh_proxy somehost 2>/dev/null || \ + fail "sftp failed" +test -f "$OBJ/ssh_proxy.tmp" || fail "sftp did not download file" +rm -f $OBJ/ssh_proxy.tmp trace "forced command in key option" +authorized_keys true ${SSH} -F $OBJ/ssh_proxy somehost false || fail "forced command in key option" -cp /dev/null $OBJ/authorized_keys_$USER -for t in ${SSH_KEYTYPES}; do - printf 'command="false" ' >> $OBJ/authorized_keys_$USER - cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER -done - +authorized_keys false cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "ForceCommand true" >> $OBJ/sshd_proxy trace "forced command in sshd_config overrides key option" ${SSH} -F $OBJ/ssh_proxy somehost false || fail "forced command config" +authorized_keys cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "ForceCommand false" >> $OBJ/sshd_proxy + +trace "force command overriding subsystem" +echo "@get $OBJ/ssh_proxy $OBJ/ssh_proxy.tmp" | \ + ${SFTP} -S ${SSH} -F $OBJ/ssh_proxy -oLoglevel=quiet somehost && \ + fail "sftp succeeded" + echo "Match User $USER" >> $OBJ/sshd_proxy echo " ForceCommand true" >> $OBJ/sshd_proxy trace "forced command with match" ${SSH} -F $OBJ/ssh_proxy somehost false || fail "forced command match" + +trace "force command in match overriding subsystem" +echo "@get $OBJ/ssh_proxy $OBJ/ssh_proxy.tmp" | \ + ${SFTP} -S ${SSH} -F $OBJ/ssh_proxy -oLoglevel=quiet somehost && \ + fail "sftp succeeded" + +trace "force command to sftpserver" +grep -vi subsystem $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy +echo "Subsystem sftp /bin/false" >> $OBJ/sshd_proxy +echo "ForceCommand ${SFTPSERVER}" >> $OBJ/sshd_proxy +rm -f $OBJ/ssh_proxy.tmp +echo "@get $OBJ/ssh_proxy $OBJ/ssh_proxy.tmp" | \ + ${SFTP} -S ${SSH} -b - -qF $OBJ/ssh_proxy somehost 2>/dev/null || \ + fail "sftp failed" +test -f "$OBJ/ssh_proxy.tmp" || fail "sftp did not download file" +rm -f $OBJ/ssh_proxy.tmp diff --git a/crypto/openssh/regress/sshsig.sh b/crypto/openssh/regress/sshsig.sh index d4daa5c9dbde..dae03706d8f0 100644 --- a/crypto/openssh/regress/sshsig.sh +++ b/crypto/openssh/regress/sshsig.sh @@ -1,476 +1,540 @@ -# $OpenBSD: sshsig.sh,v 1.14 2022/02/01 23:37:15 djm Exp $ +# $OpenBSD: sshsig.sh,v 1.15 2023/10/12 03:51:08 djm Exp $ # Placed in the Public Domain. tid="sshsig" DATA2=$OBJ/${DATANAME}.2 cat ${DATA} ${DATA} > ${DATA2} rm -f $OBJ/sshsig-*.sig $OBJ/wrong-key* $OBJ/sigca-key* sig_namespace="test-$$" sig_principal="user-$$@example.com" # Make a "wrong key" ${SSHKEYGEN} -q -t ed25519 -f $OBJ/wrong-key \ -C "wrong trousers, Grommit" -N '' \ || fatal "couldn't generate key" WRONG=$OBJ/wrong-key.pub # Make a CA key. ${SSHKEYGEN} -q -t ed25519 -f $OBJ/sigca-key -C "CA" -N '' \ || fatal "couldn't generate key" CA_PRIV=$OBJ/sigca-key CA_PUB=$OBJ/sigca-key.pub trace "start agent" eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null r=$? if [ $r -ne 0 ]; then fatal "could not start ssh-agent: exit code $r" fi SIGNKEYS="$SSH_KEYTYPES" verbose "$tid: make certificates" for t in $SSH_KEYTYPES ; do ${SSHKEYGEN} -q -s $CA_PRIV -z $$ \ -I "regress signature key for $USER" \ -V "19840101:19860101" \ -n $sig_principal $OBJ/${t} || \ fatal "couldn't sign ${t}" SIGNKEYS="$SIGNKEYS ${t}-cert.pub" done for t in $SIGNKEYS; do verbose "$tid: check signature for $t" keybase=`basename $t .pub` privkey=${OBJ}/`basename $t -cert.pub` sigfile=${OBJ}/sshsig-${keybase}.sig sigfile_agent=${OBJ}/sshsig-agent-${keybase}.sig pubkey=${OBJ}/${keybase}.pub cert=${OBJ}/${keybase}-cert.pub sigfile_cert=${OBJ}/sshsig-${keybase}-cert.sig + trace "$tid: key type $t check bad hashlg" ${SSHKEYGEN} -vvv -Y sign -f ${OBJ}/$t -n $sig_namespace \ -Ohashalg=sha1 < $DATA > $sigfile 2>/dev/null && \ fail "sign using $t with bad hash algorithm succeeded" for h in default sha256 sha512 ; do case "$h" in default) hashalg_arg="" ;; *) hashalg_arg="-Ohashalg=$h" ;; esac + trace "$tid: key type $t sign with hash $h" ${SSHKEYGEN} -vvv -Y sign -f ${OBJ}/$t -n $sig_namespace \ $hashalg_arg < $DATA > $sigfile 2>/dev/null || \ fail "sign using $t / $h failed" (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers + trace "$tid: key type $t verify with hash $h" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 || \ fail "failed signature for $t / $h key" done + trace "$tid: key type $t verify with limited namespace" (printf "$sig_principal namespaces=\"$sig_namespace,whatever\" "; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 || \ fail "failed signature for $t key w/ limited namespace" + trace "$tid: key type $t print-pubkey" (printf "$sig_principal namespaces=\"$sig_namespace,whatever\" "; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -q -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -O print-pubkey \ < $DATA | cut -d' ' -f1-2 > ${OBJ}/${keybase}-fromsig.pub || \ fail "failed signature for $t key w/ print-pubkey" cut -d' ' -f1-2 ${OBJ}/${keybase}.pub > ${OBJ}/${keybase}-strip.pub diff -r ${OBJ}/${keybase}-strip.pub ${OBJ}/${keybase}-fromsig.pub || \ fail "print-pubkey differs from signature key" # Invalid option + trace "$tid: key type $t verify with bad signers" (printf "$sig_principal octopus " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with bad signers option" # Wrong key trusted. + trace "$tid: key type $t verify with wrong key" (printf "$sig_principal " ; cat $WRONG) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with wrong key trusted" # incorrect data + trace "$tid: key type $t verify with wrong data" (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA2 >/dev/null 2>&1 && \ fail "passed signature for wrong data with $t key" # wrong principal in signers + trace "$tid: key type $t verify with wrong principal" (printf "josef.k@example.com " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with wrong principal" # wrong namespace + trace "$tid: key type $t verify with wrong namespace" (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n COWS_COWS_COWS \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with wrong namespace" # namespace excluded by option + trace "$tid: key type $t verify with excluded namespace" (printf "$sig_principal namespaces=\"whatever\" " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with excluded namespace" ( printf "$sig_principal " ; printf "valid-after=\"19800101\",valid-before=\"19900101\" " ; cat $pubkey) > $OBJ/allowed_signers # key lifespan valid + trace "$tid: key type $t verify with valid lifespan" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19850101 \ < $DATA >/dev/null 2>&1 || \ fail "failed signature for $t key with valid expiry interval" # key not yet valid + trace "$tid: key type $t verify with not-yet-valid lifespan" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19790101 \ < $DATA >/dev/null 2>&1 && \ fail "failed signature for $t not-yet-valid key" # key expired + trace "$tid: key type $t verify with expired lifespan" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19910101 \ < $DATA >/dev/null 2>&1 && \ fail "failed signature for $t with expired key" # NB. assumes we're not running this test in the 1980s + trace "$tid: key type $t verify with expired lifespan (now)" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "failed signature for $t with expired key" # key lifespan valid + trace "$tid: key type $t find-principals with valid lifespan" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19850101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed find-principals for $t key with valid expiry interval" # key not yet valid + trace "$tid: key type $t find principals with not-yet-valid lifespan" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19790101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "failed find-principals for $t not-yet-valid key" # key expired + trace "$tid: key type $t find-principals with expired lifespan" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19990101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "failed find-principals for $t with expired key" # NB. assumes we're not running this test in the 1980s + trace "$tid: key type $t find-principals with expired lifespan (now)" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "failed find-principals for $t with expired key" # public key in revoked keys file + trace "$tid: key type $t verify with revoked key" cat $pubkey > $OBJ/revoked_keys (printf "$sig_principal namespaces=\"whatever\" " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -r $OBJ/revoked_keys \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key, but key is in revoked_keys" # public key not revoked, but others are present in revoked_keysfile + trace "$tid: key type $t verify with unrevoked key" cat $WRONG > $OBJ/revoked_keys (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -r $OBJ/revoked_keys \ < $DATA >/dev/null 2>&1 || \ fail "couldn't verify signature for $t key, but key not in revoked_keys" # check-novalidate with valid data + trace "$tid: key type $t check-novalidate with valid data" ${SSHKEYGEN} -vvv -Y check-novalidate -s $sigfile -n $sig_namespace \ < $DATA >/dev/null 2>&1 || \ fail "failed to check valid signature for $t key" # check-novalidate with invalid data + trace "$tid: key type $t check-novalidate with invalid data" ${SSHKEYGEN} -vvv -Y check-novalidate -s $sigfile -n $sig_namespace \ < $DATA2 >/dev/null 2>&1 && \ fail "succeeded checking signature for $t key with invalid data" # find-principals with valid public key + trace "$tid: key type $t find-principals with valid key" (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed to find valid principals in allowed_signers" # find-principals with wrong key not in allowed_signers + trace "$tid: key type $t find-principals with wrong key" (printf "$sig_principal " ; cat $WRONG) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "succeeded finding principal with invalid signers file" # find-principals with a configured namespace but none on command-line + trace "$tid: key type $t find-principals with missing namespace" (printf "$sig_principal " ; printf "namespaces=\"test1,test2\" "; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed finding principal when namespaces are configured" # Check signing keys using ssh-agent. + trace "$tid: key type $t prepare agent" ${SSHADD} -D >/dev/null 2>&1 # Remove all previously-loaded keys. ${SSHADD} ${privkey} > /dev/null 2>&1 || fail "ssh-add failed" # Move private key to ensure agent key is used mv ${privkey} ${privkey}.tmp + trace "$tid: key type $t sign with agent" ${SSHKEYGEN} -vvv -Y sign -f $pubkey -n $sig_namespace \ < $DATA > $sigfile_agent 2>/dev/null || \ fail "ssh-agent based sign using $pubkey failed" + trace "$tid: key type $t check signature w/ agent" ${SSHKEYGEN} -vvv -Y check-novalidate -s $sigfile_agent \ -n $sig_namespace < $DATA >/dev/null 2>&1 || \ fail "failed to check valid signature for $t key" + (printf "$sig_principal namespaces=\"$sig_namespace,whatever\" "; + cat $pubkey) > $OBJ/allowed_signers + ${SSHKEYGEN} -vvv -Y verify -s $sigfile_agent -n $sig_namespace \ + -I $sig_principal -f $OBJ/allowed_signers \ + < $DATA >/dev/null 2>&1 || \ + fail "failed signature for $t key w/ limited namespace" # Move private key back mv ${privkey}.tmp ${privkey} # Duplicate principals & keys in allowed_signers but with different validities ( printf "$sig_principal " ; printf "valid-after=\"19800101\",valid-before=\"19900101\" " ; cat $pubkey; printf "${sig_principal} " ; printf "valid-after=\"19850101\",valid-before=\"20000101\" " ; cat $pubkey) > $OBJ/allowed_signers # find-principals outside of any validity lifespan + trace "$tid: key type $t find principals outside multiple validities" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="20100101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "succeeded find-principals for $t verify-time outside of validity" # find-principals matching only the first lifespan + trace "$tid: key type $t find principals matching one validity (1st)" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19830101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed find-principals for $t verify-time within first span" # find-principals matching both lifespans + trace "$tid: key type $t find principals matching two validities" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19880101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed find-principals for $t verify-time within both spans" # find-principals matching only the second lifespan + trace "$tid: key type $t find principals matching one validity (2nd)" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19950101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed find-principals for $t verify-time within second span" # verify outside of any validity lifespan + trace "$tid: key type $t verify outside multiple validities" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -Overify-time="20100101" -I $sig_principal \ -r $OBJ/revoked_keys -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "succeeded verify for $t verify-time outside of validity" # verify matching only the first lifespan + trace "$tid: key type $t verify matching one validity (1st)" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -Overify-time="19830101" -I $sig_principal \ -r $OBJ/revoked_keys -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 || \ fail "failed verify for $t verify-time within first span" # verify matching both lifespans + trace "$tid: key type $t verify matching two validities" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -Overify-time="19880101" -I $sig_principal \ -r $OBJ/revoked_keys -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 || \ fail "failed verify for $t verify-time within both spans" # verify matching only the second lifespan + trace "$tid: key type $t verify matching one validity (2nd)" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -Overify-time="19950101" -I $sig_principal \ -r $OBJ/revoked_keys -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 || \ fail "failed verify for $t verify-time within second span" # Remaining tests are for certificates only. case "$keybase" in *-cert) ;; *) continue ;; esac # Check key lifespan on find-principals when using the CA ( printf "$sig_principal " ; printf "cert-authority,valid-after=\"19800101\",valid-before=\"19900101\" "; cat $CA_PUB) > $OBJ/allowed_signers # key lifespan valid + trace "$tid: key type $t find-principals cert lifetime valid" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19850101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed find-principals for $t key with valid expiry interval" # key not yet valid + trace "$tid: key type $t find-principals cert lifetime not-yet-valid" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19790101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "failed find-principals for $t not-yet-valid key" # key expired + trace "$tid: key type $t find-principals cert lifetime expired" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time="19990101" \ -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "failed find-principals for $t with expired key" # NB. assumes we're not running this test in the 1980s + trace "$tid: key type $t find-principals cert lifetime expired (now)" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -f $OBJ/allowed_signers >/dev/null 2>&1 && \ fail "failed find-principals for $t with expired key" # correct CA key + trace "$tid: key type $t verify cert good CA" (printf "$sig_principal cert-authority " ; cat $CA_PUB) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19850101 \ < $DATA >/dev/null 2>&1 || \ fail "failed signature for $t cert" # find-principals + trace "$tid: key type $t find-principals cert good CA" ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time=19850101 \ -f $OBJ/allowed_signers >/dev/null 2>&1 || \ fail "failed find-principals for $t with ca key" # CA with wildcard principal + trace "$tid: key type $t find-principals cert good wildcard CA" (printf "*@example.com cert-authority " ; cat $CA_PUB) > $OBJ/allowed_signers # find-principals CA with wildcard principal ${SSHKEYGEN} -vvv -Y find-principals -s $sigfile \ -Overify-time=19850101 \ -f $OBJ/allowed_signers 2>/dev/null | \ fgrep "$sig_principal" >/dev/null || \ fail "failed find-principals for $t with ca key using wildcard principal" # verify CA with wildcard principal + trace "$tid: key type $t verify cert good wildcard CA" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19850101 \ < $DATA >/dev/null 2>&1 || \ fail "failed signature for $t cert using wildcard principal" # signing key listed as cert-authority + trace "$tid: key type $t verify signing key listed as CA" (printf "$sig_principal cert-authority " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature with $t key listed as CA" # CA key not flagged cert-authority + trace "$tid: key type $t verify key not marked as CA" (printf "$sig_principal " ; cat $CA_PUB) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t cert with CA not marked" # mismatch between cert principal and file + trace "$tid: key type $t verify cert with wrong principal" (printf "josef.k@example.com cert-authority " ; cat $CA_PUB) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t cert with wrong principal" # Cert valid but CA revoked + trace "$tid: key type $t verify cert with revoked CA" cat $CA_PUB > $OBJ/revoked_keys (printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -r $OBJ/revoked_keys \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key, but CA key in revoked_keys" # Set lifespan of CA key and verify signed user certs behave accordingly ( printf "$sig_principal " ; printf "cert-authority,valid-after=\"19800101\",valid-before=\"19900101\" " ; cat $CA_PUB) > $OBJ/allowed_signers # CA key lifespan valid + trace "$tid: key type $t verify cert valid CA lifespan" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19850101 \ < $DATA >/dev/null 2>&1 >/dev/null 2>&1 || \ fail "failed signature for $t key with valid CA expiry interval" # CA lifespan is valid but user key not yet valid + trace "$tid: key type $t verify cert valid CA lifespan, not-yet-valid cert" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19810101 \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with valid CA expiry interval but not yet valid cert" # CA lifespan is valid but user key expired + trace "$tid: key type $t verify cert valid CA lifespan, expired cert" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19890101 \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with valid CA expiry interval but expired cert" # CA key not yet valid + trace "$tid: key type $t verify cert CA not-yet-valid" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19790101 \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t not-yet-valid CA key" # CA key expired + trace "$tid: key type $t verify cert CA expired" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19910101 \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t with expired CA key" # NB. assumes we're not running this test in the 1980s + trace "$tid: key type $t verify cert CA expired (now)" ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t with expired CA key" # Set lifespan of CA outside of the cert validity + trace "$tid: key type $t verify CA/cert lifespan mismatch" ( printf "$sig_principal " ; printf "cert-authority,valid-after=\"19800101\",valid-before=\"19820101\" " ; cat $CA_PUB) > $OBJ/allowed_signers # valid cert validity but expired CA ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \ -I $sig_principal -f $OBJ/allowed_signers \ -Overify-time=19840101 \ < $DATA >/dev/null 2>&1 && \ fail "accepted signature for $t key with expired CA but valid cert" done # Test key independant match-principals ( printf "principal1 " ; cat $pubkey; printf "princi* " ; cat $pubkey; printf "unique " ; cat $pubkey; ) > $OBJ/allowed_signers verbose "$tid: match principals" ${SSHKEYGEN} -Y match-principals -f $OBJ/allowed_signers -I "unique" | \ fgrep "unique" >/dev/null || \ - fail "faild to match static principal" + fail "failed to match static principal" +trace "$tid: match principals wildcard" ${SSHKEYGEN} -Y match-principals -f $OBJ/allowed_signers -I "princip" | \ fgrep "princi*" >/dev/null || \ - fail "faild to match wildcard principal" + fail "failed to match wildcard principal" +trace "$tid: match principals static/wildcard" ${SSHKEYGEN} -Y match-principals -f $OBJ/allowed_signers -I "principal1" | \ fgrep -e "principal1" -e "princi*" >/dev/null || \ - fail "faild to match static and wildcard principal" + fail "failed to match static and wildcard principal" verbose "$tid: nomatch principals" for x in princ prince unknown ; do ${SSHKEYGEN} -Y match-principals -f $OBJ/allowed_signers \ -I $x >/dev/null 2>&1 && \ fail "succeeded to match unknown principal \"$x\"" done trace "kill agent" ${SSHAGENT} -k > /dev/null diff --git a/crypto/openssh/regress/test-exec.sh b/crypto/openssh/regress/test-exec.sh index eaa12992d18f..089ef73c4ebb 100644 --- a/crypto/openssh/regress/test-exec.sh +++ b/crypto/openssh/regress/test-exec.sh @@ -1,872 +1,1003 @@ -# $OpenBSD: test-exec.sh,v 1.98 2023/03/02 11:10:27 dtucker Exp $ +# $OpenBSD: test-exec.sh,v 1.105 2023/10/31 04:15:40 dtucker Exp $ # Placed in the Public Domain. #SUDO=sudo if [ ! -z "$TEST_SSH_ELAPSED_TIMES" ]; then STARTTIME=`date '+%s'` fi if [ ! -z "$TEST_SSH_PORT" ]; then PORT="$TEST_SSH_PORT" else PORT=4242 fi OBJ=$1 if [ "x$OBJ" = "x" ]; then echo '$OBJ not defined' exit 2 fi if [ ! -d $OBJ ]; then echo "not a directory: $OBJ" exit 2 fi SCRIPT=$2 if [ "x$SCRIPT" = "x" ]; then echo '$SCRIPT not defined' exit 2 fi if [ ! -f $SCRIPT ]; then echo "not a file: $SCRIPT" exit 2 fi if $TEST_SHELL -n $SCRIPT; then true else echo "syntax error in $SCRIPT" exit 2 fi unset SSH_AUTH_SOCK # Portable-specific settings. 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 if test -z "$LOGNAME"; then LOGNAME="${USER}" export LOGNAME fi # Unbreak GNU head(1) _POSIX2_VERSION=199209 export _POSIX2_VERSION case `uname -s 2>/dev/null` in OSF1*) BIN_SH=xpg4 export BIN_SH ;; CYGWIN*) os=cygwin ;; esac # 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 SRC=`dirname ${SCRIPT}` # defaults SSH=ssh SSHD=sshd SSHAGENT=ssh-agent SSHADD=ssh-add SSHKEYGEN=ssh-keygen SSHKEYSCAN=ssh-keyscan SFTP=sftp SFTPSERVER=/usr/libexec/openssh/sftp-server SCP=scp # Set by make_tmpdir() on demand (below). SSH_REGRESS_TMP= # Interop testing -PLINK=plink -PUTTYGEN=puttygen -CONCH=conch +PLINK=/usr/local/bin/plink +PUTTYGEN=/usr/local/bin/puttygen +CONCH=/usr/local/bin/conch +DROPBEAR=/usr/local/bin/dropbear +DBCLIENT=/usr/local/bin/dbclient +DROPBEARKEY=/usr/local/bin/dropbearkey +DROPBEARCONVERT=/usr/local/bin/dropbearconvert # Tools used by multiple tests NC=$OBJ/netcat # Always use the one configure tells us to, even if that's empty. #OPENSSL_BIN="${OPENSSL_BIN:-openssl}" if [ "x$TEST_SSH_SSH" != "x" ]; then SSH="${TEST_SSH_SSH}" fi if [ "x$TEST_SSH_SSHD" != "x" ]; then SSHD="${TEST_SSH_SSHD}" fi if [ "x$TEST_SSH_SSHAGENT" != "x" ]; then SSHAGENT="${TEST_SSH_SSHAGENT}" fi if [ "x$TEST_SSH_SSHADD" != "x" ]; then SSHADD="${TEST_SSH_SSHADD}" fi if [ "x$TEST_SSH_SSHKEYGEN" != "x" ]; then SSHKEYGEN="${TEST_SSH_SSHKEYGEN}" fi if [ "x$TEST_SSH_SSHKEYSCAN" != "x" ]; then SSHKEYSCAN="${TEST_SSH_SSHKEYSCAN}" fi if [ "x$TEST_SSH_SFTP" != "x" ]; then SFTP="${TEST_SSH_SFTP}" fi if [ "x$TEST_SSH_SFTPSERVER" != "x" ]; then SFTPSERVER="${TEST_SSH_SFTPSERVER}" fi if [ "x$TEST_SSH_SCP" != "x" ]; then SCP="${TEST_SSH_SCP}" fi if [ "x$TEST_SSH_PLINK" != "x" ]; then - # Find real binary, if it exists - case "${TEST_SSH_PLINK}" in - /*) PLINK="${TEST_SSH_PLINK}" ;; - *) PLINK=`which ${TEST_SSH_PLINK} 2>/dev/null` ;; - esac + PLINK="${TEST_SSH_PLINK}" fi if [ "x$TEST_SSH_PUTTYGEN" != "x" ]; then - # Find real binary, if it exists - case "${TEST_SSH_PUTTYGEN}" in - /*) PUTTYGEN="${TEST_SSH_PUTTYGEN}" ;; - *) PUTTYGEN=`which ${TEST_SSH_PUTTYGEN} 2>/dev/null` ;; - esac + PUTTYGEN="${TEST_SSH_PUTTYGEN}" fi if [ "x$TEST_SSH_CONCH" != "x" ]; then - # Find real binary, if it exists - case "${TEST_SSH_CONCH}" in - /*) CONCH="${TEST_SSH_CONCH}" ;; - *) CONCH=`which ${TEST_SSH_CONCH} 2>/dev/null` ;; - esac + CONCH="${TEST_SSH_CONCH}" +fi +if [ "x$TEST_SSH_DROPBEAR" != "x" ]; then + DROPBEAR="${TEST_SSH_DROPBEAR}" +fi +if [ "x$TEST_SSH_DBCLIENT" != "x" ]; then + DBCLIENT="${TEST_SSH_DBCLIENT}" +fi +if [ "x$TEST_SSH_DROPBEARKEY" != "x" ]; then + DROPBEARKEY="${TEST_SSH_DROPBEARKEY}" +fi +if [ "x$TEST_SSH_DROPBEARCONVERT" != "x" ]; then + DROPBEARCONVERT="${TEST_SSH_DROPBEARCONVERT}" 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 if [ "x$TEST_SSH_OPENSSL" != "x" ]; then OPENSSL_BIN="${TEST_SSH_OPENSSL}" fi # Path to sshd must be absolute for rexec case "$SSHD" in /*) ;; *) SSHD=`which $SSHD` ;; esac case "$SSHAGENT" in /*) ;; *) SSHAGENT=`which $SSHAGENT` ;; esac # Record the actual binaries used. SSH_BIN=${SSH} SSHD_BIN=${SSHD} SSHAGENT_BIN=${SSHAGENT} SSHADD_BIN=${SSHADD} SSHKEYGEN_BIN=${SSHKEYGEN} SSHKEYSCAN_BIN=${SSHKEYSCAN} SFTP_BIN=${SFTP} SFTPSERVER_BIN=${SFTPSERVER} SCP_BIN=${SCP} if [ "x$USE_VALGRIND" != "x" ]; then rm -rf $OBJ/valgrind-out $OBJ/valgrind-vgdb mkdir -p $OBJ/valgrind-out $OBJ/valgrind-vgdb # When using sudo ensure low-priv tests can write pipes and logs. if [ "x$SUDO" != "x" ]; then chmod 777 $OBJ/valgrind-out $OBJ/valgrind-vgdb fi VG_TEST=`basename $SCRIPT .sh` # Some tests are difficult to fix. case "$VG_TEST" in reexec) VG_SKIP=1 ;; sftp-chroot) if [ "x${SUDO}" != "x" ]; then VG_SKIP=1 fi ;; esac if [ x"$VG_SKIP" = "x" ]; then VG_LEAK="--leak-check=no" if [ x"$VALGRIND_CHECK_LEAKS" != "x" ]; then VG_LEAK="--leak-check=full" fi VG_IGNORE="/bin/*,/sbin/*,/usr/*,/var/*" VG_LOG="$OBJ/valgrind-out/${VG_TEST}." VG_OPTS="--track-origins=yes $VG_LEAK" VG_OPTS="$VG_OPTS --trace-children=yes" VG_OPTS="$VG_OPTS --trace-children-skip=${VG_IGNORE}" VG_OPTS="$VG_OPTS --vgdb-prefix=$OBJ/valgrind-vgdb/" VG_PATH="valgrind" if [ "x$VALGRIND_PATH" != "x" ]; then VG_PATH="$VALGRIND_PATH" fi VG="$VG_PATH $VG_OPTS" SSH="$VG --log-file=${VG_LOG}ssh.%p $SSH" SSHD="$VG --log-file=${VG_LOG}sshd.%p $SSHD" SSHAGENT="$VG --log-file=${VG_LOG}ssh-agent.%p $SSHAGENT" SSHADD="$VG --log-file=${VG_LOG}ssh-add.%p $SSHADD" SSHKEYGEN="$VG --log-file=${VG_LOG}ssh-keygen.%p $SSHKEYGEN" SSHKEYSCAN="$VG --log-file=${VG_LOG}ssh-keyscan.%p $SSHKEYSCAN" SFTP="$VG --log-file=${VG_LOG}sftp.%p ${SFTP}" SCP="$VG --log-file=${VG_LOG}scp.%p $SCP" cat > $OBJ/valgrind-sftp-server.sh << EOF #!/bin/sh exec $VG --log-file=${VG_LOG}sftp-server.%p $SFTPSERVER "\$@" EOF chmod a+rx $OBJ/valgrind-sftp-server.sh SFTPSERVER="$OBJ/valgrind-sftp-server.sh" fi fi # Logfiles. # SSH_LOGFILE should be the debug output of ssh(1) only # SSHD_LOGFILE should be the debug output of sshd(8) only # REGRESS_LOGFILE is the log of progress of the regress test itself. # TEST_SSH_LOGDIR will contain datestamped logs of all binaries run in # chronological order. if [ "x$TEST_SSH_LOGDIR" = "x" ]; then TEST_SSH_LOGDIR=$OBJ/log mkdir -p $TEST_SSH_LOGDIR fi if [ "x$TEST_SSH_LOGFILE" = "x" ]; then TEST_SSH_LOGFILE=$OBJ/ssh.log fi if [ "x$TEST_SSHD_LOGFILE" = "x" ]; then TEST_SSHD_LOGFILE=$OBJ/sshd.log fi if [ "x$TEST_REGRESS_LOGFILE" = "x" ]; then TEST_REGRESS_LOGFILE=$OBJ/regress.log fi # If set, keep track of successful tests and skip them them if we've # previously completed that test. if [ "x$TEST_REGRESS_CACHE_DIR" != "x" ]; then if [ ! -d "$TEST_REGRESS_CACHE_DIR" ]; then mkdir -p "$TEST_REGRESS_CACHE_DIR" fi TEST="`basename $SCRIPT .sh`" CACHE="${TEST_REGRESS_CACHE_DIR}/${TEST}.cache" for i in ${SSH} ${SSHD} ${SSHAGENT} ${SSHADD} ${SSHKEYGEN} ${SCP} \ ${SFTP} ${SFTPSERVER} ${SSHKEYSCAN}; do case $i in /*) bin="$i" ;; *) bin="`which $i`" ;; esac if [ "$bin" -nt "$CACHE" ]; then rm -f "$CACHE" fi done if [ -f "$CACHE" ]; then echo ok cached $CACHE exit 0 fi fi # truncate logfiles >$TEST_REGRESS_LOGFILE # Create ssh and sshd wrappers with logging. These create a datestamped # unique file for every invocation so that we can retain all logs from a # given test no matter how many times it's invoked. It also leaves a # symlink with the original name for tests (and people) who look for that. # For ssh, e can't just specify "SSH=ssh -E..." because sftp and scp don't # handle spaces in arguments. scp and sftp like to use -q so we remove those # to preserve our debug logging. In the rare instance where -q is desirable # -qq is equivalent and is not removed. SSHLOGWRAP=$OBJ/ssh-log-wrapper.sh cat >$SSHLOGWRAP <>$TEST_REGRESS_LOGFILE echo "Executing: ${SSH} \$@" >>\${logfile} for i in "\$@";do shift;case "\$i" in -q):;; *) set -- "\$@" "\$i";;esac;done rm -f $TEST_SSH_LOGFILE ln -f -s \${logfile} $TEST_SSH_LOGFILE exec ${SSH} -E\${logfile} "\$@" EOD chmod a+rx $OBJ/ssh-log-wrapper.sh REAL_SSH="$SSH" REAL_SSHD="$SSHD" SSH="$SSHLOGWRAP" SSHDLOGWRAP=$OBJ/sshd-log-wrapper.sh cat >$SSHDLOGWRAP <>$TEST_REGRESS_LOGFILE echo "Executing: ${SSHD} \$@" >>\${logfile} exec ${SSHD} -E\${logfile} "\$@" EOD chmod a+rx $OBJ/sshd-log-wrapper.sh ssh_logfile () { tool="$1" timestamp="`$OBJ/timestamp`" logfile="${TEST_SSH_LOGDIR}/${timestamp}.$tool.$$.log" echo "Logging $tool to log \${logfile}" >>$TEST_REGRESS_LOGFILE echo $logfile } # Some test data. We make a copy because some tests will overwrite it. # The tests may assume that $DATA exists and is writable and $COPY does # not exist. Tests requiring larger data files can call increase_datafile_size # [kbytes] to ensure the file is at least that large. DATANAME=data DATA=$OBJ/${DATANAME} cat ${SSHAGENT_BIN} >${DATA} chmod u+w ${DATA} COPY=$OBJ/copy rm -f ${COPY} increase_datafile_size() { while [ `du -k ${DATA} | cut -f1` -lt $1 ]; do cat ${SSHAGENT_BIN} >>${DATA} done } # these should be used in tests export SSH SSHD SSHAGENT SSHADD SSHKEYGEN SSHKEYSCAN SFTP SFTPSERVER SCP export SSH_PKCS11_HELPER SSH_SK_HELPER #echo $SSH $SSHD $SSHAGENT $SSHADD $SSHKEYGEN $SSHKEYSCAN $SFTP $SFTPSERVER $SCP # Portable specific functions which() { saved_IFS="$IFS" IFS=":" for i in $PATH do if [ -x $i/$1 ]; then IFS="$saved_IFS" echo "$i/$1" return 0 fi done IFS="$saved_IFS" echo "$i/$1" return 1 } have_prog() { which "$1" >/dev/null 2>&1 return $? } jot() { awk "BEGIN { for (i = $2; i < $2 + $1; i++) { printf \"%d\n\", i } exit }" } if [ ! -x "`which rev`" ]; then rev() { awk '{for (i=length; i>0; i--) printf "%s", substr($0, i, 1); print ""}' } fi # Check whether preprocessor symbols are defined in config.h. config_defined () { str=$1 while test "x$2" != "x" ; do str="$str|$2" shift done egrep "^#define.*($str)" ${BUILDDIR}/config.h >/dev/null 2>&1 } md5 () { if have_prog md5sum; then md5sum elif have_prog openssl; then openssl md5 elif have_prog cksum; then cksum elif have_prog sum; then sum elif [ -x ${OPENSSL_BIN} ]; then ${OPENSSL_BIN} md5 else 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 make_tmpdir () { SSH_REGRESS_TMP="$($OBJ/mkdtemp openssh-XXXXXXXX)" || \ fatal "failed to create temporary directory" } # End of portable specific functions stop_sshd () { if [ -f $PIDFILE ]; then pid=`$SUDO cat $PIDFILE` if [ "X$pid" = "X" ]; then echo no sshd running else if [ $pid -lt 2 ]; then echo bad pid for sshd: $pid else $SUDO kill $pid trace "wait for sshd to exit" i=0; while [ -f $PIDFILE -a $i -lt 5 ]; do i=`expr $i + 1` sleep $i done if test -f $PIDFILE; then if $SUDO kill -0 $pid; then echo "sshd didn't exit " \ "port $PORT pid $pid" else echo "sshd died without cleanup" fi exit 1 fi fi fi fi } # helper cleanup () { if [ "x$SSH_PID" != "x" ]; then if [ $SSH_PID -lt 2 ]; then echo bad pid for ssh: $SSH_PID else kill $SSH_PID fi fi if [ "x$SSH_REGRESS_TMP" != "x" ]; then rm -rf "$SSH_REGRESS_TMP" fi stop_sshd if [ ! -z "$TEST_SSH_ELAPSED_TIMES" ]; then now=`date '+%s'` elapsed=$(($now - $STARTTIME)) echo elapsed $elapsed `basename $SCRIPT .sh` fi } start_debug_log () { echo "trace: $@" >>$TEST_REGRESS_LOGFILE if [ -d "$TEST_SSH_LOGDIR" ]; then rm -f $TEST_SSH_LOGDIR/* fi } save_debug_log () { testname=`echo $tid | tr ' ' _` tarname="$OBJ/failed-$testname-logs.tar" + for logfile in $TEST_SSH_LOGDIR $TEST_REGRESS_LOGFILE \ + $TEST_SSH_LOGFILE $TEST_SSHD_LOGFILE; do + if [ ! -z "$SUDO" ] && [ -f "$logfile" ]; then + $SUDO chown -R $USER $logfile + fi + done echo $@ >>$TEST_REGRESS_LOGFILE echo $@ >>$TEST_SSH_LOGFILE echo $@ >>$TEST_SSHD_LOGFILE echo "Saving debug logs to $tarname" >>$TEST_REGRESS_LOGFILE (cat $TEST_REGRESS_LOGFILE; echo) >>$OBJ/failed-regress.log (cat $TEST_SSH_LOGFILE; echo) >>$OBJ/failed-ssh.log (cat $TEST_SSHD_LOGFILE; echo) >>$OBJ/failed-sshd.log # Save all logfiles in a tarball. (cd $OBJ && logfiles="" for i in $TEST_REGRESS_LOGFILE $TEST_SSH_LOGFILE $TEST_SSHD_LOGFILE \ $TEST_SSH_LOGDIR; do if [ -e "`basename $i`" ]; then logfiles="$logfiles `basename $i`" else logfiles="$logfiles $i" fi done tar cf "$tarname" $logfiles) } trace () { start_debug_log $@ if [ "X$TEST_SSH_TRACE" = "Xyes" ]; then echo "$@" fi } verbose () { start_debug_log $@ if [ "X$TEST_SSH_QUIET" != "Xyes" ]; then echo "$@" fi } fail () { save_debug_log "FAIL: $@" RESULT=1 echo "$@" if test "x$TEST_SSH_FAIL_FATAL" != "x" ; then cleanup exit $RESULT fi } fatal () { save_debug_log "FATAL: $@" printf "FATAL: " fail "$@" cleanup exit $RESULT } # Skip remaining tests in script. skip () { echo "SKIPPED: $@" cleanup exit $RESULT } maybe_add_scp_path_to_sshd () { # If we're testing a non-installed scp, add its directory to sshd's # PATH so we can test it. We don't do this for all tests as it # breaks the SetEnv tests. case "$SCP" in /*) PATH_WITH_SCP="`dirname $SCP`:$PATH" echo " SetEnv PATH='$PATH_WITH_SCP'" >>$OBJ/sshd_config echo " SetEnv PATH='$PATH_WITH_SCP'" >>$OBJ/sshd_proxy ;; esac } RESULT=0 PIDFILE=$OBJ/pidfile trap fatal 3 2 # create server config cat << EOF > $OBJ/sshd_config StrictModes no Port $PORT AddressFamily inet ListenAddress 127.0.0.1 #ListenAddress ::1 PidFile $PIDFILE AuthorizedKeysFile $OBJ/authorized_keys_%u LogLevel DEBUG3 AcceptEnv _XXX_TEST_* AcceptEnv _XXX_TEST Subsystem sftp $SFTPSERVER EOF # This may be necessary if /usr/src and/or /usr/obj are group-writable, # but if you aren't careful with permissions then the unit tests could # be abused to locally escalate privileges. if [ ! -z "$TEST_SSH_UNSAFE_PERMISSIONS" ]; then echo " StrictModes no" >> $OBJ/sshd_config 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/sshd_config fi if [ ! -z "$TEST_SSH_SSHD_CONFOPTS" ]; then trace "adding sshd_config option $TEST_SSH_SSHD_CONFOPTS" echo "$TEST_SSH_SSHD_CONFOPTS" >> $OBJ/sshd_config fi # server config for proxy connects cp $OBJ/sshd_config $OBJ/sshd_proxy # allow group-writable directories in proxy-mode echo 'StrictModes no' >> $OBJ/sshd_proxy # create client config cat << EOF > $OBJ/ssh_config Host * Hostname 127.0.0.1 HostKeyAlias localhost-with-alias Port $PORT User $USER GlobalKnownHostsFile $OBJ/known_hosts UserKnownHostsFile $OBJ/known_hosts PubkeyAuthentication yes ChallengeResponseAuthentication no PasswordAuthentication no BatchMode yes StrictHostKeyChecking yes LogLevel DEBUG3 EOF if [ ! -z "$TEST_SSH_SSH_CONFOPTS" ]; then trace "adding ssh_config option $TEST_SSH_SSH_CONFOPTS" echo "$TEST_SSH_SSH_CONFOPTS" >> $OBJ/ssh_config fi rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER SSH_SK_PROVIDER= if ! config_defined ENABLE_SK; then trace skipping sk-dummy elif [ -f "${SRC}/misc/sk-dummy/obj/sk-dummy.so" ] ; then SSH_SK_PROVIDER="${SRC}/misc/sk-dummy/obj/sk-dummy.so" elif [ -f "${OBJ}/misc/sk-dummy/sk-dummy.so" ] ; then SSH_SK_PROVIDER="${OBJ}/misc/sk-dummy/sk-dummy.so" elif [ -f "${SRC}/misc/sk-dummy/sk-dummy.so" ] ; then SSH_SK_PROVIDER="${SRC}/misc/sk-dummy/sk-dummy.so" fi export SSH_SK_PROVIDER if ! test -z "$SSH_SK_PROVIDER"; then EXTRA_AGENT_ARGS='-P/*' # XXX want realpath(1)... echo "SecurityKeyProvider $SSH_SK_PROVIDER" >> $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` for t in ${SSH_KEYTYPES}; do # generate user key 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 # use key as host key, too (umask 077; $SUDO cp $OBJ/$t $OBJ/host.$t) echo HostKey $OBJ/host.$t >> $OBJ/sshd_config # don't use SUDO for proxy connect echo HostKey $OBJ/$t >> $OBJ/sshd_proxy done chmod 644 $OBJ/authorized_keys_$USER # Activate Twisted Conch tests if the binary is present REGRESS_INTEROP_CONCH=no if test -x "$CONCH" ; then REGRESS_INTEROP_CONCH=yes fi # If PuTTY is present, new enough and we are running a PuTTY test, prepare # keys and configuration. REGRESS_INTEROP_PUTTY=no 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 *putty*) ;; *) REGRESS_INTEROP_PUTTY=no ;; esac if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then mkdir -p ${OBJ}/.putty # Add a PuTTY key to authorized_keys rm -f ${OBJ}/putty.rsa2 if ! "$PUTTYGEN" -t rsa -o ${OBJ}/putty.rsa2 \ --random-device=/dev/urandom \ --new-passphrase /dev/null < /dev/null > /dev/null; then echo "Your installed version of PuTTY is too old to support --new-passphrase, skipping test" >&2 exit 1 fi "$PUTTYGEN" -O public-openssh ${OBJ}/putty.rsa2 \ >> $OBJ/authorized_keys_$USER # Convert rsa2 host key to PuTTY format cp $OBJ/ssh-rsa $OBJ/ssh-rsa_oldfmt ${SSHKEYGEN} -p -N '' -m PEM -f $OBJ/ssh-rsa_oldfmt >/dev/null ${SRC}/ssh2putty.sh 127.0.0.1 $PORT $OBJ/ssh-rsa_oldfmt > \ ${OBJ}/.putty/sshhostkeys ${SRC}/ssh2putty.sh 127.0.0.1 22 $OBJ/ssh-rsa_oldfmt >> \ ${OBJ}/.putty/sshhostkeys rm -f $OBJ/ssh-rsa_oldfmt # Setup proxied session mkdir -p ${OBJ}/.putty/sessions rm -f ${OBJ}/.putty/sessions/localhost_proxy echo "Protocol=ssh" >> ${OBJ}/.putty/sessions/localhost_proxy echo "HostName=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy echo "ProxyTelnetCommand=${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy echo "ProxyLocalhost=1" >> ${OBJ}/.putty/sessions/localhost_proxy PUTTYDIR=${OBJ}/.putty export PUTTYDIR fi +REGRESS_INTEROP_DROPBEAR=no +if test -x "$DROPBEARKEY" -a -x "$DBCLIENT" -a -x "$DROPBEARCONVERT"; then + REGRESS_INTEROP_DROPBEAR=yes +fi +case "$SCRIPT" in +*dropbear*) ;; +*) REGRESS_INTEROP_DROPBEAR=no ;; +esac + +if test "$REGRESS_INTEROP_DROPBEAR" = "yes" ; then + trace Create dropbear keys and add to authorized_keys + mkdir -p $OBJ/.dropbear + for i in rsa ecdsa ed25519 dss; do + if [ ! -f "$OBJ/.dropbear/id_$i" ]; then + ($DROPBEARKEY -t $i -f $OBJ/.dropbear/id_$i + $DROPBEARCONVERT dropbear openssh \ + $OBJ/.dropbear/id_$i $OBJ/.dropbear/ossh.id_$i + ) > /dev/null 2>&1 + fi + $SSHKEYGEN -y -f $OBJ/.dropbear/ossh.id_$i \ + >>$OBJ/authorized_keys_$USER + done +fi + # create a proxy version of the client config ( cat $OBJ/ssh_config echo proxycommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy ) > $OBJ/ssh_proxy # check proxy config ${SSHD} -t -f $OBJ/sshd_proxy || fatal "sshd_proxy broken" +# extract proxycommand into separate shell script for use by Dropbear. +echo '#!/bin/sh' >$OBJ/ssh_proxy.sh +awk '/^proxycommand/' $OBJ/ssh_proxy | sed 's/^proxycommand//' \ + >>$OBJ/ssh_proxy.sh +chmod a+x $OBJ/ssh_proxy.sh + start_sshd () { # start sshd logfile="${TEST_SSH_LOGDIR}/sshd.`$OBJ/timestamp`.$$.log" $SUDO ${SSHD} -f $OBJ/sshd_config "$@" -t || fatal "sshd_config broken" $SUDO env SSH_SK_HELPER="$SSH_SK_HELPER" \ ${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE trace "wait for sshd" i=0; while [ ! -f $PIDFILE -a $i -lt 10 ]; do i=`expr $i + 1` sleep $i done test -f $PIDFILE || fatal "no sshd running on port $PORT" } +# Find a PKCS#11 library. +p11_find_lib() { + TEST_SSH_PKCS11="" + for _lib in "$@" ; do + if test -f "$_lib" ; then + TEST_SSH_PKCS11="$_lib" + return + fi + done +} + +# Perform PKCS#11 setup: prepares a softhsm2 token configuration, generated +# keys and loads them into the virtual token. +PKCS11_OK= +export PKCS11_OK +p11_setup() { + p11_find_lib \ + /usr/local/lib/softhsm/libsofthsm2.so \ + /usr/lib64/pkcs11/libsofthsm2.so \ + /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so + test -z "$TEST_SSH_PKCS11" && return 1 + verbose "using token library $TEST_SSH_PKCS11" + TEST_SSH_PIN=1234 + TEST_SSH_SOPIN=12345678 + if [ "x$TEST_SSH_SSHPKCS11HELPER" != "x" ]; then + SSH_PKCS11_HELPER="${TEST_SSH_SSHPKCS11HELPER}" + export SSH_PKCS11_HELPER + fi + + # setup environment for softhsm2 token + SSH_SOFTHSM_DIR=$OBJ/SOFTHSM + export SSH_SOFTHSM_DIR + rm -rf $SSH_SOFTHSM_DIR + TOKEN=$SSH_SOFTHSM_DIR/tokendir + mkdir -p $TOKEN + SOFTHSM2_CONF=$SSH_SOFTHSM_DIR/softhsm2.conf + export SOFTHSM2_CONF + cat > $SOFTHSM2_CONF << EOF +# SoftHSM v2 configuration file +directories.tokendir = ${TOKEN} +objectstore.backend = file +# ERROR, WARNING, INFO, DEBUG +log.level = DEBUG +# If CKF_REMOVABLE_DEVICE flag should be set +slots.removable = false +EOF + out=$(softhsm2-util --init-token --free --label token-slot-0 --pin "$TEST_SSH_PIN" --so-pin "$TEST_SSH_SOPIN") + slot=$(echo -- $out | sed 's/.* //') + trace "generating keys" + # RSA key + RSA=${SSH_SOFTHSM_DIR}/RSA + RSAP8=${SSH_SOFTHSM_DIR}/RSAP8 + $OPENSSL_BIN genpkey -algorithm rsa > $RSA 2>/dev/null || \ + fatal "genpkey RSA fail" + $OPENSSL_BIN pkcs8 -nocrypt -in $RSA > $RSAP8 || fatal "pkcs8 RSA fail" + softhsm2-util --slot "$slot" --label 01 --id 01 --pin "$TEST_SSH_PIN" \ + --import $RSAP8 >/dev/null || fatal "softhsm import RSA fail" + chmod 600 $RSA + ssh-keygen -y -f $RSA > ${RSA}.pub + # ECDSA key + ECPARAM=${SSH_SOFTHSM_DIR}/ECPARAM + EC=${SSH_SOFTHSM_DIR}/EC + ECP8=${SSH_SOFTHSM_DIR}/ECP8 + $OPENSSL_BIN genpkey -genparam -algorithm ec \ + -pkeyopt ec_paramgen_curve:prime256v1 > $ECPARAM || \ + fatal "param EC fail" + $OPENSSL_BIN genpkey -paramfile $ECPARAM > $EC || \ + fatal "genpkey EC fail" + $OPENSSL_BIN pkcs8 -nocrypt -in $EC > $ECP8 || fatal "pkcs8 EC fail" + softhsm2-util --slot "$slot" --label 02 --id 02 --pin "$TEST_SSH_PIN" \ + --import $ECP8 >/dev/null || fatal "softhsm import EC fail" + chmod 600 $EC + ssh-keygen -y -f $EC > ${EC}.pub + # Prepare askpass script to load PIN. + PIN_SH=$SSH_SOFTHSM_DIR/pin.sh + cat > $PIN_SH << EOF +#!/bin/sh +echo "${TEST_SSH_PIN}" +EOF + chmod 0700 "$PIN_SH" + PKCS11_OK=yes + return 0 +} + +# Peforms ssh-add with the right token PIN. +p11_ssh_add() { + env SSH_ASKPASS="$PIN_SH" SSH_ASKPASS_REQUIRE=force ${SSHADD} "$@" +} + # source test body . $SCRIPT # kill sshd cleanup if [ "x$USE_VALGRIND" != "x" ]; then # If there is an EXIT trap handler, invoke it now. # Some tests set these to clean up processes such as ssh-agent. We # need to wait for all valgrind processes to complete so we can check # their logs, but since the EXIT traps are not invoked until # test-exec.sh exits, waiting here will deadlock. # This is not very portable but then neither is valgrind itself. # As a bonus, dash (as used on the runners) has a "trap" that doesn't # work in a pipeline (hence the temp file) or a subshell. exithandler="" trap >/tmp/trap.$$ && exithandler=$(cat /tmp/trap.$$ | \ awk -F "'" '/EXIT$/{print $2}') rm -f /tmp/trap.$$ if [ "x${exithandler}" != "x" ]; then verbose invoking EXIT trap handler early: ${exithandler} eval "${exithandler}" trap '' EXIT fi # wait for any running process to complete wait; sleep 1 VG_RESULTS=$(find $OBJ/valgrind-out -type f -print) VG_RESULT_COUNT=0 VG_FAIL_COUNT=0 for i in $VG_RESULTS; do if grep "ERROR SUMMARY" $i >/dev/null; then VG_RESULT_COUNT=$(($VG_RESULT_COUNT + 1)) if ! grep "ERROR SUMMARY: 0 errors" $i >/dev/null; then VG_FAIL_COUNT=$(($VG_FAIL_COUNT + 1)) RESULT=1 verbose valgrind failure $i cat $i fi fi done if [ x"$VG_SKIP" != "x" ]; then verbose valgrind skipped else verbose valgrind results $VG_RESULT_COUNT failures $VG_FAIL_COUNT fi fi if [ $RESULT -eq 0 ]; then verbose ok $tid if [ "x$CACHE" != "x" ]; then touch "$CACHE" fi else echo failed $tid fi exit $RESULT diff --git a/crypto/openssh/regress/unittests/Makefile b/crypto/openssh/regress/unittests/Makefile index 4d26b74770e2..e370900e4de6 100644 --- a/crypto/openssh/regress/unittests/Makefile +++ b/crypto/openssh/regress/unittests/Makefile @@ -1,7 +1,6 @@ -# $OpenBSD: Makefile,v 1.12 2020/06/19 04:34:21 djm Exp $ +# $OpenBSD: Makefile,v 1.13 2023/09/24 08:14:13 claudio Exp $ -REGRESS_FAIL_EARLY?= yes SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys utf8 match conversion SUBDIR+=authopt misc sshsig .include diff --git a/crypto/openssh/regress/unittests/Makefile.inc b/crypto/openssh/regress/unittests/Makefile.inc index 370224aa5e36..623896ffa152 100644 --- a/crypto/openssh/regress/unittests/Makefile.inc +++ b/crypto/openssh/regress/unittests/Makefile.inc @@ -1,89 +1,87 @@ -# $OpenBSD: Makefile.inc,v 1.14 2019/11/25 10:32:35 djm Exp $ - -REGRESS_FAIL_EARLY?= yes +# $OpenBSD: Makefile.inc,v 1.15 2023/09/24 08:14:13 claudio Exp $ .include .include # User-settable options UNITTEST_FAST?= no # Skip slow tests (e.g. less intensive fuzzing). UNITTEST_SLOW?= no # Include slower tests (e.g. more intensive fuzzing). UNITTEST_VERBOSE?= no # Verbose test output (inc. per-test names). MALLOC_OPTIONS?= CFGJRSUX TEST_ENV?= MALLOC_OPTIONS=${MALLOC_OPTIONS} # XXX detect from ssh binary? OPENSSL?= yes .if (${OPENSSL:L} == "yes") CFLAGS+= -DWITH_OPENSSL .endif # enable warnings WARNINGS=Yes DEBUG=-g CFLAGS+= -fstack-protector-all CDIAGFLAGS= -Wall CDIAGFLAGS+= -Wextra CDIAGFLAGS+= -Werror CDIAGFLAGS+= -Wchar-subscripts CDIAGFLAGS+= -Wcomment CDIAGFLAGS+= -Wformat CDIAGFLAGS+= -Wformat-security CDIAGFLAGS+= -Wimplicit CDIAGFLAGS+= -Winline CDIAGFLAGS+= -Wmissing-declarations CDIAGFLAGS+= -Wmissing-prototypes CDIAGFLAGS+= -Wparentheses CDIAGFLAGS+= -Wpointer-arith CDIAGFLAGS+= -Wreturn-type CDIAGFLAGS+= -Wshadow CDIAGFLAGS+= -Wsign-compare CDIAGFLAGS+= -Wstrict-aliasing CDIAGFLAGS+= -Wstrict-prototypes CDIAGFLAGS+= -Wswitch CDIAGFLAGS+= -Wtrigraphs CDIAGFLAGS+= -Wuninitialized CDIAGFLAGS+= -Wunused CDIAGFLAGS+= -Wno-unused-parameter .if ${COMPILER_VERSION:L} != "gcc3" CDIAGFLAGS+= -Wold-style-definition .endif SSHREL=../../../../../usr.bin/ssh CFLAGS+=-I${.CURDIR}/../test_helper -I${.CURDIR}/${SSHREL} .if exists(${.CURDIR}/../test_helper/${__objdir}) LDADD+=-L${.CURDIR}/../test_helper/${__objdir} -ltest_helper DPADD+=${.CURDIR}/../test_helper/${__objdir}/libtest_helper.a .else LDADD+=-L${.CURDIR}/../test_helper -ltest_helper DPADD+=${.CURDIR}/../test_helper/libtest_helper.a .endif .PATH: ${.CURDIR}/${SSHREL} LDADD+= -lutil DPADD+= ${LIBUTIL} .if (${OPENSSL:L} == "yes") LDADD+= -lcrypto DPADD+= ${LIBCRYPTO} .endif LDADD+= -lfido2 -lcbor -lusbhid DPADD+= ${LIBFIDO2} ${LIBCBOR} ${LIBUSBHID} UNITTEST_ARGS?= .if (${UNITTEST_VERBOSE:L} != "no") UNITTEST_ARGS+= -v .endif .if (${UNITTEST_FAST:L} != "no") UNITTEST_ARGS+= -f .elif (${UNITTEST_SLOW:L} != "no") UNITTEST_ARGS+= -F .endif diff --git a/crypto/openssh/scp.c b/crypto/openssh/scp.c index eaa407cb1de8..492dace1233b 100644 --- a/crypto/openssh/scp.c +++ b/crypto/openssh/scp.c @@ -1,2267 +1,2275 @@ -/* $OpenBSD: scp.c,v 1.259 2023/09/10 23:12:32 djm Exp $ */ +/* $OpenBSD: scp.c,v 1.260 2023/10/11 05:42:08 djm Exp $ */ /* * scp - secure remote copy. This is basically patched BSD rcp which * uses ssh to do the data transfer (instead of using rcmd). * * NOTE: This version should NOT be suid root. (This uses ssh to * do the transfer and ssh has the necessary privileges.) * * 1995 Timo Rinne , Tatu Ylonen * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ /* * Copyright (c) 1999 Theo de Raadt. All rights reserved. * Copyright (c) 1999 Aaron Campbell. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Parts from: * * Copyright (c) 1983, 1990, 1992, 1993, 1995 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "includes.h" #include #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_POLL_H #include #else # ifdef HAVE_SYS_POLL_H # include # endif #endif #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #include #include #include #ifdef HAVE_FNMATCH_H #include #endif #ifdef USE_SYSTEM_GLOB # include #else # include "openbsd-compat/glob.h" #endif #ifdef HAVE_LIBGEN_H #include #endif #include #ifdef HAVE_UTIL_H # include #endif #include #include #include #include #ifdef HAVE_STDINT_H # include #endif #include #include #include #include #include #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) #include #endif #include "xmalloc.h" #include "ssh.h" #include "atomicio.h" #include "pathnames.h" #include "log.h" #include "misc.h" #include "progressmeter.h" #include "utf8.h" #include "sftp.h" #include "sftp-common.h" #include "sftp-client.h" extern char *__progname; #define COPY_BUFLEN 16384 int do_cmd(char *, char *, char *, int, int, char *, int *, int *, pid_t *); int do_cmd2(char *, char *, int, char *, int, int); /* Struct for addargs */ arglist args; arglist remote_remote_args; /* Bandwidth limit */ long long limit_kbps = 0; struct bwlimit bwlimit; /* Name of current file being transferred. */ char *curfile; /* This is set to non-zero to enable verbose mode. */ int verbose_mode = 0; LogLevel log_level = SYSLOG_LEVEL_INFO; /* This is set to zero if the progressmeter is not desired. */ int showprogress = 1; /* * This is set to non-zero if remote-remote copy should be piped * through this process. */ int throughlocal = 1; /* Non-standard port to use for the ssh connection or -1. */ int sshport = -1; /* This is the program to execute for the secured connection. ("ssh" or -S) */ char *ssh_program = _PATH_SSH_PROGRAM; /* This is used to store the pid of ssh_program */ pid_t do_cmd_pid = -1; pid_t do_cmd_pid2 = -1; /* SFTP copy parameters */ size_t sftp_copy_buflen; size_t sftp_nrequests; /* Needed for sftp */ volatile sig_atomic_t interrupted = 0; int sftp_glob(struct sftp_conn *, const char *, int, int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */ static void killchild(int signo) { if (do_cmd_pid > 1) { kill(do_cmd_pid, signo ? signo : SIGTERM); (void)waitpid(do_cmd_pid, NULL, 0); } if (do_cmd_pid2 > 1) { kill(do_cmd_pid2, signo ? signo : SIGTERM); (void)waitpid(do_cmd_pid2, NULL, 0); } if (signo) _exit(1); exit(1); } static void suspone(int pid, int signo) { int status; if (pid > 1) { kill(pid, signo); while (waitpid(pid, &status, WUNTRACED) == -1 && errno == EINTR) ; } } static void suspchild(int signo) { suspone(do_cmd_pid, signo); suspone(do_cmd_pid2, signo); kill(getpid(), SIGSTOP); } static int do_local_cmd(arglist *a) { u_int i; int status; pid_t pid; if (a->num == 0) fatal("do_local_cmd: no arguments"); if (verbose_mode) { fprintf(stderr, "Executing:"); for (i = 0; i < a->num; i++) fmprintf(stderr, " %s", a->list[i]); fprintf(stderr, "\n"); } if ((pid = fork()) == -1) fatal("do_local_cmd: fork: %s", strerror(errno)); if (pid == 0) { execvp(a->list[0], a->list); perror(a->list[0]); exit(1); } do_cmd_pid = pid; ssh_signal(SIGTERM, killchild); ssh_signal(SIGINT, killchild); ssh_signal(SIGHUP, killchild); while (waitpid(pid, &status, 0) == -1) if (errno != EINTR) fatal("do_local_cmd: waitpid: %s", strerror(errno)); do_cmd_pid = -1; if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) return (-1); return (0); } /* * This function executes the given command as the specified user on the * given host. This returns < 0 if execution fails, and >= 0 otherwise. This * assigns the input and output file descriptors on success. */ int do_cmd(char *program, char *host, char *remuser, int port, int subsystem, char *cmd, int *fdin, int *fdout, pid_t *pid) { #ifdef USE_PIPES int pin[2], pout[2]; #else int sv[2]; #endif if (verbose_mode) fmprintf(stderr, "Executing: program %s host %s, user %s, command %s\n", program, host, remuser ? remuser : "(unspecified)", cmd); if (port == -1) port = sshport; #ifdef USE_PIPES if (pipe(pin) == -1 || pipe(pout) == -1) fatal("pipe: %s", strerror(errno)); #else /* Create a socket pair for communicating with ssh. */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) fatal("socketpair: %s", strerror(errno)); #endif 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. */ *pid = fork(); switch (*pid) { case -1: fatal("fork: %s", strerror(errno)); case 0: /* Child. */ #ifdef USE_PIPES if (dup2(pin[0], STDIN_FILENO) == -1 || dup2(pout[1], STDOUT_FILENO) == -1) { error("dup2: %s", strerror(errno)); _exit(1); } close(pin[0]); close(pin[1]); close(pout[0]); close(pout[1]); #else if (dup2(sv[0], STDIN_FILENO) == -1 || dup2(sv[0], STDOUT_FILENO) == -1) { error("dup2: %s", strerror(errno)); _exit(1); } close(sv[0]); close(sv[1]); #endif replacearg(&args, 0, "%s", program); if (port != -1) { addargs(&args, "-p"); addargs(&args, "%d", port); } if (remuser != NULL) { addargs(&args, "-l"); addargs(&args, "%s", remuser); } if (subsystem) addargs(&args, "-s"); addargs(&args, "--"); addargs(&args, "%s", host); addargs(&args, "%s", cmd); execvp(program, args.list); perror(program); _exit(1); default: /* Parent. Close the other side, and return the local side. */ #ifdef USE_PIPES close(pin[0]); close(pout[1]); *fdout = pin[1]; *fdin = pout[0]; #else close(sv[0]); *fdin = sv[1]; *fdout = sv[1]; #endif ssh_signal(SIGTERM, killchild); ssh_signal(SIGINT, killchild); ssh_signal(SIGHUP, killchild); return 0; } } /* * This function executes a command similar to do_cmd(), but expects the * input and output descriptors to be setup by a previous call to do_cmd(). * This way the input and output of two commands can be connected. */ int do_cmd2(char *host, char *remuser, int port, char *cmd, int fdin, int fdout) { int status; pid_t pid; if (verbose_mode) fmprintf(stderr, "Executing: 2nd program %s host %s, user %s, command %s\n", ssh_program, host, remuser ? remuser : "(unspecified)", cmd); if (port == -1) port = sshport; /* Fork a child to execute the command on the remote host using ssh. */ pid = fork(); if (pid == 0) { if (dup2(fdin, 0) == -1) perror("dup2"); if (dup2(fdout, 1) == -1) perror("dup2"); replacearg(&args, 0, "%s", ssh_program); if (port != -1) { addargs(&args, "-p"); addargs(&args, "%d", port); } if (remuser != NULL) { addargs(&args, "-l"); addargs(&args, "%s", remuser); } addargs(&args, "-oBatchMode=yes"); addargs(&args, "--"); addargs(&args, "%s", host); addargs(&args, "%s", cmd); execvp(ssh_program, args.list); perror(ssh_program); exit(1); } else if (pid == -1) { fatal("fork: %s", strerror(errno)); } while (waitpid(pid, &status, 0) == -1) if (errno != EINTR) fatal("do_cmd2: waitpid: %s", strerror(errno)); return 0; } typedef struct { size_t cnt; char *buf; } BUF; BUF *allocbuf(BUF *, int, int); void lostconn(int); int okname(char *); void run_err(const char *,...) __attribute__((__format__ (printf, 1, 2))) __attribute__((__nonnull__ (1))); int note_err(const char *,...) __attribute__((__format__ (printf, 1, 2))); void verifydir(char *); struct passwd *pwd; uid_t userid; int errs, remin, remout, remin2, remout2; int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory; #define CMDNEEDS 64 char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ enum scp_mode_e { MODE_SCP, MODE_SFTP }; int response(void); void rsource(char *, struct stat *); void sink(int, char *[], const char *); void source(int, char *[]); void tolocal(int, char *[], enum scp_mode_e, char *sftp_direct); void toremote(int, char *[], enum scp_mode_e, char *sftp_direct); void usage(void); void source_sftp(int, char *, char *, struct sftp_conn *); void sink_sftp(int, char *, const char *, struct sftp_conn *); void throughlocal_sftp(struct sftp_conn *, struct sftp_conn *, char *, char *); int main(int argc, char **argv) { int ch, fflag, tflag, status, r, n; char **newargv, *argv0; const char *errstr; extern char *optarg; extern int optind; enum scp_mode_e mode = MODE_SFTP; char *sftp_direct = NULL; long long llv; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); msetlocale(); /* Copy argv, because we modify it */ argv0 = argv[0]; newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv)); for (n = 0; n < argc; n++) newargv[n] = xstrdup(argv[n]); argv = newargv; __progname = ssh_get_progname(argv[0]); log_init(argv0, log_level, SYSLOG_FACILITY_USER, 2); memset(&args, '\0', sizeof(args)); memset(&remote_remote_args, '\0', sizeof(remote_remote_args)); args.list = remote_remote_args.list = NULL; addargs(&args, "%s", ssh_program); addargs(&args, "-x"); addargs(&args, "-oPermitLocalCommand=no"); addargs(&args, "-oClearAllForwardings=yes"); addargs(&args, "-oRemoteCommand=none"); addargs(&args, "-oRequestTTY=no"); fflag = Tflag = tflag = 0; while ((ch = getopt(argc, argv, "12346ABCTdfOpqRrstvD:F:J:M:P:S:c:i:l:o:X:")) != -1) { switch (ch) { /* User-visible flags. */ case '1': fatal("SSH protocol v.1 is no longer supported"); break; case '2': /* Ignored */ break; case 'A': case '4': case '6': case 'C': addargs(&args, "-%c", ch); addargs(&remote_remote_args, "-%c", ch); break; case 'D': sftp_direct = optarg; break; case '3': throughlocal = 1; break; case 'R': throughlocal = 0; break; case 'o': case 'c': case 'i': case 'F': case 'J': addargs(&remote_remote_args, "-%c", ch); addargs(&remote_remote_args, "%s", optarg); addargs(&args, "-%c", ch); addargs(&args, "%s", optarg); break; case 'O': mode = MODE_SCP; break; case 's': mode = MODE_SFTP; break; case 'P': sshport = a2port(optarg); if (sshport <= 0) fatal("bad port \"%s\"\n", optarg); break; case 'B': addargs(&remote_remote_args, "-oBatchmode=yes"); addargs(&args, "-oBatchmode=yes"); break; case 'l': limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024, &errstr); if (errstr != NULL) usage(); limit_kbps *= 1024; /* kbps */ bandwidth_limit_init(&bwlimit, limit_kbps, COPY_BUFLEN); break; case 'p': pflag = 1; break; case 'r': iamrecursive = 1; break; case 'S': ssh_program = xstrdup(optarg); break; case 'v': addargs(&args, "-v"); addargs(&remote_remote_args, "-v"); if (verbose_mode == 0) log_level = SYSLOG_LEVEL_DEBUG1; else if (log_level < SYSLOG_LEVEL_DEBUG3) log_level++; verbose_mode = 1; break; case 'q': addargs(&args, "-q"); addargs(&remote_remote_args, "-q"); showprogress = 0; break; case 'X': /* Please keep in sync with sftp.c -X */ if (strncmp(optarg, "buffer=", 7) == 0) { r = scan_scaled(optarg + 7, &llv); if (r == 0 && (llv <= 0 || llv > 256 * 1024)) { r = -1; errno = EINVAL; } if (r == -1) { fatal("Invalid buffer size \"%s\": %s", optarg + 7, strerror(errno)); } sftp_copy_buflen = (size_t)llv; } else if (strncmp(optarg, "nrequests=", 10) == 0) { llv = strtonum(optarg + 10, 1, 256 * 1024, &errstr); if (errstr != NULL) { fatal("Invalid number of requests " "\"%s\": %s", optarg + 10, errstr); } sftp_nrequests = (size_t)llv; } else { fatal("Invalid -X option"); } break; /* Server options. */ case 'd': targetshouldbedirectory = 1; break; case 'f': /* "from" */ iamremote = 1; fflag = 1; break; case 't': /* "to" */ iamremote = 1; tflag = 1; #ifdef HAVE_CYGWIN setmode(0, O_BINARY); #endif break; case 'T': Tflag = 1; break; default: usage(); } } argc -= optind; argv += optind; log_init(argv0, log_level, SYSLOG_FACILITY_USER, 2); /* Do this last because we want the user to be able to override it */ addargs(&args, "-oForwardAgent=no"); if (iamremote) mode = MODE_SCP; if ((pwd = getpwuid(userid = getuid())) == NULL) fatal("unknown user %u", (u_int) userid); if (!isatty(STDOUT_FILENO)) showprogress = 0; if (pflag) { /* Cannot pledge: -p allows setuid/setgid files... */ } else { if (pledge("stdio rpath wpath cpath fattr tty proc exec", NULL) == -1) { perror("pledge"); exit(1); } } remin = STDIN_FILENO; remout = STDOUT_FILENO; if (fflag) { /* Follow "protocol", send data. */ (void) response(); source(argc, argv); exit(errs != 0); } if (tflag) { /* Receive data. */ sink(argc, argv, NULL); exit(errs != 0); } if (argc < 2) usage(); if (argc > 2) targetshouldbedirectory = 1; remin = remout = -1; do_cmd_pid = -1; /* Command to be executed on remote system using "ssh". */ (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s", verbose_mode ? " -v" : "", iamrecursive ? " -r" : "", pflag ? " -p" : "", targetshouldbedirectory ? " -d" : ""); (void) ssh_signal(SIGPIPE, lostconn); if (colon(argv[argc - 1])) /* Dest is remote host. */ toremote(argc, argv, mode, sftp_direct); else { if (targetshouldbedirectory) verifydir(argv[argc - 1]); tolocal(argc, argv, mode, sftp_direct); /* Dest is local host. */ } /* * Finally check the exit status of the ssh process, if one was forked * and no error has occurred yet */ if (do_cmd_pid != -1 && (mode == MODE_SFTP || errs == 0)) { if (remin != -1) (void) close(remin); if (remout != -1) (void) close(remout); if (waitpid(do_cmd_pid, &status, 0) == -1) errs = 1; else { if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) errs = 1; } } exit(errs != 0); } /* Callback from atomicio6 to update progress meter and limit bandwidth */ static int scpio(void *_cnt, size_t s) { off_t *cnt = (off_t *)_cnt; *cnt += s; refresh_progress_meter(0); if (limit_kbps > 0) bandwidth_limit(&bwlimit, s); return 0; } static int do_times(int fd, int verb, const struct stat *sb) { /* strlen(2^64) == 20; strlen(10^6) == 7 */ char buf[(20 + 7 + 2) * 2 + 2]; (void)snprintf(buf, sizeof(buf), "T%llu 0 %llu 0\n", (unsigned long long) (sb->st_mtime < 0 ? 0 : sb->st_mtime), (unsigned long long) (sb->st_atime < 0 ? 0 : sb->st_atime)); if (verb) { fprintf(stderr, "File mtime %lld atime %lld\n", (long long)sb->st_mtime, (long long)sb->st_atime); fprintf(stderr, "Sending file timestamps: %s", buf); } (void) atomicio(vwrite, fd, buf, strlen(buf)); return (response()); } static int parse_scp_uri(const char *uri, char **userp, char **hostp, int *portp, char **pathp) { int r; r = parse_uri("scp", uri, userp, hostp, portp, pathp); if (r == 0 && *pathp == NULL) *pathp = xstrdup("."); return r; } /* Appends a string to an array; returns 0 on success, -1 on alloc failure */ static int append(char *cp, char ***ap, size_t *np) { char **tmp; if ((tmp = reallocarray(*ap, *np + 1, sizeof(*tmp))) == NULL) return -1; tmp[(*np)] = cp; (*np)++; *ap = tmp; return 0; } /* * Finds the start and end of the first brace pair in the pattern. * returns 0 on success or -1 for invalid patterns. */ static int find_brace(const char *pattern, int *startp, int *endp) { int i; int in_bracket, brace_level; *startp = *endp = -1; in_bracket = brace_level = 0; for (i = 0; i < INT_MAX && *endp < 0 && pattern[i] != '\0'; i++) { switch (pattern[i]) { case '\\': /* skip next character */ if (pattern[i + 1] != '\0') i++; break; case '[': in_bracket = 1; break; case ']': in_bracket = 0; break; case '{': if (in_bracket) break; if (pattern[i + 1] == '}') { /* Protect a single {}, for find(1), like csh */ i++; /* skip */ break; } if (*startp == -1) *startp = i; brace_level++; break; case '}': if (in_bracket) break; if (*startp < 0) { /* Unbalanced brace */ return -1; } if (--brace_level <= 0) *endp = i; break; } } /* unbalanced brackets/braces */ if (*endp < 0 && (*startp >= 0 || in_bracket)) return -1; return 0; } /* * Assembles and records a successfully-expanded pattern, returns -1 on * alloc failure. */ static int emit_expansion(const char *pattern, int brace_start, int brace_end, int sel_start, int sel_end, char ***patternsp, size_t *npatternsp) { char *cp; size_t pattern_len; int o = 0, tail_len; if ((pattern_len = strlen(pattern)) == 0 || pattern_len >= INT_MAX) return -1; tail_len = strlen(pattern + brace_end + 1); if ((cp = malloc(brace_start + (sel_end - sel_start) + tail_len + 1)) == NULL) return -1; /* Pattern before initial brace */ if (brace_start > 0) { memcpy(cp, pattern, brace_start); o = brace_start; } /* Current braced selection */ if (sel_end - sel_start > 0) { memcpy(cp + o, pattern + sel_start, sel_end - sel_start); o += sel_end - sel_start; } /* Remainder of pattern after closing brace */ if (tail_len > 0) { memcpy(cp + o, pattern + brace_end + 1, tail_len); o += tail_len; } cp[o] = '\0'; if (append(cp, patternsp, npatternsp) != 0) { free(cp); return -1; } return 0; } /* * Expand the first encountered brace in pattern, appending the expanded * patterns it yielded to the *patternsp array. * * Returns 0 on success or -1 on allocation failure. * * Signals whether expansion was performed via *expanded and whether * pattern was invalid via *invalid. */ static int brace_expand_one(const char *pattern, char ***patternsp, size_t *npatternsp, int *expanded, int *invalid) { int i; int in_bracket, brace_start, brace_end, brace_level; int sel_start, sel_end; *invalid = *expanded = 0; if (find_brace(pattern, &brace_start, &brace_end) != 0) { *invalid = 1; return 0; } else if (brace_start == -1) return 0; in_bracket = brace_level = 0; for (i = sel_start = brace_start + 1; i < brace_end; i++) { switch (pattern[i]) { case '{': if (in_bracket) break; brace_level++; break; case '}': if (in_bracket) break; brace_level--; break; case '[': in_bracket = 1; break; case ']': in_bracket = 0; break; case '\\': if (i < brace_end - 1) i++; /* skip */ break; } if (pattern[i] == ',' || i == brace_end - 1) { if (in_bracket || brace_level > 0) continue; /* End of a selection, emit an expanded pattern */ /* Adjust end index for last selection */ sel_end = (i == brace_end - 1) ? brace_end : i; if (emit_expansion(pattern, brace_start, brace_end, sel_start, sel_end, patternsp, npatternsp) != 0) return -1; /* move on to the next selection */ sel_start = i + 1; continue; } } if (in_bracket || brace_level > 0) { *invalid = 1; return 0; } /* success */ *expanded = 1; return 0; } /* Expand braces from pattern. Returns 0 on success, -1 on failure */ static int brace_expand(const char *pattern, char ***patternsp, size_t *npatternsp) { char *cp, *cp2, **active = NULL, **done = NULL; size_t i, nactive = 0, ndone = 0; int ret = -1, invalid = 0, expanded = 0; *patternsp = NULL; *npatternsp = 0; /* Start the worklist with the original pattern */ if ((cp = strdup(pattern)) == NULL) return -1; if (append(cp, &active, &nactive) != 0) { free(cp); return -1; } while (nactive > 0) { cp = active[nactive - 1]; nactive--; if (brace_expand_one(cp, &active, &nactive, &expanded, &invalid) == -1) { free(cp); goto fail; } if (invalid) fatal_f("invalid brace pattern \"%s\"", cp); if (expanded) { /* * Current entry expanded to new entries on the * active list; discard the progenitor pattern. */ free(cp); continue; } /* * Pattern did not expand; append the finename component to * the completed list */ if ((cp2 = strrchr(cp, '/')) != NULL) *cp2++ = '\0'; else cp2 = cp; if (append(xstrdup(cp2), &done, &ndone) != 0) { free(cp); goto fail; } free(cp); } /* success */ *patternsp = done; *npatternsp = ndone; done = NULL; ndone = 0; ret = 0; fail: for (i = 0; i < nactive; i++) free(active[i]); free(active); for (i = 0; i < ndone; i++) free(done[i]); free(done); return ret; } static struct sftp_conn * do_sftp_connect(char *host, char *user, int port, char *sftp_direct, int *reminp, int *remoutp, int *pidp) { if (sftp_direct == NULL) { if (do_cmd(ssh_program, host, user, port, 1, "sftp", reminp, remoutp, pidp) < 0) return NULL; } else { freeargs(&args); addargs(&args, "sftp-server"); if (do_cmd(sftp_direct, host, NULL, -1, 0, "sftp", reminp, remoutp, pidp) < 0) return NULL; } return sftp_init(*reminp, *remoutp, sftp_copy_buflen, sftp_nrequests, limit_kbps); } void toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) { char *suser = NULL, *host = NULL, *src = NULL; char *bp, *tuser, *thost, *targ; int sport = -1, tport = -1; struct sftp_conn *conn = NULL, *conn2 = NULL; arglist alist; int i, r, status; struct stat sb; u_int j; memset(&alist, '\0', sizeof(alist)); alist.list = NULL; /* Parse target */ r = parse_scp_uri(argv[argc - 1], &tuser, &thost, &tport, &targ); if (r == -1) { fmprintf(stderr, "%s: invalid uri\n", argv[argc - 1]); ++errs; goto out; } if (r != 0) { if (parse_user_host_path(argv[argc - 1], &tuser, &thost, &targ) == -1) { fmprintf(stderr, "%s: invalid target\n", argv[argc - 1]); ++errs; goto out; } } /* Parse source files */ for (i = 0; i < argc - 1; i++) { free(suser); free(host); free(src); r = parse_scp_uri(argv[i], &suser, &host, &sport, &src); if (r == -1) { fmprintf(stderr, "%s: invalid uri\n", argv[i]); ++errs; continue; } if (r != 0) { parse_user_host_path(argv[i], &suser, &host, &src); } if (suser != NULL && !okname(suser)) { ++errs; continue; } if (host && throughlocal) { /* extended remote to remote */ if (mode == MODE_SFTP) { if (remin == -1) { /* Connect to dest now */ conn = do_sftp_connect(thost, tuser, tport, sftp_direct, &remin, &remout, &do_cmd_pid); if (conn == NULL) { fatal("Unable to open " "destination connection"); } debug3_f("origin in %d out %d pid %ld", remin, remout, (long)do_cmd_pid); } /* * XXX remember suser/host/sport and only * reconnect if they change between arguments. * would save reconnections for cases like * scp -3 hosta:/foo hosta:/bar hostb: */ /* Connect to origin now */ conn2 = do_sftp_connect(host, suser, sport, sftp_direct, &remin2, &remout2, &do_cmd_pid2); if (conn2 == NULL) { fatal("Unable to open " "source connection"); } debug3_f("destination in %d out %d pid %ld", remin2, remout2, (long)do_cmd_pid2); throughlocal_sftp(conn2, conn, src, targ); (void) close(remin2); (void) close(remout2); remin2 = remout2 = -1; if (waitpid(do_cmd_pid2, &status, 0) == -1) ++errs; else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) ++errs; do_cmd_pid2 = -1; continue; } else { xasprintf(&bp, "%s -f %s%s", cmd, *src == '-' ? "-- " : "", src); if (do_cmd(ssh_program, host, suser, sport, 0, bp, &remin, &remout, &do_cmd_pid) < 0) exit(1); free(bp); xasprintf(&bp, "%s -t %s%s", cmd, *targ == '-' ? "-- " : "", targ); if (do_cmd2(thost, tuser, tport, bp, remin, remout) < 0) exit(1); free(bp); (void) close(remin); (void) close(remout); remin = remout = -1; } } else if (host) { /* standard remote to remote */ /* * Second remote user is passed to first remote side * via scp command-line. Ensure it contains no obvious * shell characters. */ if (tuser != NULL && !okname(tuser)) { ++errs; continue; } if (tport != -1 && tport != SSH_DEFAULT_PORT) { /* This would require the remote support URIs */ fatal("target port not supported with two " "remote hosts and the -R option"); } freeargs(&alist); addargs(&alist, "%s", ssh_program); addargs(&alist, "-x"); addargs(&alist, "-oClearAllForwardings=yes"); addargs(&alist, "-n"); for (j = 0; j < remote_remote_args.num; j++) { addargs(&alist, "%s", remote_remote_args.list[j]); } if (sport != -1) { addargs(&alist, "-p"); addargs(&alist, "%d", sport); } if (suser) { addargs(&alist, "-l"); addargs(&alist, "%s", suser); } addargs(&alist, "--"); addargs(&alist, "%s", host); addargs(&alist, "%s", cmd); addargs(&alist, "%s", src); addargs(&alist, "%s%s%s:%s", tuser ? tuser : "", tuser ? "@" : "", thost, targ); if (do_local_cmd(&alist) != 0) errs = 1; } else { /* local to remote */ if (mode == MODE_SFTP) { /* no need to glob: already done by shell */ if (stat(argv[i], &sb) != 0) { fatal("stat local \"%s\": %s", argv[i], strerror(errno)); } if (remin == -1) { /* Connect to remote now */ conn = do_sftp_connect(thost, tuser, tport, sftp_direct, &remin, &remout, &do_cmd_pid); if (conn == NULL) { fatal("Unable to open sftp " "connection"); } } /* The protocol */ source_sftp(1, argv[i], targ, conn); continue; } /* SCP */ if (remin == -1) { xasprintf(&bp, "%s -t %s%s", cmd, *targ == '-' ? "-- " : "", targ); if (do_cmd(ssh_program, thost, tuser, tport, 0, bp, &remin, &remout, &do_cmd_pid) < 0) exit(1); if (response() < 0) exit(1); free(bp); } source(1, argv + i); } } out: if (mode == MODE_SFTP) free(conn); free(tuser); free(thost); free(targ); free(suser); free(host); free(src); } void tolocal(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) { char *bp, *host = NULL, *src = NULL, *suser = NULL; arglist alist; struct sftp_conn *conn = NULL; int i, r, sport = -1; memset(&alist, '\0', sizeof(alist)); alist.list = NULL; for (i = 0; i < argc - 1; i++) { free(suser); free(host); free(src); r = parse_scp_uri(argv[i], &suser, &host, &sport, &src); if (r == -1) { fmprintf(stderr, "%s: invalid uri\n", argv[i]); ++errs; continue; } if (r != 0) parse_user_host_path(argv[i], &suser, &host, &src); if (suser != NULL && !okname(suser)) { ++errs; continue; } if (!host) { /* Local to local. */ freeargs(&alist); addargs(&alist, "%s", _PATH_CP); if (iamrecursive) addargs(&alist, "-r"); if (pflag) addargs(&alist, "-p"); addargs(&alist, "--"); addargs(&alist, "%s", argv[i]); addargs(&alist, "%s", argv[argc-1]); if (do_local_cmd(&alist)) ++errs; continue; } /* Remote to local. */ if (mode == MODE_SFTP) { conn = do_sftp_connect(host, suser, sport, sftp_direct, &remin, &remout, &do_cmd_pid); if (conn == NULL) { error("sftp connection failed"); ++errs; continue; } /* The protocol */ sink_sftp(1, argv[argc - 1], src, conn); free(conn); (void) close(remin); (void) close(remout); remin = remout = -1; continue; } /* SCP */ xasprintf(&bp, "%s -f %s%s", cmd, *src == '-' ? "-- " : "", src); if (do_cmd(ssh_program, host, suser, sport, 0, bp, &remin, &remout, &do_cmd_pid) < 0) { free(bp); ++errs; continue; } free(bp); sink(1, argv + argc - 1, src); (void) close(remin); remin = remout = -1; } free(suser); free(host); free(src); } /* Prepare remote path, handling ~ by assuming cwd is the homedir */ static char * prepare_remote_path(struct sftp_conn *conn, const char *path) { size_t nslash; /* Handle ~ prefixed paths */ if (*path == '\0' || strcmp(path, "~") == 0) return xstrdup("."); if (*path != '~') return xstrdup(path); if (strncmp(path, "~/", 2) == 0) { if ((nslash = strspn(path + 2, "/")) == strlen(path + 2)) return xstrdup("."); return xstrdup(path + 2 + nslash); } if (sftp_can_expand_path(conn)) return sftp_expand_path(conn, path); /* No protocol extension */ error("server expand-path extension is required " "for ~user paths in SFTP mode"); return NULL; } void source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn) { char *target = NULL, *filename = NULL, *abs_dst = NULL; int src_is_dir, target_is_dir; Attrib a; struct stat st; memset(&a, '\0', sizeof(a)); if (stat(src, &st) != 0) fatal("stat local \"%s\": %s", src, strerror(errno)); src_is_dir = S_ISDIR(st.st_mode); if ((filename = basename(src)) == NULL) fatal("basename \"%s\": %s", src, strerror(errno)); /* * No need to glob here - the local shell already took care of * the expansions */ if ((target = prepare_remote_path(conn, targ)) == NULL) cleanup_exit(255); target_is_dir = sftp_remote_is_dir(conn, target); if (targetshouldbedirectory && !target_is_dir) { debug("target directory \"%s\" does not exist", target); a.flags = SSH2_FILEXFER_ATTR_PERMISSIONS; a.perm = st.st_mode | 0700; /* ensure writable */ if (sftp_mkdir(conn, target, &a, 1) != 0) cleanup_exit(255); /* error already logged */ target_is_dir = 1; } if (target_is_dir) abs_dst = sftp_path_append(target, filename); else { abs_dst = target; target = NULL; } debug3_f("copying local %s to remote %s", src, abs_dst); if (src_is_dir && iamrecursive) { if (sftp_upload_dir(conn, src, abs_dst, pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) { error("failed to upload directory %s to %s", src, targ); errs = 1; } } else if (sftp_upload(conn, src, abs_dst, pflag, 0, 0, 1) != 0) { error("failed to upload file %s to %s", src, targ); errs = 1; } free(abs_dst); free(target); } void source(int argc, char **argv) { struct stat stb; static BUF buffer; BUF *bp; off_t i, statbytes; size_t amt, nr; int fd = -1, haderr, indx; char *last, *name, buf[PATH_MAX + 128], encname[PATH_MAX]; int len; for (indx = 0; indx < argc; ++indx) { name = argv[indx]; statbytes = 0; len = strlen(name); while (len > 1 && name[len-1] == '/') name[--len] = '\0'; if ((fd = open(name, O_RDONLY|O_NONBLOCK)) == -1) goto syserr; if (strchr(name, '\n') != NULL) { strnvis(encname, name, sizeof(encname), VIS_NL); name = encname; } if (fstat(fd, &stb) == -1) { syserr: run_err("%s: %s", name, strerror(errno)); goto next; } if (stb.st_size < 0) { run_err("%s: %s", name, "Negative file size"); goto next; } unset_nonblock(fd); switch (stb.st_mode & S_IFMT) { case S_IFREG: break; case S_IFDIR: if (iamrecursive) { rsource(name, &stb); goto next; } /* FALLTHROUGH */ default: run_err("%s: not a regular file", name); goto next; } if ((last = strrchr(name, '/')) == NULL) last = name; else ++last; curfile = last; if (pflag) { if (do_times(remout, verbose_mode, &stb) < 0) goto next; } #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) snprintf(buf, sizeof buf, "C%04o %lld %s\n", (u_int) (stb.st_mode & FILEMODEMASK), (long long)stb.st_size, last); if (verbose_mode) fmprintf(stderr, "Sending file modes: %s", buf); (void) atomicio(vwrite, remout, buf, strlen(buf)); if (response() < 0) goto next; if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) { next: if (fd != -1) { (void) close(fd); fd = -1; } continue; } if (showprogress) start_progress_meter(curfile, stb.st_size, &statbytes); set_nonblock(remout); for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { amt = bp->cnt; if (i + (off_t)amt > stb.st_size) amt = stb.st_size - i; if (!haderr) { if ((nr = atomicio(read, fd, bp->buf, amt)) != amt) { haderr = errno; memset(bp->buf + nr, 0, amt - nr); } } /* Keep writing after error to retain sync */ if (haderr) { (void)atomicio(vwrite, remout, bp->buf, amt); memset(bp->buf, 0, amt); continue; } if (atomicio6(vwrite, remout, bp->buf, amt, scpio, &statbytes) != amt) haderr = errno; } unset_nonblock(remout); if (fd != -1) { if (close(fd) == -1 && !haderr) haderr = errno; fd = -1; } if (!haderr) (void) atomicio(vwrite, remout, "", 1); else run_err("%s: %s", name, strerror(haderr)); (void) response(); if (showprogress) stop_progress_meter(); } } void rsource(char *name, struct stat *statp) { DIR *dirp; struct dirent *dp; char *last, *vect[1], path[PATH_MAX]; if (!(dirp = opendir(name))) { run_err("%s: %s", name, strerror(errno)); return; } last = strrchr(name, '/'); if (last == NULL) last = name; else last++; if (pflag) { if (do_times(remout, verbose_mode, statp) < 0) { closedir(dirp); return; } } (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n", (u_int) (statp->st_mode & FILEMODEMASK), 0, last); if (verbose_mode) fmprintf(stderr, "Entering directory: %s", path); (void) atomicio(vwrite, remout, path, strlen(path)); if (response() < 0) { closedir(dirp); return; } while ((dp = readdir(dirp)) != NULL) { if (dp->d_ino == 0) continue; if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) { run_err("%s/%s: name too long", name, dp->d_name); continue; } (void) snprintf(path, sizeof path, "%s/%s", name, dp->d_name); vect[0] = path; source(1, vect); } (void) closedir(dirp); (void) atomicio(vwrite, remout, "E\n", 2); (void) response(); } void sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn) { char *abs_src = NULL; char *abs_dst = NULL; glob_t g; char *filename, *tmp = NULL; int i, r, err = 0, dst_is_dir; struct stat st; memset(&g, 0, sizeof(g)); /* * Here, we need remote glob as SFTP can not depend on remote shell * expansions */ if ((abs_src = prepare_remote_path(conn, src)) == NULL) { err = -1; goto out; } debug3_f("copying remote %s to local %s", abs_src, dst); if ((r = sftp_glob(conn, abs_src, GLOB_NOCHECK|GLOB_MARK, NULL, &g)) != 0) { if (r == GLOB_NOSPACE) error("%s: too many glob matches", src); else error("%s: %s", src, strerror(ENOENT)); err = -1; goto out; } /* Did we actually get any matches back from the glob? */ if (g.gl_matchc == 0 && g.gl_pathc == 1 && g.gl_pathv[0] != 0) { /* * If nothing matched but a path returned, then it's probably * a GLOB_NOCHECK result. Check whether the unglobbed path * exists so we can give a nice error message early. */ if (sftp_stat(conn, g.gl_pathv[0], 1, NULL) != 0) { error("%s: %s", src, strerror(ENOENT)); err = -1; goto out; } } if ((r = stat(dst, &st)) != 0) debug2_f("stat local \"%s\": %s", dst, strerror(errno)); dst_is_dir = r == 0 && S_ISDIR(st.st_mode); if (g.gl_matchc > 1 && !dst_is_dir) { if (r == 0) { error("Multiple files match pattern, but destination " "\"%s\" is not a directory", dst); err = -1; goto out; } debug2_f("creating destination \"%s\"", dst); if (mkdir(dst, 0777) != 0) { error("local mkdir \"%s\": %s", dst, strerror(errno)); err = -1; goto out; } dst_is_dir = 1; } for (i = 0; g.gl_pathv[i] && !interrupted; i++) { tmp = xstrdup(g.gl_pathv[i]); if ((filename = basename(tmp)) == NULL) { error("basename %s: %s", tmp, strerror(errno)); err = -1; goto out; } if (dst_is_dir) abs_dst = sftp_path_append(dst, filename); else abs_dst = xstrdup(dst); debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); if (sftp_globpath_is_dir(g.gl_pathv[i]) && iamrecursive) { if (sftp_download_dir(conn, g.gl_pathv[i], abs_dst, NULL, pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) == -1) err = -1; } else { if (sftp_download(conn, g.gl_pathv[i], abs_dst, NULL, pflag, 0, 0, 1) == -1) err = -1; } free(abs_dst); abs_dst = NULL; free(tmp); tmp = NULL; } out: free(abs_src); free(tmp); globfree(&g); if (err == -1) errs = 1; } #define TYPE_OVERFLOW(type, val) \ ((sizeof(type) == 4 && (val) > INT32_MAX) || \ (sizeof(type) == 8 && (val) > INT64_MAX) || \ (sizeof(type) != 4 && sizeof(type) != 8)) void sink(int argc, char **argv, const char *src) { static BUF buffer; struct stat stb; BUF *bp; off_t i; size_t j, count; int amt, exists, first, ofd; mode_t mode, omode, mask; off_t size, statbytes; unsigned long long ull; int setimes, targisdir, wrerr; char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048]; char **patterns = NULL; size_t n, npatterns = 0; struct timeval tv[2]; #define atime tv[0] #define mtime tv[1] #define SCREWUP(str) { why = str; goto screwup; } if (TYPE_OVERFLOW(time_t, 0) || TYPE_OVERFLOW(off_t, 0)) SCREWUP("Unexpected off_t/time_t size"); setimes = targisdir = 0; mask = umask(0); if (!pflag) (void) umask(mask); if (argc != 1) { run_err("ambiguous target"); exit(1); } targ = *argv; if (targetshouldbedirectory) verifydir(targ); (void) atomicio(vwrite, remout, "", 1); if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) targisdir = 1; if (src != NULL && !iamrecursive && !Tflag) { /* * Prepare to try to restrict incoming filenames to match * the requested destination file glob. */ if (brace_expand(src, &patterns, &npatterns) != 0) fatal_f("could not expand pattern"); } for (first = 1;; first = 0) { cp = buf; if (atomicio(read, remin, cp, 1) != 1) goto done; if (*cp++ == '\n') SCREWUP("unexpected "); do { if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch)) SCREWUP("lost connection"); *cp++ = ch; } while (cp < &buf[sizeof(buf) - 1] && ch != '\n'); *cp = 0; if (verbose_mode) fmprintf(stderr, "Sink: %s", buf); if (buf[0] == '\01' || buf[0] == '\02') { if (iamremote == 0) { (void) snmprintf(visbuf, sizeof(visbuf), NULL, "%s", buf + 1); (void) atomicio(vwrite, STDERR_FILENO, visbuf, strlen(visbuf)); } if (buf[0] == '\02') exit(1); ++errs; continue; } if (buf[0] == 'E') { (void) atomicio(vwrite, remout, "", 1); goto done; } if (ch == '\n') *--cp = 0; cp = buf; if (*cp == 'T') { setimes++; cp++; if (!isdigit((unsigned char)*cp)) SCREWUP("mtime.sec not present"); ull = strtoull(cp, &cp, 10); if (!cp || *cp++ != ' ') SCREWUP("mtime.sec not delimited"); if (TYPE_OVERFLOW(time_t, ull)) setimes = 0; /* out of range */ mtime.tv_sec = ull; mtime.tv_usec = strtol(cp, &cp, 10); if (!cp || *cp++ != ' ' || mtime.tv_usec < 0 || mtime.tv_usec > 999999) SCREWUP("mtime.usec not delimited"); if (!isdigit((unsigned char)*cp)) SCREWUP("atime.sec not present"); ull = strtoull(cp, &cp, 10); if (!cp || *cp++ != ' ') SCREWUP("atime.sec not delimited"); if (TYPE_OVERFLOW(time_t, ull)) setimes = 0; /* out of range */ atime.tv_sec = ull; atime.tv_usec = strtol(cp, &cp, 10); if (!cp || *cp++ != '\0' || atime.tv_usec < 0 || atime.tv_usec > 999999) SCREWUP("atime.usec not delimited"); (void) atomicio(vwrite, remout, "", 1); continue; } if (*cp != 'C' && *cp != 'D') { /* * Check for the case "rcp remote:foo\* local:bar". * In this case, the line "No match." can be returned * by the shell before the rcp command on the remote is * executed so the ^Aerror_message convention isn't * followed. */ if (first) { run_err("%s", cp); exit(1); } SCREWUP("expected control record"); } mode = 0; for (++cp; cp < buf + 5; cp++) { if (*cp < '0' || *cp > '7') SCREWUP("bad mode"); mode = (mode << 3) | (*cp - '0'); } if (!pflag) mode &= ~mask; if (*cp++ != ' ') SCREWUP("mode not delimited"); if (!isdigit((unsigned char)*cp)) SCREWUP("size not present"); ull = strtoull(cp, &cp, 10); if (!cp || *cp++ != ' ') SCREWUP("size not delimited"); if (TYPE_OVERFLOW(off_t, ull)) SCREWUP("size out of range"); size = (off_t)ull; if (*cp == '\0' || strchr(cp, '/') != NULL || strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) { run_err("error: unexpected filename: %s", cp); exit(1); } if (npatterns > 0) { for (n = 0; n < npatterns; n++) { if (strcmp(patterns[n], cp) == 0 || fnmatch(patterns[n], cp, 0) == 0) break; } - if (n >= npatterns) + if (n >= npatterns) { + debug2_f("incoming filename \"%s\" does not " + "match any of %zu expected patterns", cp, + npatterns); + for (n = 0; n < npatterns; n++) { + debug3_f("expected pattern %zu: \"%s\"", + n, patterns[n]); + } SCREWUP("filename does not match request"); + } } if (targisdir) { static char *namebuf; static size_t cursize; size_t need; need = strlen(targ) + strlen(cp) + 250; if (need > cursize) { free(namebuf); namebuf = xmalloc(need); cursize = need; } (void) snprintf(namebuf, need, "%s%s%s", targ, strcmp(targ, "/") ? "/" : "", cp); np = namebuf; } else np = targ; curfile = cp; exists = stat(np, &stb) == 0; if (buf[0] == 'D') { int mod_flag = pflag; if (!iamrecursive) SCREWUP("received directory without -r"); if (exists) { if (!S_ISDIR(stb.st_mode)) { errno = ENOTDIR; goto bad; } if (pflag) (void) chmod(np, mode); } else { /* Handle copying from a read-only directory */ mod_flag = 1; if (mkdir(np, mode | S_IRWXU) == -1) goto bad; } vect[0] = xstrdup(np); sink(1, vect, src); if (setimes) { setimes = 0; (void) utimes(vect[0], tv); } if (mod_flag) (void) chmod(vect[0], mode); free(vect[0]); continue; } omode = mode; mode |= S_IWUSR; if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) { bad: run_err("%s: %s", np, strerror(errno)); continue; } (void) atomicio(vwrite, remout, "", 1); if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) { (void) close(ofd); continue; } cp = bp->buf; wrerr = 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); set_nonblock(remin); for (count = i = 0; i < size; i += bp->cnt) { amt = bp->cnt; if (i + amt > size) amt = size - i; count += amt; do { j = atomicio6(read, remin, cp, amt, scpio, &statbytes); if (j == 0) { run_err("%s", j != EPIPE ? strerror(errno) : "dropped connection"); exit(1); } amt -= j; cp += j; } while (amt > 0); if (count == bp->cnt) { /* Keep reading so we stay sync'd up. */ if (!wrerr) { if (atomicio(vwrite, ofd, bp->buf, count) != count) { note_err("%s: %s", np, strerror(errno)); wrerr = 1; } } count = 0; cp = bp->buf; } } unset_nonblock(remin); if (count != 0 && !wrerr && atomicio(vwrite, ofd, bp->buf, count) != count) { 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 if (fchmod(ofd, omode)) { #else /* HAVE_FCHMOD */ if (chmod(np, omode)) { #endif /* HAVE_FCHMOD */ note_err("%s: set mode: %s", np, strerror(errno)); } } else { if (!exists && omode != mode) #ifdef HAVE_FCHMOD if (fchmod(ofd, omode & ~mask)) { #else /* HAVE_FCHMOD */ if (chmod(np, omode & ~mask)) { #endif /* HAVE_FCHMOD */ note_err("%s: set mode: %s", np, strerror(errno)); } } if (close(ofd) == -1) note_err("%s: close: %s", np, strerror(errno)); (void) response(); if (showprogress) stop_progress_meter(); if (setimes && !wrerr) { setimes = 0; if (utimes(np, tv) == -1) { note_err("%s: set times: %s", np, strerror(errno)); } } /* If no error was noted then signal success for this file */ if (note_err(NULL) == 0) (void) atomicio(vwrite, remout, "", 1); } done: for (n = 0; n < npatterns; n++) free(patterns[n]); free(patterns); return; screwup: for (n = 0; n < npatterns; n++) free(patterns[n]); free(patterns); run_err("protocol error: %s", why); exit(1); } void throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to, char *src, char *targ) { char *target = NULL, *filename = NULL, *abs_dst = NULL; char *abs_src = NULL, *tmp = NULL; glob_t g; int i, r, targetisdir, err = 0; if ((filename = basename(src)) == NULL) fatal("basename %s: %s", src, strerror(errno)); if ((abs_src = prepare_remote_path(from, src)) == NULL || (target = prepare_remote_path(to, targ)) == NULL) cleanup_exit(255); memset(&g, 0, sizeof(g)); targetisdir = sftp_remote_is_dir(to, target); if (!targetisdir && targetshouldbedirectory) { error("%s: destination is not a directory", targ); err = -1; goto out; } debug3_f("copying remote %s to remote %s", abs_src, target); if ((r = sftp_glob(from, abs_src, GLOB_NOCHECK|GLOB_MARK, NULL, &g)) != 0) { if (r == GLOB_NOSPACE) error("%s: too many glob matches", src); else error("%s: %s", src, strerror(ENOENT)); err = -1; goto out; } /* Did we actually get any matches back from the glob? */ if (g.gl_matchc == 0 && g.gl_pathc == 1 && g.gl_pathv[0] != 0) { /* * If nothing matched but a path returned, then it's probably * a GLOB_NOCHECK result. Check whether the unglobbed path * exists so we can give a nice error message early. */ if (sftp_stat(from, g.gl_pathv[0], 1, NULL) != 0) { error("%s: %s", src, strerror(ENOENT)); err = -1; goto out; } } for (i = 0; g.gl_pathv[i] && !interrupted; i++) { tmp = xstrdup(g.gl_pathv[i]); if ((filename = basename(tmp)) == NULL) { error("basename %s: %s", tmp, strerror(errno)); err = -1; goto out; } if (targetisdir) abs_dst = sftp_path_append(target, filename); else abs_dst = xstrdup(target); debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); if (sftp_globpath_is_dir(g.gl_pathv[i]) && iamrecursive) { if (sftp_crossload_dir(from, to, g.gl_pathv[i], abs_dst, NULL, pflag, SFTP_PROGRESS_ONLY, 1) == -1) err = -1; } else { if (sftp_crossload(from, to, g.gl_pathv[i], abs_dst, NULL, pflag) == -1) err = -1; } free(abs_dst); abs_dst = NULL; free(tmp); tmp = NULL; } out: free(abs_src); free(abs_dst); free(target); free(tmp); globfree(&g); if (err == -1) errs = 1; } int response(void) { char ch, *cp, resp, rbuf[2048], visbuf[2048]; if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp)) lostconn(0); cp = rbuf; switch (resp) { case 0: /* ok */ return (0); default: *cp++ = resp; /* FALLTHROUGH */ case 1: /* error, followed by error msg */ case 2: /* fatal error, "" */ do { if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch)) lostconn(0); *cp++ = ch; } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n'); if (!iamremote) { cp[-1] = '\0'; (void) snmprintf(visbuf, sizeof(visbuf), NULL, "%s\n", rbuf); (void) atomicio(vwrite, STDERR_FILENO, visbuf, strlen(visbuf)); } ++errs; if (resp == 1) return (-1); exit(1); } /* NOTREACHED */ } void usage(void) { (void) fprintf(stderr, "usage: scp [-346ABCOpqRrsTv] [-c cipher] [-D sftp_server_path] [-F ssh_config]\n" " [-i identity_file] [-J destination] [-l limit] [-o ssh_option]\n" " [-P port] [-S program] [-X sftp_option] source ... target\n"); exit(1); } void run_err(const char *fmt,...) { static FILE *fp; va_list ap; ++errs; if (fp != NULL || (remout != -1 && (fp = fdopen(remout, "w")))) { (void) fprintf(fp, "%c", 0x01); (void) fprintf(fp, "scp: "); va_start(ap, fmt); (void) vfprintf(fp, fmt, ap); va_end(ap); (void) fprintf(fp, "\n"); (void) fflush(fp); } if (!iamremote) { va_start(ap, fmt); vfmprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); } } /* * 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) { struct stat stb; if (!stat(cp, &stb)) { if (S_ISDIR(stb.st_mode)) return; errno = ENOTDIR; } run_err("%s: %s", cp, strerror(errno)); killchild(0); } int okname(char *cp0) { int c; char *cp; cp = cp0; do { c = (int)*cp; if (c & 0200) goto bad; if (!isalpha(c) && !isdigit((unsigned char)c)) { switch (c) { case '\'': case '"': case '`': case ' ': case '#': goto bad; default: break; } } } while (*++cp); return (1); bad: fmprintf(stderr, "%s: invalid user name\n", cp0); return (0); } BUF * allocbuf(BUF *bp, int fd, int blksize) { size_t size; #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE struct stat stb; if (fstat(fd, &stb) == -1) { run_err("fstat: %s", strerror(errno)); return (0); } size = ROUNDUP(stb.st_blksize, blksize); if (size == 0) size = blksize; #else /* HAVE_STRUCT_STAT_ST_BLKSIZE */ size = blksize; #endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ if (bp->cnt >= size) return (bp); bp->buf = xrecallocarray(bp->buf, bp->cnt, size, 1); bp->cnt = size; return (bp); } void lostconn(int signo) { if (!iamremote) (void)write(STDERR_FILENO, "lost connection\n", 16); if (signo) _exit(1); else exit(1); } void cleanup_exit(int i) { if (remin > 0) close(remin); if (remout > 0) close(remout); if (remin2 > 0) close(remin2); if (remout2 > 0) close(remout2); if (do_cmd_pid > 0) (void)waitpid(do_cmd_pid, NULL, 0); if (do_cmd_pid2 > 0) (void)waitpid(do_cmd_pid2, NULL, 0); exit(i); } diff --git a/crypto/openssh/servconf.c b/crypto/openssh/servconf.c index c114f95c6677..dd8238f938cd 100644 --- a/crypto/openssh/servconf.c +++ b/crypto/openssh/servconf.c @@ -1,3254 +1,3222 @@ -/* $OpenBSD: servconf.c,v 1.402 2023/09/08 06:34:24 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.403 2023/10/11 22:42:26 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #include "includes.h" #include #include #include #ifdef __OpenBSD__ #include #endif #include #include #include #ifdef HAVE_NET_ROUTE_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #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" #include "ssh.h" #include "log.h" #include "sshbuf.h" #include "misc.h" #include "servconf.h" #include "pathnames.h" #include "cipher.h" #include "sshkey.h" #include "kex.h" #include "mac.h" #include "match.h" #include "channels.h" #include "groupaccess.h" #include "canohost.h" #include "packet.h" #include "ssherr.h" #include "hostfile.h" #include "auth.h" #include "myproposal.h" #include "digest.h" #include "version.h" 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; extern struct sshbuf *cfg; /* Initializes the server options to their default values. */ void initialize_server_options(ServerOptions *options) { memset(options, 0, sizeof(*options)); /* Portable-specific options */ options->use_pam = -1; /* Standard Options */ options->num_ports = 0; options->ports_from_cmdline = 0; options->queued_listen_addrs = NULL; options->num_queued_listens = 0; options->listen_addrs = NULL; options->num_listen_addrs = 0; options->address_family = -1; options->routing_domain = NULL; options->num_host_key_files = 0; options->num_host_cert_files = 0; options->host_key_agent = NULL; options->pid_file = NULL; options->login_grace_time = -1; options->permit_root_login = PERMIT_NOT_SET; options->ignore_rhosts = -1; options->ignore_user_known_hosts = -1; options->print_motd = -1; options->print_lastlog = -1; options->x11_forwarding = -1; options->x11_display_offset = -1; options->x11_use_localhost = -1; options->permit_tty = -1; options->permit_user_rc = -1; options->xauth_location = NULL; options->strict_modes = -1; options->tcp_keep_alive = -1; options->log_facility = SYSLOG_FACILITY_NOT_SET; options->log_level = SYSLOG_LEVEL_NOT_SET; options->num_log_verbose = 0; options->log_verbose = NULL; options->hostbased_authentication = -1; options->hostbased_uses_name_from_packet_only = -1; options->hostbased_accepted_algos = NULL; options->hostkeyalgorithms = NULL; options->pubkey_authentication = -1; 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; options->kerberos_get_afs_token = -1; options->gss_authentication=-1; options->gss_cleanup_creds = -1; options->gss_strict_acceptor = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->permit_empty_passwd = -1; options->permit_user_env = -1; options->permit_user_env_allowlist = NULL; options->compression = -1; options->rekey_limit = -1; options->rekey_interval = -1; options->allow_tcp_forwarding = -1; options->allow_streamlocal_forwarding = -1; options->allow_agent_forwarding = -1; options->num_allow_users = 0; options->num_deny_users = 0; options->num_allow_groups = 0; options->num_deny_groups = 0; options->ciphers = NULL; options->macs = NULL; options->kex_algorithms = NULL; options->ca_sign_algorithms = NULL; options->fwd_opts.gateway_ports = -1; options->fwd_opts.streamlocal_bind_mask = (mode_t)-1; options->fwd_opts.streamlocal_bind_unlink = -1; options->num_subsystems = 0; options->max_startups_begin = -1; options->max_startups_rate = -1; options->max_startups = -1; options->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; options->use_dns = -1; options->client_alive_interval = -1; options->client_alive_count_max = -1; options->num_authkeys_files = 0; options->num_accept_env = 0; options->num_setenv = 0; options->permit_tun = -1; options->permitted_opens = NULL; options->permitted_listens = NULL; options->adm_forced_command = NULL; options->chroot_directory = NULL; options->authorized_keys_command = NULL; options->authorized_keys_command_user = NULL; options->revoked_keys_file = NULL; options->sk_provider = NULL; options->trusted_user_ca_keys = NULL; options->authorized_principals_file = NULL; options->authorized_principals_command = NULL; options->authorized_principals_command_user = NULL; options->ip_qos_interactive = -1; options->ip_qos_bulk = -1; options->version_addendum = NULL; options->fingerprint_hash = -1; options->disable_forwarding = -1; options->expose_userauth_info = -1; options->required_rsa_size = -1; options->channel_timeouts = NULL; options->num_channel_timeouts = 0; options->unused_connection_timeout = -1; options->use_blacklist = -1; } /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ static int option_clear_or_none(const char *o) { return o == NULL || strcasecmp(o, "none") == 0; } static void assemble_algorithms(ServerOptions *o) { char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig; char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig; int r; all_cipher = cipher_alg_list(',', 0); all_mac = mac_alg_list(','); all_kex = kex_alg_list(','); all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); /* 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_fr(r, "%s", #what); \ } while (0) 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); free(def_cipher); free(def_mac); free(def_kex); free(def_key); free(def_sig); } static const char *defaultkey = "[default]"; void servconf_add_hostkey(const char *file, const int line, ServerOptions *options, const char *path, int userprovided) { char *apath = derelativise_path(path); if (file == defaultkey && access(path, R_OK) != 0) return; opt_array_append2(file, line, "HostKey", &options->host_key_files, &options->host_key_file_userprovided, &options->num_host_key_files, apath, userprovided); free(apath); } void servconf_add_hostcert(const char *file, const int line, ServerOptions *options, const char *path) { char *apath = derelativise_path(path); opt_array_append(file, line, "HostCertificate", &options->host_cert_files, &options->num_host_cert_files, apath); free(apath); } void fill_default_server_options(ServerOptions *options) { u_int i; /* Portable-specific options */ if (options->use_pam == -1) options->use_pam = 1; /* Standard Options */ if (options->num_host_key_files == 0) { /* fill default hostkeys for protocols */ servconf_add_hostkey(defaultkey, 0, options, _PATH_HOST_RSA_KEY_FILE, 0); #ifdef OPENSSL_HAS_ECC servconf_add_hostkey(defaultkey, 0, options, _PATH_HOST_ECDSA_KEY_FILE, 0); #endif servconf_add_hostkey(defaultkey, 0, options, _PATH_HOST_ED25519_KEY_FILE, 0); #ifdef WITH_XMSS servconf_add_hostkey(defaultkey, 0, options, _PATH_HOST_XMSS_KEY_FILE, 0); #endif /* WITH_XMSS */ } if (options->num_host_key_files == 0) fatal("No host key files found"); /* No certificates by default */ if (options->num_ports == 0) options->ports[options->num_ports++] = SSH_DEFAULT_PORT; if (options->address_family == -1) options->address_family = AF_UNSPEC; if (options->listen_addrs == NULL) add_listen_addr(options, NULL, NULL, 0); if (options->pid_file == NULL) options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE); if (options->moduli_file == NULL) options->moduli_file = xstrdup(_PATH_DH_MODULI); if (options->login_grace_time == -1) options->login_grace_time = 120; if (options->permit_root_login == PERMIT_NOT_SET) options->permit_root_login = PERMIT_NO; if (options->ignore_rhosts == -1) options->ignore_rhosts = 1; if (options->ignore_user_known_hosts == -1) options->ignore_user_known_hosts = 0; if (options->print_motd == -1) options->print_motd = 1; if (options->print_lastlog == -1) options->print_lastlog = 1; if (options->x11_forwarding == -1) options->x11_forwarding = 0; if (options->x11_display_offset == -1) options->x11_display_offset = 10; if (options->x11_use_localhost == -1) options->x11_use_localhost = 1; if (options->xauth_location == NULL) options->xauth_location = xstrdup(_PATH_XAUTH); if (options->permit_tty == -1) options->permit_tty = 1; if (options->permit_user_rc == -1) options->permit_user_rc = 1; if (options->strict_modes == -1) options->strict_modes = 1; if (options->tcp_keep_alive == -1) options->tcp_keep_alive = 1; if (options->log_facility == SYSLOG_FACILITY_NOT_SET) options->log_facility = SYSLOG_FACILITY_AUTH; if (options->log_level == SYSLOG_LEVEL_NOT_SET) options->log_level = SYSLOG_LEVEL_INFO; if (options->hostbased_authentication == -1) options->hostbased_authentication = 0; if (options->hostbased_uses_name_from_packet_only == -1) options->hostbased_uses_name_from_packet_only = 0; if (options->pubkey_authentication == -1) options->pubkey_authentication = 1; if (options->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) options->kerberos_or_local_passwd = 1; if (options->kerberos_ticket_cleanup == -1) options->kerberos_ticket_cleanup = 1; if (options->kerberos_get_afs_token == -1) options->kerberos_get_afs_token = 0; if (options->gss_authentication == -1) options->gss_authentication = 0; if (options->gss_cleanup_creds == -1) options->gss_cleanup_creds = 1; if (options->gss_strict_acceptor == -1) options->gss_strict_acceptor = 1; if (options->password_authentication == -1) options->password_authentication = 0; if (options->kbd_interactive_authentication == -1) options->kbd_interactive_authentication = 1; if (options->permit_empty_passwd == -1) options->permit_empty_passwd = 0; if (options->permit_user_env == -1) { options->permit_user_env = 0; options->permit_user_env_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) options->rekey_interval = 0; if (options->allow_tcp_forwarding == -1) options->allow_tcp_forwarding = FORWARD_ALLOW; if (options->allow_streamlocal_forwarding == -1) options->allow_streamlocal_forwarding = FORWARD_ALLOW; if (options->allow_agent_forwarding == -1) options->allow_agent_forwarding = 1; if (options->fwd_opts.gateway_ports == -1) options->fwd_opts.gateway_ports = 0; if (options->max_startups == -1) options->max_startups = 100; if (options->max_startups_rate == -1) options->max_startups_rate = 30; /* 30% */ if (options->max_startups_begin == -1) options->max_startups_begin = 10; if (options->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) options->max_sessions = DEFAULT_SESSIONS_MAX; if (options->use_dns == -1) options->use_dns = 1; if (options->client_alive_interval == -1) options->client_alive_interval = 0; if (options->client_alive_count_max == -1) options->client_alive_count_max = 3; if (options->num_authkeys_files == 0) { opt_array_append(defaultkey, 0, "AuthorizedKeysFiles", &options->authorized_keys_files, &options->num_authkeys_files, _PATH_SSH_USER_PERMITTED_KEYS); opt_array_append(defaultkey, 0, "AuthorizedKeysFiles", &options->authorized_keys_files, &options->num_authkeys_files, _PATH_SSH_USER_PERMITTED_KEYS2); } if (options->permit_tun == -1) options->permit_tun = SSH_TUNMODE_NO; if (options->ip_qos_interactive == -1) options->ip_qos_interactive = IPTOS_DSCP_AF21; if (options->ip_qos_bulk == -1) options->ip_qos_bulk = IPTOS_DSCP_CS1; if (options->version_addendum == NULL) options->version_addendum = xstrdup(SSH_VERSION_FREEBSD); if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) options->fwd_opts.streamlocal_bind_mask = 0177; if (options->fwd_opts.streamlocal_bind_unlink == -1) options->fwd_opts.streamlocal_bind_unlink = 0; if (options->fingerprint_hash == -1) options->fingerprint_hash = SSH_FP_HASH_DEFAULT; if (options->disable_forwarding == -1) options->disable_forwarding = 0; if (options->expose_userauth_info == -1) options->expose_userauth_info = 0; if (options->sk_provider == NULL) options->sk_provider = xstrdup("internal"); if (options->required_rsa_size == -1) options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; if (options->unused_connection_timeout == -1) options->unused_connection_timeout = 0; if (options->use_blacklist == -1) options->use_blacklist = 0; assemble_algorithms(options); /* Turn privilege separation and sandboxing on by default */ if (use_privsep == -1) use_privsep = PRIVSEP_ON; #define CLEAR_ON_NONE(v) \ do { \ if (option_clear_or_none(v)) { \ free(v); \ v = NULL; \ } \ } while(0) #define CLEAR_ON_NONE_ARRAY(v, nv, none) \ do { \ if (options->nv == 1 && \ strcasecmp(options->v[0], none) == 0) { \ free(options->v[0]); \ free(options->v); \ options->v = NULL; \ options->nv = 0; \ } \ } while (0) CLEAR_ON_NONE(options->pid_file); CLEAR_ON_NONE(options->xauth_location); CLEAR_ON_NONE(options->banner); CLEAR_ON_NONE(options->trusted_user_ca_keys); CLEAR_ON_NONE(options->revoked_keys_file); CLEAR_ON_NONE(options->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++) CLEAR_ON_NONE(options->host_cert_files[i]); CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none"); CLEAR_ON_NONE_ARRAY(auth_methods, num_auth_methods, "any"); #undef CLEAR_ON_NONE #undef CLEAR_ON_NONE_ARRAY } /* Keyword tokens. */ typedef enum { sBadOption, /* == unknown option */ /* Portable-specific options */ sUsePAM, /* Standard Options */ sPort, sHostKeyFile, sLoginGraceTime, sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, sKerberosGetAFSToken, sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, sPrintMotd, sPrintLastLog, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, sPermitUserEnvironment, sAllowTcpForwarding, sCompression, sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile, sModuliFile, sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedAlgorithms, sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions, sBanner, sUseDNS, sHostbasedAuthentication, sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedAlgorithms, sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, sHostCertificate, sInclude, sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser, sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum, sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, sAuthenticationMethods, sHostKeyAgent, sPermitUserRC, sStreamLocalBindMask, sStreamLocalBindUnlink, sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout, sUseBlacklist, sDeprecated, sIgnore, sUnsupported } ServerOpCodes; #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 { const char *name; ServerOpCodes opcode; u_int flags; } keywords[] = { /* Portable-specific options */ #ifdef USE_PAM { "usepam", sUsePAM, SSHCFG_GLOBAL }, #else { "usepam", sUnsupported, SSHCFG_GLOBAL }, #endif { "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL }, /* Standard Options */ { "port", sPort, SSHCFG_GLOBAL }, { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ { "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL }, { "pidfile", sPidFile, SSHCFG_GLOBAL }, { "modulifile", sModuliFile, SSHCFG_GLOBAL }, { "serverkeybits", sDeprecated, SSHCFG_GLOBAL }, { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, { "keyregenerationinterval", sDeprecated, SSHCFG_GLOBAL }, { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL }, { "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, { "loglevel", sLogLevel, SSHCFG_ALL }, { "logverbose", sLogVerbose, SSHCFG_ALL }, { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL }, { "rhostsrsaauthentication", sDeprecated, SSHCFG_ALL }, { "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL }, { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL }, { "hostbasedacceptedalgorithms", sHostbasedAcceptedAlgorithms, SSHCFG_ALL }, { "hostbasedacceptedkeytypes", sHostbasedAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */ { "hostkeyalgorithms", sHostKeyAlgorithms, SSHCFG_GLOBAL }, { "rsaauthentication", sDeprecated, SSHCFG_ALL }, { "pubkeyauthentication", sPubkeyAuthentication, 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 }, { "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL }, { "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL }, #ifdef USE_AFS { "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL }, #else { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, #endif #else { "kerberosauthentication", sUnsupported, SSHCFG_ALL }, { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL }, { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL }, { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, #endif { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, #ifdef GSSAPI { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, #else { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, #endif { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ { "skeyauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ { "checkmail", sDeprecated, SSHCFG_GLOBAL }, { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, { "printmotd", sPrintMotd, SSHCFG_GLOBAL }, #ifdef DISABLE_LASTLOG { "printlastlog", sUnsupported, SSHCFG_GLOBAL }, #else { "printlastlog", sPrintLastLog, SSHCFG_GLOBAL }, #endif { "ignorerhosts", sIgnoreRhosts, SSHCFG_ALL }, { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, { "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL }, { "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL }, { "uselogin", sDeprecated, SSHCFG_GLOBAL }, { "compression", sCompression, SSHCFG_GLOBAL }, { "rekeylimit", sRekeyLimit, SSHCFG_ALL }, { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL }, { "allowusers", sAllowUsers, SSHCFG_ALL }, { "denyusers", sDenyUsers, SSHCFG_ALL }, { "allowgroups", sAllowGroups, SSHCFG_ALL }, { "denygroups", sDenyGroups, SSHCFG_ALL }, { "ciphers", sCiphers, SSHCFG_GLOBAL }, { "macs", sMacs, SSHCFG_GLOBAL }, { "protocol", sIgnore, SSHCFG_GLOBAL }, { "gatewayports", sGatewayPorts, SSHCFG_ALL }, { "subsystem", sSubsystem, SSHCFG_ALL }, { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, { "persourcemaxstartups", sPerSourceMaxStartups, SSHCFG_GLOBAL }, { "persourcenetblocksize", sPerSourceNetBlockSize, SSHCFG_GLOBAL }, { "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, { "maxsessions", sMaxSessions, SSHCFG_ALL }, { "banner", sBanner, SSHCFG_ALL }, { "usedns", sUseDNS, SSHCFG_GLOBAL }, { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL }, { "clientaliveinterval", sClientAliveInterval, SSHCFG_ALL }, { "clientalivecountmax", sClientAliveCountMax, SSHCFG_ALL }, { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, { "useprivilegeseparation", sDeprecated, SSHCFG_GLOBAL}, { "acceptenv", sAcceptEnv, SSHCFG_ALL }, { "setenv", sSetEnv, SSHCFG_ALL }, { "permittunnel", sPermitTunnel, SSHCFG_ALL }, { "permittty", sPermitTTY, SSHCFG_ALL }, { "permituserrc", sPermitUserRC, SSHCFG_ALL }, { "match", sMatch, SSHCFG_ALL }, { "permitopen", sPermitOpen, SSHCFG_ALL }, { "permitlisten", sPermitListen, SSHCFG_ALL }, { "forcecommand", sForceCommand, SSHCFG_ALL }, { "chrootdirectory", sChrootDirectory, SSHCFG_ALL }, { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL }, { "revokedkeys", sRevokedKeys, SSHCFG_ALL }, { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, { "include", sInclude, SSHCFG_ALL }, { "ipqos", sIPQoS, SSHCFG_ALL }, { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, { "authorizedprincipalscommand", sAuthorizedPrincipalsCommand, SSHCFG_ALL }, { "authorizedprincipalscommanduser", sAuthorizedPrincipalsCommandUser, SSHCFG_ALL }, { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL }, { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL }, { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL }, { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, { "disableforwarding", sDisableForwarding, SSHCFG_ALL }, { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL }, { "rdomain", sRDomain, SSHCFG_ALL }, { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL }, { "channeltimeout", sChannelTimeout, SSHCFG_ALL }, { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL }, { "useblacklist", sUseBlacklist, SSHCFG_GLOBAL }, { "useblocklist", sUseBlacklist, SSHCFG_GLOBAL }, /* alias */ { NULL, sBadOption, 0 } }; static struct { int val; char *text; } tunmode_desc[] = { { SSH_TUNMODE_NO, "no" }, { SSH_TUNMODE_POINTOPOINT, "point-to-point" }, { SSH_TUNMODE_ETHERNET, "ethernet" }, { SSH_TUNMODE_YES, "yes" }, { -1, NULL } }; /* Returns an opcode name from its number */ static const char * lookup_opcode_name(ServerOpCodes code) { u_int i; for (i = 0; keywords[i].name != NULL; i++) if (keywords[i].opcode == code) return(keywords[i].name); return "UNKNOWN"; } /* * Returns the number of the token pointed to by cp or sBadOption. */ static ServerOpCodes parse_token(const char *cp, const char *filename, int linenum, u_int *flags) { u_int i; for (i = 0; keywords[i].name; i++) if (strcasecmp(cp, keywords[i].name) == 0) { *flags = keywords[i].flags; return keywords[i].opcode; } error("%s: line %d: Bad configuration option: %s", filename, linenum, cp); return sBadOption; } char * derelativise_path(const char *path) { char *expanded, *ret, cwd[PATH_MAX]; if (strcasecmp(path, "none") == 0) return xstrdup("none"); expanded = tilde_expand_filename(path, getuid()); if (path_absolute(expanded)) return expanded; if (getcwd(cwd, sizeof(cwd)) == NULL) fatal_f("getcwd: %s", strerror(errno)); xasprintf(&ret, "%s/%s", cwd, expanded); free(expanded); return ret; } static void add_listen_addr(ServerOptions *options, const char *addr, const char *rdomain, int port) { u_int i; if (port > 0) add_one_listen_addr(options, addr, rdomain, port); else { for (i = 0; i < options->num_ports; i++) { add_one_listen_addr(options, addr, rdomain, options->ports[i]); } } } static void add_one_listen_addr(ServerOptions *options, const char *addr, const char *rdomain, int port) { struct addrinfo hints, *ai, *aitop; char strport[NI_MAXSERV]; int gaierr; u_int i; /* Find listen_addrs entry for this rdomain */ for (i = 0; i < options->num_listen_addrs; i++) { if (rdomain == NULL && options->listen_addrs[i].rdomain == NULL) break; if (rdomain == NULL || options->listen_addrs[i].rdomain == NULL) continue; if (strcmp(rdomain, options->listen_addrs[i].rdomain) == 0) break; } if (i >= options->num_listen_addrs) { /* No entry for this rdomain; allocate one */ if (i >= INT_MAX) fatal_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)); i = options->num_listen_addrs++; if (rdomain != NULL) options->listen_addrs[i].rdomain = xstrdup(rdomain); } /* options->listen_addrs[i] points to the addresses for this rdomain */ memset(&hints, 0, sizeof(hints)); hints.ai_family = options->address_family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; snprintf(strport, sizeof strport, "%d", port); if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) fatal("bad addr or host: %s (%s)", addr ? addr : "", ssh_gai_strerror(gaierr)); for (ai = aitop; ai->ai_next; ai = ai->ai_next) ; ai->ai_next = options->listen_addrs[i].addrs; options->listen_addrs[i].addrs = aitop; } /* Returns nonzero if the routing domain name is valid */ static int valid_rdomain(const char *name) { #if defined(HAVE_SYS_VALID_RDOMAIN) return sys_valid_rdomain(name); #elif defined(__OpenBSD__) const char *errstr; long long num; struct rt_tableinfo info; int mib[6]; size_t miblen = sizeof(mib); if (name == NULL) return 1; num = strtonum(name, 0, 255, &errstr); if (errstr != NULL) return 0; /* Check whether the table actually exists */ memset(mib, 0, sizeof(mib)); mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[4] = NET_RT_TABLE; mib[5] = (int)num; if (sysctl(mib, 6, &info, &miblen, NULL, 0) == -1) return 0; return 1; #else /* defined(__OpenBSD__) */ error("Routing domains are not supported on this platform"); return 0; #endif } /* * Queue a ListenAddress to be processed once we have all of the Ports * and AddressFamily options. */ static void queue_listen_addr(ServerOptions *options, const char *addr, const char *rdomain, int port) { struct queued_listenaddr *qla; options->queued_listen_addrs = xrecallocarray( options->queued_listen_addrs, options->num_queued_listens, options->num_queued_listens + 1, sizeof(*options->queued_listen_addrs)); qla = &options->queued_listen_addrs[options->num_queued_listens++]; qla->addr = xstrdup(addr); qla->port = port; qla->rdomain = rdomain == NULL ? NULL : xstrdup(rdomain); } /* * Process queued (text) ListenAddress entries. */ static void process_queued_listen_addrs(ServerOptions *options) { u_int i; struct queued_listenaddr *qla; if (options->num_ports == 0) options->ports[options->num_ports++] = SSH_DEFAULT_PORT; if (options->address_family == -1) options->address_family = AF_UNSPEC; for (i = 0; i < options->num_queued_listens; i++) { qla = &options->queued_listen_addrs[i]; add_listen_addr(options, qla->addr, qla->rdomain, qla->port); free(qla->addr); free(qla->rdomain); } free(options->queued_listen_addrs); options->queued_listen_addrs = NULL; options->num_queued_listens = 0; } /* * Inform channels layer of permitopen options for a single forwarding * direction (local/remote). */ static void process_permitopen_list(struct ssh *ssh, ServerOpCodes opcode, char **opens, u_int num_opens) { u_int i; int port; char *host, *arg, *oarg; int where = opcode == sPermitOpen ? FORWARD_LOCAL : FORWARD_REMOTE; const char *what = lookup_opcode_name(opcode); channel_clear_permission(ssh, FORWARD_ADM, where); if (num_opens == 0) return; /* permit any */ /* handle keywords: "any" / "none" */ if (num_opens == 1 && strcmp(opens[0], "any") == 0) return; if (num_opens == 1 && strcmp(opens[0], "none") == 0) { channel_disable_admin(ssh, where); return; } /* Otherwise treat it as a list of permitted host:port */ for (i = 0; i < num_opens; i++) { oarg = arg = xstrdup(opens[i]); host = hpdelim(&arg); if (host == NULL) fatal_f("missing host in %s", what); host = cleanhostname(host); 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, host, port); free(oarg); } } /* * Inform channels layer of permitopen options from configuration. */ void process_permitopen(struct ssh *ssh, ServerOptions *options) { process_permitopen_list(ssh, sPermitOpen, options->permitted_opens, options->num_permitted_opens); process_permitopen_list(ssh, sPermitListen, options->permitted_listens, options->num_permitted_listens); } -/* Parse a ChannelTimeout clause "pattern=interval" */ -static int -parse_timeout(const char *s, char **typep, int *secsp) -{ - char *cp, *sdup; - int secs; - - if (typep != NULL) - *typep = NULL; - if (secsp != NULL) - *secsp = 0; - if (s == NULL) - return -1; - sdup = xstrdup(s); - - if ((cp = strchr(sdup, '=')) == NULL || cp == sdup) { - free(sdup); - return -1; - } - *cp++ = '\0'; - if ((secs = convtime(cp)) < 0) { - free(sdup); - return -1; - } - /* success */ - if (typep != NULL) - *typep = xstrdup(sdup); - if (secsp != NULL) - *secsp = secs; - free(sdup); - return 0; -} - void process_channel_timeouts(struct ssh *ssh, ServerOptions *options) { int secs; u_int i; char *type; debug3_f("setting %u timeouts", options->num_channel_timeouts); channel_clear_timeouts(ssh); for (i = 0; i < options->num_channel_timeouts; i++) { - if (parse_timeout(options->channel_timeouts[i], + if (parse_pattern_interval(options->channel_timeouts[i], &type, &secs) != 0) { fatal_f("internal error: bad timeout %s", options->channel_timeouts[i]); } channel_add_timeout(ssh, type, secs); free(type); } } struct connection_info * get_connection_info(struct ssh *ssh, int populate, int use_dns) { static struct connection_info ci; if (ssh == NULL || !populate) return &ci; ci.host = auth_get_canonical_hostname(ssh, use_dns); ci.address = ssh_remote_ipaddr(ssh); ci.laddress = ssh_local_ipaddr(ssh); ci.lport = ssh_local_port(ssh); ci.rdomain = ssh_packet_rdomain_in(ssh); return &ci; } /* * The strategy for the Match blocks is that the config file is parsed twice. * * The first time is at startup. activep is initialized to 1 and the * directives in the global context are processed and acted on. Hitting a * Match directive unsets activep and the directives inside the block are * checked for syntax only. * * The second time is after a connection has been established but before * authentication. activep is initialized to 2 and global config directives * are ignored since they have already been processed. If the criteria in a * Match block is met, activep is set and the subsequent directives * processed and actioned until EOF or another Match block unsets it. Any * options set are copied into the main server config. * * Potential additions/improvements: * - Add Match support for pre-kex directives, eg. Ciphers. * * - Add a Tag directive (idea from David Leonard) ala pf, eg: * Match Address 192.168.0.* * Tag trusted * Match Group wheel * Tag trusted * Match Tag trusted * AllowTcpForwarding yes * GatewayPorts clientspecified * [...] * * - Add a PermittedChannelRequests directive * Match Group shell * PermittedChannelRequests session,forwarded-tcpip */ static int match_cfg_line_group(const char *grps, int line, const char *user) { int result = 0; struct passwd *pw; if (user == NULL) goto out; if ((pw = getpwnam(user)) == NULL) { debug("Can't match group at line %d because user %.100s does " "not exist", line, user); } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) { debug("Can't Match group because user %.100s not in any group " "at line %d", user, line); } else if (ga_match_pattern_list(grps) != 1) { debug("user %.100s does not match group list %.100s at line %d", user, grps, line); } else { debug("user %.100s matched group list %.100s at line %d", user, grps, line); result = 1; } out: ga_free(); return result; } static void match_test_missing_fatal(const char *criteria, const char *attrib) { fatal("'Match %s' in configuration but '%s' not in connection " "test specification.", criteria, attrib); } /* * All of the attributes on a single Match line are ANDed together, so we need * to check every attribute and set the result to zero if any attribute does * not match. */ static int match_cfg_line(char **condition, int line, struct connection_info *ci) { int result = 1, attributes = 0, port; char *arg, *attrib, *cp = *condition; if (ci == NULL) debug3("checking syntax for 'Match %s'", cp); else debug3("checking match for '%s' user %s host %s addr %s " "laddr %s lport %d", cp, ci->user ? ci->user : "(null)", ci->host ? ci->host : "(null)", ci->address ? ci->address : "(null)", ci->laddress ? ci->laddress : "(null)", ci->lport); while ((attrib = strdelim(&cp)) && *attrib != '\0') { /* Terminate on comment */ if (*attrib == '#') { cp = NULL; /* mark all arguments consumed */ break; } arg = NULL; attributes++; /* Criterion "all" has no argument and must appear alone */ if (strcasecmp(attrib, "all") == 0) { if (attributes > 1 || ((arg = strdelim(&cp)) != NULL && *arg != '\0' && *arg != '#')) { error("'all' cannot be combined with other " "Match attributes"); return -1; } if (arg != NULL && *arg == '#') cp = NULL; /* mark all arguments consumed */ *condition = cp; return 1; } /* All other criteria require an argument */ if ((arg = strdelim(&cp)) == NULL || *arg == '\0' || *arg == '#') { error("Missing Match criteria for %s", attrib); return -1; } if (strcasecmp(attrib, "user") == 0) { if (ci == NULL || (ci->test && ci->user == NULL)) { result = 0; continue; } if (ci->user == NULL) match_test_missing_fatal("User", "user"); if (match_usergroup_pattern_list(ci->user, arg) != 1) result = 0; else debug("user %.100s matched 'User %.100s' at " "line %d", ci->user, arg, line); } else if (strcasecmp(attrib, "group") == 0) { if (ci == NULL || (ci->test && ci->user == NULL)) { result = 0; continue; } if (ci->user == NULL) match_test_missing_fatal("Group", "user"); switch (match_cfg_line_group(arg, line, ci->user)) { case -1: return -1; case 0: result = 0; } } else if (strcasecmp(attrib, "host") == 0) { if (ci == NULL || (ci->test && ci->host == NULL)) { result = 0; continue; } if (ci->host == NULL) match_test_missing_fatal("Host", "host"); if (match_hostname(ci->host, arg) != 1) result = 0; else debug("connection from %.100s matched 'Host " "%.100s' at line %d", ci->host, arg, line); } else if (strcasecmp(attrib, "address") == 0) { if (ci == NULL || (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; } if (ci->address == NULL) match_test_missing_fatal("Address", "addr"); switch (addr_match_list(ci->address, arg)) { case 1: debug("connection from %.100s matched 'Address " "%.100s' at line %d", ci->address, arg, line); break; case 0: case -1: result = 0; break; case -2: return -1; } } else if (strcasecmp(attrib, "localaddress") == 0){ if (ci == NULL || (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; } if (ci->laddress == NULL) match_test_missing_fatal("LocalAddress", "laddr"); switch (addr_match_list(ci->laddress, arg)) { case 1: debug("connection from %.100s matched " "'LocalAddress %.100s' at line %d", ci->laddress, arg, line); break; case 0: case -1: result = 0; break; case -2: return -1; } } else if (strcasecmp(attrib, "localport") == 0) { if ((port = a2port(arg)) == -1) { error("Invalid LocalPort '%s' on Match line", arg); return -1; } if (ci == NULL || (ci->test && ci->lport == -1)) { result = 0; continue; } if (ci->lport == 0) match_test_missing_fatal("LocalPort", "lport"); /* TODO support port lists */ if (port == ci->lport) debug("connection from %.100s matched " "'LocalPort %d' at line %d", ci->laddress, port, line); else result = 0; } else if (strcasecmp(attrib, "rdomain") == 0) { if (ci == NULL || (ci->test && ci->rdomain == NULL)) { result = 0; continue; } if (ci->rdomain == NULL) match_test_missing_fatal("RDomain", "rdomain"); if (match_pattern_list(ci->rdomain, arg, 0) != 1) result = 0; else debug("user %.100s matched 'RDomain %.100s' at " "line %d", ci->rdomain, arg, line); } else { error("Unsupported Match attribute %s", attrib); return -1; } } if (attributes == 0) { error("One or more attributes required for Match"); return -1; } if (ci != NULL) debug3("match %sfound", result ? "" : "not "); *condition = cp; return result; } #define WHITESPACE " \t\r\n" /* Multistate option parsing */ struct multistate { char *key; int value; }; static const struct multistate multistate_flag[] = { { "yes", 1 }, { "no", 0 }, { NULL, -1 } }; static const struct multistate multistate_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 }, { "any", AF_UNSPEC }, { NULL, -1 } }; static const struct multistate multistate_permitrootlogin[] = { { "without-password", PERMIT_NO_PASSWD }, { "prohibit-password", PERMIT_NO_PASSWD }, { "forced-commands-only", PERMIT_FORCED_ONLY }, { "yes", PERMIT_YES }, { "no", PERMIT_NO }, { NULL, -1 } }; static const struct multistate multistate_compression[] = { #ifdef WITH_ZLIB { "yes", COMP_DELAYED }, { "delayed", COMP_DELAYED }, #endif { "no", COMP_NONE }, { NULL, -1 } }; static const struct multistate multistate_gatewayports[] = { { "clientspecified", 2 }, { "yes", 1 }, { "no", 0 }, { NULL, -1 } }; static const struct multistate multistate_tcpfwd[] = { { "yes", FORWARD_ALLOW }, { "all", FORWARD_ALLOW }, { "no", FORWARD_DENY }, { "remote", FORWARD_REMOTE }, { "local", FORWARD_LOCAL }, { NULL, -1 } }; static int process_server_config_line_depth(ServerOptions *options, char *line, const char *filename, int linenum, int *activep, struct connection_info *connectinfo, int *inc_flags, int depth, struct include_list *includes) { char *str, ***chararrayptr, **charptr, *arg, *arg2, *p, *keyword; int cmdline = 0, *intptr, value, value2, n, port, oactive, r, found; int ca_only = 0; SyslogFacility *log_facility_ptr; LogLevel *log_level_ptr; ServerOpCodes opcode; u_int i, *uintptr, uvalue, flags = 0; size_t len; long long val64; const struct multistate *multistate_ptr; const char *errstr; struct include_item *item; glob_t gbuf; char **oav = NULL, **av; int oac = 0, ac; int ret = -1; /* Strip trailing whitespace. Allow \f (form feed) at EOL only */ if ((len = strlen(line)) == 0) return 0; for (len--; len > 0; len--) { if (strchr(WHITESPACE "\f", line[len]) == NULL) break; line[len] = '\0'; } str = line; if ((keyword = strdelim(&str)) == NULL) return 0; /* Ignore leading whitespace */ if (*keyword == '\0') keyword = strdelim(&str); if (!keyword || !*keyword || *keyword == '#') return 0; if (str == NULL || *str == '\0') { error("%s line %d: no argument after keyword \"%s\"", filename, linenum, keyword); return -1; } intptr = NULL; charptr = NULL; opcode = parse_token(keyword, filename, linenum, &flags); if (argv_split(str, &oac, &oav, 1) != 0) { error("%s line %d: invalid quotes", filename, linenum); return -1; } ac = oac; av = oav; if (activep == NULL) { /* We are processing a command line directive */ cmdline = 1; activep = &cmdline; } if (*activep && opcode != sMatch && opcode != sInclude) debug3("%s:%d setting %s %s", filename, linenum, keyword, str); if (*activep == 0 && !(flags & SSHCFG_MATCH)) { if (connectinfo == NULL) { fatal("%s line %d: Directive '%s' is not allowed " "within a Match block", filename, linenum, keyword); } else { /* this is a directive we have already processed */ ret = 0; goto out; } } switch (opcode) { /* Portable-specific options */ case sUsePAM: intptr = &options->use_pam; goto parse_flag; /* Standard Options */ case sBadOption: goto out; case sPort: /* ignore ports from configfile if cmdline specifies ports */ if (options->ports_from_cmdline) { argv_consume(&ac); break; } if (options->num_ports >= MAX_PORTS) fatal("%s line %d: too many ports.", filename, linenum); arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: missing port number.", filename, linenum); options->ports[options->num_ports++] = a2port(arg); if (options->ports[options->num_ports-1] <= 0) fatal("%s line %d: Badly formatted port number.", filename, linenum); break; case sLoginGraceTime: intptr = &options->login_grace_time; parse_time: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: missing time value.", filename, linenum); if ((value = convtime(arg)) == -1) fatal("%s line %d: invalid time value.", filename, linenum); if (*activep && *intptr == -1) *intptr = value; break; case sListenAddress: arg = argv_next(&ac, &av); if (arg == NULL || *arg == '\0') fatal("%s line %d: missing address", filename, linenum); /* check for bare IPv6 address: no "[]" and 2 or more ":" */ if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL && strchr(p+1, ':') != NULL) { port = 0; p = arg; } else { arg2 = NULL; p = hpdelim(&arg); if (p == NULL) fatal("%s line %d: bad address:port usage", filename, linenum); p = cleanhostname(p); if (arg == NULL) port = 0; else if ((port = a2port(arg)) <= 0) fatal("%s line %d: bad port number", filename, linenum); } /* Optional routing table */ arg2 = NULL; if ((arg = argv_next(&ac, &av)) != NULL) { if (strcmp(arg, "rdomain") != 0 || (arg2 = argv_next(&ac, &av)) == NULL) fatal("%s line %d: bad ListenAddress syntax", filename, linenum); if (!valid_rdomain(arg2)) fatal("%s line %d: bad routing domain", filename, linenum); } queue_listen_addr(options, p, arg2, port); break; case sAddressFamily: intptr = &options->address_family; multistate_ptr = multistate_addressfamily; parse_multistate: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: missing argument.", filename, linenum); value = -1; for (i = 0; multistate_ptr[i].key != NULL; i++) { if (strcasecmp(arg, multistate_ptr[i].key) == 0) { value = multistate_ptr[i].value; break; } } if (value == -1) fatal("%s line %d: unsupported option \"%s\".", filename, linenum, arg); if (*activep && *intptr == -1) *intptr = value; break; case sHostKeyFile: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: missing file name.", filename, linenum); if (*activep) { servconf_add_hostkey(filename, linenum, options, arg, 1); } break; case sHostKeyAgent: charptr = &options->host_key_agent; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: missing socket name.", filename, linenum); if (*activep && *charptr == NULL) *charptr = !strcmp(arg, SSH_AUTHSOCKET_ENV_NAME) ? xstrdup(arg) : derelativise_path(arg); break; case sHostCertificate: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: missing file name.", filename, linenum); if (*activep) servconf_add_hostcert(filename, linenum, options, arg); break; case sPidFile: charptr = &options->pid_file; parse_filename: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: missing file name.", filename, linenum); if (*activep && *charptr == NULL) { *charptr = derelativise_path(arg); /* increase optional counter */ if (intptr != NULL) *intptr = *intptr + 1; } break; case sModuliFile: charptr = &options->moduli_file; goto parse_filename; case sPermitRootLogin: intptr = &options->permit_root_login; multistate_ptr = multistate_permitrootlogin; goto parse_multistate; case sIgnoreRhosts: intptr = &options->ignore_rhosts; multistate_ptr = multistate_ignore_rhosts; goto parse_multistate; case sIgnoreUserKnownHosts: intptr = &options->ignore_user_known_hosts; parse_flag: multistate_ptr = multistate_flag; goto parse_multistate; case sHostbasedAuthentication: intptr = &options->hostbased_authentication; goto parse_flag; case sHostbasedUsesNameFromPacketOnly: intptr = &options->hostbased_uses_name_from_packet_only; goto parse_flag; case sHostbasedAcceptedAlgorithms: charptr = &options->hostbased_accepted_algos; ca_only = 0; parse_pubkey_algos: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: Missing argument.", filename, linenum); if (*arg != '-' && !sshkey_names_valid2(*arg == '+' || *arg == '^' ? arg + 1 : arg, 1, ca_only)) fatal("%s line %d: Bad key types '%s'.", filename, linenum, arg ? arg : ""); if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case sHostKeyAlgorithms: charptr = &options->hostkeyalgorithms; ca_only = 0; goto parse_pubkey_algos; case sCASignatureAlgorithms: charptr = &options->ca_sign_algorithms; ca_only = 1; goto parse_pubkey_algos; case sPubkeyAuthentication: intptr = &options->pubkey_authentication; ca_only = 0; goto parse_flag; case sPubkeyAcceptedAlgorithms: charptr = &options->pubkey_accepted_algos; ca_only = 0; goto parse_pubkey_algos; case sPubkeyAuthOptions: intptr = &options->pubkey_auth_options; value = 0; while ((arg = argv_next(&ac, &av)) != NULL) { 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 { error("%s line %d: unsupported %s option %s", filename, linenum, keyword, arg); goto out; } } if (*activep && *intptr == -1) *intptr = value; break; case sKerberosAuthentication: intptr = &options->kerberos_authentication; goto parse_flag; case sKerberosOrLocalPasswd: intptr = &options->kerberos_or_local_passwd; goto parse_flag; case sKerberosTicketCleanup: intptr = &options->kerberos_ticket_cleanup; goto parse_flag; case sKerberosGetAFSToken: intptr = &options->kerberos_get_afs_token; goto parse_flag; case sGssAuthentication: intptr = &options->gss_authentication; goto parse_flag; case sGssCleanupCreds: intptr = &options->gss_cleanup_creds; goto parse_flag; case sGssStrictAcceptor: intptr = &options->gss_strict_acceptor; goto parse_flag; case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; case sKbdInteractiveAuthentication: intptr = &options->kbd_interactive_authentication; goto parse_flag; case sPrintMotd: intptr = &options->print_motd; goto parse_flag; case sPrintLastLog: intptr = &options->print_lastlog; goto parse_flag; case sX11Forwarding: intptr = &options->x11_forwarding; goto parse_flag; case sX11DisplayOffset: intptr = &options->x11_display_offset; parse_int: arg = argv_next(&ac, &av); if ((errstr = atoi_err(arg, &value)) != NULL) fatal("%s line %d: %s integer value %s.", filename, linenum, keyword, errstr); if (*activep && *intptr == -1) *intptr = value; break; case sX11UseLocalhost: intptr = &options->x11_use_localhost; goto parse_flag; case sXAuthLocation: charptr = &options->xauth_location; goto parse_filename; case sPermitTTY: intptr = &options->permit_tty; goto parse_flag; case sPermitUserRC: intptr = &options->permit_user_rc; goto parse_flag; case sStrictModes: intptr = &options->strict_modes; goto parse_flag; case sTCPKeepAlive: intptr = &options->tcp_keep_alive; goto parse_flag; case sEmptyPasswd: intptr = &options->permit_empty_passwd; goto parse_flag; case sPermitUserEnvironment: intptr = &options->permit_user_env; charptr = &options->permit_user_env_allowlist; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); value = 0; p = NULL; if (strcmp(arg, "yes") == 0) value = 1; else if (strcmp(arg, "no") == 0) value = 0; else { /* Pattern-list specified */ value = 1; p = xstrdup(arg); } if (*activep && *intptr == -1) { *intptr = value; *charptr = p; p = NULL; } free(p); break; case sCompression: intptr = &options->compression; multistate_ptr = multistate_compression; goto parse_multistate; case sRekeyLimit: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (strcmp(arg, "default") == 0) { val64 = 0; } else { if (scan_scaled(arg, &val64) == -1) fatal("%.200s line %d: Bad %s number '%s': %s", filename, linenum, keyword, arg, strerror(errno)); if (val64 != 0 && val64 < 16) fatal("%.200s line %d: %s too small", filename, linenum, keyword); } if (*activep && options->rekey_limit == -1) options->rekey_limit = val64; if (ac != 0) { /* optional rekey interval present */ if (strcmp(av[0], "none") == 0) { (void)argv_next(&ac, &av); /* discard */ break; } intptr = &options->rekey_interval; goto parse_time; } break; case sGatewayPorts: intptr = &options->fwd_opts.gateway_ports; multistate_ptr = multistate_gatewayports; goto parse_multistate; case sUseDNS: intptr = &options->use_dns; goto parse_flag; case sLogFacility: log_facility_ptr = &options->log_facility; arg = argv_next(&ac, &av); value = log_facility_number(arg); if (value == SYSLOG_FACILITY_NOT_SET) fatal("%.200s line %d: unsupported log facility '%s'", filename, linenum, arg ? arg : ""); if (*log_facility_ptr == -1) *log_facility_ptr = (SyslogFacility) value; break; case sLogLevel: log_level_ptr = &options->log_level; arg = argv_next(&ac, &av); value = log_level_number(arg); if (value == SYSLOG_LEVEL_NOT_SET) fatal("%.200s line %d: unsupported log level '%s'", filename, linenum, arg ? arg : ""); if (*activep && *log_level_ptr == -1) *log_level_ptr = (LogLevel) value; break; case sLogVerbose: found = options->num_log_verbose == 0; i = 0; while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { error("%s line %d: keyword %s empty argument", filename, linenum, keyword); goto out; } /* Allow "none" only in first position */ if (strcasecmp(arg, "none") == 0) { if (i > 0 || ac > 0) { error("%s line %d: keyword %s \"none\" " "argument must appear alone.", filename, linenum, keyword); goto out; } } i++; if (!found || !*activep) continue; opt_array_append(filename, linenum, keyword, &options->log_verbose, &options->num_log_verbose, arg); } break; case sAllowTcpForwarding: intptr = &options->allow_tcp_forwarding; multistate_ptr = multistate_tcpfwd; goto parse_multistate; case sAllowStreamLocalForwarding: intptr = &options->allow_streamlocal_forwarding; multistate_ptr = multistate_tcpfwd; goto parse_multistate; case sAllowAgentForwarding: intptr = &options->allow_agent_forwarding; goto parse_flag; case sDisableForwarding: intptr = &options->disable_forwarding; goto parse_flag; case sAllowUsers: chararrayptr = &options->allow_users; uintptr = &options->num_allow_users; parse_allowdenyusers: while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0' || match_user(NULL, NULL, NULL, arg) == -1) fatal("%s line %d: invalid %s pattern: \"%s\"", filename, linenum, keyword, arg); if (!*activep) continue; opt_array_append(filename, linenum, keyword, chararrayptr, uintptr, arg); } break; case sDenyUsers: chararrayptr = &options->deny_users; uintptr = &options->num_deny_users; goto parse_allowdenyusers; case sAllowGroups: chararrayptr = &options->allow_groups; uintptr = &options->num_allow_groups; parse_allowdenygroups: while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') fatal("%s line %d: empty %s pattern", filename, linenum, keyword); if (!*activep) continue; opt_array_append(filename, linenum, keyword, chararrayptr, uintptr, arg); } break; case sDenyGroups: chararrayptr = &options->deny_groups; uintptr = &options->num_deny_groups; goto parse_allowdenygroups; case sCiphers: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*arg != '-' && !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) fatal("%s line %d: Bad SSH2 cipher spec '%s'.", filename, linenum, arg ? arg : ""); if (options->ciphers == NULL) options->ciphers = xstrdup(arg); break; case sMacs: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*arg != '-' && !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) fatal("%s line %d: Bad SSH2 mac spec '%s'.", filename, linenum, arg ? arg : ""); if (options->macs == NULL) options->macs = xstrdup(arg); break; case sKexAlgorithms: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*arg != '-' && !kex_names_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) fatal("%s line %d: Bad SSH2 KexAlgorithms '%s'.", filename, linenum, arg ? arg : ""); if (options->kex_algorithms == NULL) options->kex_algorithms = xstrdup(arg); break; case sSubsystem: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (!*activep) { argv_consume(&ac); break; } found = 0; for (i = 0; i < options->num_subsystems; i++) { if (strcmp(arg, options->subsystem_name[i]) == 0) { found = 1; break; } } if (found) { debug("%s line %d: Subsystem '%s' already defined.", filename, linenum, arg); argv_consume(&ac); break; } options->subsystem_name = xrecallocarray( options->subsystem_name, options->num_subsystems, options->num_subsystems + 1, sizeof(*options->subsystem_name)); options->subsystem_command = xrecallocarray( options->subsystem_command, options->num_subsystems, options->num_subsystems + 1, sizeof(*options->subsystem_command)); options->subsystem_args = xrecallocarray( options->subsystem_args, options->num_subsystems, options->num_subsystems + 1, sizeof(*options->subsystem_args)); options->subsystem_name[options->num_subsystems] = xstrdup(arg); arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { fatal("%s line %d: Missing subsystem command.", filename, linenum); } options->subsystem_command[options->num_subsystems] = xstrdup(arg); /* Collect arguments (separate to executable) */ arg = argv_assemble(1, &arg); /* quote command correctly */ arg2 = argv_assemble(ac, av); /* rest of command */ xasprintf(&options->subsystem_args[options->num_subsystems], "%s %s", arg, arg2); free(arg2); argv_consume(&ac); options->num_subsystems++; break; case sMaxStartups: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if ((n = sscanf(arg, "%d:%d:%d", &options->max_startups_begin, &options->max_startups_rate, &options->max_startups)) == 3) { if (options->max_startups_begin > options->max_startups || options->max_startups_rate > 100 || options->max_startups_rate < 1) fatal("%s line %d: Invalid %s spec.", filename, linenum, keyword); } else if (n != 1) fatal("%s line %d: Invalid %s spec.", filename, linenum, keyword); else options->max_startups = options->max_startups_begin; if (options->max_startups <= 0 || options->max_startups_begin <= 0) fatal("%s line %d: Invalid %s spec.", filename, linenum, keyword); break; case sPerSourceNetBlockSize: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); 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 %s spec.", filename, linenum, keyword); if (*activep) { options->per_source_masklen_ipv4 = value; options->per_source_masklen_ipv6 = value2; } break; case sPerSourceMaxStartups: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (strcmp(arg, "none") == 0) { /* no limit */ value = INT_MAX; } else { if ((errstr = atoi_err(arg, &value)) != NULL) fatal("%s line %d: %s integer value %s.", filename, linenum, keyword, errstr); } if (*activep && options->per_source_max_startups == -1) options->per_source_max_startups = value; break; case sMaxAuthTries: intptr = &options->max_authtries; goto parse_int; case sMaxSessions: intptr = &options->max_sessions; goto parse_int; case sBanner: charptr = &options->banner; goto parse_filename; /* * These options can contain %X options expanded at * connect time, so that you can specify paths like: * * AuthorizedKeysFile /etc/ssh_keys/%u */ case sAuthorizedKeysFile: uvalue = options->num_authkeys_files; while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0') { error("%s line %d: keyword %s empty argument", filename, linenum, keyword); goto out; } arg2 = tilde_expand_filename(arg, getuid()); if (*activep && uvalue == 0) { opt_array_append(filename, linenum, keyword, &options->authorized_keys_files, &options->num_authkeys_files, arg2); } free(arg2); } break; case sAuthorizedPrincipalsFile: charptr = &options->authorized_principals_file; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*activep && *charptr == NULL) { *charptr = tilde_expand_filename(arg, getuid()); /* increase optional counter */ if (intptr != NULL) *intptr = *intptr + 1; } break; case sClientAliveInterval: intptr = &options->client_alive_interval; goto parse_time; case sClientAliveCountMax: intptr = &options->client_alive_count_max; goto parse_int; case sAcceptEnv: while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0' || strchr(arg, '=') != NULL) fatal("%s line %d: Invalid environment name.", filename, linenum); if (!*activep) continue; opt_array_append(filename, linenum, keyword, &options->accept_env, &options->num_accept_env, arg); } break; case sSetEnv: uvalue = options->num_setenv; while ((arg = argv_next(&ac, &av)) != NULL) { if (*arg == '\0' || strchr(arg, '=') == NULL) fatal("%s line %d: Invalid environment.", filename, linenum); if (!*activep || uvalue != 0) continue; if (lookup_setenv_in_list(arg, options->setenv, options->num_setenv) != NULL) { debug2("%s line %d: ignoring duplicate env " "name \"%.64s\"", filename, linenum, arg); continue; } opt_array_append(filename, linenum, keyword, &options->setenv, &options->num_setenv, arg); } break; case sPermitTunnel: intptr = &options->permit_tun; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); value = -1; for (i = 0; tunmode_desc[i].val != -1; i++) if (strcmp(tunmode_desc[i].text, arg) == 0) { value = tunmode_desc[i].val; break; } if (value == -1) fatal("%s line %d: bad %s argument %s", filename, linenum, keyword, arg); if (*activep && *intptr == -1) *intptr = value; break; case sInclude: if (cmdline) { fatal("Include directive not supported as a " "command-line option"); } value = 0; while ((arg2 = argv_next(&ac, &av)) != NULL) { if (*arg2 == '\0') { error("%s line %d: keyword %s empty argument", filename, linenum, keyword); goto out; } 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: %s missing filename argument", filename, linenum, keyword); } break; case sMatch: if (cmdline) fatal("Match directive not supported as a command-line " "option"); value = match_cfg_line(&str, linenum, (*inc_flags & SSHCFG_NEVERMATCH ? NULL : connectinfo)); if (value < 0) fatal("%s line %d: Bad Match condition", filename, linenum); *activep = (*inc_flags & SSHCFG_NEVERMATCH) ? 0 : value; /* * The MATCH_ONLY flag is applicable only until the first * match block. */ *inc_flags &= ~SSHCFG_MATCH_ONLY; /* * If match_cfg_line() didn't consume all its arguments then * arrange for the extra arguments check below to fail. */ if (str == NULL || *str == '\0') argv_consume(&ac); break; case sPermitListen: case sPermitOpen: if (opcode == sPermitListen) { uintptr = &options->num_permitted_listens; chararrayptr = &options->permitted_listens; } else { uintptr = &options->num_permitted_opens; chararrayptr = &options->permitted_opens; } arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); uvalue = *uintptr; /* modified later */ if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) { if (*activep && uvalue == 0) { *uintptr = 1; *chararrayptr = xcalloc(1, sizeof(**chararrayptr)); (*chararrayptr)[0] = xstrdup(arg); } break; } for (; arg != NULL && *arg != '\0'; arg = argv_next(&ac, &av)) { if (opcode == sPermitListen && strchr(arg, ':') == NULL) { /* * Allow bare port number for PermitListen * to indicate a wildcard listen host. */ xasprintf(&arg2, "*:%s", arg); } else { arg2 = xstrdup(arg); p = hpdelim(&arg); if (p == NULL) { fatal("%s line %d: %s missing host", filename, linenum, keyword); } p = cleanhostname(p); } if (arg == NULL || ((port = permitopen_port(arg)) < 0)) { fatal("%s line %d: %s bad port number", filename, linenum, keyword); } if (*activep && uvalue == 0) { opt_array_append(filename, linenum, keyword, chararrayptr, uintptr, arg2); } free(arg2); } break; case sForceCommand: if (str == NULL || *str == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); len = strspn(str, WHITESPACE); if (*activep && options->adm_forced_command == NULL) options->adm_forced_command = xstrdup(str + len); argv_consume(&ac); break; case sChrootDirectory: charptr = &options->chroot_directory; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case sTrustedUserCAKeys: charptr = &options->trusted_user_ca_keys; goto parse_filename; case sRevokedKeys: charptr = &options->revoked_keys_file; goto parse_filename; case sSecurityKeyProvider: charptr = &options->sk_provider; arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); 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 = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if ((value = parse_ipqos(arg)) == -1) fatal("%s line %d: Bad %s value: %s", filename, linenum, keyword, arg); arg = argv_next(&ac, &av); if (arg == NULL) value2 = value; else if ((value2 = parse_ipqos(arg)) == -1) fatal("%s line %d: Bad %s value: %s", filename, linenum, keyword, arg); if (*activep) { options->ip_qos_interactive = value; options->ip_qos_bulk = value2; } break; case sVersionAddendum: if (str == NULL || *str == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); len = strspn(str, WHITESPACE); if (strchr(str + len, '\r') != NULL) { fatal("%.200s line %d: Invalid %s argument", filename, linenum, keyword); } if ((arg = strchr(line, '#')) != NULL) { *arg = '\0'; rtrim(line); } if (*activep && options->version_addendum == NULL) { if (strcasecmp(str + len, "none") == 0) options->version_addendum = xstrdup(""); else options->version_addendum = xstrdup(str + len); } argv_consume(&ac); break; case sAuthorizedKeysCommand: charptr = &options->authorized_keys_command; parse_command: len = strspn(str, WHITESPACE); if (str[len] != '/' && strcasecmp(str + len, "none") != 0) { fatal("%.200s line %d: %s must be an absolute path", filename, linenum, keyword); } if (*activep && *charptr == NULL) *charptr = xstrdup(str + len); argv_consume(&ac); break; case sAuthorizedKeysCommandUser: charptr = &options->authorized_keys_command_user; parse_localuser: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') { fatal("%s line %d: missing %s argument.", filename, linenum, keyword); } if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case sAuthorizedPrincipalsCommand: charptr = &options->authorized_principals_command; goto parse_command; case sAuthorizedPrincipalsCommandUser: charptr = &options->authorized_principals_command_user; goto parse_localuser; case sAuthenticationMethods: found = options->num_auth_methods == 0; value = 0; /* seen "any" pseudo-method */ value2 = 0; /* successfully parsed any method */ while ((arg = argv_next(&ac, &av)) != NULL) { if (strcmp(arg, "any") == 0) { if (options->num_auth_methods > 0) { fatal("%s line %d: \"any\" must " "appear alone in %s", filename, linenum, keyword); } value = 1; } else if (value) { fatal("%s line %d: \"any\" must appear " "alone in %s", filename, linenum, keyword); } else if (auth2_methods_valid(arg, 0) != 0) { fatal("%s line %d: invalid %s method list.", filename, linenum, keyword); } value2 = 1; if (!found || !*activep) continue; opt_array_append(filename, linenum, keyword, &options->auth_methods, &options->num_auth_methods, arg); } if (value2 == 0) { fatal("%s line %d: no %s specified", filename, linenum, keyword); } break; case sStreamLocalBindMask: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); /* Parse mode in octal format */ value = strtol(arg, &p, 8); if (arg == p || value < 0 || value > 0777) fatal("%s line %d: Invalid %s.", filename, linenum, keyword); if (*activep) options->fwd_opts.streamlocal_bind_mask = (mode_t)value; break; case sStreamLocalBindUnlink: intptr = &options->fwd_opts.streamlocal_bind_unlink; goto parse_flag; case sFingerprintHash: arg = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if ((value = ssh_digest_alg_by_name(arg)) == -1) fatal("%.200s line %d: Invalid %s algorithm \"%s\".", filename, linenum, keyword, arg); if (*activep) options->fingerprint_hash = value; break; case sExposeAuthInfo: intptr = &options->expose_userauth_info; 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 = argv_next(&ac, &av); if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); if (strcasecmp(arg, "none") != 0 && strcmp(arg, "%D") != 0 && !valid_rdomain(arg)) fatal("%s line %d: invalid routing domain", filename, linenum); if (*activep && *charptr == NULL) *charptr = xstrdup(arg); break; case sRequiredRSASize: intptr = &options->required_rsa_size; goto parse_int; case sChannelTimeout: uvalue = options->num_channel_timeouts; i = 0; while ((arg = argv_next(&ac, &av)) != NULL) { /* Allow "none" only in first position */ if (strcasecmp(arg, "none") == 0) { if (i > 0 || ac > 0) { error("%s line %d: keyword %s \"none\" " "argument must appear alone.", filename, linenum, keyword); goto out; } - } else if (parse_timeout(arg, NULL, NULL) != 0) { + } else if (parse_pattern_interval(arg, + NULL, NULL) != 0) { fatal("%s line %d: invalid channel timeout %s", filename, linenum, arg); } if (!*activep || uvalue != 0) continue; opt_array_append(filename, linenum, keyword, &options->channel_timeouts, &options->num_channel_timeouts, arg); } break; case sUnusedConnectionTimeout: intptr = &options->unused_connection_timeout; /* peek at first arg for "none" so we can reuse parse_time */ if (av[0] != NULL && strcasecmp(av[0], "none") == 0) { (void)argv_next(&ac, &av); /* consume arg */ if (*activep) *intptr = 0; break; } goto parse_time; case sUseBlacklist: intptr = &options->use_blacklist; goto parse_flag; case sDeprecated: case sIgnore: case sUnsupported: do_log2(opcode == sIgnore ? SYSLOG_LEVEL_DEBUG2 : SYSLOG_LEVEL_INFO, "%s line %d: %s option %s", filename, linenum, opcode == sUnsupported ? "Unsupported" : "Deprecated", keyword); argv_consume(&ac); break; default: fatal("%s line %d: Missing handler for opcode %s (%d)", filename, linenum, keyword, opcode); } /* Check that there is no garbage at end of line. */ if (ac > 0) { error("%.200s line %d: keyword %s extra arguments " "at end of line", filename, linenum, keyword); goto out; } /* success */ ret = 0; out: argv_free(oav, oac); return ret; } 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; 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) { /* * Strip whitespace * NB - preserve newlines, they are needed to reproduce * line numbers later for error messages */ cp = line + strspn(line, " \t\r"); if ((r = sshbuf_put(conf, cp, strlen(cp))) != 0) fatal_fr(r, "sshbuf_put"); } free(line); if ((r = sshbuf_put_u8(conf, 0)) != 0) fatal_fr(r, "sshbuf_put_u8"); fclose(f); debug2_f("done config len = %zu", sshbuf_len(conf)); } void parse_server_match_config(ServerOptions *options, struct include_list *includes, struct connection_info *connectinfo) { ServerOptions mo; initialize_server_options(&mo); parse_server_config(&mo, "reprocess config", cfg, includes, connectinfo, 0); copy_set_server_options(options, &mo, 0); } int parse_server_match_testspec(struct connection_info *ci, char *spec) { char *p; while ((p = strsep(&spec, ",")) && *p != '\0') { if (strncmp(p, "addr=", 5) == 0) { ci->address = xstrdup(p + 5); } else if (strncmp(p, "host=", 5) == 0) { ci->host = xstrdup(p + 5); } else if (strncmp(p, "user=", 5) == 0) { ci->user = xstrdup(p + 5); } else if (strncmp(p, "laddr=", 6) == 0) { ci->laddress = xstrdup(p + 6); } else if (strncmp(p, "rdomain=", 8) == 0) { ci->rdomain = xstrdup(p + 8); } else if (strncmp(p, "lport=", 6) == 0) { ci->lport = a2port(p + 6); if (ci->lport == -1) { fprintf(stderr, "Invalid port '%s' in test mode" " specification %s\n", p+6, p); return -1; } } else { fprintf(stderr, "Invalid test mode specification %s\n", p); return -1; } } return 0; } void servconf_merge_subsystems(ServerOptions *dst, ServerOptions *src) { u_int i, j, found; for (i = 0; i < src->num_subsystems; i++) { found = 0; for (j = 0; j < dst->num_subsystems; j++) { if (strcmp(src->subsystem_name[i], dst->subsystem_name[j]) == 0) { found = 1; break; } } if (found) { debug_f("override \"%s\"", dst->subsystem_name[j]); free(dst->subsystem_command[j]); free(dst->subsystem_args[j]); dst->subsystem_command[j] = xstrdup(src->subsystem_command[i]); dst->subsystem_args[j] = xstrdup(src->subsystem_args[i]); continue; } debug_f("add \"%s\"", src->subsystem_name[i]); dst->subsystem_name = xrecallocarray( dst->subsystem_name, dst->num_subsystems, dst->num_subsystems + 1, sizeof(*dst->subsystem_name)); dst->subsystem_command = xrecallocarray( dst->subsystem_command, dst->num_subsystems, dst->num_subsystems + 1, sizeof(*dst->subsystem_command)); dst->subsystem_args = xrecallocarray( dst->subsystem_args, dst->num_subsystems, dst->num_subsystems + 1, sizeof(*dst->subsystem_args)); j = dst->num_subsystems++; dst->subsystem_name[j] = xstrdup(src->subsystem_name[i]); dst->subsystem_command[j] = xstrdup(src->subsystem_command[i]); dst->subsystem_args[j] = xstrdup(src->subsystem_args[i]); } } /* * Copy any supported values that are set. * * If the preauth flag is set, we do not bother copying the string or * array values that are not used pre-authentication, because any that we * do use must be explicitly sent in mm_getpwnamallow(). */ void copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) { #define M_CP_INTOPT(n) do {\ if (src->n != -1) \ dst->n = src->n; \ } while (0) M_CP_INTOPT(password_authentication); M_CP_INTOPT(gss_authentication); M_CP_INTOPT(pubkey_authentication); M_CP_INTOPT(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); M_CP_INTOPT(allow_agent_forwarding); M_CP_INTOPT(disable_forwarding); M_CP_INTOPT(expose_userauth_info); M_CP_INTOPT(permit_tun); M_CP_INTOPT(fwd_opts.gateway_ports); M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink); M_CP_INTOPT(x11_display_offset); M_CP_INTOPT(x11_forwarding); M_CP_INTOPT(x11_use_localhost); M_CP_INTOPT(permit_tty); M_CP_INTOPT(permit_user_rc); M_CP_INTOPT(max_sessions); M_CP_INTOPT(max_authtries); M_CP_INTOPT(client_alive_count_max); M_CP_INTOPT(client_alive_interval); M_CP_INTOPT(ip_qos_interactive); M_CP_INTOPT(ip_qos_bulk); M_CP_INTOPT(rekey_limit); M_CP_INTOPT(rekey_interval); M_CP_INTOPT(log_level); M_CP_INTOPT(required_rsa_size); M_CP_INTOPT(unused_connection_timeout); /* * The bind_mask is a mode_t that may be unsigned, so we can't use * M_CP_INTOPT - it does a signed comparison that causes compiler * warnings. */ if (src->fwd_opts.streamlocal_bind_mask != (mode_t)-1) { dst->fwd_opts.streamlocal_bind_mask = src->fwd_opts.streamlocal_bind_mask; } /* M_CP_STROPT and M_CP_STRARRAYOPT should not appear before here */ #define M_CP_STROPT(n) do {\ if (src->n != NULL && dst->n != src->n) { \ free(dst->n); \ dst->n = src->n; \ } \ } while(0) #define M_CP_STRARRAYOPT(s, num_s) do {\ u_int i; \ if (src->num_s != 0) { \ for (i = 0; i < dst->num_s; i++) \ free(dst->s[i]); \ free(dst->s); \ dst->s = xcalloc(src->num_s, sizeof(*dst->s)); \ for (i = 0; i < src->num_s; i++) \ dst->s[i] = xstrdup(src->s[i]); \ dst->num_s = src->num_s; \ } \ } while(0) /* See comment in servconf.h */ COPY_MATCH_STRING_OPTS(); /* Arguments that accept '+...' need to be expanded */ assemble_algorithms(dst); /* * The only things that should be below this point are string options * which are only used after authentication. */ if (preauth) return; /* These options may be "none" to clear a global setting */ M_CP_STROPT(adm_forced_command); if (option_clear_or_none(dst->adm_forced_command)) { free(dst->adm_forced_command); dst->adm_forced_command = NULL; } M_CP_STROPT(chroot_directory); if (option_clear_or_none(dst->chroot_directory)) { free(dst->chroot_directory); dst->chroot_directory = NULL; } /* Subsystems require merging. */ servconf_merge_subsystems(dst, src); } #undef M_CP_INTOPT #undef M_CP_STROPT #undef M_CP_STRARRAYOPT #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 linenum, bad_options = 0; char *cp, *obuf, *cbuf; 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_f("sshbuf_dup_string failed"); linenum = 1; while ((cp = strsep(&cbuf, "\n")) != NULL) { 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 reexec) { int active = connectinfo ? 0 : 1; parse_server_config_depth(options, filename, conf, includes, connectinfo, (connectinfo ? SSHCFG_MATCH_ONLY : 0), &active, 0); if (!reexec) process_queued_listen_addrs(options); } static const char * fmt_multistate_int(int val, const struct multistate *m) { u_int i; for (i = 0; m[i].key != NULL; i++) { if (m[i].value == val) return m[i].key; } return "UNKNOWN"; } static const char * fmt_intarg(ServerOpCodes code, int val) { if (val == -1) return "unset"; switch (code) { case sAddressFamily: return fmt_multistate_int(val, multistate_addressfamily); case sPermitRootLogin: return fmt_multistate_int(val, multistate_permitrootlogin); case sGatewayPorts: return fmt_multistate_int(val, multistate_gatewayports); case sCompression: return fmt_multistate_int(val, multistate_compression); case sAllowTcpForwarding: return fmt_multistate_int(val, multistate_tcpfwd); case sAllowStreamLocalForwarding: return fmt_multistate_int(val, multistate_tcpfwd); case sIgnoreRhosts: return fmt_multistate_int(val, multistate_ignore_rhosts); case sFingerprintHash: return ssh_digest_alg_name(val); default: switch (val) { case 0: return "no"; case 1: return "yes"; default: return "UNKNOWN"; } } } static void dump_cfg_int(ServerOpCodes code, int val) { if (code == sUnusedConnectionTimeout && val == 0) { printf("%s none\n", lookup_opcode_name(code)); return; } printf("%s %d\n", lookup_opcode_name(code), val); } static void dump_cfg_oct(ServerOpCodes code, int val) { printf("%s 0%o\n", lookup_opcode_name(code), val); } static void dump_cfg_fmtint(ServerOpCodes code, int val) { printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val)); } static void dump_cfg_string(ServerOpCodes code, const char *val) { printf("%s %s\n", lookup_opcode_name(code), val == NULL ? "none" : val); } static void dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals) { u_int i; for (i = 0; i < count; i++) printf("%s %s\n", lookup_opcode_name(code), vals[i]); } static void dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals) { u_int i; switch (code) { case sAuthenticationMethods: case sChannelTimeout: break; default: if (count <= 0) return; break; } printf("%s", lookup_opcode_name(code)); for (i = 0; i < count; i++) printf(" %s", vals[i]); if (code == sAuthenticationMethods && count == 0) printf(" any"); else if (code == sChannelTimeout && count == 0) printf(" none"); printf("\n"); } static char * format_listen_addrs(struct listenaddr *la) { int r; struct addrinfo *ai; char addr[NI_MAXHOST], port[NI_MAXSERV]; char *laddr1 = xstrdup(""), *laddr2 = NULL; /* * ListenAddress must be after Port. add_one_listen_addr pushes * addresses onto a stack, so to maintain ordering we need to * print these in reverse order. */ for (ai = la->addrs; ai; ai = ai->ai_next) { if ((r = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, sizeof(addr), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { error("getnameinfo: %.100s", ssh_gai_strerror(r)); continue; } laddr2 = laddr1; if (ai->ai_family == AF_INET6) { xasprintf(&laddr1, "listenaddress [%s]:%s%s%s\n%s", addr, port, la->rdomain == NULL ? "" : " rdomain ", la->rdomain == NULL ? "" : la->rdomain, laddr2); } else { xasprintf(&laddr1, "listenaddress %s:%s%s%s\n%s", addr, port, la->rdomain == NULL ? "" : " rdomain ", la->rdomain == NULL ? "" : la->rdomain, laddr2); } free(laddr2); } return laddr1; } void dump_config(ServerOptions *o) { char *s; u_int i; /* these are usually at the top of the config */ for (i = 0; i < o->num_ports; i++) printf("port %d\n", o->ports[i]); dump_cfg_fmtint(sAddressFamily, o->address_family); for (i = 0; i < o->num_listen_addrs; i++) { s = format_listen_addrs(&o->listen_addrs[i]); printf("%s", s); free(s); } /* integer arguments */ #ifdef USE_PAM dump_cfg_fmtint(sUsePAM, o->use_pam); #endif dump_cfg_int(sLoginGraceTime, o->login_grace_time); dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); dump_cfg_int(sMaxAuthTries, o->max_authtries); dump_cfg_int(sMaxSessions, o->max_sessions); dump_cfg_int(sClientAliveInterval, o->client_alive_interval); dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max); dump_cfg_int(sRequiredRSASize, o->required_rsa_size); dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask); dump_cfg_int(sUnusedConnectionTimeout, o->unused_connection_timeout); /* formatted integer arguments */ dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login); dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts); dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts); dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication); dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly, o->hostbased_uses_name_from_packet_only); dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication); #ifdef KRB5 dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication); dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd); dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup); # ifdef USE_AFS dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); # endif #endif #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); #endif dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, o->kbd_interactive_authentication); dump_cfg_fmtint(sPrintMotd, o->print_motd); #ifndef DISABLE_LASTLOG dump_cfg_fmtint(sPrintLastLog, o->print_lastlog); #endif dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding); dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost); dump_cfg_fmtint(sPermitTTY, o->permit_tty); dump_cfg_fmtint(sPermitUserRC, o->permit_user_rc); dump_cfg_fmtint(sStrictModes, o->strict_modes); dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive); dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd); dump_cfg_fmtint(sCompression, o->compression); dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports); dump_cfg_fmtint(sUseDNS, o->use_dns); dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding); dump_cfg_fmtint(sDisableForwarding, o->disable_forwarding); dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding); dump_cfg_fmtint(sStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink); dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash); dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info); dump_cfg_fmtint(sUseBlacklist, o->use_blacklist); /* string arguments */ dump_cfg_string(sPidFile, o->pid_file); dump_cfg_string(sModuliFile, o->moduli_file); dump_cfg_string(sXAuthLocation, o->xauth_location); 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' ? "none" : o->version_addendum); dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user); dump_cfg_string(sAuthorizedPrincipalsCommand, o->authorized_principals_command); dump_cfg_string(sAuthorizedPrincipalsCommandUser, o->authorized_principals_command_user); dump_cfg_string(sHostKeyAgent, o->host_key_agent); dump_cfg_string(sKexAlgorithms, o->kex_algorithms); 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)); dump_cfg_string(sLogFacility, log_facility_name(o->log_facility)); /* string array arguments */ dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files, o->authorized_keys_files); dump_cfg_strarray(sHostKeyFile, o->num_host_key_files, o->host_key_files); dump_cfg_strarray(sHostCertificate, o->num_host_cert_files, o->host_cert_files); dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users); dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users); dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups); dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups); dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env); dump_cfg_strarray(sSetEnv, o->num_setenv, o->setenv); dump_cfg_strarray_oneline(sAuthenticationMethods, o->num_auth_methods, o->auth_methods); dump_cfg_strarray_oneline(sLogVerbose, o->num_log_verbose, o->log_verbose); dump_cfg_strarray_oneline(sChannelTimeout, o->num_channel_timeouts, o->channel_timeouts); /* other arguments */ for (i = 0; i < o->num_subsystems; i++) printf("subsystem %s %s\n", o->subsystem_name[i], o->subsystem_args[i]); printf("maxstartups %d:%d:%d\n", o->max_startups_begin, o->max_startups_rate, o->max_startups); 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++) { if (tunmode_desc[i].val == o->permit_tun) { s = tunmode_desc[i].text; break; } } dump_cfg_string(sPermitTunnel, s); printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); printf("%s\n", iptos2str(o->ip_qos_bulk)); printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit, o->rekey_interval); printf("permitopen"); if (o->num_permitted_opens == 0) printf(" any"); else { for (i = 0; i < o->num_permitted_opens; i++) printf(" %s", o->permitted_opens[i]); } printf("\n"); printf("permitlisten"); if (o->num_permitted_listens == 0) printf(" any"); else { for (i = 0; i < o->num_permitted_listens; i++) printf(" %s", o->permitted_listens[i]); } printf("\n"); if (o->permit_user_env_allowlist == NULL) { dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); } else { printf("permituserenvironment %s\n", 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/crypto/openssh/sftp-client.c b/crypto/openssh/sftp-client.c index 2598029f7bd2..5cc8bb539a6e 100644 --- a/crypto/openssh/sftp-client.c +++ b/crypto/openssh/sftp-client.c @@ -1,3009 +1,3009 @@ -/* $OpenBSD: sftp-client.c,v 1.174 2023/09/08 06:10:02 djm Exp $ */ +/* $OpenBSD: sftp-client.c,v 1.175 2023/11/13 09:18:19 tobhe Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* XXX: memleaks */ /* XXX: signed vs unsigned */ /* XXX: remove all logging, only return status codes */ /* XXX: copy between two remote sites */ #include "includes.h" #include #ifdef HAVE_SYS_STATVFS_H #include #endif #include "openbsd-compat/sys-queue.h" #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #ifdef HAVE_POLL_H #include #else # ifdef HAVE_SYS_POLL_H # include # endif #endif #include #include #include #include #include #include #include #include "xmalloc.h" #include "ssherr.h" #include "sshbuf.h" #include "log.h" #include "atomicio.h" #include "progressmeter.h" #include "misc.h" #include "utf8.h" #include "sftp.h" #include "sftp-common.h" #include "sftp-client.h" extern volatile sig_atomic_t interrupted; extern int showprogress; /* Default size of buffer for up/download (fix sftp.1 scp.1 if changed) */ #define DEFAULT_COPY_BUFLEN 32768 /* Default number of concurrent xfer requests (fix sftp.1 scp.1 if changed) */ #define DEFAULT_NUM_REQUESTS 64 /* Minimum amount of data to read at a time */ #define MIN_READ_SIZE 512 /* Maximum depth to descend in directory trees */ #define MAX_DIR_DEPTH 64 /* Directory separator characters */ #ifdef HAVE_CYGWIN # define SFTP_DIRECTORY_CHARS "/\\" #else /* HAVE_CYGWIN */ # define SFTP_DIRECTORY_CHARS "/" #endif /* HAVE_CYGWIN */ struct sftp_conn { int fd_in; int fd_out; u_int download_buflen; u_int upload_buflen; u_int num_requests; u_int version; u_int msg_id; #define SFTP_EXT_POSIX_RENAME 0x00000001 #define SFTP_EXT_STATVFS 0x00000002 #define SFTP_EXT_FSTATVFS 0x00000004 #define SFTP_EXT_HARDLINK 0x00000008 #define SFTP_EXT_FSYNC 0x00000010 #define SFTP_EXT_LSETSTAT 0x00000020 #define SFTP_EXT_LIMITS 0x00000040 #define SFTP_EXT_PATH_EXPAND 0x00000080 #define SFTP_EXT_COPY_DATA 0x00000100 #define SFTP_EXT_GETUSERSGROUPS_BY_ID 0x00000200 u_int exts; u_int64_t limit_kbps; struct bwlimit bwlimit_in, bwlimit_out; }; /* Tracks in-progress requests during file transfers */ struct request { u_int id; size_t len; u_int64_t offset; TAILQ_ENTRY(request) tq; }; TAILQ_HEAD(requests, request); static u_char * get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, const char *errfmt, ...) __attribute__((format(printf, 4, 5))); static struct request * request_enqueue(struct requests *requests, u_int id, size_t len, uint64_t offset) { struct request *req; req = xcalloc(1, sizeof(*req)); req->id = id; req->len = len; req->offset = offset; TAILQ_INSERT_TAIL(requests, req, tq); return req; } static struct request * request_find(struct requests *requests, u_int id) { struct request *req; for (req = TAILQ_FIRST(requests); req != NULL && req->id != id; req = TAILQ_NEXT(req, tq)) ; return req; } static int sftpio(void *_bwlimit, size_t amount) { struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit; refresh_progress_meter(0); if (bwlimit != NULL) bandwidth_limit(bwlimit, amount); return 0; } static void send_msg(struct sftp_conn *conn, struct sshbuf *m) { u_char mlen[4]; struct iovec iov[2]; if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH) fatal("Outbound message too long %zu", sshbuf_len(m)); /* Send length first */ put_u32(mlen, sshbuf_len(m)); iov[0].iov_base = mlen; iov[0].iov_len = sizeof(mlen); iov[1].iov_base = (u_char *)sshbuf_ptr(m); iov[1].iov_len = sshbuf_len(m); if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio, conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) != sshbuf_len(m) + sizeof(mlen)) fatal("Couldn't send packet: %s", strerror(errno)); sshbuf_reset(m); } static void get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial) { u_int msg_len; u_char *p; int r; sshbuf_reset(m); if ((r = sshbuf_reserve(m, 4, &p)) != 0) 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) fatal("Connection closed"); else fatal("Couldn't read packet: %s", strerror(errno)); } if ((r = sshbuf_get_u32(m, &msg_len)) != 0) 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); fatal("Ensure the remote shell produces no output " "for non-interactive sessions."); } if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) fatal_fr(r, "reserve"); if (atomicio6(read, conn->fd_in, p, msg_len, sftpio, conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != msg_len) { if (errno == EPIPE) fatal("Connection closed"); else fatal("Read packet: %s", strerror(errno)); } } static void get_msg(struct sftp_conn *conn, struct sshbuf *m) { get_msg_extended(conn, m, 0); } static void send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s, u_int len) { struct sshbuf *msg; int r; if ((msg = sshbuf_new()) == NULL) fatal_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_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); sshbuf_free(msg); } static void send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, const void *s, u_int len, Attrib *a) { struct sshbuf *msg; int r; if ((msg = sshbuf_new()) == NULL) fatal_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_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message fd %d T:%u I:%u F:0x%04x M:%05o", conn->fd_out, code, id, a->flags, a->perm); sshbuf_free(msg); } static u_int get_status(struct sftp_conn *conn, u_int expected_id) { struct sshbuf *msg; u_char type; u_int id, status; int r; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "compose"); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type != SSH2_FXP_STATUS) fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", SSH2_FXP_STATUS, type); if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse"); sshbuf_free(msg); debug3("SSH2_FXP_STATUS %u", status); return status; } static u_char * get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, const char *errfmt, ...) { struct sshbuf *msg; u_int id, status; u_char type; u_char *handle; char errmsg[256]; va_list args; int r; va_start(args, errfmt); if (errfmt != NULL) vsnprintf(errmsg, sizeof(errmsg), errfmt, args); va_end(args); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) 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_fr(r, "parse status"); if (errfmt != NULL) error("%s: %s", errmsg, fx2txt(status)); sshbuf_free(msg); return(NULL); } else if (type != SSH2_FXP_HANDLE) fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u", errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type); if ((r = sshbuf_get_string(msg, &handle, len)) != 0) fatal_fr(r, "parse handle"); sshbuf_free(msg); return handle; } static int get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet, Attrib *a) { struct sshbuf *msg; u_int id; u_char type; int r; Attrib attr; if (a != NULL) memset(a, '\0', sizeof(*a)); if ((msg = sshbuf_new()) == NULL) 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_fr(r, "parse"); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int status; if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse status"); if (quiet) debug("stat remote: %s", fx2txt(status)); else error("stat remote: %s", fx2txt(status)); sshbuf_free(msg); return -1; } else if (type != SSH2_FXP_ATTRS) { fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", SSH2_FXP_ATTRS, type); } if ((r = decode_attrib(msg, &attr)) != 0) { error_fr(r, "decode_attrib"); sshbuf_free(msg); return -1; } /* success */ if (a != NULL) *a = attr; debug3("Received stat reply T:%u I:%u F:0x%04x M:%05o", type, id, attr.flags, attr.perm); sshbuf_free(msg); return 0; } static int get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, u_int expected_id, int quiet) { struct sshbuf *msg; u_char type; u_int id; u_int64_t flag; int r; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "parse"); debug3("Received statvfs reply T:%u I:%u", type, id); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int status; if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse status"); if (quiet) debug("remote statvfs: %s", fx2txt(status)); else error("remote statvfs: %s", fx2txt(status)); sshbuf_free(msg); return -1; } else if (type != SSH2_FXP_EXTENDED_REPLY) { fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", SSH2_FXP_EXTENDED_REPLY, type); } memset(st, 0, sizeof(*st)); if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 || (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 || (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 || (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 || (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 || (r = sshbuf_get_u64(msg, &st->f_files)) != 0 || (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 || (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 || (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 || (r = sshbuf_get_u64(msg, &flag)) != 0 || (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0) fatal_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; sshbuf_free(msg); return 0; } struct sftp_conn * sftp_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, u_int64_t limit_kbps) { u_char type; struct sshbuf *msg; struct sftp_conn *ret; int r; ret = xcalloc(1, sizeof(*ret)); ret->msg_id = 1; ret->fd_in = fd_in; ret->fd_out = fd_out; ret->download_buflen = ret->upload_buflen = transfer_buflen ? transfer_buflen : DEFAULT_COPY_BUFLEN; ret->num_requests = num_requests ? num_requests : DEFAULT_NUM_REQUESTS; ret->exts = 0; ret->limit_kbps = 0; if ((msg = sshbuf_new()) == NULL) 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_fr(r, "parse"); send_msg(ret, msg); get_msg_extended(ret, msg, 1); /* Expecting a VERSION reply */ if ((r = sshbuf_get_u8(msg, &type)) != 0) fatal_fr(r, "parse type"); if (type != SSH2_FXP_VERSION) { error("Invalid packet back from SSH2_FXP_INIT (type %u)", type); sshbuf_free(msg); free(ret); return(NULL); } if ((r = sshbuf_get_u32(msg, &ret->version)) != 0) fatal_fr(r, "parse version"); debug2("Remote version: %u", ret->version); /* Check for extensions */ while (sshbuf_len(msg) > 0) { char *name; u_char *value; size_t vlen; int known = 0; if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 || (r = sshbuf_get_string(msg, &value, &vlen)) != 0) fatal_fr(r, "parse extension"); if (strcmp(name, "posix-rename@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_POSIX_RENAME; known = 1; } else if (strcmp(name, "statvfs@openssh.com") == 0 && strcmp((char *)value, "2") == 0) { ret->exts |= SFTP_EXT_STATVFS; known = 1; } else if (strcmp(name, "fstatvfs@openssh.com") == 0 && strcmp((char *)value, "2") == 0) { ret->exts |= SFTP_EXT_FSTATVFS; known = 1; } else if (strcmp(name, "hardlink@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_HARDLINK; known = 1; } else if (strcmp(name, "fsync@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_FSYNC; known = 1; } else if (strcmp(name, "lsetstat@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_LSETSTAT; known = 1; } else if (strcmp(name, "limits@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_LIMITS; known = 1; } else if (strcmp(name, "expand-path@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_PATH_EXPAND; known = 1; } else if (strcmp(name, "copy-data") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_COPY_DATA; known = 1; } else if (strcmp(name, "users-groups-by-id@openssh.com") == 0 && strcmp((char *)value, "1") == 0) { ret->exts |= SFTP_EXT_GETUSERSGROUPS_BY_ID; known = 1; } if (known) { debug2("Server supports extension \"%s\" revision %s", name, value); } else { debug2("Unrecognised server extension \"%s\"", name); } free(name); free(value); } sshbuf_free(msg); /* Query the server for its limits */ if (ret->exts & SFTP_EXT_LIMITS) { struct sftp_limits limits; if (sftp_get_limits(ret, &limits) != 0) fatal_f("limits failed"); /* If the caller did not specify, find a good value */ if (transfer_buflen == 0) { ret->download_buflen = MINIMUM(limits.read_length, SFTP_MAX_MSG_LENGTH - 1024); ret->upload_buflen = MINIMUM(limits.write_length, SFTP_MAX_MSG_LENGTH - 1024); ret->download_buflen = MAXIMUM(ret->download_buflen, 64); ret->upload_buflen = MAXIMUM(ret->upload_buflen, 64); debug3("server upload/download buffer sizes " "%llu / %llu; using %u / %u", (unsigned long long)limits.write_length, (unsigned long long)limits.read_length, ret->upload_buflen, ret->download_buflen); } /* Use the server limit to scale down our value only */ if (num_requests == 0 && limits.open_handles) { ret->num_requests = MINIMUM(DEFAULT_NUM_REQUESTS, limits.open_handles); if (ret->num_requests == 0) ret->num_requests = 1; debug3("server handle limit %llu; using %u", (unsigned long long)limits.open_handles, ret->num_requests); } } /* Some filexfer v.0 servers don't support large packets */ if (ret->version == 0) { ret->download_buflen = MINIMUM(ret->download_buflen, 20480); ret->upload_buflen = MINIMUM(ret->upload_buflen, 20480); } ret->limit_kbps = limit_kbps; if (ret->limit_kbps > 0) { bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps, ret->download_buflen); bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps, ret->upload_buflen); } return ret; } u_int sftp_proto_version(struct sftp_conn *conn) { return conn->version; } int sftp_get_limits(struct sftp_conn *conn, struct sftp_limits *limits) { u_int id, msg_id; u_char type; struct sshbuf *msg; int r; if ((conn->exts & SFTP_EXT_LIMITS) == 0) { error("Server does not support limits@openssh.com extension"); return -1; } if ((msg = sshbuf_new()) == NULL) 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, "limits@openssh.com")) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message limits@openssh.com I:%u", id); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &msg_id)) != 0) fatal_fr(r, "parse"); debug3("Received limits reply T:%u I:%u", type, msg_id); if (id != msg_id) fatal("ID mismatch (%u != %u)", msg_id, id); if (type != SSH2_FXP_EXTENDED_REPLY) { debug_f("expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", SSH2_FXP_EXTENDED_REPLY, type); /* Disable the limits extension */ conn->exts &= ~SFTP_EXT_LIMITS; sshbuf_free(msg); - return 0; + return -1; } memset(limits, 0, sizeof(*limits)); if ((r = sshbuf_get_u64(msg, &limits->packet_length)) != 0 || (r = sshbuf_get_u64(msg, &limits->read_length)) != 0 || (r = sshbuf_get_u64(msg, &limits->write_length)) != 0 || (r = sshbuf_get_u64(msg, &limits->open_handles)) != 0) fatal_fr(r, "parse limits"); sshbuf_free(msg); return 0; } int sftp_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len) { u_int id, status; struct sshbuf *msg; int r; if ((msg = sshbuf_new()) == NULL) fatal_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_fr(r, "parse"); send_msg(conn, msg); debug3("Sent message SSH2_FXP_CLOSE I:%u", id); status = get_status(conn, id); if (status != SSH2_FX_OK) error("close remote: %s", fx2txt(status)); sshbuf_free(msg); return status == SSH2_FX_OK ? 0 : -1; } static int sftp_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, SFTP_DIRENT ***dir) { struct sshbuf *msg; u_int count, id, i, expected_id, ents = 0; size_t handle_len; u_char type, *handle; int status = SSH2_FX_FAILURE; int r; if (dir) *dir = NULL; id = conn->msg_id++; if ((msg = sshbuf_new()) == NULL) fatal_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_fr(r, "compose OPENDIR"); send_msg(conn, msg); handle = get_handle(conn, id, &handle_len, "remote readdir(\"%s\")", path); if (handle == NULL) { sshbuf_free(msg); return -1; } if (dir) { ents = 0; *dir = xcalloc(1, sizeof(**dir)); (*dir)[0] = NULL; } for (; !interrupted;) { id = expected_id = conn->msg_id++; debug3("Sending SSH2_FXP_READDIR I:%u", id); sshbuf_reset(msg); if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_string(msg, handle, handle_len)) != 0) fatal_fr(r, "compose READDIR"); send_msg(conn, msg); sshbuf_reset(msg); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "parse"); debug3("Received reply T:%u I:%u", type, id); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int rstatus; if ((r = sshbuf_get_u32(msg, &rstatus)) != 0) fatal_fr(r, "parse status"); debug3("Received SSH2_FXP_STATUS %d", rstatus); if (rstatus == SSH2_FX_EOF) break; error("Couldn't read directory: %s", fx2txt(rstatus)); goto out; } else if (type != SSH2_FXP_NAME) fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", SSH2_FXP_NAME, type); if ((r = sshbuf_get_u32(msg, &count)) != 0) fatal_fr(r, "parse count"); if (count > SSHBUF_SIZE_MAX) fatal_f("nonsensical number of entries"); if (count == 0) break; debug3("Received %d SSH2_FXP_NAME responses", count); for (i = 0; i < count; i++) { char *filename, *longname; Attrib a; if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0) fatal_fr(r, "parse filenames"); if ((r = decode_attrib(msg, &a)) != 0) { error_fr(r, "couldn't decode attrib"); free(filename); free(longname); goto out; } if (print_flag) mprintf("%s\n", longname); /* * Directory entries should never contain '/' * These can be used to attack recursive ops * (e.g. send '../../../../etc/passwd') */ if (strpbrk(filename, SFTP_DIRECTORY_CHARS) != NULL) { error("Server sent suspect path \"%s\" " "during readdir of \"%s\"", filename, path); } else if (dir) { *dir = xreallocarray(*dir, ents + 2, sizeof(**dir)); (*dir)[ents] = xcalloc(1, sizeof(***dir)); (*dir)[ents]->filename = xstrdup(filename); (*dir)[ents]->longname = xstrdup(longname); memcpy(&(*dir)[ents]->a, &a, sizeof(a)); (*dir)[++ents] = NULL; } free(filename); free(longname); } } status = 0; out: sshbuf_free(msg); sftp_close(conn, handle, handle_len); free(handle); if (status != 0 && dir != NULL) { /* Don't return results on error */ sftp_free_dirents(*dir); *dir = NULL; } else if (interrupted && dir != NULL && *dir != NULL) { /* Don't return partial matches on interrupt */ sftp_free_dirents(*dir); *dir = xcalloc(1, sizeof(**dir)); **dir = NULL; } return status == SSH2_FX_OK ? 0 : -1; } int sftp_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) { return sftp_lsreaddir(conn, path, 0, dir); } void sftp_free_dirents(SFTP_DIRENT **s) { int i; if (s == NULL) return; for (i = 0; s[i]; i++) { free(s[i]->filename); free(s[i]->longname); free(s[i]); } free(s); } int sftp_rm(struct sftp_conn *conn, const char *path) { u_int status, id; debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); id = conn->msg_id++; send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path)); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote delete %s: %s", path, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } int sftp_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag) { u_int status, id; debug2("Sending SSH2_FXP_MKDIR \"%s\"", path); id = conn->msg_id++; send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path, strlen(path), a); status = get_status(conn, id); if (status != SSH2_FX_OK && print_flag) error("remote mkdir \"%s\": %s", path, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } int sftp_rmdir(struct sftp_conn *conn, const char *path) { u_int status, id; debug2("Sending SSH2_FXP_RMDIR \"%s\"", path); id = conn->msg_id++; send_string_request(conn, id, SSH2_FXP_RMDIR, path, strlen(path)); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote rmdir \"%s\": %s", path, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } int sftp_stat(struct sftp_conn *conn, const char *path, int quiet, Attrib *a) { u_int id; debug2("Sending SSH2_FXP_STAT \"%s\"", path); id = conn->msg_id++; send_string_request(conn, id, conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, path, strlen(path)); return get_decode_stat(conn, id, quiet, a); } int sftp_lstat(struct sftp_conn *conn, const char *path, int quiet, Attrib *a) { u_int id; if (conn->version == 0) { do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO, "Server version does not support lstat operation"); return sftp_stat(conn, path, quiet, a); } id = conn->msg_id++; send_string_request(conn, id, SSH2_FXP_LSTAT, path, strlen(path)); return get_decode_stat(conn, id, quiet, a); } #ifdef notyet int sftp_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, int quiet, Attrib *a) { u_int id; debug2("Sending SSH2_FXP_FSTAT \"%s\""); id = conn->msg_id++; send_string_request(conn, id, SSH2_FXP_FSTAT, handle, handle_len); return get_decode_stat(conn, id, quiet, a); } #endif int sftp_setstat(struct sftp_conn *conn, const char *path, Attrib *a) { u_int status, id; debug2("Sending SSH2_FXP_SETSTAT \"%s\"", path); id = conn->msg_id++; send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path, strlen(path), a); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote setstat \"%s\": %s", path, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } int sftp_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, Attrib *a) { u_int status, id; debug2("Sending SSH2_FXP_FSETSTAT"); id = conn->msg_id++; send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle, handle_len, a); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote fsetstat: %s", fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } /* Implements both the realpath and expand-path operations */ static char * sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand) { struct sshbuf *msg; u_int expected_id, count, id; char *filename, *longname; Attrib a; u_char type; int r; const char *what = "SSH2_FXP_REALPATH"; if (expand) what = "expand-path@openssh.com"; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); expected_id = id = conn->msg_id++; if (expand) { debug2("Sending SSH2_FXP_EXTENDED(expand-path@openssh.com) " "\"%s\"", path); if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, "expand-path@openssh.com")) != 0 || (r = sshbuf_put_cstring(msg, path)) != 0) fatal_fr(r, "compose %s", what); send_msg(conn, msg); } else { debug2("Sending SSH2_FXP_REALPATH \"%s\"", path); send_string_request(conn, id, SSH2_FXP_REALPATH, path, strlen(path)); } get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "parse"); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int status; char *errmsg; if ((r = sshbuf_get_u32(msg, &status)) != 0 || (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) fatal_fr(r, "parse status"); error("%s %s: %s", expand ? "expand" : "realpath", path, *errmsg == '\0' ? fx2txt(status) : errmsg); free(errmsg); sshbuf_free(msg); return NULL; } else if (type != SSH2_FXP_NAME) fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", SSH2_FXP_NAME, type); if ((r = sshbuf_get_u32(msg, &count)) != 0) fatal_fr(r, "parse count"); if (count != 1) fatal("Got multiple names (%d) from %s", count, what); if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || (r = decode_attrib(msg, &a)) != 0) fatal_fr(r, "parse filename/attrib"); debug3("%s %s -> %s", what, path, filename); free(longname); sshbuf_free(msg); return(filename); } char * sftp_realpath(struct sftp_conn *conn, const char *path) { return sftp_realpath_expand(conn, path, 0); } int sftp_can_expand_path(struct sftp_conn *conn) { return (conn->exts & SFTP_EXT_PATH_EXPAND) != 0; } char * sftp_expand_path(struct sftp_conn *conn, const char *path) { if (!sftp_can_expand_path(conn)) { debug3_f("no server support, fallback to realpath"); return sftp_realpath_expand(conn, path, 0); } return sftp_realpath_expand(conn, path, 1); } int sftp_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) { Attrib junk, attr; struct sshbuf *msg; u_char *old_handle, *new_handle; u_int mode, status, id; size_t old_handle_len, new_handle_len; int r; /* Return if the extension is not supported */ if ((conn->exts & SFTP_EXT_COPY_DATA) == 0) { error("Server does not support copy-data extension"); return -1; } /* Make sure the file exists, and we can copy its perms */ if (sftp_stat(conn, oldpath, 0, &attr) != 0) return -1; /* Do not preserve set[ug]id here, as we do not preserve ownership */ if (attr.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { mode = attr.perm & 0777; if (!S_ISREG(attr.perm)) { error("Cannot copy non-regular file: %s", oldpath); return -1; } } else { /* NB: The user's umask will apply to this */ mode = 0666; } /* Set up the new perms for the new file */ attrib_clear(&attr); attr.perm = mode; attr.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; if ((msg = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); attrib_clear(&junk); /* Send empty attributes */ /* Open the old file for reading */ id = conn->msg_id++; if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, oldpath)) != 0 || (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 || (r = encode_attrib(msg, &junk)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); send_msg(conn, msg); debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, oldpath); sshbuf_reset(msg); old_handle = get_handle(conn, id, &old_handle_len, "remote open(\"%s\")", oldpath); if (old_handle == NULL) { sshbuf_free(msg); return -1; } /* Open the new file for writing */ id = conn->msg_id++; if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, newpath)) != 0 || (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| SSH2_FXF_TRUNC)) != 0 || (r = encode_attrib(msg, &attr)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); send_msg(conn, msg); debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, newpath); sshbuf_reset(msg); new_handle = get_handle(conn, id, &new_handle_len, "remote open(\"%s\")", newpath); if (new_handle == NULL) { sshbuf_free(msg); free(old_handle); return -1; } /* Copy the file data */ 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, "copy-data")) != 0 || (r = sshbuf_put_string(msg, old_handle, old_handle_len)) != 0 || (r = sshbuf_put_u64(msg, 0)) != 0 || (r = sshbuf_put_u64(msg, 0)) != 0 || (r = sshbuf_put_string(msg, new_handle, new_handle_len)) != 0 || (r = sshbuf_put_u64(msg, 0)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); send_msg(conn, msg); debug3("Sent message copy-data \"%s\" 0 0 -> \"%s\" 0", oldpath, newpath); status = get_status(conn, id); if (status != SSH2_FX_OK) error("Couldn't copy file \"%s\" to \"%s\": %s", oldpath, newpath, fx2txt(status)); /* Clean up everything */ sshbuf_free(msg); sftp_close(conn, old_handle, old_handle_len); sftp_close(conn, new_handle, new_handle_len); free(old_handle); free(new_handle); return status == SSH2_FX_OK ? 0 : -1; } int sftp_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, int force_legacy) { struct sshbuf *msg; u_int status, id; int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* Send rename request */ id = conn->msg_id++; if (use_ext) { debug2("Sending SSH2_FXP_EXTENDED(posix-rename@openssh.com) " "\"%s\" to \"%s\"", oldpath, newpath); if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, "posix-rename@openssh.com")) != 0) fatal_fr(r, "compose posix-rename"); } else { debug2("Sending SSH2_FXP_RENAME \"%s\" to \"%s\"", oldpath, newpath); if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0) fatal_fr(r, "compose rename"); } if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 || (r = sshbuf_put_cstring(msg, newpath)) != 0) fatal_fr(r, "compose paths"); send_msg(conn, msg); debug3("Sent message %s \"%s\" -> \"%s\"", use_ext ? "posix-rename@openssh.com" : "SSH2_FXP_RENAME", oldpath, newpath); sshbuf_free(msg); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote rename \"%s\" to \"%s\": %s", oldpath, newpath, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } int sftp_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) { struct sshbuf *msg; u_int status, id; int r; if ((conn->exts & SFTP_EXT_HARDLINK) == 0) { error("Server does not support hardlink@openssh.com extension"); return -1; } debug2("Sending SSH2_FXP_EXTENDED(hardlink@openssh.com) " "\"%s\" to \"%s\"", oldpath, newpath); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* Send link request */ id = conn->msg_id++; if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 || (r = sshbuf_put_cstring(msg, oldpath)) != 0 || (r = sshbuf_put_cstring(msg, newpath)) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"", oldpath, newpath); sshbuf_free(msg); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote link \"%s\" to \"%s\": %s", oldpath, newpath, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } int sftp_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) { struct sshbuf *msg; u_int status, id; int r; if (conn->version < 3) { error("This server does not support the symlink operation"); return(SSH2_FX_OP_UNSUPPORTED); } debug2("Sending SSH2_FXP_SYMLINK \"%s\" to \"%s\"", oldpath, newpath); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* Send symlink request */ id = conn->msg_id++; if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, oldpath)) != 0 || (r = sshbuf_put_cstring(msg, newpath)) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, newpath); sshbuf_free(msg); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote symlink file \"%s\" to \"%s\": %s", oldpath, newpath, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } int sftp_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len) { struct sshbuf *msg; u_int status, id; int r; /* Silently return if the extension is not supported */ if ((conn->exts & SFTP_EXT_FSYNC) == 0) return -1; debug2("Sending SSH2_FXP_EXTENDED(fsync@openssh.com)"); /* Send fsync request */ if ((msg = sshbuf_new()) == NULL) 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_fr(r, "compose"); send_msg(conn, msg); debug3("Sent message fsync@openssh.com I:%u", id); sshbuf_free(msg); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote fsync: %s", fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } #ifdef notyet char * sftp_readlink(struct sftp_conn *conn, const char *path) { struct sshbuf *msg; u_int expected_id, count, id; char *filename, *longname; Attrib a; u_char type; int r; debug2("Sending SSH2_FXP_READLINK \"%s\"", path); expected_id = id = conn->msg_id++; send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); if ((msg = sshbuf_new()) == NULL) 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_fr(r, "parse"); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int status; if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse status"); error("Couldn't readlink: %s", fx2txt(status)); sshbuf_free(msg); return(NULL); } else if (type != SSH2_FXP_NAME) fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", SSH2_FXP_NAME, type); if ((r = sshbuf_get_u32(msg, &count)) != 0) fatal_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_fr(r, "parse filenames/attrib"); debug3("SSH_FXP_READLINK %s -> %s", path, filename); free(longname); sshbuf_free(msg); return filename; } #endif int sftp_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, int quiet) { struct sshbuf *msg; u_int id; int r; if ((conn->exts & SFTP_EXT_STATVFS) == 0) { error("Server does not support statvfs@openssh.com extension"); return -1; } debug2("Sending SSH2_FXP_EXTENDED(statvfs@openssh.com) \"%s\"", path); id = conn->msg_id++; if ((msg = sshbuf_new()) == NULL) 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_fr(r, "compose"); send_msg(conn, msg); sshbuf_free(msg); return get_decode_statvfs(conn, st, id, quiet); } #ifdef notyet int sftp_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len, struct sftp_statvfs *st, int quiet) { struct sshbuf *msg; u_int id; if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) { error("Server does not support fstatvfs@openssh.com extension"); return -1; } debug2("Sending SSH2_FXP_EXTENDED(fstatvfs@openssh.com)"); id = conn->msg_id++; if ((msg = sshbuf_new()) == NULL) 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_fr(r, "compose"); send_msg(conn, msg); sshbuf_free(msg); return get_decode_statvfs(conn, st, id, quiet); } #endif int sftp_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a) { struct sshbuf *msg; u_int status, id; int r; if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) { error("Server does not support lsetstat@openssh.com extension"); return -1; } debug2("Sending SSH2_FXP_EXTENDED(lsetstat@openssh.com) \"%s\"", path); id = conn->msg_id++; if ((msg = sshbuf_new()) == NULL) 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_fr(r, "compose"); send_msg(conn, msg); sshbuf_free(msg); status = get_status(conn, id); if (status != SSH2_FX_OK) error("remote lsetstat \"%s\": %s", path, fx2txt(status)); return status == SSH2_FX_OK ? 0 : -1; } static void send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, u_int len, const u_char *handle, u_int handle_len) { struct sshbuf *msg; int r; if ((msg = sshbuf_new()) == NULL) fatal_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_fr(r, "compose"); send_msg(conn, msg); sshbuf_free(msg); } static int send_open(struct sftp_conn *conn, const char *path, const char *tag, u_int openmode, Attrib *a, u_char **handlep, size_t *handle_lenp) { Attrib junk; u_char *handle; size_t handle_len; struct sshbuf *msg; int r; u_int id; debug2("Sending SSH2_FXP_OPEN \"%s\"", path); *handlep = NULL; *handle_lenp = 0; if (a == NULL) { attrib_clear(&junk); /* Send empty attributes */ a = &junk; } /* Send open request */ if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); id = conn->msg_id++; if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, path)) != 0 || (r = sshbuf_put_u32(msg, openmode)) != 0 || (r = encode_attrib(msg, a)) != 0) fatal_fr(r, "compose %s open", tag); send_msg(conn, msg); sshbuf_free(msg); debug3("Sent %s message SSH2_FXP_OPEN I:%u P:%s M:0x%04x", tag, id, path, openmode); if ((handle = get_handle(conn, id, &handle_len, "%s open \"%s\"", tag, path)) == NULL) return -1; /* success */ *handlep = handle; *handle_lenp = handle_len; return 0; } static const char * progress_meter_path(const char *path) { const char *progresspath; if ((progresspath = strrchr(path, '/')) == NULL) return path; progresspath++; if (*progresspath == '\0') return path; return progresspath; } int sftp_download(struct sftp_conn *conn, const char *remote_path, const char *local_path, Attrib *a, int preserve_flag, int resume_flag, int fsync_flag, int inplace_flag) { struct sshbuf *msg; u_char *handle; int local_fd = -1, write_error; int read_error, write_errno, lmodified = 0, reordered = 0, r; u_int64_t offset = 0, size, highwater = 0, maxack = 0; u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK; off_t progress_counter; size_t handle_len; struct stat st; struct requests requests; struct request *req; u_char type; Attrib attr; debug2_f("download remote \"%s\" to local \"%s\"", remote_path, local_path); TAILQ_INIT(&requests); if (a == NULL) { if (sftp_stat(conn, remote_path, 0, &attr) != 0) return -1; a = &attr; } /* Do not preserve set[ug]id here, as we do not preserve ownership */ if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) mode = a->perm & 0777; else mode = 0666; if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && (!S_ISREG(a->perm))) { error("download %s: not a regular file", remote_path); return(-1); } if (a->flags & SSH2_FILEXFER_ATTR_SIZE) size = a->size; else size = 0; buflen = conn->download_buflen; /* Send open request */ if (send_open(conn, remote_path, "remote", SSH2_FXF_READ, NULL, &handle, &handle_len) != 0) return -1; local_fd = open(local_path, O_WRONLY | O_CREAT | ((resume_flag || inplace_flag) ? 0 : O_TRUNC), mode | S_IWUSR); if (local_fd == -1) { error("open local \"%s\": %s", local_path, strerror(errno)); goto fail; } if (resume_flag) { if (fstat(local_fd, &st) == -1) { error("stat local \"%s\": %s", local_path, strerror(errno)); goto fail; } if (st.st_size < 0) { error("\"%s\" has negative size", local_path); goto fail; } if ((u_int64_t)st.st_size > size) { error("Unable to resume download of \"%s\": " "local file is larger than remote", local_path); fail: sftp_close(conn, handle, handle_len); free(handle); if (local_fd != -1) close(local_fd); return -1; } offset = highwater = maxack = st.st_size; } /* Read from remote and write to local */ write_error = read_error = write_errno = num_req = 0; max_req = 1; progress_counter = offset; if (showprogress && size != 0) { start_progress_meter(progress_meter_path(remote_path), size, &progress_counter); } if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); while (num_req > 0 || max_req > 0) { u_char *data; size_t len; /* * Simulate EOF on interrupt: stop sending new requests and * allow outstanding requests to drain gracefully */ if (interrupted) { if (num_req == 0) /* If we haven't started yet... */ break; max_req = 0; } /* Send some more requests */ while (num_req < max_req) { debug3("Request range %llu -> %llu (%d/%d)", (unsigned long long)offset, (unsigned long long)offset + buflen - 1, num_req, max_req); req = request_enqueue(&requests, conn->msg_id++, buflen, offset); offset += buflen; num_req++; send_read_request(conn, req->id, req->offset, req->len, handle, handle_len); } sshbuf_reset(msg); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "parse"); debug3("Received reply T:%u I:%u R:%d", type, id, max_req); /* Find the request in our queue */ if ((req = request_find(&requests, id)) == NULL) fatal("Unexpected reply %u", id); switch (type) { case SSH2_FXP_STATUS: if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse status"); if (status != SSH2_FX_EOF) read_error = 1; max_req = 0; TAILQ_REMOVE(&requests, req, tq); free(req); num_req--; break; case SSH2_FXP_DATA: if ((r = sshbuf_get_string(msg, &data, &len)) != 0) fatal_fr(r, "parse data"); debug3("Received data %llu -> %llu", (unsigned long long)req->offset, (unsigned long long)req->offset + len - 1); if (len > req->len) fatal("Received more data than asked for " "%zu > %zu", len, req->len); lmodified = 1; if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || atomicio(vwrite, local_fd, data, len) != len) && !write_error) { write_errno = errno; write_error = 1; max_req = 0; } else { /* * Track both the highest offset acknowledged * and the highest *contiguous* offset * acknowledged. * We'll need the latter for ftruncate()ing * interrupted transfers. */ if (maxack < req->offset + len) maxack = req->offset + len; if (!reordered && req->offset <= highwater) highwater = maxack; else if (!reordered && req->offset > highwater) reordered = 1; } progress_counter += len; free(data); if (len == req->len) { TAILQ_REMOVE(&requests, req, tq); free(req); num_req--; } else { /* Resend the request for the missing data */ debug3("Short data block, re-requesting " "%llu -> %llu (%2d)", (unsigned long long)req->offset + len, (unsigned long long)req->offset + req->len - 1, num_req); req->id = conn->msg_id++; req->len -= len; req->offset += len; send_read_request(conn, req->id, req->offset, req->len, handle, handle_len); /* Reduce the request size */ if (len < buflen) buflen = MAXIMUM(MIN_READ_SIZE, len); } if (max_req > 0) { /* max_req = 0 iff EOF received */ if (size > 0 && offset > size) { /* Only one request at a time * after the expected EOF */ debug3("Finish at %llu (%2d)", (unsigned long long)offset, num_req); max_req = 1; } else if (max_req < conn->num_requests) { ++max_req; } } break; default: fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", SSH2_FXP_DATA, type); } } if (showprogress && size) stop_progress_meter(); /* Sanity check */ if (TAILQ_FIRST(&requests) != NULL) fatal("Transfer complete, but requests still in queue"); if (!read_error && !write_error && !interrupted) { /* we got everything */ highwater = maxack; } /* * Truncate at highest contiguous point to avoid holes on interrupt, * or unconditionally if writing in place. */ if (inplace_flag || read_error || write_error || interrupted) { if (reordered && resume_flag && (read_error || write_error || interrupted)) { error("Unable to resume download of \"%s\": " "server reordered requests", local_path); } debug("truncating at %llu", (unsigned long long)highwater); if (ftruncate(local_fd, highwater) == -1) error("local ftruncate \"%s\": %s", local_path, strerror(errno)); } if (read_error) { error("read remote \"%s\" : %s", remote_path, fx2txt(status)); status = -1; sftp_close(conn, handle, handle_len); } else if (write_error) { error("write local \"%s\": %s", local_path, strerror(write_errno)); status = SSH2_FX_FAILURE; sftp_close(conn, handle, handle_len); } else { if (sftp_close(conn, handle, handle_len) != 0 || interrupted) status = SSH2_FX_FAILURE; else status = SSH2_FX_OK; /* Override umask and utimes if asked */ #ifdef HAVE_FCHMOD if (preserve_flag && fchmod(local_fd, mode) == -1) #else if (preserve_flag && chmod(local_path, mode) == -1) #endif /* HAVE_FCHMOD */ error("local chmod \"%s\": %s", local_path, strerror(errno)); if (preserve_flag && (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) { struct timeval tv[2]; tv[0].tv_sec = a->atime; tv[1].tv_sec = a->mtime; tv[0].tv_usec = tv[1].tv_usec = 0; if (utimes(local_path, tv) == -1) error("local set times \"%s\": %s", local_path, strerror(errno)); } if (resume_flag && !lmodified) logit("File \"%s\" was not modified", local_path); else if (fsync_flag) { debug("syncing \"%s\"", local_path); if (fsync(local_fd) == -1) error("local sync \"%s\": %s", local_path, strerror(errno)); } } close(local_fd); sshbuf_free(msg); free(handle); return status == SSH2_FX_OK ? 0 : -1; } static int download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, int depth, Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, int fsync_flag, int follow_link_flag, int inplace_flag) { int i, ret = 0; SFTP_DIRENT **dir_entries; char *filename, *new_src = NULL, *new_dst = NULL; mode_t mode = 0777, tmpmode = mode; Attrib *a, ldirattrib, lsym; if (depth >= MAX_DIR_DEPTH) { error("Maximum directory depth exceeded: %d levels", depth); return -1; } debug2_f("download dir remote \"%s\" to local \"%s\"", src, dst); if (dirattrib == NULL) { if (sftp_stat(conn, src, 1, &ldirattrib) != 0) { error("stat remote \"%s\" directory failed", src); return -1; } dirattrib = &ldirattrib; } if (!S_ISDIR(dirattrib->perm)) { error("\"%s\" is not a directory", src); return -1; } if (print_flag && print_flag != SFTP_PROGRESS_ONLY) mprintf("Retrieving %s\n", src); if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { mode = dirattrib->perm & 01777; tmpmode = mode | (S_IWUSR|S_IXUSR); } else { debug("download remote \"%s\": server " "did not send permissions", dst); } if (mkdir(dst, tmpmode) == -1 && errno != EEXIST) { error("mkdir %s: %s", dst, strerror(errno)); return -1; } if (sftp_readdir(conn, src, &dir_entries) == -1) { error("remote readdir \"%s\" failed", src); return -1; } for (i = 0; dir_entries[i] != NULL && !interrupted; i++) { free(new_dst); free(new_src); filename = dir_entries[i]->filename; new_dst = sftp_path_append(dst, filename); new_src = sftp_path_append(src, filename); a = &dir_entries[i]->a; if (S_ISLNK(a->perm)) { if (!follow_link_flag) { logit("download \"%s\": not a regular file", new_src); continue; } /* Replace the stat contents with the symlink target */ if (sftp_stat(conn, new_src, 1, &lsym) != 0) { logit("remote stat \"%s\" failed", new_src); ret = -1; continue; } a = &lsym; } if (S_ISDIR(a->perm)) { if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) continue; if (download_dir_internal(conn, new_src, new_dst, depth + 1, a, preserve_flag, print_flag, resume_flag, fsync_flag, follow_link_flag, inplace_flag) == -1) ret = -1; } else if (S_ISREG(a->perm)) { if (sftp_download(conn, new_src, new_dst, a, preserve_flag, resume_flag, fsync_flag, inplace_flag) == -1) { error("Download of file %s to %s failed", new_src, new_dst); ret = -1; } } else logit("download \"%s\": not a regular file", new_src); } free(new_dst); free(new_src); if (preserve_flag) { if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { struct timeval tv[2]; tv[0].tv_sec = dirattrib->atime; tv[1].tv_sec = dirattrib->mtime; tv[0].tv_usec = tv[1].tv_usec = 0; if (utimes(dst, tv) == -1) error("local set times on \"%s\": %s", dst, strerror(errno)); } else debug("Server did not send times for directory " "\"%s\"", dst); } if (mode != tmpmode && chmod(dst, mode) == -1) error("local chmod directory \"%s\": %s", dst, strerror(errno)); sftp_free_dirents(dir_entries); return ret; } int sftp_download_dir(struct sftp_conn *conn, const char *src, const char *dst, Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, int fsync_flag, int follow_link_flag, int inplace_flag) { char *src_canon; int ret; if ((src_canon = sftp_realpath(conn, src)) == NULL) { error("download \"%s\": path canonicalization failed", src); return -1; } ret = download_dir_internal(conn, src_canon, dst, 0, dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag, follow_link_flag, inplace_flag); free(src_canon); return ret; } int sftp_upload(struct sftp_conn *conn, const char *local_path, const char *remote_path, int preserve_flag, int resume, int fsync_flag, int inplace_flag) { int r, local_fd; u_int openmode, id, status = SSH2_FX_OK, reordered = 0; off_t offset, progress_counter; u_char type, *handle, *data; struct sshbuf *msg; struct stat sb; Attrib a, t, c; u_int32_t startid, ackid; u_int64_t highwater = 0, maxack = 0; struct request *ack = NULL; struct requests acks; size_t handle_len; debug2_f("upload local \"%s\" to remote \"%s\"", local_path, remote_path); TAILQ_INIT(&acks); if ((local_fd = open(local_path, O_RDONLY)) == -1) { error("open local \"%s\": %s", local_path, strerror(errno)); return(-1); } if (fstat(local_fd, &sb) == -1) { error("fstat local \"%s\": %s", local_path, strerror(errno)); close(local_fd); return(-1); } if (!S_ISREG(sb.st_mode)) { error("local \"%s\" is not a regular file", local_path); close(local_fd); return(-1); } stat_to_attrib(&sb, &a); a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; a.perm &= 0777; if (!preserve_flag) a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; if (resume) { /* Get remote file size if it exists */ if (sftp_stat(conn, remote_path, 0, &c) != 0) { close(local_fd); return -1; } if ((off_t)c.size >= sb.st_size) { error("resume \"%s\": destination file " "same size or larger", local_path); close(local_fd); return -1; } if (lseek(local_fd, (off_t)c.size, SEEK_SET) == -1) { close(local_fd); return -1; } } openmode = SSH2_FXF_WRITE|SSH2_FXF_CREAT; if (resume) openmode |= SSH2_FXF_APPEND; else if (!inplace_flag) openmode |= SSH2_FXF_TRUNC; /* Send open request */ if (send_open(conn, remote_path, "dest", openmode, &a, &handle, &handle_len) != 0) { close(local_fd); return -1; } id = conn->msg_id; startid = ackid = id + 1; data = xmalloc(conn->upload_buflen); /* Read from local and write to remote */ offset = progress_counter = (resume ? c.size : 0); if (showprogress) { start_progress_meter(progress_meter_path(local_path), sb.st_size, &progress_counter); } if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); for (;;) { int len; /* * Can't use atomicio here because it returns 0 on EOF, * thus losing the last block of the file. * Simulate an EOF on interrupt, allowing ACKs from the * server to drain. */ if (interrupted || status != SSH2_FX_OK) len = 0; else do len = read(local_fd, data, conn->upload_buflen); while ((len == -1) && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); if (len == -1) { fatal("read local \"%s\": %s", local_path, strerror(errno)); } else if (len != 0) { ack = request_enqueue(&acks, ++id, len, offset); sshbuf_reset(msg); if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || (r = sshbuf_put_u32(msg, ack->id)) != 0 || (r = sshbuf_put_string(msg, handle, handle_len)) != 0 || (r = sshbuf_put_u64(msg, offset)) != 0 || (r = sshbuf_put_string(msg, data, len)) != 0) fatal_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); } else if (TAILQ_FIRST(&acks) == NULL) break; if (ack == NULL) fatal("Unexpected ACK %u", id); if (id == startid || len == 0 || id - ackid >= conn->num_requests) { u_int rid; sshbuf_reset(msg); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &rid)) != 0) fatal_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_fr(r, "parse status"); debug3("SSH2_FXP_STATUS %u", status); /* Find the request in our queue */ if ((ack = request_find(&acks, rid)) == NULL) fatal("Can't find request for ID %u", rid); TAILQ_REMOVE(&acks, ack, tq); debug3("In write loop, ack for %u %zu bytes at %lld", ack->id, ack->len, (unsigned long long)ack->offset); ++ackid; progress_counter += ack->len; /* * Track both the highest offset acknowledged and the * highest *contiguous* offset acknowledged. * We'll need the latter for ftruncate()ing * interrupted transfers. */ if (maxack < ack->offset + ack->len) maxack = ack->offset + ack->len; if (!reordered && ack->offset <= highwater) highwater = maxack; else if (!reordered && ack->offset > highwater) { debug3_f("server reordered ACKs"); reordered = 1; } free(ack); } offset += len; if (offset < 0) fatal_f("offset < 0"); } sshbuf_free(msg); if (showprogress) stop_progress_meter(); free(data); if (status == SSH2_FX_OK && !interrupted) { /* we got everything */ highwater = maxack; } if (status != SSH2_FX_OK) { error("write remote \"%s\": %s", remote_path, fx2txt(status)); status = SSH2_FX_FAILURE; } if (inplace_flag || (resume && (status != SSH2_FX_OK || interrupted))) { debug("truncating at %llu", (unsigned long long)highwater); attrib_clear(&t); t.flags = SSH2_FILEXFER_ATTR_SIZE; t.size = highwater; sftp_fsetstat(conn, handle, handle_len, &t); } if (close(local_fd) == -1) { error("close local \"%s\": %s", local_path, strerror(errno)); status = SSH2_FX_FAILURE; } /* Override umask and utimes if asked */ if (preserve_flag) sftp_fsetstat(conn, handle, handle_len, &a); if (fsync_flag) (void)sftp_fsync(conn, handle, handle_len); if (sftp_close(conn, handle, handle_len) != 0) status = SSH2_FX_FAILURE; free(handle); return status == SSH2_FX_OK ? 0 : -1; } static int upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, int depth, int preserve_flag, int print_flag, int resume, int fsync_flag, int follow_link_flag, int inplace_flag) { int ret = 0; DIR *dirp; struct dirent *dp; char *filename, *new_src = NULL, *new_dst = NULL; struct stat sb; Attrib a, dirattrib; u_int32_t saved_perm; debug2_f("upload local dir \"%s\" to remote \"%s\"", src, dst); if (depth >= MAX_DIR_DEPTH) { error("Maximum directory depth exceeded: %d levels", depth); return -1; } if (stat(src, &sb) == -1) { error("stat local \"%s\": %s", src, strerror(errno)); return -1; } if (!S_ISDIR(sb.st_mode)) { error("\"%s\" is not a directory", src); return -1; } if (print_flag && print_flag != SFTP_PROGRESS_ONLY) mprintf("Entering %s\n", src); stat_to_attrib(&sb, &a); a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; a.perm &= 01777; if (!preserve_flag) a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; /* * sftp lacks a portable status value to match errno EEXIST, * so if we get a failure back then we must check whether * the path already existed and is a directory. 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 (sftp_mkdir(conn, dst, &a, 0) != 0) { if (sftp_stat(conn, dst, 0, &dirattrib) != 0) return -1; if (!S_ISDIR(dirattrib.perm)) { error("\"%s\" exists but is not a directory", dst); return -1; } } a.perm = saved_perm; if ((dirp = opendir(src)) == NULL) { error("local opendir \"%s\": %s", src, strerror(errno)); return -1; } while (((dp = readdir(dirp)) != NULL) && !interrupted) { if (dp->d_ino == 0) continue; free(new_dst); free(new_src); filename = dp->d_name; new_dst = sftp_path_append(dst, filename); new_src = sftp_path_append(src, filename); if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) continue; if (lstat(new_src, &sb) == -1) { logit("local lstat \"%s\": %s", filename, strerror(errno)); ret = -1; continue; } if (S_ISLNK(sb.st_mode)) { if (!follow_link_flag) { logit("%s: not a regular file", filename); continue; } /* Replace the stat contents with the symlink target */ if (stat(new_src, &sb) == -1) { logit("local stat \"%s\": %s", filename, strerror(errno)); ret = -1; continue; } } if (S_ISDIR(sb.st_mode)) { if (upload_dir_internal(conn, new_src, new_dst, depth + 1, preserve_flag, print_flag, resume, fsync_flag, follow_link_flag, inplace_flag) == -1) ret = -1; } else if (S_ISREG(sb.st_mode)) { if (sftp_upload(conn, new_src, new_dst, preserve_flag, resume, fsync_flag, inplace_flag) == -1) { error("upload \"%s\" to \"%s\" failed", new_src, new_dst); ret = -1; } } else logit("%s: not a regular file", filename); } free(new_dst); free(new_src); sftp_setstat(conn, dst, &a); (void) closedir(dirp); return ret; } int sftp_upload_dir(struct sftp_conn *conn, const char *src, const char *dst, int preserve_flag, int print_flag, int resume, int fsync_flag, int follow_link_flag, int inplace_flag) { char *dst_canon; int ret; if ((dst_canon = sftp_realpath(conn, dst)) == NULL) { error("upload \"%s\": path canonicalization failed", dst); return -1; } ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, print_flag, resume, fsync_flag, follow_link_flag, inplace_flag); free(dst_canon); return ret; } static void handle_dest_replies(struct sftp_conn *to, const char *to_path, int synchronous, u_int *nreqsp, u_int *write_errorp) { struct sshbuf *msg; u_char type; u_int id, status; int r; struct pollfd pfd; if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); /* Try to eat replies from the upload side */ while (*nreqsp > 0) { debug3_f("%u outstanding replies", *nreqsp); if (!synchronous) { /* Bail out if no data is ready to be read */ pfd.fd = to->fd_in; pfd.events = POLLIN; if ((r = poll(&pfd, 1, 0)) == -1) { if (errno == EINTR) break; fatal_f("poll: %s", strerror(errno)); } else if (r == 0) break; /* fd not ready */ } sshbuf_reset(msg); get_msg(to, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "dest parse"); debug3("Received dest reply T:%u I:%u R:%u", type, id, *nreqsp); if (type != SSH2_FXP_STATUS) { fatal_f("Expected SSH2_FXP_STATUS(%d) packet, got %d", SSH2_FXP_STATUS, type); } if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse dest status"); debug3("dest SSH2_FXP_STATUS %u", status); if (status != SSH2_FX_OK) { /* record first error */ if (*write_errorp == 0) *write_errorp = status; } /* * XXX this doesn't do full reply matching like sftp_upload and * so cannot gracefully truncate terminated uploads at a * high-water mark. ATM the only caller of this function (scp) * doesn't support transfer resumption, so this doesn't matter * a whole lot. * * To be safe, sftp_crossload truncates the destination file to * zero length on upload failure, since we can't trust the * server not to have reordered replies that could have * inserted holes where none existed in the source file. * * XXX we could get a more accutate progress bar if we updated * the counter based on the reply from the destination... */ (*nreqsp)--; } debug3_f("done: %u outstanding replies", *nreqsp); sshbuf_free(msg); } int sftp_crossload(struct sftp_conn *from, struct sftp_conn *to, const char *from_path, const char *to_path, Attrib *a, int preserve_flag) { struct sshbuf *msg; int write_error, read_error, r; u_int64_t offset = 0, size; u_int id, buflen, num_req, max_req, status = SSH2_FX_OK; u_int num_upload_req; off_t progress_counter; u_char *from_handle, *to_handle; size_t from_handle_len, to_handle_len; struct requests requests; struct request *req; u_char type; Attrib attr; debug2_f("crossload src \"%s\" to dst \"%s\"", from_path, to_path); TAILQ_INIT(&requests); if (a == NULL) { if (sftp_stat(from, from_path, 0, &attr) != 0) return -1; a = &attr; } if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && (!S_ISREG(a->perm))) { error("download \"%s\": not a regular file", from_path); return(-1); } if (a->flags & SSH2_FILEXFER_ATTR_SIZE) size = a->size; else size = 0; buflen = from->download_buflen; if (buflen > to->upload_buflen) buflen = to->upload_buflen; /* Send open request to read side */ if (send_open(from, from_path, "origin", SSH2_FXF_READ, NULL, &from_handle, &from_handle_len) != 0) return -1; /* Send open request to write side */ a->flags &= ~SSH2_FILEXFER_ATTR_SIZE; a->flags &= ~SSH2_FILEXFER_ATTR_UIDGID; a->perm &= 0777; if (!preserve_flag) a->flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; if (send_open(to, to_path, "dest", SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a, &to_handle, &to_handle_len) != 0) { sftp_close(from, from_handle, from_handle_len); return -1; } /* Read from remote "from" and write to remote "to" */ offset = 0; write_error = read_error = num_req = num_upload_req = 0; max_req = 1; progress_counter = 0; if (showprogress && size != 0) { start_progress_meter(progress_meter_path(from_path), size, &progress_counter); } if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); while (num_req > 0 || max_req > 0) { u_char *data; size_t len; /* * Simulate EOF on interrupt: stop sending new requests and * allow outstanding requests to drain gracefully */ if (interrupted) { if (num_req == 0) /* If we haven't started yet... */ break; max_req = 0; } /* Send some more requests */ while (num_req < max_req) { debug3("Request range %llu -> %llu (%d/%d)", (unsigned long long)offset, (unsigned long long)offset + buflen - 1, num_req, max_req); req = request_enqueue(&requests, from->msg_id++, buflen, offset); offset += buflen; num_req++; send_read_request(from, req->id, req->offset, req->len, from_handle, from_handle_len); } /* Try to eat replies from the upload side (nonblocking) */ handle_dest_replies(to, to_path, 0, &num_upload_req, &write_error); sshbuf_reset(msg); get_msg(from, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "parse"); debug3("Received origin reply T:%u I:%u R:%d", type, id, max_req); /* Find the request in our queue */ if ((req = request_find(&requests, id)) == NULL) fatal("Unexpected reply %u", id); switch (type) { case SSH2_FXP_STATUS: if ((r = sshbuf_get_u32(msg, &status)) != 0) fatal_fr(r, "parse status"); if (status != SSH2_FX_EOF) read_error = 1; max_req = 0; TAILQ_REMOVE(&requests, req, tq); free(req); num_req--; break; case SSH2_FXP_DATA: if ((r = sshbuf_get_string(msg, &data, &len)) != 0) fatal_fr(r, "parse data"); debug3("Received data %llu -> %llu", (unsigned long long)req->offset, (unsigned long long)req->offset + len - 1); if (len > req->len) fatal("Received more data than asked for " "%zu > %zu", len, req->len); /* Write this chunk out to the destination */ sshbuf_reset(msg); if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || (r = sshbuf_put_u32(msg, to->msg_id++)) != 0 || (r = sshbuf_put_string(msg, to_handle, to_handle_len)) != 0 || (r = sshbuf_put_u64(msg, req->offset)) != 0 || (r = sshbuf_put_string(msg, data, len)) != 0) fatal_fr(r, "compose write"); send_msg(to, msg); debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%zu", id, (unsigned long long)offset, len); num_upload_req++; progress_counter += len; free(data); if (len == req->len) { TAILQ_REMOVE(&requests, req, tq); free(req); num_req--; } else { /* Resend the request for the missing data */ debug3("Short data block, re-requesting " "%llu -> %llu (%2d)", (unsigned long long)req->offset + len, (unsigned long long)req->offset + req->len - 1, num_req); req->id = from->msg_id++; req->len -= len; req->offset += len; send_read_request(from, req->id, req->offset, req->len, from_handle, from_handle_len); /* Reduce the request size */ if (len < buflen) buflen = MAXIMUM(MIN_READ_SIZE, len); } if (max_req > 0) { /* max_req = 0 iff EOF received */ if (size > 0 && offset > size) { /* Only one request at a time * after the expected EOF */ debug3("Finish at %llu (%2d)", (unsigned long long)offset, num_req); max_req = 1; } else if (max_req < from->num_requests) { ++max_req; } } break; default: fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", SSH2_FXP_DATA, type); } } if (showprogress && size) stop_progress_meter(); /* Drain replies from the server (blocking) */ debug3_f("waiting for %u replies from destination", num_upload_req); handle_dest_replies(to, to_path, 1, &num_upload_req, &write_error); /* Sanity check */ if (TAILQ_FIRST(&requests) != NULL) fatal("Transfer complete, but requests still in queue"); /* Truncate at 0 length on interrupt or error to avoid holes at dest */ if (read_error || write_error || interrupted) { debug("truncating \"%s\" at 0", to_path); sftp_close(to, to_handle, to_handle_len); free(to_handle); if (send_open(to, to_path, "dest", SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a, &to_handle, &to_handle_len) != 0) { error("dest truncate \"%s\" failed", to_path); to_handle = NULL; } } if (read_error) { error("read origin \"%s\": %s", from_path, fx2txt(status)); status = -1; sftp_close(from, from_handle, from_handle_len); if (to_handle != NULL) sftp_close(to, to_handle, to_handle_len); } else if (write_error) { error("write dest \"%s\": %s", to_path, fx2txt(write_error)); status = SSH2_FX_FAILURE; sftp_close(from, from_handle, from_handle_len); if (to_handle != NULL) sftp_close(to, to_handle, to_handle_len); } else { if (sftp_close(from, from_handle, from_handle_len) != 0 || interrupted) status = -1; else status = SSH2_FX_OK; if (to_handle != NULL) { /* Need to resend utimes after write */ if (preserve_flag) sftp_fsetstat(to, to_handle, to_handle_len, a); sftp_close(to, to_handle, to_handle_len); } } sshbuf_free(msg); free(from_handle); free(to_handle); return status == SSH2_FX_OK ? 0 : -1; } static int crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to, const char *from_path, const char *to_path, int depth, Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag) { int i, ret = 0; SFTP_DIRENT **dir_entries; char *filename, *new_from_path = NULL, *new_to_path = NULL; mode_t mode = 0777; Attrib *a, curdir, ldirattrib, newdir, lsym; debug2_f("crossload dir src \"%s\" to dst \"%s\"", from_path, to_path); if (depth >= MAX_DIR_DEPTH) { error("Maximum directory depth exceeded: %d levels", depth); return -1; } if (dirattrib == NULL) { if (sftp_stat(from, from_path, 1, &ldirattrib) != 0) { error("stat remote \"%s\" failed", from_path); return -1; } dirattrib = &ldirattrib; } if (!S_ISDIR(dirattrib->perm)) { error("\"%s\" is not a directory", from_path); return -1; } if (print_flag && print_flag != SFTP_PROGRESS_ONLY) mprintf("Retrieving %s\n", from_path); curdir = *dirattrib; /* dirattrib will be clobbered */ curdir.flags &= ~SSH2_FILEXFER_ATTR_SIZE; curdir.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; if ((curdir.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) == 0) { debug("Origin did not send permissions for " "directory \"%s\"", to_path); curdir.perm = S_IWUSR|S_IXUSR; curdir.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; } /* We need to be able to write to the directory while we transfer it */ mode = curdir.perm & 01777; curdir.perm = mode | (S_IWUSR|S_IXUSR); /* * 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. Ensure we can * write to the directory we create for the duration of the transfer. */ if (sftp_mkdir(to, to_path, &curdir, 0) != 0) { if (sftp_stat(to, to_path, 0, &newdir) != 0) return -1; if (!S_ISDIR(newdir.perm)) { error("\"%s\" exists but is not a directory", to_path); return -1; } } curdir.perm = mode; if (sftp_readdir(from, from_path, &dir_entries) == -1) { error("origin readdir \"%s\" failed", from_path); return -1; } for (i = 0; dir_entries[i] != NULL && !interrupted; i++) { free(new_from_path); free(new_to_path); filename = dir_entries[i]->filename; new_from_path = sftp_path_append(from_path, filename); new_to_path = sftp_path_append(to_path, filename); a = &dir_entries[i]->a; if (S_ISLNK(a->perm)) { if (!follow_link_flag) { logit("%s: not a regular file", filename); continue; } /* Replace the stat contents with the symlink target */ if (sftp_stat(from, new_from_path, 1, &lsym) != 0) { logit("remote stat \"%s\" failed", new_from_path); ret = -1; continue; } a = &lsym; } if (S_ISDIR(a->perm)) { if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) continue; if (crossload_dir_internal(from, to, new_from_path, new_to_path, depth + 1, a, preserve_flag, print_flag, follow_link_flag) == -1) ret = -1; } else if (S_ISREG(a->perm)) { if (sftp_crossload(from, to, new_from_path, new_to_path, a, preserve_flag) == -1) { error("crossload \"%s\" to \"%s\" failed", new_from_path, new_to_path); ret = -1; } } else { logit("origin \"%s\": not a regular file", new_from_path); } } free(new_to_path); free(new_from_path); sftp_setstat(to, to_path, &curdir); sftp_free_dirents(dir_entries); return ret; } int sftp_crossload_dir(struct sftp_conn *from, struct sftp_conn *to, const char *from_path, const char *to_path, Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag) { char *from_path_canon; int ret; if ((from_path_canon = sftp_realpath(from, from_path)) == NULL) { error("crossload \"%s\": path canonicalization failed", from_path); return -1; } ret = crossload_dir_internal(from, to, from_path_canon, to_path, 0, dirattrib, preserve_flag, print_flag, follow_link_flag); free(from_path_canon); return ret; } int sftp_can_get_users_groups_by_id(struct sftp_conn *conn) { return (conn->exts & SFTP_EXT_GETUSERSGROUPS_BY_ID) != 0; } int sftp_get_users_groups_by_id(struct sftp_conn *conn, const u_int *uids, u_int nuids, const u_int *gids, u_int ngids, char ***usernamesp, char ***groupnamesp) { struct sshbuf *msg, *uidbuf, *gidbuf; u_int i, expected_id, id; char *name, **usernames = NULL, **groupnames = NULL; u_char type; int r; *usernamesp = *groupnamesp = NULL; if (!sftp_can_get_users_groups_by_id(conn)) return SSH_ERR_FEATURE_UNSUPPORTED; if ((msg = sshbuf_new()) == NULL || (uidbuf = sshbuf_new()) == NULL || (gidbuf = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); expected_id = id = conn->msg_id++; debug2("Sending SSH2_FXP_EXTENDED(users-groups-by-id@openssh.com)"); for (i = 0; i < nuids; i++) { if ((r = sshbuf_put_u32(uidbuf, uids[i])) != 0) fatal_fr(r, "compose uids"); } for (i = 0; i < ngids; i++) { if ((r = sshbuf_put_u32(gidbuf, gids[i])) != 0) fatal_fr(r, "compose gids"); } if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || (r = sshbuf_put_u32(msg, id)) != 0 || (r = sshbuf_put_cstring(msg, "users-groups-by-id@openssh.com")) != 0 || (r = sshbuf_put_stringb(msg, uidbuf)) != 0 || (r = sshbuf_put_stringb(msg, gidbuf)) != 0) fatal_fr(r, "compose"); send_msg(conn, msg); get_msg(conn, msg); if ((r = sshbuf_get_u8(msg, &type)) != 0 || (r = sshbuf_get_u32(msg, &id)) != 0) fatal_fr(r, "parse"); if (id != expected_id) fatal("ID mismatch (%u != %u)", id, expected_id); if (type == SSH2_FXP_STATUS) { u_int status; char *errmsg; if ((r = sshbuf_get_u32(msg, &status)) != 0 || (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) fatal_fr(r, "parse status"); error("users-groups-by-id %s", *errmsg == '\0' ? fx2txt(status) : errmsg); free(errmsg); sshbuf_free(msg); sshbuf_free(uidbuf); sshbuf_free(gidbuf); return -1; } else if (type != SSH2_FXP_EXTENDED_REPLY) fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", SSH2_FXP_EXTENDED_REPLY, type); /* reuse */ sshbuf_free(uidbuf); sshbuf_free(gidbuf); uidbuf = gidbuf = NULL; if ((r = sshbuf_froms(msg, &uidbuf)) != 0 || (r = sshbuf_froms(msg, &gidbuf)) != 0) fatal_fr(r, "parse response"); if (nuids > 0) { usernames = xcalloc(nuids, sizeof(*usernames)); for (i = 0; i < nuids; i++) { if ((r = sshbuf_get_cstring(uidbuf, &name, NULL)) != 0) fatal_fr(r, "parse user name"); /* Handle unresolved names */ if (*name == '\0') { free(name); name = NULL; } usernames[i] = name; } } if (ngids > 0) { groupnames = xcalloc(ngids, sizeof(*groupnames)); for (i = 0; i < ngids; i++) { if ((r = sshbuf_get_cstring(gidbuf, &name, NULL)) != 0) fatal_fr(r, "parse user name"); /* Handle unresolved names */ if (*name == '\0') { free(name); name = NULL; } groupnames[i] = name; } } if (sshbuf_len(uidbuf) != 0) fatal_f("unexpected extra username data"); if (sshbuf_len(gidbuf) != 0) fatal_f("unexpected extra groupname data"); sshbuf_free(uidbuf); sshbuf_free(gidbuf); sshbuf_free(msg); /* success */ *usernamesp = usernames; *groupnamesp = groupnames; return 0; } char * sftp_path_append(const char *p1, const char *p2) { char *ret; size_t len = strlen(p1) + strlen(p2) + 2; ret = xmalloc(len); strlcpy(ret, p1, len); if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/') strlcat(ret, "/", len); strlcat(ret, p2, len); return(ret); } /* * Arg p must be dynamically allocated. It will either be returned or * freed and a replacement allocated. Caller must free returned string. */ char * sftp_make_absolute(char *p, const char *pwd) { char *abs_str; /* Derelativise */ if (p && !path_absolute(p)) { abs_str = sftp_path_append(pwd, p); free(p); return(abs_str); } else return(p); } int sftp_remote_is_dir(struct sftp_conn *conn, const char *path) { Attrib a; /* XXX: report errors? */ if (sftp_stat(conn, path, 1, &a) != 0) 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 */ int sftp_globpath_is_dir(const char *pathname) { size_t l = strlen(pathname); return l > 0 && pathname[l - 1] == '/'; } diff --git a/crypto/openssh/ssh-add.1 b/crypto/openssh/ssh-add.1 index 4601f5981cd3..f0186cd5fd71 100644 --- a/crypto/openssh/ssh-add.1 +++ b/crypto/openssh/ssh-add.1 @@ -1,342 +1,350 @@ -.\" $OpenBSD: ssh-add.1,v 1.84 2022/02/04 02:49:17 dtucker Exp $ +.\" $OpenBSD: ssh-add.1,v 1.85 2023/12/18 14:46:56 djm Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland .\" All rights reserved .\" .\" As far as I am concerned, the code I have written for this software .\" can be used freely for any purpose. Any derived versions of this .\" software must be clearly marked as such, and if the derived work is .\" incompatible with the protocol description in the RFC file, it must be .\" called by a name other than "ssh" or "Secure Shell". .\" .\" .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: February 4 2022 $ +.Dd $Mdocdate: December 18 2023 $ .Dt SSH-ADD 1 .Os .Sh NAME .Nm ssh-add .Nd adds private key identities to the OpenSSH authentication agent .Sh SYNOPSIS .Nm ssh-add -.Op Fl cDdKkLlqvXx +.Op Fl cCDdKkLlqvXx .Op Fl E Ar fingerprint_hash .Op Fl H Ar hostkey_file .Op Fl h Ar destination_constraint .Op Fl S Ar provider .Op Fl t Ar life .Op Ar .Nm ssh-add .Fl s Ar pkcs11 +.Op Fl vC +.Op Ar certificate ... .Nm ssh-add .Fl e Ar pkcs11 .Nm ssh-add .Fl T .Ar pubkey ... .Sh DESCRIPTION .Nm adds private key identities to the authentication agent, .Xr ssh-agent 1 . When run without arguments, it adds the files .Pa ~/.ssh/id_rsa , .Pa ~/.ssh/id_ecdsa , .Pa ~/.ssh/id_ecdsa_sk , .Pa ~/.ssh/id_ed25519 , .Pa ~/.ssh/id_ed25519_sk , and .Pa ~/.ssh/id_dsa . After loading a private key, .Nm will try to load corresponding certificate information from the filename obtained by appending .Pa -cert.pub to the name of the private key file. Alternative file names can be given on the command line. .Pp If any file requires a passphrase, .Nm asks for the passphrase from the user. The passphrase is read from the user's tty. .Nm retries the last passphrase if multiple identity files are given. .Pp The authentication agent must be running and the .Ev SSH_AUTH_SOCK environment variable must contain the name of its socket for .Nm to work. .Pp The options are as follows: .Bl -tag -width Ds .It Fl c Indicates that added identities should be subject to confirmation before being used for authentication. Confirmation is performed by .Xr ssh-askpass 1 . Successful confirmation is signaled by a zero exit status from .Xr ssh-askpass 1 , rather than text entered into the requester. +.It Fl C +When loading keys into or deleting keys from the agent, process +certificates only and skip plain keys. .It Fl D Deletes all identities from the agent. .It Fl d Instead of adding identities, removes identities from the agent. If .Nm has been run without arguments, the keys for the default identities and their corresponding certificates will be removed. Otherwise, the argument list will be interpreted as a list of paths to public key files to specify keys and certificates to be removed from the agent. If no public key is found at a given path, .Nm will append .Pa .pub and retry. 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: .Dq md5 and .Dq sha256 . The default is .Dq sha256 . .It Fl e Ar pkcs11 Remove keys provided by the PKCS#11 shared library .Ar pkcs11 . .It Fl H Ar hostkey_file Specifies a known hosts file to look up hostkeys when using destination-constrained keys via the .Fl h flag. This option may be specified multiple times to allow multiple files to be searched. If no files are specified, .Nm will use the default .Xr ssh_config 5 known hosts files: .Pa ~/.ssh/known_hosts , .Pa ~/.ssh/known_hosts2 , .Pa /etc/ssh/ssh_known_hosts , and .Pa /etc/ssh/ssh_known_hosts2 . .It Fl h Ar destination_constraint When adding keys, constrain them to be usable only through specific hosts or to specific destinations. .Pp Destination constraints of the form .Sq [user@]dest-hostname permit use of the key only from the origin host (the one running .Xr ssh-agent 1 ) to the listed destination host, with optional user name. .Pp Constraints of the form .Sq src-hostname>[user@]dst-hostname allow a key available on a forwarded .Xr ssh-agent 1 to be used through a particular host (as specified by .Sq src-hostname ) to authenticate to a further host, specified by .Sq dst-hostname . .Pp Multiple destination constraints may be added when loading keys. When attempting authentication with a key that has destination constraints, the whole connection path, including .Xr ssh-agent 1 forwarding, is tested against those constraints and each hop must be permitted for the attempt to succeed. For example, if key is forwarded to a remote host, .Sq host-b , and is attempting authentication to another host, .Sq host-c , then the operation will be successful only if .Sq host-b was permitted from the origin host and the subsequent .Sq host-b>host-c hop is also permitted by destination constraints. .Pp Hosts are identified by their host keys, and are looked up from known hosts files by .Nm . Wildcards patterns may be used for hostnames and certificate host keys are supported. By default, keys added by .Nm are not destination constrained. .Pp Destination constraints were added in OpenSSH release 8.9. Support in both the remote SSH client and server is required when using destination-constrained keys over a forwarded .Xr ssh-agent 1 channel. .Pp It is also important to note that destination constraints can only be enforced by .Xr ssh-agent 1 when a key is used, or when it is forwarded by a .Sy cooperating .Xr ssh 1 . Specifically, it does not prevent an attacker with access to a remote .Ev SSH_AUTH_SOCK from forwarding it again and using it on a different host (but only to a permitted destination). .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. .It Fl L Lists public key parameters of all identities currently represented by the agent. .It Fl l Lists fingerprints of all identities currently represented by the agent. .It Fl q Be quiet after a successful operation. .It Fl S Ar 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 . +Certificate files may optionally be listed as command-line arguments. +If these are present, then they will be loaded into the agent using any +corresponding private keys loaded from the PKCS#11 token. .It Fl T Ar pubkey ... Tests whether the private keys that correspond to the specified .Ar pubkey files are usable by performing sign and verify operations on each. .It Fl t Ar life Set a maximum lifetime when adding identities to an agent. The lifetime may be specified in seconds or in a time format specified in .Xr sshd_config 5 . .It Fl v Verbose mode. Causes .Nm to print debugging messages about its progress. This is helpful in debugging problems. Multiple .Fl v options increase the verbosity. The maximum is 3. .It Fl X Unlock the agent. .It Fl x Lock the agent with a password. .El .Sh ENVIRONMENT .Bl -tag -width Ds .It Ev "DISPLAY", "SSH_ASKPASS" and "SSH_ASKPASS_REQUIRE" If .Nm needs a passphrase, it will read the passphrase from the current terminal if it was run from a terminal. If .Nm does not have a terminal associated with it but .Ev DISPLAY and .Ev SSH_ASKPASS are set, it will execute the program specified by .Ev SSH_ASKPASS (by default .Dq ssh-askpass ) and open an X11 window to read the passphrase. This is particularly useful when calling .Nm from a .Pa .xsession or related script. .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 -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, 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. Note that .Nm ignores identity files if they are accessible by others. .Sh EXIT STATUS Exit status is 0 on success, 1 if the specified command fails, and 2 if .Nm is unable to contact the authentication agent. .Sh SEE ALSO .Xr ssh 1 , .Xr ssh-agent 1 , .Xr ssh-askpass 1 , .Xr ssh-keygen 1 , .Xr sshd 8 .Sh AUTHORS OpenSSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt and Dug Song removed many bugs, re-added newer features and created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. diff --git a/crypto/openssh/ssh-add.c b/crypto/openssh/ssh-add.c index 775a9a8efcd7..99ba23b525e5 100644 --- a/crypto/openssh/ssh-add.c +++ b/crypto/openssh/ssh-add.c @@ -1,1017 +1,1053 @@ -/* $OpenBSD: ssh-add.c,v 1.168 2023/07/06 22:17:59 dtucker Exp $ */ +/* $OpenBSD: ssh-add.c,v 1.169 2023/12/18 14:46:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Adds an identity to the authentication server, or removes an identity. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * SSH2 implementation, * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #ifdef WITH_OPENSSL # include # include "openbsd-compat/openssl-compat.h" #endif #include #include #include #include #include #include #include #include #include #include "xmalloc.h" #include "ssh.h" #include "log.h" #include "sshkey.h" #include "sshbuf.h" #include "authfd.h" #include "authfile.h" #include "pathnames.h" #include "misc.h" #include "ssherr.h" #include "digest.h" #include "ssh-sk.h" #include "sk-api.h" #include "hostfile.h" /* argv0 */ extern char *__progname; /* Default files to add */ static char *default_files[] = { #ifdef WITH_OPENSSL _PATH_SSH_CLIENT_ID_RSA, #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, _PATH_SSH_CLIENT_ID_DSA, NULL }; static int fingerprint_hash = SSH_FP_HASH_DEFAULT; /* Default lifetime (0 == forever) */ static int lifetime = 0; /* User has to confirm key use */ static int confirm = 0; /* Maximum number of signatures (XMSS) */ static u_int maxsign = 0; static u_int minleft = 0; /* we keep a cache of one passphrase */ static char *pass = NULL; static void clear_pass(void) { if (pass) { 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 ? comment : "no comment"); } return 0; } static int -delete_stdin(int agent_fd, int qflag) +delete_stdin(int agent_fd, int qflag, int key_only, int cert_only) { 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; + if ((!key_only && !cert_only) || + (key_only && !sshkey_is_cert(key)) || + (cert_only && sshkey_is_cert(key))) { + 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) +delete_file(int agent_fd, const char *filename, int key_only, + int cert_only, int qflag) { struct sshkey *public, *cert = NULL; char *certpath = NULL, *comment = NULL; int r, ret = -1; if (strcmp(filename, "-") == 0) - return delete_stdin(agent_fd, qflag); + return delete_stdin(agent_fd, qflag, key_only, cert_only); if ((r = sshkey_load_public(filename, &public, &comment)) != 0) { printf("Bad key file %s: %s\n", filename, ssh_err(r)); return -1; } - if (delete_one(agent_fd, public, comment, filename, qflag) == 0) - ret = 0; + if ((!key_only && !cert_only) || + (key_only && !sshkey_is_cert(public)) || + (cert_only && sshkey_is_cert(public))) { + if (delete_one(agent_fd, public, comment, filename, qflag) == 0) + ret = 0; + } if (key_only) goto out; /* Now try to delete the corresponding certificate too */ free(comment); comment = NULL; xasprintf(&certpath, "%s-cert.pub", filename); if ((r = sshkey_load_public(certpath, &cert, &comment)) != 0) { if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT) error_r(r, "Failed to load certificate \"%s\"", certpath); goto out; } if (!sshkey_equal_public(cert, public)) fatal("Certificate %s does not match private key %s", certpath, filename); if (delete_one(agent_fd, cert, comment, certpath, qflag) == 0) ret = 0; out: sshkey_free(cert); sshkey_free(public); free(certpath); free(comment); return ret; } /* Send a request to remove all identities. */ static int delete_all(int agent_fd, int qflag) { int ret = -1; /* * Since the agent might be forwarded, old or non-OpenSSH, when asked * to remove all keys, attempt to remove both protocol v.1 and v.2 * keys. */ if (ssh_remove_all_identities(agent_fd, 2) == 0) ret = 0; /* ignore error-code for ssh1 */ ssh_remove_all_identities(agent_fd, 1); if (ret != 0) fprintf(stderr, "Failed to remove all identities.\n"); else if (!qflag) fprintf(stderr, "All identities removed.\n"); return ret; } static int -add_file(int agent_fd, const char *filename, int key_only, int qflag, - const char *skprovider, struct dest_constraint **dest_constraints, +add_file(int agent_fd, const char *filename, int key_only, int cert_only, + int qflag, const char *skprovider, + struct dest_constraint **dest_constraints, size_t ndest_constraints) { struct sshkey *private, *cert; char *comment = NULL; char msg[1024], *certpath = NULL; int r, fd, ret = -1; size_t i; u_int32_t left; struct sshbuf *keyblob; struct ssh_identitylist *idlist; if (strcmp(filename, "-") == 0) { fd = STDIN_FILENO; filename = "(stdin)"; } else if ((fd = open(filename, O_RDONLY)) == -1) { perror(filename); return -1; } /* * Since we'll try to load a keyfile multiple times, permission errors * will occur multiple times, so check perms first and bail if wrong. */ if (fd != STDIN_FILENO) { if (sshkey_perm_ok(fd, filename) != 0) { close(fd); return -1; } } if ((r = sshbuf_load_fd(fd, &keyblob)) != 0) { fprintf(stderr, "Error loading key \"%s\": %s\n", filename, ssh_err(r)); sshbuf_free(keyblob); close(fd); return -1; } close(fd); /* At first, try empty passphrase */ if ((r = sshkey_parse_private_fileblob(keyblob, "", &private, &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) { fprintf(stderr, "Error loading key \"%s\": %s\n", filename, ssh_err(r)); goto fail_load; } /* try last */ if (private == NULL && pass != NULL) { if ((r = sshkey_parse_private_fileblob(keyblob, pass, &private, &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE) { fprintf(stderr, "Error loading key \"%s\": %s\n", filename, ssh_err(r)); goto fail_load; } } if (private == NULL) { /* clear passphrase since it did not work */ clear_pass(); snprintf(msg, sizeof msg, "Enter passphrase for %s%s: ", filename, confirm ? " (will confirm each use)" : ""); for (;;) { pass = read_passphrase(msg, RP_ALLOW_STDIN); if (strcmp(pass, "") == 0) goto fail_load; if ((r = sshkey_parse_private_fileblob(keyblob, pass, &private, &comment)) == 0) break; else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) { fprintf(stderr, "Error loading key \"%s\": %s\n", filename, ssh_err(r)); fail_load: clear_pass(); sshbuf_free(keyblob); return -1; } clear_pass(); snprintf(msg, sizeof msg, "Bad passphrase, try again for %s%s: ", filename, confirm ? " (will confirm each use)" : ""); } } if (comment == NULL || *comment == '\0') comment = xstrdup(filename); sshbuf_free(keyblob); /* For XMSS */ if ((r = sshkey_set_filename(private, filename)) != 0) { fprintf(stderr, "Could not add filename to private key: %s (%s)\n", filename, comment); goto out; } if (maxsign && minleft && (r = ssh_fetch_identitylist(agent_fd, &idlist)) == 0) { for (i = 0; i < idlist->nkeys; i++) { if (!sshkey_equal_public(idlist->keys[i], private)) continue; left = sshkey_signatures_left(idlist->keys[i]); if (left < minleft) { fprintf(stderr, "Only %d signatures left.\n", left); break; } fprintf(stderr, "Skipping update: "); if (left == minleft) { fprintf(stderr, "required signatures left (%d).\n", left); } else { fprintf(stderr, "more signatures left (%d) than" " required (%d).\n", left, minleft); } ssh_free_identitylist(idlist); goto out; } ssh_free_identitylist(idlist); } if (sshkey_is_sk(private)) { if (skprovider == NULL) { fprintf(stderr, "Cannot load FIDO key %s " "without provider\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, + if (!cert_only && + (r = ssh_add_identity_constrained(agent_fd, private, comment, lifetime, confirm, maxsign, skprovider, dest_constraints, ndest_constraints)) == 0) { ret = 0; if (!qflag) { fprintf(stderr, "Identity added: %s (%s)\n", filename, comment); if (lifetime != 0) { fprintf(stderr, "Lifetime set to %d seconds\n", lifetime); } if (confirm != 0) { fprintf(stderr, "The user must confirm " "each use of the key\n"); } } } else { fprintf(stderr, "Could not add identity \"%s\": %s\n", filename, ssh_err(r)); } /* Skip trying to load the cert if requested */ if (key_only) goto out; /* Now try to add the certificate flavour too */ xasprintf(&certpath, "%s-cert.pub", filename); if ((r = sshkey_load_public(certpath, &cert, NULL)) != 0) { if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT) - error_r(r, "Failed to load certificate \"%s\"", certpath); + error_r(r, "Failed to load certificate \"%s\"", + certpath); goto out; } if (!sshkey_equal_public(cert, private)) { error("Certificate %s does not match private key %s", certpath, filename); sshkey_free(cert); goto out; } /* Graft with private bits */ if ((r = sshkey_to_certified(private)) != 0) { error_fr(r, "sshkey_to_certified"); sshkey_free(cert); goto out; } if ((r = sshkey_cert_copy(cert, private)) != 0) { 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, skprovider, dest_constraints, ndest_constraints)) != 0) { error_r(r, "Certificate %s (%s) add failed", certpath, private->cert->key_id); goto out; } /* success */ if (!qflag) { fprintf(stderr, "Certificate added: %s (%s)\n", certpath, private->cert->key_id); if (lifetime != 0) { fprintf(stderr, "Lifetime set to %d seconds\n", lifetime); } if (confirm != 0) { fprintf(stderr, "The user must confirm each use " "of the key\n"); } } out: free(certpath); free(comment); sshkey_free(private); return ret; } static int update_card(int agent_fd, int add, const char *id, int qflag, - struct dest_constraint **dest_constraints, size_t ndest_constraints) + int key_only, int cert_only, + struct dest_constraint **dest_constraints, size_t ndest_constraints, + struct sshkey **certs, size_t ncerts) { char *pin = NULL; int r, ret = -1; + if (key_only) + ncerts = 0; + if (add) { if ((pin = read_passphrase("Enter passphrase for PKCS#11: ", RP_ALLOW_STDIN)) == NULL) return -1; } if ((r = ssh_update_card(agent_fd, add, id, pin == NULL ? "" : pin, - lifetime, confirm, dest_constraints, ndest_constraints)) == 0) { + lifetime, confirm, dest_constraints, ndest_constraints, + cert_only, certs, ncerts)) == 0) { ret = 0; if (!qflag) { fprintf(stderr, "Card %s: %s\n", add ? "added" : "removed", id); } } else { fprintf(stderr, "Could not %s card \"%s\": %s\n", add ? "add" : "remove", id, ssh_err(r)); ret = -1; } free(pin); return ret; } static int test_key(int agent_fd, const char *filename) { struct sshkey *key = NULL; u_char *sig = NULL; const char *alg = NULL; size_t slen = 0; int r, ret = -1; char data[1024]; if ((r = sshkey_load_public(filename, &key, NULL)) != 0) { error_r(r, "Couldn't read public key %s", filename); return -1; } if (sshkey_type_plain(key->type) == KEY_RSA) alg = "rsa-sha2-256"; arc4random_buf(data, sizeof(data)); if ((r = ssh_agent_sign(agent_fd, key, &sig, &slen, data, sizeof(data), alg, 0)) != 0) { error_r(r, "Agent signature failed for %s", filename); goto done; } if ((r = sshkey_verify(key, sig, slen, data, sizeof(data), alg, 0, NULL)) != 0) { error_r(r, "Signature verification failed for %s", filename); goto done; } /* success */ ret = 0; done: free(sig); sshkey_free(key); return ret; } static int list_identities(int agent_fd, int do_fp) { char *fp; int r; struct ssh_identitylist *idlist; u_int32_t left; size_t i; if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) { if (r != SSH_ERR_AGENT_NO_IDENTITIES) fprintf(stderr, "error fetching identities: %s\n", ssh_err(r)); else printf("The agent has no identities.\n"); return -1; } for (i = 0; i < idlist->nkeys; i++) { if (do_fp) { fp = sshkey_fingerprint(idlist->keys[i], fingerprint_hash, SSH_FP_DEFAULT); printf("%u %s %s (%s)\n", sshkey_size(idlist->keys[i]), fp == NULL ? "(null)" : fp, idlist->comments[i], sshkey_type(idlist->keys[i])); free(fp); } else { if ((r = sshkey_write(idlist->keys[i], stdout)) != 0) { fprintf(stderr, "sshkey_write: %s\n", ssh_err(r)); continue; } fprintf(stdout, " %s", idlist->comments[i]); left = sshkey_signatures_left(idlist->keys[i]); if (left > 0) fprintf(stdout, " [signatures left %d]", left); fprintf(stdout, "\n"); } } ssh_free_identitylist(idlist); return 0; } static int lock_agent(int agent_fd, int lock) { char prompt[100], *p1, *p2; int r, passok = 1, ret = -1; strlcpy(prompt, "Enter lock password: ", sizeof(prompt)); p1 = read_passphrase(prompt, RP_ALLOW_STDIN); if (lock) { strlcpy(prompt, "Again: ", sizeof prompt); p2 = read_passphrase(prompt, RP_ALLOW_STDIN); if (strcmp(p1, p2) != 0) { fprintf(stderr, "Passwords do not match.\n"); passok = 0; } freezero(p2, strlen(p2)); } if (passok) { if ((r = ssh_lock_agent(agent_fd, lock, p1)) == 0) { fprintf(stderr, "Agent %slocked.\n", lock ? "" : "un"); ret = 0; } else { fprintf(stderr, "Failed to %slock agent: %s\n", lock ? "" : "un", ssh_err(r)); } } freezero(p1, strlen(p1)); return (ret); } static int load_resident_keys(int agent_fd, const char *skprovider, int qflag, struct dest_constraint **dest_constraints, size_t ndest_constraints) { struct sshsk_resident_key **srks; size_t nsrks, i; struct sshkey *key; int r, ok = 0; char *fp; pass = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN); if ((r = sshsk_load_resident(skprovider, NULL, pass, 0, &srks, &nsrks)) != 0) { error_r(r, "Unable to load resident keys"); return r; } for (i = 0; i < nsrks; i++) { key = srks[i]->key; if ((fp = sshkey_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal_f("sshkey_fingerprint failed"); if ((r = ssh_add_identity_constrained(agent_fd, key, "", lifetime, confirm, maxsign, skprovider, dest_constraints, ndest_constraints)) != 0) { error("Unable to add key %s %s", sshkey_type(key), fp); free(fp); ok = r; continue; } if (ok == 0) ok = 1; if (!qflag) { fprintf(stderr, "Resident identity added: %s %s\n", sshkey_type(key), 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); } sshsk_free_resident_keys(srks, nsrks); if (nsrks == 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, struct dest_constraint **dest_constraints, - size_t ndest_constraints) +do_file(int agent_fd, int deleting, int key_only, int cert_only, + char *file, int qflag, const char *skprovider, + struct dest_constraint **dest_constraints, size_t ndest_constraints) { if (deleting) { - if (delete_file(agent_fd, file, key_only, qflag) == -1) + if (delete_file(agent_fd, file, key_only, + cert_only, qflag) == -1) return -1; } else { - if (add_file(agent_fd, file, key_only, qflag, skprovider, - dest_constraints, ndest_constraints) == -1) + if (add_file(agent_fd, file, key_only, cert_only, qflag, + skprovider, dest_constraints, ndest_constraints) == -1) return -1; } return 0; } /* Append string 's' to a NULL-terminated array of strings */ static void stringlist_append(char ***listp, const char *s) { size_t i = 0; if (*listp == NULL) *listp = xcalloc(2, sizeof(**listp)); else { for (i = 0; (*listp)[i] != NULL; i++) ; /* count */ *listp = xrecallocarray(*listp, i + 1, i + 2, sizeof(**listp)); } (*listp)[i] = xstrdup(s); } static void parse_dest_constraint_hop(const char *s, struct dest_constraint_hop *dch, char **hostkey_files) { char *user = NULL, *host, *os, *path; size_t i; struct hostkeys *hostkeys; const struct hostkey_entry *hke; int r, want_ca; memset(dch, '\0', sizeof(*dch)); os = xstrdup(s); if ((host = strchr(os, '@')) == NULL) host = os; else { *host++ = '\0'; user = os; } cleanhostname(host); /* Trivial case: username@ (all hosts) */ if (*host == '\0') { if (user == NULL) { fatal("Invalid key destination constraint \"%s\": " "does not specify user or host", s); } dch->user = xstrdup(user); /* other fields left blank */ free(os); return; } if (hostkey_files == NULL) fatal_f("no hostkey files"); /* Otherwise we need to look up the keys for this hostname */ hostkeys = init_hostkeys(); for (i = 0; hostkey_files[i]; i++) { path = tilde_expand_filename(hostkey_files[i], getuid()); debug2_f("looking up host keys for \"%s\" in %s", host, path); load_hostkeys(hostkeys, host, path, 0); free(path); } dch->user = user == NULL ? NULL : xstrdup(user); dch->hostname = xstrdup(host); for (i = 0; i < hostkeys->num_entries; i++) { hke = hostkeys->entries + i; want_ca = hke->marker == MRK_CA; if (hke->marker != MRK_NONE && !want_ca) continue; debug3_f("%s%s%s: adding %s %skey from %s:%lu as key %u", user == NULL ? "": user, user == NULL ? "" : "@", host, sshkey_type(hke->key), want_ca ? "CA " : "", hke->file, hke->line, dch->nkeys); dch->keys = xrecallocarray(dch->keys, dch->nkeys, dch->nkeys + 1, sizeof(*dch->keys)); dch->key_is_ca = xrecallocarray(dch->key_is_ca, dch->nkeys, dch->nkeys + 1, sizeof(*dch->key_is_ca)); if ((r = sshkey_from_private(hke->key, &(dch->keys[dch->nkeys]))) != 0) fatal_fr(r, "sshkey_from_private"); dch->key_is_ca[dch->nkeys] = want_ca; dch->nkeys++; } if (dch->nkeys == 0) fatal("No host keys found for destination \"%s\"", host); free_hostkeys(hostkeys); free(os); return; } static void parse_dest_constraint(const char *s, struct dest_constraint ***dcp, size_t *ndcp, char **hostkey_files) { struct dest_constraint *dc; char *os, *cp; dc = xcalloc(1, sizeof(*dc)); os = xstrdup(s); if ((cp = strchr(os, '>')) == NULL) { /* initial hop; no 'from' hop specified */ parse_dest_constraint_hop(os, &dc->to, hostkey_files); } else { /* two hops specified */ *(cp++) = '\0'; parse_dest_constraint_hop(os, &dc->from, hostkey_files); parse_dest_constraint_hop(cp, &dc->to, hostkey_files); if (dc->from.user != NULL) { fatal("Invalid key constraint %s: cannot specify " "user on 'from' host", os); } } /* XXX eliminate or error on duplicates */ debug2_f("constraint %zu: %s%s%s (%u keys) > %s%s%s (%u keys)", *ndcp, dc->from.user ? dc->from.user : "", dc->from.user ? "@" : "", dc->from.hostname ? dc->from.hostname : "(ORIGIN)", dc->from.nkeys, dc->to.user ? dc->to.user : "", dc->to.user ? "@" : "", dc->to.hostname ? dc->to.hostname : "(ANY)", dc->to.nkeys); *dcp = xrecallocarray(*dcp, *ndcp, *ndcp + 1, sizeof(**dcp)); (*dcp)[(*ndcp)++] = dc; free(os); } static void usage(void) { fprintf(stderr, "usage: ssh-add [-cDdKkLlqvXx] [-E fingerprint_hash] [-H hostkey_file]\n" " [-h destination_constraint] [-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 main(int argc, char **argv) { extern char *optarg; extern int optind; int agent_fd; char *pkcs11provider = NULL, *skprovider = NULL; char **dest_constraint_strings = NULL, **hostkey_files = 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; + int r, i, ch, deleting = 0, ret = 0, key_only = 0, cert_only = 0; + int do_download = 0, xflag = 0, lflag = 0, Dflag = 0; + int qflag = 0, Tflag = 0; SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; LogLevel log_level = SYSLOG_LEVEL_INFO; + struct sshkey *k, **certs = NULL; struct dest_constraint **dest_constraints = NULL; - size_t ndest_constraints = 0; + size_t ndest_constraints = 0i, ncerts = 0; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); __progname = ssh_get_progname(argv[0]); seed_rng(); log_init(__progname, log_level, log_facility, 1); setvbuf(stdout, NULL, _IOLBF, 0); /* First, get a connection to the authentication agent. */ switch (r = ssh_get_authentication_socket(&agent_fd)) { case 0: break; case SSH_ERR_AGENT_NOT_PRESENT: fprintf(stderr, "Could not open a connection to your " "authentication agent.\n"); exit(2); default: fprintf(stderr, "Error connecting to agent: %s\n", ssh_err(r)); exit(2); } skprovider = getenv("SSH_SK_PROVIDER"); - while ((ch = getopt(argc, argv, "vkKlLcdDTxXE:e:h:H:M:m:qs:S:t:")) != -1) { + while ((ch = getopt(argc, argv, "vkKlLCcdDTxXE:e:h:H:M:m:qs:S:t:")) != -1) { switch (ch) { case 'v': if (log_level == SYSLOG_LEVEL_INFO) log_level = SYSLOG_LEVEL_DEBUG1; else if (log_level < SYSLOG_LEVEL_DEBUG3) log_level++; break; case 'E': fingerprint_hash = ssh_digest_alg_by_name(optarg); if (fingerprint_hash == -1) fatal("Invalid hash algorithm \"%s\"", optarg); break; case 'H': stringlist_append(&hostkey_files, optarg); break; case 'h': stringlist_append(&dest_constraint_strings, optarg); break; case 'k': key_only = 1; break; + case 'C': + cert_only = 1; + break; case 'K': do_download = 1; break; case 'l': case 'L': if (lflag != 0) fatal("-%c flag already specified", lflag); lflag = ch; break; case 'x': case 'X': if (xflag != 0) fatal("-%c flag already specified", xflag); xflag = ch; break; case 'c': confirm = 1; break; case 'm': minleft = (u_int)strtonum(optarg, 1, UINT_MAX, NULL); if (minleft == 0) { usage(); ret = 1; goto done; } break; case 'M': maxsign = (u_int)strtonum(optarg, 1, UINT_MAX, NULL); if (maxsign == 0) { usage(); ret = 1; goto done; } break; case 'd': deleting = 1; break; case 'D': Dflag = 1; break; case 's': pkcs11provider = optarg; break; case 'S': skprovider = optarg; break; case 'e': deleting = 1; pkcs11provider = optarg; break; case 't': if ((lifetime = convtime(optarg)) == -1 || lifetime < 0 || (u_long)lifetime > UINT32_MAX) { fprintf(stderr, "Invalid lifetime\n"); ret = 1; goto done; } break; case 'q': qflag = 1; break; case 'T': Tflag = 1; break; default: usage(); ret = 1; goto done; } } log_init(__progname, log_level, log_facility, 1); if ((xflag != 0) + (lflag != 0) + (Dflag != 0) > 1) fatal("Invalid combination of actions"); else if (xflag) { if (lock_agent(agent_fd, xflag == 'x' ? 1 : 0) == -1) ret = 1; goto done; } else if (lflag) { if (list_identities(agent_fd, lflag == 'l' ? 1 : 0) == -1) ret = 1; goto done; } else if (Dflag) { if (delete_all(agent_fd, qflag) == -1) ret = 1; goto done; } #ifdef ENABLE_SK_INTERNAL if (skprovider == NULL) skprovider = "internal"; #endif if (hostkey_files == NULL) { /* use defaults from readconf.c */ stringlist_append(&hostkey_files, _PATH_SSH_USER_HOSTFILE); stringlist_append(&hostkey_files, _PATH_SSH_USER_HOSTFILE2); stringlist_append(&hostkey_files, _PATH_SSH_SYSTEM_HOSTFILE); stringlist_append(&hostkey_files, _PATH_SSH_SYSTEM_HOSTFILE2); } if (dest_constraint_strings != NULL) { for (i = 0; dest_constraint_strings[i] != NULL; i++) { parse_dest_constraint(dest_constraint_strings[i], &dest_constraints, &ndest_constraints, hostkey_files); } } argc -= optind; argv += optind; if (Tflag) { if (argc <= 0) fatal("no keys to test"); for (r = i = 0; i < argc; i++) r |= test_key(agent_fd, argv[i]); ret = r == 0 ? 0 : 1; goto done; } if (pkcs11provider != NULL) { + for (i = 0; i < argc; i++) { + if ((r = sshkey_load_public(argv[i], &k, NULL)) != 0) + fatal_fr(r, "load certificate %s", argv[i]); + certs = xrecallocarray(certs, ncerts, ncerts + 1, + sizeof(*certs)); + debug2("%s: %s", argv[i], sshkey_ssh_name(k)); + certs[ncerts++] = k; + } + debug2_f("loaded %zu certificates", ncerts); if (update_card(agent_fd, !deleting, pkcs11provider, - qflag, dest_constraints, ndest_constraints) == -1) + qflag, key_only, cert_only, + dest_constraints, ndest_constraints, + certs, ncerts) == -1) ret = 1; goto done; } if (do_download) { if (skprovider == NULL) fatal("Cannot download keys without provider"); if (load_resident_keys(agent_fd, skprovider, qflag, dest_constraints, ndest_constraints) != 0) ret = 1; goto done; } if (argc == 0) { char buf[PATH_MAX]; struct passwd *pw; struct stat st; int count = 0; if ((pw = getpwuid(getuid())) == NULL) { fprintf(stderr, "No user found with uid %u\n", (u_int)getuid()); ret = 1; goto done; } for (i = 0; default_files[i]; i++) { snprintf(buf, sizeof(buf), "%s/%s", pw->pw_dir, default_files[i]); if (stat(buf, &st) == -1) continue; - if (do_file(agent_fd, deleting, key_only, buf, - qflag, skprovider, + if (do_file(agent_fd, deleting, key_only, cert_only, + buf, qflag, skprovider, dest_constraints, ndest_constraints) == -1) ret = 1; else count++; } if (count == 0) ret = 1; } else { for (i = 0; i < argc; i++) { - if (do_file(agent_fd, deleting, key_only, + if (do_file(agent_fd, deleting, key_only, cert_only, argv[i], qflag, skprovider, dest_constraints, ndest_constraints) == -1) ret = 1; } } done: clear_pass(); ssh_close_authentication_socket(agent_fd); return ret; } diff --git a/crypto/openssh/ssh-agent.c b/crypto/openssh/ssh-agent.c index a4d75a37d358..2c785f93f7ea 100644 --- a/crypto/openssh/ssh-agent.c +++ b/crypto/openssh/ssh-agent.c @@ -1,2315 +1,2494 @@ -/* $OpenBSD: ssh-agent.c,v 1.300 2023/07/19 13:56:33 djm Exp $ */ +/* $OpenBSD: ssh-agent.c,v 1.303 2023/12/18 14:48:08 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * The authentication agent program. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_SYS_UN_H # include #endif #include "openbsd-compat/sys-queue.h" #ifdef WITH_OPENSSL #include #include "openbsd-compat/openssl-compat.h" #endif #include #include #include #ifdef HAVE_PATHS_H # include #endif #ifdef HAVE_POLL_H # include #endif #include #include #include #include #include #include #include #ifdef HAVE_UTIL_H # include #endif #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "sshbuf.h" #include "sshkey.h" #include "authfd.h" #include "log.h" #include "misc.h" #include "digest.h" #include "ssherr.h" #include "match.h" #include "msg.h" #include "pathnames.h" #include "ssh-pkcs11.h" #include "sk-api.h" #include "myproposal.h" #ifndef DEFAULT_ALLOWED_PROVIDERS # define DEFAULT_ALLOWED_PROVIDERS "/usr/lib*/*,/usr/local/lib*/*" #endif /* Maximum accepted message length */ #define AGENT_MAX_LEN (256*1024) /* Maximum bytes to read from client socket */ #define AGENT_RBUF_LEN (4096) /* Maximum number of recorded session IDs/hostkeys per connection */ #define AGENT_MAX_SESSION_IDS 16 /* Maximum size of session ID */ #define AGENT_MAX_SID_LEN 128 /* Maximum number of destination constraints to accept on a key */ #define AGENT_MAX_DEST_CONSTRAINTS 1024 +/* Maximum number of associated certificate constraints to accept on a key */ +#define AGENT_MAX_EXT_CERTS 1024 /* XXX store hostkey_sid in a refcounted tree */ typedef enum { AUTH_UNUSED = 0, AUTH_SOCKET = 1, AUTH_CONNECTION = 2, } sock_type; struct hostkey_sid { struct sshkey *key; struct sshbuf *sid; int forwarded; }; typedef struct socket_entry { int fd; sock_type type; struct sshbuf *input; struct sshbuf *output; struct sshbuf *request; size_t nsession_ids; struct hostkey_sid *session_ids; + int session_bind_attempted; } SocketEntry; u_int sockets_alloc = 0; SocketEntry *sockets = NULL; typedef struct identity { TAILQ_ENTRY(identity) next; struct sshkey *key; char *comment; char *provider; time_t death; u_int confirm; char *sk_provider; struct dest_constraint *dest_constraints; size_t ndest_constraints; } Identity; struct idtable { int nentries; TAILQ_HEAD(idqueue, identity) idlist; }; /* private key table */ struct idtable *idtab; int max_fd = 0; /* pid of shell == parent of agent */ pid_t parent_pid = -1; time_t parent_alive_interval = 0; /* pid of process for which cleanup_socket is applicable */ pid_t cleanup_pid = 0; /* pathname and directory for AUTH_SOCKET */ char socket_name[PATH_MAX]; char socket_dir[PATH_MAX]; /* Pattern-list of allowed PKCS#11/Security key paths */ static char *allowed_providers; /* * Allows PKCS11 providers or SK keys that use non-internal providers to * be added over a remote connection (identified by session-bind@openssh.com). */ static int remote_add_provider; /* locking */ #define LOCK_SIZE 32 #define LOCK_SALT_SIZE 16 #define LOCK_ROUNDS 1 int locked = 0; u_char lock_pwhash[LOCK_SIZE]; u_char lock_salt[LOCK_SALT_SIZE]; extern char *__progname; /* Default lifetime in seconds (0 == forever) */ static 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; /* * Client connection count; incremented in new_socket() and decremented in * close_socket(). When it reaches 0, ssh-agent will exit. Since it is * normally initialized to 1, it will never reach 0. However, if the -x * option is specified, it is initialized to 0 in main(); in that case, * ssh-agent will exit as soon as it has had at least one client but no * longer has any. */ static int xcount = 1; static void close_socket(SocketEntry *e) { size_t i; int last = 0; if (e->type == AUTH_CONNECTION) { debug("xcount %d -> %d", xcount, xcount - 1); if (--xcount == 0) last = 1; } close(e->fd); sshbuf_free(e->input); sshbuf_free(e->output); sshbuf_free(e->request); for (i = 0; i < e->nsession_ids; i++) { sshkey_free(e->session_ids[i].key); sshbuf_free(e->session_ids[i].sid); } free(e->session_ids); memset(e, '\0', sizeof(*e)); e->fd = -1; e->type = AUTH_UNUSED; if (last) cleanup_exit(0); } static void idtab_init(void) { idtab = xcalloc(1, sizeof(*idtab)); TAILQ_INIT(&idtab->idlist); idtab->nentries = 0; } static void free_dest_constraint_hop(struct dest_constraint_hop *dch) { u_int i; if (dch == NULL) return; free(dch->user); free(dch->hostname); for (i = 0; i < dch->nkeys; i++) sshkey_free(dch->keys[i]); free(dch->keys); free(dch->key_is_ca); } static void free_dest_constraints(struct dest_constraint *dcs, size_t ndcs) { size_t i; for (i = 0; i < ndcs; i++) { free_dest_constraint_hop(&dcs[i].from); free_dest_constraint_hop(&dcs[i].to); } free(dcs); } +static void +dup_dest_constraint_hop(const struct dest_constraint_hop *dch, + struct dest_constraint_hop *out) +{ + u_int i; + int r; + + out->user = dch->user == NULL ? NULL : xstrdup(dch->user); + out->hostname = dch->hostname == NULL ? NULL : xstrdup(dch->hostname); + out->is_ca = dch->is_ca; + out->nkeys = dch->nkeys; + out->keys = out->nkeys == 0 ? NULL : + xcalloc(out->nkeys, sizeof(*out->keys)); + out->key_is_ca = out->nkeys == 0 ? NULL : + xcalloc(out->nkeys, sizeof(*out->key_is_ca)); + for (i = 0; i < dch->nkeys; i++) { + if (dch->keys[i] != NULL && + (r = sshkey_from_private(dch->keys[i], + &(out->keys[i]))) != 0) + fatal_fr(r, "copy key"); + out->key_is_ca[i] = dch->key_is_ca[i]; + } +} + +static struct dest_constraint * +dup_dest_constraints(const struct dest_constraint *dcs, size_t ndcs) +{ + size_t i; + struct dest_constraint *ret; + + if (ndcs == 0) + return NULL; + ret = xcalloc(ndcs, sizeof(*ret)); + for (i = 0; i < ndcs; i++) { + dup_dest_constraint_hop(&dcs[i].from, &ret[i].from); + dup_dest_constraint_hop(&dcs[i].to, &ret[i].to); + } + return ret; +} + +#ifdef DEBUG_CONSTRAINTS +static void +dump_dest_constraint_hop(const struct dest_constraint_hop *dch) +{ + u_int i; + char *fp; + + debug_f("user %s hostname %s is_ca %d nkeys %u", + dch->user == NULL ? "(null)" : dch->user, + dch->hostname == NULL ? "(null)" : dch->hostname, + dch->is_ca, dch->nkeys); + for (i = 0; i < dch->nkeys; i++) { + fp = NULL; + if (dch->keys[i] != NULL && + (fp = sshkey_fingerprint(dch->keys[i], + SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) + fatal_f("fingerprint failed"); + debug_f("key %u/%u: %s%s%s key_is_ca %d", i, dch->nkeys, + dch->keys[i] == NULL ? "" : sshkey_ssh_name(dch->keys[i]), + dch->keys[i] == NULL ? "" : " ", + dch->keys[i] == NULL ? "none" : fp, + dch->key_is_ca[i]); + free(fp); + } +} +#endif /* DEBUG_CONSTRAINTS */ + +static void +dump_dest_constraints(const char *context, + const struct dest_constraint *dcs, size_t ndcs) +{ +#ifdef DEBUG_CONSTRAINTS + size_t i; + + debug_f("%s: %zu constraints", context, ndcs); + for (i = 0; i < ndcs; i++) { + debug_f("constraint %zu / %zu: from: ", i, ndcs); + dump_dest_constraint_hop(&dcs[i].from); + debug_f("constraint %zu / %zu: to: ", i, ndcs); + dump_dest_constraint_hop(&dcs[i].to); + } + debug_f("done for %s", context); +#endif /* DEBUG_CONSTRAINTS */ +} + static void free_identity(Identity *id) { sshkey_free(id->key); free(id->provider); free(id->comment); free(id->sk_provider); free_dest_constraints(id->dest_constraints, id->ndest_constraints); free(id); } /* * Match 'key' against the key/CA list in a destination constraint hop * Returns 0 on success or -1 otherwise. */ static int match_key_hop(const char *tag, const struct sshkey *key, const struct dest_constraint_hop *dch) { const char *reason = NULL; const char *hostname = dch->hostname ? dch->hostname : "(ORIGIN)"; u_int i; char *fp; if (key == NULL) return -1; /* XXX logspam */ if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); debug3_f("%s: entering hostname %s, requested key %s %s, %u keys avail", tag, hostname, sshkey_type(key), fp, dch->nkeys); free(fp); for (i = 0; i < dch->nkeys; i++) { if (dch->keys[i] == NULL) return -1; /* XXX logspam */ if ((fp = sshkey_fingerprint(dch->keys[i], SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); debug3_f("%s: key %u: %s%s %s", tag, i, dch->key_is_ca[i] ? "CA " : "", sshkey_type(dch->keys[i]), fp); free(fp); if (!sshkey_is_cert(key)) { /* plain key */ if (dch->key_is_ca[i] || !sshkey_equal(key, dch->keys[i])) continue; return 0; } /* certificate */ if (!dch->key_is_ca[i]) continue; if (key->cert == NULL || key->cert->signature_key == NULL) return -1; /* shouldn't happen */ if (!sshkey_equal(key->cert->signature_key, dch->keys[i])) continue; if (sshkey_cert_check_host(key, hostname, 1, SSH_ALLOWED_CA_SIGALGS, &reason) != 0) { debug_f("cert %s / hostname %s rejected: %s", key->cert->key_id, hostname, reason); continue; } return 0; } return -1; } /* Check destination constraints on an identity against the hostkey/user */ static int permitted_by_dest_constraints(const struct sshkey *fromkey, const struct sshkey *tokey, Identity *id, const char *user, const char **hostnamep) { size_t i; struct dest_constraint *d; if (hostnamep != NULL) *hostnamep = NULL; for (i = 0; i < id->ndest_constraints; i++) { d = id->dest_constraints + i; /* XXX remove logspam */ debug2_f("constraint %zu %s%s%s (%u keys) > %s%s%s (%u keys)", i, d->from.user ? d->from.user : "", d->from.user ? "@" : "", d->from.hostname ? d->from.hostname : "(ORIGIN)", d->from.nkeys, d->to.user ? d->to.user : "", d->to.user ? "@" : "", d->to.hostname ? d->to.hostname : "(ANY)", d->to.nkeys); /* Match 'from' key */ if (fromkey == NULL) { /* We are matching the first hop */ if (d->from.hostname != NULL || d->from.nkeys != 0) continue; } else if (match_key_hop("from", fromkey, &d->from) != 0) continue; /* Match 'to' key */ if (tokey != NULL && match_key_hop("to", tokey, &d->to) != 0) continue; /* Match user if specified */ if (d->to.user != NULL && user != NULL && !match_pattern(user, d->to.user)) continue; /* successfully matched this constraint */ if (hostnamep != NULL) *hostnamep = d->to.hostname; debug2_f("allowed for hostname %s", d->to.hostname == NULL ? "*" : d->to.hostname); return 0; } /* no match */ debug2_f("%s identity \"%s\" not permitted for this destination", sshkey_type(id->key), id->comment); return -1; } /* * Check whether hostkeys on a SocketEntry and the optionally specified user * are permitted by the destination constraints on the Identity. * Returns 0 on success or -1 otherwise. */ static int identity_permitted(Identity *id, SocketEntry *e, char *user, const char **forward_hostnamep, const char **last_hostnamep) { size_t i; const char **hp; struct hostkey_sid *hks; const struct sshkey *fromkey = NULL; const char *test_user; char *fp1, *fp2; /* XXX remove logspam */ debug3_f("entering: key %s comment \"%s\", %zu socket bindings, " "%zu constraints", sshkey_type(id->key), id->comment, e->nsession_ids, id->ndest_constraints); if (id->ndest_constraints == 0) return 0; /* unconstrained */ + if (e->session_bind_attempted && e->nsession_ids == 0) { + error_f("previous session bind failed on socket"); + return -1; + } if (e->nsession_ids == 0) return 0; /* local use */ /* * Walk through the hops recorded by session_id and try to find a * constraint that satisfies each. */ for (i = 0; i < e->nsession_ids; i++) { hks = e->session_ids + i; if (hks->key == NULL) fatal_f("internal error: no bound key"); /* XXX remove logspam */ fp1 = fp2 = NULL; if (fromkey != NULL && (fp1 = sshkey_fingerprint(fromkey, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); if ((fp2 = sshkey_fingerprint(hks->key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); debug3_f("socketentry fd=%d, entry %zu %s, " "from hostkey %s %s to user %s hostkey %s %s", e->fd, i, hks->forwarded ? "FORWARD" : "AUTH", fromkey ? sshkey_type(fromkey) : "(ORIGIN)", fromkey ? fp1 : "", user ? user : "(ANY)", sshkey_type(hks->key), fp2); free(fp1); free(fp2); /* * Record the hostnames for the initial forwarding and * the final destination. */ hp = NULL; if (i == e->nsession_ids - 1) hp = last_hostnamep; else if (i == 0) hp = forward_hostnamep; /* Special handling for final recorded binding */ test_user = NULL; if (i == e->nsession_ids - 1) { /* Can only check user at final hop */ test_user = user; /* * user is only presented for signature requests. * If this is the case, make sure last binding is not * for a forwarding. */ if (hks->forwarded && user != NULL) { error_f("tried to sign on forwarding hop"); return -1; } } else if (!hks->forwarded) { error_f("tried to forward though signing bind"); return -1; } if (permitted_by_dest_constraints(fromkey, hks->key, id, test_user, hp) != 0) return -1; fromkey = hks->key; } /* * Another special case: if the last bound session ID was for a * forwarding, and this function is not being called to check a sign * request (i.e. no 'user' supplied), then only permit the key if * there is a permission that would allow it to be used at another * destination. This hides keys that are allowed to be used to * authenticate *to* a host but not permitted for *use* beyond it. */ hks = &e->session_ids[e->nsession_ids - 1]; if (hks->forwarded && user == NULL && permitted_by_dest_constraints(hks->key, NULL, id, NULL, NULL) != 0) { debug3_f("key permitted at host but not after"); return -1; } /* success */ return 0; } +static int +socket_is_remote(SocketEntry *e) +{ + return e->session_bind_attempted || (e->nsession_ids != 0); +} + /* return matching private key for given public key */ static Identity * lookup_identity(struct sshkey *key) { Identity *id; TAILQ_FOREACH(id, &idtab->idlist, next) { if (sshkey_equal(key, id->key)) return (id); } return (NULL); } /* Check confirmation of keysign request */ static int confirm_key(Identity *id, 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.%s%s", id->comment, p, extra == NULL ? "" : "\n", extra == NULL ? "" : extra)) ret = 0; free(p); return (ret); } static void send_status(SocketEntry *e, int success) { int r; if ((r = sshbuf_put_u32(e->output, 1)) != 0 || (r = sshbuf_put_u8(e->output, success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0) fatal_fr(r, "compose"); } /* send list of supported public keys to 'client' */ static void process_request_identities(SocketEntry *e) { Identity *id; struct sshbuf *msg, *keys; int r; - u_int nentries = 0; + u_int i = 0, nentries = 0; + char *fp; debug2_f("entering"); if ((msg = sshbuf_new()) == NULL || (keys = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); TAILQ_FOREACH(id, &idtab->idlist, next) { + if ((fp = sshkey_fingerprint(id->key, SSH_FP_HASH_DEFAULT, + SSH_FP_DEFAULT)) == NULL) + fatal_f("fingerprint failed"); + debug_f("key %u / %u: %s %s", i++, idtab->nentries, + sshkey_ssh_name(id->key), fp); + dump_dest_constraints(__func__, + id->dest_constraints, id->ndest_constraints); + free(fp); /* identity not visible, don't include in response */ if (identity_permitted(id, e, NULL, NULL, NULL) != 0) continue; if ((r = sshkey_puts_opts(id->key, keys, SSHKEY_SERIALIZE_INFO)) != 0 || (r = sshbuf_put_cstring(keys, id->comment)) != 0) { error_fr(r, "compose key/comment"); continue; } nentries++; } debug2_f("replying with %u allowed of %u available keys", nentries, idtab->nentries); if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || (r = sshbuf_put_u32(msg, nentries)) != 0 || (r = sshbuf_putb(msg, keys)) != 0) fatal_fr(r, "compose"); if ((r = sshbuf_put_stringb(e->output, msg)) != 0) fatal_fr(r, "enqueue"); sshbuf_free(msg); sshbuf_free(keys); } static char * agent_decode_alg(struct sshkey *key, u_int flags) { if (key->type == KEY_RSA) { if (flags & SSH_AGENT_RSA_SHA2_256) return "rsa-sha2-256"; else if (flags & SSH_AGENT_RSA_SHA2_512) return "rsa-sha2-512"; } else if (key->type == KEY_RSA_CERT) { if (flags & SSH_AGENT_RSA_SHA2_256) return "rsa-sha2-256-cert-v01@openssh.com"; else if (flags & SSH_AGENT_RSA_SHA2_512) return "rsa-sha2-512-cert-v01@openssh.com"; } 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, session ID and/or hostkey from the request. */ static int parse_userauth_request(struct sshbuf *msg, const struct sshkey *expected_key, char **userp, struct sshbuf **sess_idp, struct sshkey **hostkeyp) { 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, *hostkey = NULL; if (userp != NULL) *userp = NULL; if (sess_idp != NULL) *sess_idp = NULL; if (hostkeyp != NULL) *hostkeyp = 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-hostbound-v00@openssh.com") == 0) { if ((r = sshkey_froms(b, &hostkey)) != 0) goto out; } else 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; } if (hostkeyp != NULL) { *hostkeyp = hostkey; hostkey = NULL; } out: sshbuf_free(b); sshbuf_free(sess_id); free(user); free(service); free(method); free(pkalg); sshkey_free(mkey); sshkey_free(hostkey); 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, 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; } static int buf_equal(const struct sshbuf *a, const struct sshbuf *b) { if (sshbuf_ptr(a) == NULL || sshbuf_ptr(b) == NULL) return SSH_ERR_INVALID_ARGUMENT; if (sshbuf_len(a) != sshbuf_len(b)) return SSH_ERR_INVALID_FORMAT; if (timingsafe_bcmp(sshbuf_ptr(a), sshbuf_ptr(b), sshbuf_len(a)) != 0) return SSH_ERR_INVALID_FORMAT; return 0; } /* ssh2 only */ static void process_sign_request2(SocketEntry *e) { u_char *signature = NULL; size_t slen = 0; u_int compat = 0, flags; int r, ok = -1, retried = 0; char *fp = NULL, *pin = NULL, *prompt = NULL; char *user = NULL, *sig_dest = NULL; const char *fwd_host = NULL, *dest_host = NULL; struct sshbuf *msg = NULL, *data = NULL, *sid = NULL; struct sshkey *key = NULL, *hostkey = NULL; struct identity *id; struct notifier_ctx *notifier = NULL; 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_stringb(e->request, data)) != 0 || (r = sshbuf_get_u32(e->request, &flags)) != 0) { error_fr(r, "parse"); goto send; } if ((id = lookup_identity(key)) == NULL) { verbose_f("%s key not found", sshkey_type(key)); goto send; } if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); if (id->ndest_constraints != 0) { if (e->nsession_ids == 0) { logit_f("refusing use of destination-constrained key " "to sign on unbound connection"); goto send; } if (parse_userauth_request(data, key, &user, &sid, &hostkey) != 0) { logit_f("refusing use of destination-constrained key " "to sign an unidentified signature"); goto send; } /* XXX logspam */ debug_f("user=%s", user); if (identity_permitted(id, e, user, &fwd_host, &dest_host) != 0) goto send; /* XXX display fwd_host/dest_host in askpass UI */ /* * Ensure that the session ID is the most recent one * registered on the socket - it should have been bound by * ssh immediately before userauth. */ if (buf_equal(sid, e->session_ids[e->nsession_ids - 1].sid) != 0) { error_f("unexpected session ID (%zu listed) on " "signature request for target user %s with " "key %s %s", e->nsession_ids, user, sshkey_type(id->key), fp); goto send; } /* * Ensure that the hostkey embedded in the signature matches * the one most recently bound to the socket. An exception is * made for the initial forwarding hop. */ if (e->nsession_ids > 1 && hostkey == NULL) { error_f("refusing use of destination-constrained key: " "no hostkey recorded in signature for forwarded " "connection"); goto send; } if (hostkey != NULL && !sshkey_equal(hostkey, e->session_ids[e->nsession_ids - 1].key)) { error_f("refusing use of destination-constrained key: " "mismatch between hostkey in request and most " "recently bound session"); goto send; } xasprintf(&sig_dest, "public key authentication request for " "user \"%s\" to listed host", user); } if (id->confirm && confirm_key(id, sig_dest) != 0) { verbose_f("user refused key"); goto send; } if (sshkey_is_sk(id->key)) { if (restrict_websafe && 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) { notifier = notify_start(0, "Confirm user presence for key %s %s%s%s", sshkey_type(id->key), fp, sig_dest == NULL ? "" : "\n", sig_dest == NULL ? "" : sig_dest); } } retry_pin: if ((r = sshkey_sign(id->key, &signature, &slen, sshbuf_ptr(data), sshbuf_len(data), agent_decode_alg(key, flags), id->sk_provider, pin, compat)) != 0) { debug_fr(r, "sshkey_sign"); if (pin == NULL && !retried && sshkey_is_sk(id->key) && r == SSH_ERR_KEY_WRONG_PASSPHRASE) { notify_complete(notifier, NULL); notifier = NULL; /* XXX include sig_dest */ xasprintf(&prompt, "Enter PIN%sfor %s key %s: ", (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD) ? " and confirm user presence " : " ", sshkey_type(id->key), fp); pin = read_passphrase(prompt, RP_USE_ASKPASS); retried = 1; goto retry_pin; } error_fr(r, "sshkey_sign"); goto send; } /* Success */ ok = 0; debug_f("good signature"); send: 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_fr(r, "compose"); } else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0) fatal_fr(r, "compose failure"); if ((r = sshbuf_put_stringb(e->output, msg)) != 0) fatal_fr(r, "enqueue"); sshbuf_free(sid); sshbuf_free(data); sshbuf_free(msg); sshkey_free(key); sshkey_free(hostkey); free(fp); free(signature); free(sig_dest); free(user); free(prompt); if (pin != NULL) freezero(pin, strlen(pin)); } /* shared */ static void process_remove_identity(SocketEntry *e) { int r, success = 0; struct sshkey *key = NULL; Identity *id; debug2_f("entering"); if ((r = sshkey_froms(e->request, &key)) != 0) { error_fr(r, "parse key"); goto done; } if ((id = lookup_identity(key)) == NULL) { debug_f("key not found"); goto done; } /* identity not visible, cannot be removed */ if (identity_permitted(id, e, NULL, NULL, NULL) != 0) goto done; /* error already logged */ /* We have this key, free it. */ if (idtab->nentries < 1) fatal_f("internal error: nentries %d", idtab->nentries); TAILQ_REMOVE(&idtab->idlist, id, next); free_identity(id); idtab->nentries--; success = 1; done: sshkey_free(key); send_status(e, success); } static void 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)) { TAILQ_REMOVE(&idtab->idlist, id, next); free_identity(id); } /* Mark that there are no identities. */ idtab->nentries = 0; /* Send success. */ send_status(e, 1); } /* removes expired keys and returns number of seconds until the next expiry */ static time_t reaper(void) { time_t deadline = 0, now = monotime(); Identity *id, *nxt; for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) { nxt = TAILQ_NEXT(id, next); if (id->death == 0) continue; if (now >= id->death) { debug("expiring key '%s'", id->comment); TAILQ_REMOVE(&idtab->idlist, id, next); free_identity(id); idtab->nentries--; } else deadline = (deadline == 0) ? id->death : MINIMUM(deadline, id->death); } if (deadline == 0 || deadline <= now) return 0; else return (deadline - now); } static int parse_dest_constraint_hop(struct sshbuf *b, struct dest_constraint_hop *dch) { u_char key_is_ca; size_t elen = 0; int r; struct sshkey *k = NULL; char *fp; memset(dch, '\0', sizeof(*dch)); if ((r = sshbuf_get_cstring(b, &dch->user, NULL)) != 0 || (r = sshbuf_get_cstring(b, &dch->hostname, NULL)) != 0 || (r = sshbuf_get_string_direct(b, NULL, &elen)) != 0) { error_fr(r, "parse"); goto out; } if (elen != 0) { error_f("unsupported extensions (len %zu)", elen); r = SSH_ERR_FEATURE_UNSUPPORTED; goto out; } if (*dch->hostname == '\0') { free(dch->hostname); dch->hostname = NULL; } if (*dch->user == '\0') { free(dch->user); dch->user = NULL; } while (sshbuf_len(b) != 0) { dch->keys = xrecallocarray(dch->keys, dch->nkeys, dch->nkeys + 1, sizeof(*dch->keys)); dch->key_is_ca = xrecallocarray(dch->key_is_ca, dch->nkeys, dch->nkeys + 1, sizeof(*dch->key_is_ca)); if ((r = sshkey_froms(b, &k)) != 0 || (r = sshbuf_get_u8(b, &key_is_ca)) != 0) goto out; if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); debug3_f("%s%s%s: adding %skey %s %s", dch->user == NULL ? "" : dch->user, dch->user == NULL ? "" : "@", dch->hostname, key_is_ca ? "CA " : "", sshkey_type(k), fp); free(fp); dch->keys[dch->nkeys] = k; dch->key_is_ca[dch->nkeys] = key_is_ca != 0; dch->nkeys++; k = NULL; /* transferred */ } /* success */ r = 0; out: sshkey_free(k); return r; } static int parse_dest_constraint(struct sshbuf *m, struct dest_constraint *dc) { struct sshbuf *b = NULL, *frombuf = NULL, *tobuf = NULL; int r; size_t elen = 0; debug3_f("entering"); memset(dc, '\0', sizeof(*dc)); if ((r = sshbuf_froms(m, &b)) != 0 || (r = sshbuf_froms(b, &frombuf)) != 0 || (r = sshbuf_froms(b, &tobuf)) != 0 || (r = sshbuf_get_string_direct(b, NULL, &elen)) != 0) { error_fr(r, "parse"); goto out; } if ((r = parse_dest_constraint_hop(frombuf, &dc->from)) != 0 || (r = parse_dest_constraint_hop(tobuf, &dc->to)) != 0) goto out; /* already logged */ if (elen != 0) { error_f("unsupported extensions (len %zu)", elen); r = SSH_ERR_FEATURE_UNSUPPORTED; goto out; } debug2_f("parsed %s (%u keys) > %s%s%s (%u keys)", dc->from.hostname ? dc->from.hostname : "(ORIGIN)", dc->from.nkeys, dc->to.user ? dc->to.user : "", dc->to.user ? "@" : "", dc->to.hostname ? dc->to.hostname : "(ANY)", dc->to.nkeys); /* check consistency */ if ((dc->from.hostname == NULL) != (dc->from.nkeys == 0) || dc->from.user != NULL) { error_f("inconsistent \"from\" specification"); r = SSH_ERR_INVALID_FORMAT; goto out; } if (dc->to.hostname == NULL || dc->to.nkeys == 0) { error_f("incomplete \"to\" specification"); r = SSH_ERR_INVALID_FORMAT; goto out; } /* success */ r = 0; out: sshbuf_free(b); sshbuf_free(frombuf); sshbuf_free(tobuf); return r; } static int parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp, - struct dest_constraint **dcsp, size_t *ndcsp) + struct dest_constraint **dcsp, size_t *ndcsp, int *cert_onlyp, + struct sshkey ***certs, size_t *ncerts) { char *ext_name = NULL; int r; struct sshbuf *b = NULL; + u_char v; + struct sshkey *k; 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 if (strcmp(ext_name, "restrict-destination-v00@openssh.com") == 0) { if (*dcsp != NULL) { error_f("%s already set", ext_name); goto out; } if ((r = sshbuf_froms(m, &b)) != 0) { error_fr(r, "parse %s outer", ext_name); goto out; } while (sshbuf_len(b) != 0) { if (*ndcsp >= AGENT_MAX_DEST_CONSTRAINTS) { error_f("too many %s constraints", ext_name); goto out; } *dcsp = xrecallocarray(*dcsp, *ndcsp, *ndcsp + 1, sizeof(**dcsp)); if ((r = parse_dest_constraint(b, *dcsp + (*ndcsp)++)) != 0) goto out; /* error already logged */ } + } else if (strcmp(ext_name, + "associated-certs-v00@openssh.com") == 0) { + if (certs == NULL || ncerts == NULL || cert_onlyp == NULL) { + error_f("%s not valid here", ext_name); + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if (*certs != NULL) { + error_f("%s already set", ext_name); + goto out; + } + if ((r = sshbuf_get_u8(m, &v)) != 0 || + (r = sshbuf_froms(m, &b)) != 0) { + error_fr(r, "parse %s", ext_name); + goto out; + } + *cert_onlyp = v != 0; + while (sshbuf_len(b) != 0) { + if (*ncerts >= AGENT_MAX_EXT_CERTS) { + error_f("too many %s constraints", ext_name); + goto out; + } + *certs = xrecallocarray(*certs, *ncerts, *ncerts + 1, + sizeof(**certs)); + if ((r = sshkey_froms(b, &k)) != 0) { + error_fr(r, "parse key"); + goto out; + } + (*certs)[(*ncerts)++] = k; + } } else { error_f("unsupported constraint \"%s\"", ext_name); r = SSH_ERR_FEATURE_UNSUPPORTED; goto out; } /* success */ r = 0; out: free(ext_name); sshbuf_free(b); return r; } static int parse_key_constraints(struct sshbuf *m, struct sshkey *k, time_t *deathp, u_int *secondsp, int *confirmp, char **sk_providerp, - struct dest_constraint **dcsp, size_t *ndcsp) + struct dest_constraint **dcsp, size_t *ndcsp, + int *cert_onlyp, size_t *ncerts, struct sshkey ***certs) { 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, dcsp, ndcsp)) != 0) + sk_providerp, dcsp, ndcsp, + cert_onlyp, certs, ncerts)) != 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; char *fp, *comment = NULL, *sk_provider = NULL; char canonical_provider[PATH_MAX]; time_t death = 0; u_int seconds = 0; struct dest_constraint *dest_constraints = NULL; size_t ndest_constraints = 0; struct sshkey *k = NULL; 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_fr(r, "parse"); goto out; } if (parse_key_constraints(e->request, k, &death, &seconds, &confirm, - &sk_provider, &dest_constraints, &ndest_constraints) != 0) { + &sk_provider, &dest_constraints, &ndest_constraints, + NULL, NULL, NULL) != 0) { error_f("failed to parse constraints"); sshbuf_reset(e->request); goto out; } + dump_dest_constraints(__func__, dest_constraints, ndest_constraints); 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 (e->nsession_ids != 0 && !remote_add_provider) { + if (socket_is_remote(e) && !remote_add_provider) { verbose("failed add of SK provider \"%.100s\": " "remote addition of providers is disabled", sk_provider); goto out; } 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) { id = xcalloc(1, sizeof(Identity)); TAILQ_INSERT_TAIL(&idtab->idlist, id, next); /* Increment the number of identities. */ idtab->nentries++; } else { /* identity not visible, do not update */ if (identity_permitted(id, e, NULL, NULL, NULL) != 0) goto out; /* error already logged */ /* key state might have been updated */ sshkey_free(id->key); free(id->comment); free(id->sk_provider); free_dest_constraints(id->dest_constraints, id->ndest_constraints); } /* success */ id->key = k; id->comment = comment; id->death = death; id->confirm = confirm; id->sk_provider = sk_provider; id->dest_constraints = dest_constraints; id->ndest_constraints = ndest_constraints; 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) (destination constraints: %zu)", sshkey_ssh_name(k), fp, comment, seconds, confirm, sk_provider == NULL ? "none" : sk_provider, ndest_constraints); free(fp); /* transferred */ k = NULL; comment = NULL; sk_provider = NULL; dest_constraints = NULL; ndest_constraints = 0; success = 1; out: free(sk_provider); free(comment); sshkey_free(k); free_dest_constraints(dest_constraints, ndest_constraints); send_status(e, success); } /* XXX todo: encrypt sensitive data with passphrase */ static void process_lock_agent(SocketEntry *e, int lock) { int r, success = 0, delay; char *passwd; u_char passwdhash[LOCK_SIZE]; static u_int fail_count = 0; size_t pwlen; 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_fr(r, "parse"); if (pwlen == 0) { debug("empty password not supported"); } else if (locked && !lock) { if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt), passwdhash, sizeof(passwdhash), LOCK_ROUNDS) < 0) fatal("bcrypt_pbkdf"); if (timingsafe_bcmp(passwdhash, lock_pwhash, LOCK_SIZE) == 0) { debug("agent unlocked"); locked = 0; fail_count = 0; explicit_bzero(lock_pwhash, sizeof(lock_pwhash)); success = 1; } else { /* delay in 0.1s increments up to 10s */ if (fail_count < 100) fail_count++; delay = 100000 * fail_count; debug("unlock failed, delaying %0.1lf seconds", (double)delay/1000000); usleep(delay); } explicit_bzero(passwdhash, sizeof(passwdhash)); } else if (!locked && lock) { debug("agent locked"); locked = 1; arc4random_buf(lock_salt, sizeof(lock_salt)); if (bcrypt_pbkdf(passwd, pwlen, lock_salt, sizeof(lock_salt), lock_pwhash, sizeof(lock_pwhash), LOCK_ROUNDS) < 0) fatal("bcrypt_pbkdf"); success = 1; } freezero(passwd, pwlen); send_status(e, success); } static void no_identities(SocketEntry *e) { struct sshbuf *msg; int r; if ((msg = sshbuf_new()) == NULL) 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_fr(r, "compose"); sshbuf_free(msg); } +/* Add an identity to idlist; takes ownership of 'key' and 'comment' */ +static void +add_p11_identity(struct sshkey *key, char *comment, const char *provider, + time_t death, int confirm, struct dest_constraint *dest_constraints, + size_t ndest_constraints) +{ + Identity *id; + + if (lookup_identity(key) != NULL) { + sshkey_free(key); + free(comment); + return; + } + id = xcalloc(1, sizeof(Identity)); + id->key = key; + id->comment = comment; + id->provider = xstrdup(provider); + id->death = death; + id->confirm = confirm; + id->dest_constraints = dup_dest_constraints(dest_constraints, + ndest_constraints); + id->ndest_constraints = ndest_constraints; + TAILQ_INSERT_TAIL(&idtab->idlist, id, next); + idtab->nentries++; +} + #ifdef ENABLE_PKCS11 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 = 0; time_t death = 0; struct sshkey **keys = NULL, *k; - Identity *id; struct dest_constraint *dest_constraints = NULL; - size_t ndest_constraints = 0; + size_t j, ndest_constraints = 0, ncerts = 0; + struct sshkey **certs = NULL; + int cert_only = 0; debug2_f("entering"); if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) { error_fr(r, "parse"); goto send; } if (parse_key_constraints(e->request, NULL, &death, &seconds, &confirm, - NULL, &dest_constraints, &ndest_constraints) != 0) { + NULL, &dest_constraints, &ndest_constraints, &cert_only, + &ncerts, &certs) != 0) { error_f("failed to parse constraints"); goto send; } - if (e->nsession_ids != 0 && !remote_add_provider) { + dump_dest_constraints(__func__, dest_constraints, ndest_constraints); + if (socket_is_remote(e) && !remote_add_provider) { verbose("failed PKCS#11 add of \"%.100s\": remote addition of " "providers is disabled", provider); 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, allowed_providers, 0) != 1) { verbose("refusing PKCS#11 add of \"%.100s\": " "provider not allowed", canonical_provider); goto send; } debug_f("add %.100s", canonical_provider); if (lifetime && !death) death = monotime() + lifetime; 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); - if (*comments[i] != '\0') { - id->comment = comments[i]; - comments[i] = NULL; /* transferred */ - } else { - id->comment = xstrdup(canonical_provider); - } - id->death = death; - id->confirm = confirm; - id->dest_constraints = dest_constraints; - id->ndest_constraints = ndest_constraints; - dest_constraints = NULL; /* transferred */ - ndest_constraints = 0; - TAILQ_INSERT_TAIL(&idtab->idlist, id, next); - idtab->nentries++; + if (comments[i] == NULL || comments[i][0] == '\0') { + free(comments[i]); + comments[i] = xstrdup(canonical_provider); + } + for (j = 0; j < ncerts; j++) { + if (!sshkey_is_cert(certs[j])) + continue; + if (!sshkey_equal_public(keys[i], certs[j])) + continue; + if (pkcs11_make_cert(keys[i], certs[j], &k) != 0) + continue; + add_p11_identity(k, xstrdup(comments[i]), + canonical_provider, death, confirm, + dest_constraints, ndest_constraints); + success = 1; + } + if (!cert_only && lookup_identity(keys[i]) == NULL) { + add_p11_identity(keys[i], comments[i], + canonical_provider, death, confirm, + dest_constraints, ndest_constraints); + keys[i] = NULL; /* transferred */ + comments[i] = NULL; /* transferred */ success = 1; } /* XXX update constraints for existing keys */ sshkey_free(keys[i]); free(comments[i]); } send: free(pin); free(provider); free(keys); free(comments); free_dest_constraints(dest_constraints, ndest_constraints); + for (j = 0; j < ncerts; j++) + sshkey_free(certs[j]); + free(certs); send_status(e, success); } static void process_remove_smartcard_key(SocketEntry *e) { char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX]; int r, success = 0; Identity *id, *nxt; debug2_f("entering"); if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) { error_fr(r, "parse"); goto send; } free(pin); if (realpath(provider, canonical_provider) == NULL) { verbose("failed PKCS#11 add of \"%.100s\": realpath: %s", provider, strerror(errno)); goto send; } debug_f("remove %.100s", canonical_provider); for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) { nxt = TAILQ_NEXT(id, next); /* Skip file--based keys */ if (id->provider == NULL) continue; if (!strcmp(canonical_provider, id->provider)) { TAILQ_REMOVE(&idtab->idlist, id, next); free_identity(id); idtab->nentries--; } } if (pkcs11_del_provider(canonical_provider) == 0) success = 1; else error_f("pkcs11_del_provider failed"); send: free(provider); send_status(e, success); } #endif /* ENABLE_PKCS11 */ static int process_ext_session_bind(SocketEntry *e) { int r, sid_match, key_match; struct sshkey *key = NULL; struct sshbuf *sid = NULL, *sig = NULL; char *fp = NULL; size_t i; u_char fwd = 0; debug2_f("entering"); + e->session_bind_attempted = 1; if ((r = sshkey_froms(e->request, &key)) != 0 || (r = sshbuf_froms(e->request, &sid)) != 0 || (r = sshbuf_froms(e->request, &sig)) != 0 || (r = sshbuf_get_u8(e->request, &fwd)) != 0) { error_fr(r, "parse"); goto out; } if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT, SSH_FP_DEFAULT)) == NULL) fatal_f("fingerprint failed"); /* check signature with hostkey on session ID */ if ((r = sshkey_verify(key, sshbuf_ptr(sig), sshbuf_len(sig), sshbuf_ptr(sid), sshbuf_len(sid), NULL, 0, NULL)) != 0) { error_fr(r, "sshkey_verify for %s %s", sshkey_type(key), fp); goto out; } /* check whether sid/key already recorded */ for (i = 0; i < e->nsession_ids; i++) { if (!e->session_ids[i].forwarded) { error_f("attempt to bind session ID to socket " "previously bound for authentication attempt"); r = -1; goto out; } sid_match = buf_equal(sid, e->session_ids[i].sid) == 0; key_match = sshkey_equal(key, e->session_ids[i].key); if (sid_match && key_match) { debug_f("session ID already recorded for %s %s", sshkey_type(key), fp); r = 0; goto out; } else if (sid_match) { error_f("session ID recorded against different key " "for %s %s", sshkey_type(key), fp); r = -1; goto out; } /* * new sid with previously-seen key can happen, e.g. multiple * connections to the same host. */ } /* record new key/sid */ if (e->nsession_ids >= AGENT_MAX_SESSION_IDS) { error_f("too many session IDs recorded"); goto out; } e->session_ids = xrecallocarray(e->session_ids, e->nsession_ids, e->nsession_ids + 1, sizeof(*e->session_ids)); i = e->nsession_ids++; debug_f("recorded %s %s (slot %zu of %d)", sshkey_type(key), fp, i, AGENT_MAX_SESSION_IDS); e->session_ids[i].key = key; e->session_ids[i].forwarded = fwd != 0; key = NULL; /* transferred */ /* can't transfer sid; it's refcounted and scoped to request's life */ if ((e->session_ids[i].sid = sshbuf_new()) == NULL) fatal_f("sshbuf_new"); if ((r = sshbuf_putb(e->session_ids[i].sid, sid)) != 0) fatal_fr(r, "sshbuf_putb session ID"); /* success */ r = 0; out: free(fp); sshkey_free(key); sshbuf_free(sid); sshbuf_free(sig); return r == 0 ? 1 : 0; } static void process_extension(SocketEntry *e) { int r, success = 0; char *name; debug2_f("entering"); if ((r = sshbuf_get_cstring(e->request, &name, NULL)) != 0) { error_fr(r, "parse"); goto send; } if (strcmp(name, "session-bind@openssh.com") == 0) success = process_ext_session_bind(e); else debug_f("unsupported extension \"%s\"", name); free(name); send: send_status(e, success); } /* * dispatch incoming message. * returns 1 on success, 0 for incomplete messages or -1 on error. */ static int process_message(u_int socknum) { u_int msg_len; u_char type; const u_char *cp; int r; SocketEntry *e; if (socknum >= sockets_alloc) fatal_f("sock %u >= allocated %u", socknum, sockets_alloc); e = &sockets[socknum]; if (sshbuf_len(e->input) < 5) return 0; /* Incomplete message header. */ cp = sshbuf_ptr(e->input); msg_len = PEEK_U32(cp); if (msg_len > AGENT_MAX_LEN) { debug_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) return 0; /* Incomplete message body. */ /* move the current input to e->request */ sshbuf_reset(e->request); if ((r = sshbuf_get_stringb(e->input, e->request)) != 0 || (r = sshbuf_get_u8(e->request, &type)) != 0) { if (r == SSH_ERR_MESSAGE_INCOMPLETE || r == SSH_ERR_STRING_TOO_LARGE) { error_fr(r, "parse"); return -1; } fatal_fr(r, "parse"); } debug_f("socket %u (fd=%d) type %d", socknum, e->fd, type); /* check whether agent is locked */ if (locked && type != SSH_AGENTC_UNLOCK) { sshbuf_reset(e->request); switch (type) { case SSH2_AGENTC_REQUEST_IDENTITIES: /* send empty lists */ no_identities(e); break; default: /* send a fail message for all other request types */ send_status(e, 0); } return 1; } switch (type) { case SSH_AGENTC_LOCK: case SSH_AGENTC_UNLOCK: process_lock_agent(e, type == SSH_AGENTC_LOCK); break; case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: process_remove_all_identities(e); /* safe for !WITH_SSH1 */ break; /* ssh2 */ case SSH2_AGENTC_SIGN_REQUEST: process_sign_request2(e); break; case SSH2_AGENTC_REQUEST_IDENTITIES: process_request_identities(e); break; case SSH2_AGENTC_ADD_IDENTITY: case SSH2_AGENTC_ADD_ID_CONSTRAINED: process_add_identity(e); break; case SSH2_AGENTC_REMOVE_IDENTITY: process_remove_identity(e); break; case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: process_remove_all_identities(e); break; #ifdef ENABLE_PKCS11 case SSH_AGENTC_ADD_SMARTCARD_KEY: case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED: process_add_smartcard_key(e); break; case SSH_AGENTC_REMOVE_SMARTCARD_KEY: process_remove_smartcard_key(e); break; #endif /* ENABLE_PKCS11 */ case SSH_AGENTC_EXTENSION: process_extension(e); break; default: /* Unknown message. Respond with failure. */ error("Unknown message %d", type); sshbuf_reset(e->request); send_status(e, 0); break; } return 1; } static void 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")); if (type == AUTH_CONNECTION) { debug("xcount %d -> %d", xcount, xcount + 1); ++xcount; } set_nonblock(fd); if (fd > max_fd) max_fd = fd; for (i = 0; i < sockets_alloc; i++) if (sockets[i].type == AUTH_UNUSED) { sockets[i].fd = fd; if ((sockets[i].input = sshbuf_new()) == NULL || (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 = 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 || (sockets[old_alloc].output = sshbuf_new()) == NULL || (sockets[old_alloc].request = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); sockets[old_alloc].type = type; } static int handle_socket_read(u_int socknum) { struct sockaddr_un sunaddr; socklen_t slen; uid_t euid; gid_t egid; int fd; slen = sizeof(sunaddr); fd = accept(sockets[socknum].fd, (struct sockaddr *)&sunaddr, &slen); if (fd == -1) { error("accept from AUTH_SOCKET: %s", strerror(errno)); return -1; } if (getpeereid(fd, &euid, &egid) == -1) { error("getpeereid %d failed: %s", fd, strerror(errno)); close(fd); return -1; } if ((euid != 0) && (getuid() != euid)) { error("uid mismatch: peer euid %u != uid %u", (u_int) euid, (u_int) getuid()); close(fd); return -1; } new_socket(AUTH_CONNECTION, fd); return 0; } static int handle_conn_read(u_int socknum) { char buf[AGENT_RBUF_LEN]; ssize_t len; int r; if ((len = read(sockets[socknum].fd, buf, sizeof(buf))) <= 0) { if (len == -1) { if (errno == EAGAIN || errno == EINTR) return 0; error_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_fr(r, "compose"); explicit_bzero(buf, sizeof(buf)); for (;;) { if ((r = process_message(socknum)) == -1) return -1; else if (r == 0) break; } return 0; } static int handle_conn_write(u_int socknum) { ssize_t len; int r; if (sshbuf_len(sockets[socknum].output) == 0) return 0; /* shouldn't happen */ if ((len = write(sockets[socknum].fd, sshbuf_ptr(sockets[socknum].output), sshbuf_len(sockets[socknum].output))) <= 0) { if (len == -1) { if (errno == EAGAIN || errno == EINTR) return 0; error_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_fr(r, "consume"); return 0; } static void after_poll(struct pollfd *pfd, size_t npfd, u_int maxfds) { size_t i; u_int socknum, activefds = npfd; for (i = 0; i < npfd; i++) { if (pfd[i].revents == 0) continue; /* Find sockets entry */ for (socknum = 0; socknum < sockets_alloc; socknum++) { if (sockets[socknum].type != AUTH_SOCKET && sockets[socknum].type != AUTH_CONNECTION) continue; if (pfd[i].fd == sockets[socknum].fd) break; } if (socknum >= sockets_alloc) { error_f("no socket for fd %d", pfd[i].fd); continue; } /* Process events */ switch (sockets[socknum].type) { case AUTH_SOCKET: if ((pfd[i].revents & (POLLIN|POLLERR)) == 0) break; if (npfd > maxfds) { debug3("out of fds (active %u >= limit %u); " "skipping accept", activefds, maxfds); break; } if (handle_socket_read(socknum) == 0) activefds++; break; case AUTH_CONNECTION: if ((pfd[i].revents & (POLLIN|POLLHUP|POLLERR)) != 0 && handle_conn_read(socknum) != 0) goto close_sock; if ((pfd[i].revents & (POLLOUT|POLLHUP)) != 0 && handle_conn_write(socknum) != 0) { close_sock: if (activefds == 0) fatal("activefds == 0 at close_sock"); close_socket(&sockets[socknum]); activefds--; break; } break; default: break; } } } static int prepare_poll(struct pollfd **pfdp, size_t *npfdp, int *timeoutp, u_int maxfds) { struct pollfd *pfd = *pfdp; size_t i, j, npfd = 0; time_t deadline; int r; /* Count active sockets */ for (i = 0; i < sockets_alloc; i++) { switch (sockets[i].type) { case AUTH_SOCKET: case AUTH_CONNECTION: npfd++; break; case AUTH_UNUSED: break; default: fatal("Unknown socket type %d", sockets[i].type); break; } } if (npfd != *npfdp && (pfd = recallocarray(pfd, *npfdp, npfd, sizeof(*pfd))) == NULL) fatal_f("recallocarray failed"); *pfdp = pfd; *npfdp = npfd; for (i = j = 0; i < sockets_alloc; i++) { switch (sockets[i].type) { case AUTH_SOCKET: if (npfd > maxfds) { debug3("out of fds (active %zu >= limit %u); " "skipping arming listener", npfd, maxfds); break; } pfd[j].fd = sockets[i].fd; pfd[j].revents = 0; pfd[j].events = POLLIN; j++; break; case AUTH_CONNECTION: pfd[j].fd = sockets[i].fd; pfd[j].revents = 0; /* * Only prepare to read if we can handle a full-size * input read buffer and enqueue a max size reply.. */ if ((r = sshbuf_check_reserve(sockets[i].input, AGENT_RBUF_LEN)) == 0 && (r = sshbuf_check_reserve(sockets[i].output, AGENT_MAX_LEN)) == 0) pfd[j].events = POLLIN; else if (r != SSH_ERR_NO_BUFFER_SPACE) fatal_fr(r, "reserve"); if (sshbuf_len(sockets[i].output) > 0) pfd[j].events |= POLLOUT; j++; break; default: break; } } deadline = reaper(); if (parent_alive_interval != 0) deadline = (deadline == 0) ? parent_alive_interval : MINIMUM(deadline, parent_alive_interval); if (deadline == 0) { *timeoutp = -1; /* INFTIM */ } else { if (deadline > INT_MAX / 1000) *timeoutp = INT_MAX / 1000; else *timeoutp = deadline * 1000; } return (1); } static void cleanup_socket(void) { if (cleanup_pid != 0 && getpid() != cleanup_pid) return; debug_f("cleanup"); if (socket_name[0]) unlink(socket_name); if (socket_dir[0]) rmdir(socket_dir); } void cleanup_exit(int i) { cleanup_socket(); _exit(i); } static void cleanup_handler(int sig) { cleanup_socket(); #ifdef ENABLE_PKCS11 pkcs11_terminate(); #endif _exit(2); } static void check_parent_exists(void) { /* * If our parent has exited then getppid() will return (pid_t)1, * so testing for that should be safe. */ if (parent_pid != -1 && getppid() != parent_pid) { /* printf("Parent has died - Authentication agent exiting.\n"); */ cleanup_socket(); _exit(2); } } static void usage(void) { fprintf(stderr, "usage: ssh-agent [-c | -s] [-Ddx] [-a bind_address] [-E fingerprint_hash]\n" " [-O option] [-P allowed_providers] [-t life]\n" " ssh-agent [-a bind_address] [-E fingerprint_hash] [-O option]\n" " [-P allowed_providers] [-t life] command [arg ...]\n" " ssh-agent [-c | -s] -k\n"); exit(1); } int main(int ac, char **av) { int c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0, s_flag = 0; int sock, ch, result, saved_errno; char *shell, *format, *pidstr, *agentsocket = NULL; #ifdef HAVE_SETRLIMIT struct rlimit rlim; #endif extern int optind; extern char *optarg; pid_t pid; char pidstrbuf[1 + 3 * sizeof pid]; size_t len; mode_t prev_mask; int timeout = -1; /* INFTIM */ struct pollfd *pfd = NULL; size_t npfd = 0; u_int maxfds; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); /* drop */ (void)setegid(getgid()); (void)setgid(getgid()); setuid(geteuid()); 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:O:P:t:x")) != -1) { switch (ch) { case 'E': fingerprint_hash = ssh_digest_alg_by_name(optarg); if (fingerprint_hash == -1) fatal("Invalid hash algorithm \"%s\"", optarg); break; case 'c': if (s_flag) usage(); c_flag++; break; case 'k': k_flag++; break; case 'O': if (strcmp(optarg, "no-restrict-websafe") == 0) restrict_websafe = 0; else if (strcmp(optarg, "allow-remote-pkcs11") == 0) remote_add_provider = 1; else fatal("Unknown -O option"); break; case 'P': if (allowed_providers != NULL) fatal("-P option already specified"); allowed_providers = xstrdup(optarg); break; case 's': if (c_flag) usage(); s_flag++; break; case 'd': if (d_flag || D_flag) usage(); d_flag++; break; case 'D': if (d_flag || D_flag) usage(); D_flag++; break; case 'a': agentsocket = optarg; break; case 't': if ((lifetime = convtime(optarg)) == -1) { fprintf(stderr, "Invalid lifetime\n"); usage(); } break; case 'x': xcount = 0; break; default: usage(); } } ac -= optind; av += optind; if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || D_flag)) usage(); if (allowed_providers == NULL) allowed_providers = xstrdup(DEFAULT_ALLOWED_PROVIDERS); if (ac == 0 && !c_flag && !s_flag) { shell = getenv("SHELL"); if (shell != NULL && (len = strlen(shell)) > 2 && strncmp(shell + len - 3, "csh", 3) == 0) c_flag = 1; } if (k_flag) { const char *errstr = NULL; pidstr = getenv(SSH_AGENTPID_ENV_NAME); if (pidstr == NULL) { fprintf(stderr, "%s not set, cannot kill agent\n", SSH_AGENTPID_ENV_NAME); exit(1); } pid = (int)strtonum(pidstr, 2, INT_MAX, &errstr); if (errstr) { fprintf(stderr, "%s=\"%s\", which is not a good PID: %s\n", SSH_AGENTPID_ENV_NAME, pidstr, errstr); exit(1); } if (kill(pid, SIGTERM) == -1) { perror("kill"); exit(1); } format = c_flag ? "unsetenv %s;\n" : "unset %s;\n"; printf(format, SSH_AUTHSOCKET_ENV_NAME); printf(format, SSH_AGENTPID_ENV_NAME); printf("echo Agent pid %ld killed;\n", (long)pid); exit(0); } /* * Minimum file descriptors: * stdio (3) + listener (1) + syslog (1 maybe) + connection (1) + * a few spare for libc / stack protectors / sanitisers, etc. */ #define SSH_AGENT_MIN_FDS (3+1+1+1+4) if (rlim.rlim_cur < SSH_AGENT_MIN_FDS) fatal("%s: file descriptor rlimit %lld too low (minimum %u)", __progname, (long long)rlim.rlim_cur, SSH_AGENT_MIN_FDS); maxfds = rlim.rlim_cur - SSH_AGENT_MIN_FDS; parent_pid = getpid(); if (agentsocket == NULL) { /* Create private directory for agent socket */ mktemp_proto(socket_dir, sizeof(socket_dir)); if (mkdtemp(socket_dir) == NULL) { perror("mkdtemp: private socket dir"); exit(1); } snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir, (long)parent_pid); } else { /* Try to use specified agent socket */ socket_dir[0] = '\0'; strlcpy(socket_name, agentsocket, sizeof socket_name); } /* * Create socket early so it will exist before command gets run from * the parent. */ prev_mask = umask(0177); sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0); if (sock < 0) { /* XXX - unix_listener() calls error() not perror() */ *socket_name = '\0'; /* Don't unlink any existing file */ cleanup_exit(1); } umask(prev_mask); /* * Fork, and have the parent execute the command, if any, or present * the socket data. The child continues as the authentication agent. */ if (D_flag || d_flag) { log_init(__progname, d_flag ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 1); format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, SSH_AUTHSOCKET_ENV_NAME); printf("echo Agent pid %ld;\n", (long)parent_pid); fflush(stdout); goto skip; } pid = fork(); if (pid == -1) { perror("fork"); cleanup_exit(1); } if (pid != 0) { /* Parent - execute the given command. */ close(sock); snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid); if (ac == 0) { format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, SSH_AUTHSOCKET_ENV_NAME); printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf, SSH_AGENTPID_ENV_NAME); printf("echo Agent pid %ld;\n", (long)pid); exit(0); } if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 || setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) { perror("setenv"); exit(1); } execvp(av[0], av); perror(av[0]); exit(1); } /* child */ log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0); if (setsid() == -1) { error("setsid: %s", strerror(errno)); cleanup_exit(1); } (void)chdir("/"); if (stdfd_devnull(1, 1, 1) == -1) error_f("stdfd_devnull failed"); #ifdef HAVE_SETRLIMIT /* deny core dumps, since memory contains unencrypted private keys */ rlim.rlim_cur = rlim.rlim_max = 0; if (setrlimit(RLIMIT_CORE, &rlim) == -1) { error("setrlimit RLIMIT_CORE: %s", strerror(errno)); cleanup_exit(1); } #endif skip: cleanup_pid = getpid(); #ifdef ENABLE_PKCS11 pkcs11_init(0); #endif new_socket(AUTH_SOCKET, sock); if (ac > 0) parent_alive_interval = 10; idtab_init(); 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)); platform_pledge_agent(); while (1) { prepare_poll(&pfd, &npfd, &timeout, maxfds); result = poll(pfd, npfd, timeout); saved_errno = errno; if (parent_alive_interval != 0) check_parent_exists(); (void) reaper(); /* remove expired keys */ if (result == -1) { if (saved_errno == EINTR) continue; fatal("poll: %s", strerror(saved_errno)); } else if (result > 0) after_poll(pfd, npfd, maxfds); } /* NOTREACHED */ } diff --git a/crypto/openssh/ssh-pkcs11-client.c b/crypto/openssh/ssh-pkcs11-client.c index 061b0681e43a..82e86a518443 100644 --- a/crypto/openssh/ssh-pkcs11-client.c +++ b/crypto/openssh/ssh-pkcs11-client.c @@ -1,600 +1,654 @@ -/* $OpenBSD: ssh-pkcs11-client.c,v 1.18 2023/07/19 14:03:45 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11-client.c,v 1.19 2023/12/18 14:46:56 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * Copyright (c) 2014 Pedro Martelletto. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "includes.h" #ifdef ENABLE_PKCS11 #include #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #include #include #include #include #include #include "pathnames.h" #include "xmalloc.h" #include "sshbuf.h" #include "log.h" #include "misc.h" #include "sshkey.h" #include "authfd.h" #include "atomicio.h" #include "ssh-pkcs11.h" #include "ssherr.h" #include "openbsd-compat/openssl-compat.h" #if !defined(OPENSSL_HAS_ECC) || !defined(HAVE_EC_KEY_METHOD_NEW) #define EC_KEY_METHOD void #define EC_KEY void #endif /* borrows code from sftp-server and ssh-agent */ /* * Maintain a list of ssh-pkcs11-helper subprocesses. These may be looked up * by provider path or their unique EC/RSA METHOD pointers. */ struct helper { char *path; pid_t pid; int fd; RSA_METHOD *rsa_meth; EC_KEY_METHOD *ec_meth; int (*rsa_finish)(RSA *rsa); void (*ec_finish)(EC_KEY *key); size_t nrsa, nec; /* number of active keys of each type */ }; static struct helper **helpers; static size_t nhelpers; static struct helper * helper_by_provider(const char *path) { size_t i; for (i = 0; i < nhelpers; i++) { if (helpers[i] == NULL || helpers[i]->path == NULL || helpers[i]->fd == -1) continue; if (strcmp(helpers[i]->path, path) == 0) return helpers[i]; } return NULL; } static struct helper * helper_by_rsa(const RSA *rsa) { size_t i; const RSA_METHOD *meth; if ((meth = RSA_get_method(rsa)) == NULL) return NULL; for (i = 0; i < nhelpers; i++) { if (helpers[i] != NULL && helpers[i]->rsa_meth == meth) return helpers[i]; } return NULL; } #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) static struct helper * helper_by_ec(const EC_KEY *ec) { size_t i; const EC_KEY_METHOD *meth; if ((meth = EC_KEY_get_method(ec)) == NULL) return NULL; for (i = 0; i < nhelpers; i++) { if (helpers[i] != NULL && helpers[i]->ec_meth == meth) return helpers[i]; } return NULL; } #endif /* defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) */ static void helper_free(struct helper *helper) { size_t i; int found = 0; if (helper == NULL) return; if (helper->path == NULL || helper->ec_meth == NULL || helper->rsa_meth == NULL) fatal_f("inconsistent helper"); debug3_f("free helper for provider %s", helper->path); for (i = 0; i < nhelpers; i++) { if (helpers[i] == helper) { if (found) fatal_f("helper recorded more than once"); found = 1; } else if (found) helpers[i - 1] = helpers[i]; } if (found) { helpers = xrecallocarray(helpers, nhelpers, nhelpers - 1, sizeof(*helpers)); nhelpers--; } free(helper->path); #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) EC_KEY_METHOD_free(helper->ec_meth); #endif RSA_meth_free(helper->rsa_meth); free(helper); } static void helper_terminate(struct helper *helper) { if (helper == NULL) { return; } else if (helper->fd == -1) { debug3_f("already terminated"); } else { debug3_f("terminating helper for %s; " "remaining %zu RSA %zu ECDSA", helper->path, helper->nrsa, helper->nec); close(helper->fd); /* XXX waitpid() */ helper->fd = -1; helper->pid = -1; } /* * Don't delete the helper entry until there are no remaining keys * that reference it. Otherwise, any signing operation would call * a free'd METHOD pointer and that would be bad. */ if (helper->nrsa == 0 && helper->nec == 0) helper_free(helper); } static void send_msg(int fd, struct sshbuf *m) { u_char buf[4]; size_t mlen = sshbuf_len(m); int r; if (fd == -1) return; POKE_U32(buf, mlen); if (atomicio(vwrite, fd, buf, 4) != 4 || atomicio(vwrite, fd, sshbuf_mutable_ptr(m), sshbuf_len(m)) != sshbuf_len(m)) error("write to helper failed"); if ((r = sshbuf_consume(m, mlen)) != 0) fatal_fr(r, "consume"); } static int recv_msg(int fd, struct sshbuf *m) { u_int l, len; u_char c, buf[1024]; int r; sshbuf_reset(m); if (fd == -1) return 0; /* XXX */ if ((len = atomicio(read, fd, buf, 4)) != 4) { error("read from helper failed: %u", len); return (0); /* XXX */ } len = PEEK_U32(buf); if (len > 256 * 1024) fatal("response too long: %u", len); /* read len bytes into m */ while (len > 0) { l = len; if (l > sizeof(buf)) l = sizeof(buf); if (atomicio(read, fd, buf, l) != l) { error("response from helper failed."); return (0); /* XXX */ } if ((r = sshbuf_put(m, buf, l)) != 0) fatal_fr(r, "sshbuf_put"); len -= l; } if ((r = sshbuf_get_u8(m, &c)) != 0) fatal_fr(r, "parse type"); return c; } int pkcs11_init(int interactive) { return 0; } void pkcs11_terminate(void) { size_t i; debug3_f("terminating %zu helpers", nhelpers); for (i = 0; i < nhelpers; i++) helper_terminate(helpers[i]); } static int rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding) { struct sshkey *key = NULL; struct sshbuf *msg = NULL; u_char *blob = NULL, *signature = NULL; size_t blen, slen = 0; int r, ret = -1; struct helper *helper; if ((helper = helper_by_rsa(rsa)) == NULL || helper->fd == -1) fatal_f("no helper for PKCS11 key"); debug3_f("signing with PKCS11 provider %s", helper->path); if (padding != RSA_PKCS1_PADDING) goto fail; key = sshkey_new(KEY_UNSPEC); if (key == NULL) { 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_fr(r, "encode key"); goto fail; } if ((msg = sshbuf_new()) == NULL) 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_fr(r, "compose"); send_msg(helper->fd, msg); sshbuf_reset(msg); if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) { if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0) fatal_fr(r, "parse"); if (slen <= (size_t)RSA_size(rsa)) { memcpy(to, signature, slen); ret = slen; } free(signature); } fail: free(blob); sshkey_free(key); sshbuf_free(msg); return (ret); } static int rsa_finish(RSA *rsa) { struct helper *helper; if ((helper = helper_by_rsa(rsa)) == NULL) fatal_f("no helper for PKCS11 key"); debug3_f("free PKCS11 RSA key for provider %s", helper->path); if (helper->rsa_finish != NULL) helper->rsa_finish(rsa); if (helper->nrsa == 0) fatal_f("RSA refcount error"); helper->nrsa--; debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA", helper->path, helper->nrsa, helper->nec); if (helper->nrsa == 0 && helper->nec == 0) helper_terminate(helper); return 1; } #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) static ECDSA_SIG * ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, const BIGNUM *rp, EC_KEY *ec) { struct sshkey *key = NULL; struct sshbuf *msg = NULL; ECDSA_SIG *ret = NULL; const u_char *cp; u_char *blob = NULL, *signature = NULL; size_t blen, slen = 0; int r, nid; struct helper *helper; if ((helper = helper_by_ec(ec)) == NULL || helper->fd == -1) fatal_f("no helper for PKCS11 key"); debug3_f("signing with PKCS11 provider %s", helper->path); nid = sshkey_ecdsa_key_to_nid(ec); if (nid < 0) { error_f("couldn't get curve nid"); goto fail; } key = sshkey_new(KEY_UNSPEC); if (key == NULL) { error_f("sshkey_new failed"); goto fail; } key->ecdsa = ec; key->ecdsa_nid = nid; key->type = KEY_ECDSA; EC_KEY_up_ref(ec); if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) { error_fr(r, "encode key"); goto fail; } if ((msg = sshbuf_new()) == NULL) 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_fr(r, "compose"); send_msg(helper->fd, msg); sshbuf_reset(msg); if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) { if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0) fatal_fr(r, "parse"); cp = signature; ret = d2i_ECDSA_SIG(NULL, &cp, slen); free(signature); } fail: free(blob); sshkey_free(key); sshbuf_free(msg); return (ret); } static void ecdsa_do_finish(EC_KEY *ec) { struct helper *helper; if ((helper = helper_by_ec(ec)) == NULL) fatal_f("no helper for PKCS11 key"); debug3_f("free PKCS11 ECDSA key for provider %s", helper->path); if (helper->ec_finish != NULL) helper->ec_finish(ec); if (helper->nec == 0) fatal_f("ECDSA refcount error"); helper->nec--; debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA", helper->path, helper->nrsa, helper->nec); if (helper->nrsa == 0 && helper->nec == 0) helper_terminate(helper); } #endif /* defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) */ /* redirect private key crypto operations to the ssh-pkcs11-helper */ static void wrap_key(struct helper *helper, struct sshkey *k) { debug3_f("wrap %s for provider %s", sshkey_type(k), helper->path); if (k->type == KEY_RSA) { RSA_set_method(k->rsa, helper->rsa_meth); if (helper->nrsa++ >= INT_MAX) fatal_f("RSA refcount error"); #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) } else if (k->type == KEY_ECDSA) { EC_KEY_set_method(k->ecdsa, helper->ec_meth); if (helper->nec++ >= INT_MAX) fatal_f("EC refcount error"); #endif } else fatal_f("unknown key type"); k->flags |= SSHKEY_FLAG_EXT; debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA", helper->path, helper->nrsa, helper->nec); } +/* + * Make a private PKCS#11-backed certificate by grafting a previously-loaded + * PKCS#11 private key and a public certificate key. + */ +int +pkcs11_make_cert(const struct sshkey *priv, + const struct sshkey *certpub, struct sshkey **certprivp) +{ + struct helper *helper = NULL; + struct sshkey *ret; + int r; + + debug3_f("private key type %s cert type %s", sshkey_type(priv), + sshkey_type(certpub)); + *certprivp = NULL; + if (!sshkey_is_cert(certpub) || sshkey_is_cert(priv) || + !sshkey_equal_public(priv, certpub)) { + error_f("private key %s doesn't match cert %s", + sshkey_type(priv), sshkey_type(certpub)); + return SSH_ERR_INVALID_ARGUMENT; + } + *certprivp = NULL; + if (priv->type == KEY_RSA) { + if ((helper = helper_by_rsa(priv->rsa)) == NULL || + helper->fd == -1) + fatal_f("no helper for PKCS11 RSA key"); + if ((r = sshkey_from_private(priv, &ret)) != 0) + fatal_fr(r, "copy key"); + RSA_set_method(ret->rsa, helper->rsa_meth); + if (helper->nrsa++ >= INT_MAX) + fatal_f("RSA refcount error"); + } else if (priv->type == KEY_ECDSA) { + if ((helper = helper_by_ec(priv->ecdsa)) == NULL || + helper->fd == -1) + fatal_f("no helper for PKCS11 EC key"); + if ((r = sshkey_from_private(priv, &ret)) != 0) + fatal_fr(r, "copy key"); + EC_KEY_set_method(ret->ecdsa, helper->ec_meth); + if (helper->nec++ >= INT_MAX) + fatal_f("EC refcount error"); + } else + fatal_f("unknown key type %s", sshkey_type(priv)); + + ret->flags |= SSHKEY_FLAG_EXT; + if ((r = sshkey_to_certified(ret)) != 0 || + (r = sshkey_cert_copy(certpub, ret)) != 0) + fatal_fr(r, "graft certificate"); + debug3_f("provider %s remaining keys: %zu RSA %zu ECDSA", + helper->path, helper->nrsa, helper->nec); + /* success */ + *certprivp = ret; + return 0; +} + static int pkcs11_start_helper_methods(struct helper *helper) { RSA_METHOD *rsa_meth; EC_KEY_METHOD *ec_meth = NULL; #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) int (*ec_init)(EC_KEY *key); int (*ec_copy)(EC_KEY *dest, const EC_KEY *src); int (*ec_set_group)(EC_KEY *key, const EC_GROUP *grp); int (*ec_set_private)(EC_KEY *key, const BIGNUM *priv_key); int (*ec_set_public)(EC_KEY *key, const EC_POINT *pub_key); int (*ec_sign)(int, const unsigned char *, int, unsigned char *, unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL; if ((ec_meth = EC_KEY_METHOD_new(EC_KEY_OpenSSL())) == NULL) return -1; EC_KEY_METHOD_get_sign(ec_meth, &ec_sign, NULL, NULL); EC_KEY_METHOD_set_sign(ec_meth, ec_sign, NULL, ecdsa_do_sign); EC_KEY_METHOD_get_init(ec_meth, &ec_init, &helper->ec_finish, &ec_copy, &ec_set_group, &ec_set_private, &ec_set_public); EC_KEY_METHOD_set_init(ec_meth, ec_init, ecdsa_do_finish, ec_copy, ec_set_group, ec_set_private, ec_set_public); #endif /* defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) */ if ((rsa_meth = RSA_meth_dup(RSA_get_default_method())) == NULL) fatal_f("RSA_meth_dup failed"); helper->rsa_finish = RSA_meth_get_finish(rsa_meth); if (!RSA_meth_set1_name(rsa_meth, "ssh-pkcs11-helper") || !RSA_meth_set_priv_enc(rsa_meth, rsa_encrypt) || !RSA_meth_set_finish(rsa_meth, rsa_finish)) fatal_f("failed to prepare method"); helper->ec_meth = ec_meth; helper->rsa_meth = rsa_meth; return 0; } static struct helper * pkcs11_start_helper(const char *path) { int pair[2]; char *prog, *verbosity = NULL; struct helper *helper; pid_t pid; if (nhelpers >= INT_MAX) fatal_f("too many helpers"); debug3_f("start helper for %s", path); if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { error_f("socketpair: %s", strerror(errno)); return NULL; } helper = xcalloc(1, sizeof(*helper)); if (pkcs11_start_helper_methods(helper) == -1) { error_f("pkcs11_start_helper_methods failed"); goto fail; } if ((pid = fork()) == -1) { error_f("fork: %s", strerror(errno)); fail: close(pair[0]); close(pair[1]); RSA_meth_free(helper->rsa_meth); #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) EC_KEY_METHOD_free(helper->ec_meth); #endif free(helper); return NULL; } else if (pid == 0) { if ((dup2(pair[1], STDIN_FILENO) == -1) || (dup2(pair[1], STDOUT_FILENO) == -1)) { fprintf(stderr, "dup2: %s\n", strerror(errno)); _exit(1); } close(pair[0]); close(pair[1]); prog = getenv("SSH_PKCS11_HELPER"); if (prog == NULL || strlen(prog) == 0) prog = _PATH_SSH_PKCS11_HELPER; if (log_level_get() >= SYSLOG_LEVEL_DEBUG1) verbosity = "-vvv"; debug_f("starting %s %s", prog, verbosity == NULL ? "" : verbosity); execlp(prog, prog, verbosity, (char *)NULL); fprintf(stderr, "exec: %s: %s\n", prog, strerror(errno)); _exit(1); } close(pair[1]); helper->fd = pair[0]; helper->path = xstrdup(path); helper->pid = pid; debug3_f("helper %zu for \"%s\" on fd %d pid %ld", nhelpers, helper->path, helper->fd, (long)helper->pid); helpers = xrecallocarray(helpers, nhelpers, nhelpers + 1, sizeof(*helpers)); helpers[nhelpers++] = helper; return helper; } int 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; struct helper *helper; if ((helper = helper_by_provider(name)) == NULL && (helper = pkcs11_start_helper(name)) == NULL) return -1; if ((msg = sshbuf_new()) == NULL) 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_fr(r, "compose"); send_msg(helper->fd, msg); sshbuf_reset(msg); type = recv_msg(helper->fd, msg); if (type == SSH2_AGENT_IDENTITIES_ANSWER) { if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) 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_get_cstring(msg, &label, NULL)) != 0) fatal_fr(r, "parse key"); if ((r = sshkey_from_blob(blob, blen, &k)) != 0) fatal_fr(r, "decode key"); wrap_key(helper, k); (*keysp)[i] = k; if (labelsp) (*labelsp)[i] = label; else free(label); free(blob); } } else if (type == SSH2_AGENT_FAILURE) { if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) nkeys = -1; } else { nkeys = -1; } sshbuf_free(msg); return (nkeys); } int pkcs11_del_provider(char *name) { struct helper *helper; /* * ssh-agent deletes keys before calling this, so the helper entry * should be gone before we get here. */ debug3_f("delete %s", name); if ((helper = helper_by_provider(name)) != NULL) helper_terminate(helper); return 0; } #endif /* ENABLE_PKCS11 */ diff --git a/crypto/openssh/ssh-pkcs11.h b/crypto/openssh/ssh-pkcs11.h index 81f1d7c5d392..526022319b4b 100644 --- a/crypto/openssh/ssh-pkcs11.h +++ b/crypto/openssh/ssh-pkcs11.h @@ -1,40 +1,43 @@ -/* $OpenBSD: ssh-pkcs11.h,v 1.6 2020/01/25 00:03:36 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11.h,v 1.7 2023/12/18 14:46:56 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* Errors for pkcs11_add_provider() */ #define SSH_PKCS11_ERR_GENERIC 1 #define SSH_PKCS11_ERR_LOGIN_FAIL 2 #define SSH_PKCS11_ERR_NO_SLOTS 3 #define SSH_PKCS11_ERR_PIN_REQUIRED 4 #define SSH_PKCS11_ERR_PIN_LOCKED 5 int pkcs11_init(int); void pkcs11_terminate(void); int pkcs11_add_provider(char *, char *, struct sshkey ***, char ***); int pkcs11_del_provider(char *); #ifdef WITH_PKCS11_KEYGEN struct sshkey * pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int, unsigned int, unsigned char, u_int32_t *); struct sshkey * pkcs11_destroy_keypair(char *, char *, unsigned long, unsigned char, u_int32_t *); #endif +/* Only available in ssh-pkcs11-client.c so far */ +int pkcs11_make_cert(const struct sshkey *, + const struct sshkey *, struct sshkey **); #if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11) #undef ENABLE_PKCS11 #endif diff --git a/crypto/openssh/ssh.1 b/crypto/openssh/ssh.1 index bd8c2ff6a55a..936c995ba448 100644 --- a/crypto/openssh/ssh.1 +++ b/crypto/openssh/ssh.1 @@ -1,1796 +1,1797 @@ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland .\" All rights reserved .\" .\" As far as I am concerned, the code I have written for this software .\" can be used freely for any purpose. Any derived versions of this .\" software must be clearly marked as such, and if the derived work is .\" incompatible with the protocol description in the RFC file, it must be .\" called by a name other than "ssh" or "Secure Shell". .\" .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh.1,v 1.437 2023/07/23 20:04:45 naddy Exp $ -.Dd $Mdocdate: July 23 2023 $ +.\" $OpenBSD: ssh.1,v 1.438 2023/10/11 23:14:33 djm Exp $ +.Dd $Mdocdate: October 11 2023 $ .Dt SSH 1 .Os .Sh NAME .Nm ssh .Nd OpenSSH remote login client .Sh SYNOPSIS .Nm ssh .Op Fl 46AaCfGgKkMNnqsTtVvXxYy .Op Fl B Ar bind_interface .Op Fl b Ar bind_address .Op Fl c Ar cipher_spec .Op Fl D Oo Ar bind_address : Oc Ns Ar port .Op Fl E Ar log_file .Op Fl e Ar escape_char .Op Fl F Ar configfile .Op Fl I Ar pkcs11 .Op Fl i Ar identity_file .Op Fl J Ar destination .Op Fl L Ar address .Op Fl l Ar login_name .Op Fl m Ar mac_spec .Op Fl O Ar ctl_cmd .Op Fl o Ar option .Op Fl P Ar tag .Op Fl p Ar port -.Op Fl Q Ar query_option .Op Fl R Ar address .Op Fl S Ar ctl_path .Op Fl W Ar host : Ns Ar port .Op Fl w Ar local_tun Ns Op : Ns Ar remote_tun .Ar destination .Op Ar command Op Ar argument ... +.Nm +.Op Fl Q Ar query_option .Sh DESCRIPTION .Nm (SSH client) is a program for logging into a remote machine and for executing commands on a remote machine. It is intended to provide secure encrypted communications between two untrusted hosts over an insecure network. X11 connections, arbitrary TCP ports and .Ux Ns -domain sockets can also be forwarded over the secure channel. .Pp .Nm connects and logs into the specified .Ar destination , which may be specified as either .Sm off .Oo user @ Oc hostname .Sm on or a URI of the form .Sm off .No ssh:// Oo user @ Oc hostname Op : port . .Sm on The user must prove their identity to the remote machine using one of several methods (see below). .Pp If a .Ar command is specified, it will be executed on the remote host instead of a login shell. A complete command line may be specified as .Ar command , or it may have additional arguments. If supplied, the arguments will be appended to the command, separated by spaces, before it is sent to the server to be executed. .Pp The options are as follows: .Pp .Bl -tag -width Ds -compact .It Fl 4 Forces .Nm to use IPv4 addresses only. .Pp .It Fl 6 Forces .Nm to use IPv6 addresses only. .Pp .It Fl A Enables forwarding of 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. Users with the ability to bypass file permissions on the remote host (for the agent's .Ux Ns -domain socket) can access the local agent through the forwarded connection. An attacker cannot obtain key material from the agent, however they can perform operations on the keys that enable them to authenticate using the identities loaded into the agent. A safer alternative may be to use a jump host (see .Fl J ) . .Pp .It Fl a Disables forwarding of the authentication agent connection. .Pp .It Fl B Ar bind_interface Bind to the address of .Ar bind_interface before attempting to connect to the destination host. This is only useful on systems with more than one address. .Pp .It Fl b Ar bind_address Use .Ar bind_address on the local machine as the source address of the connection. Only useful on systems with more than one address. .Pp .It Fl C Requests compression of all data (including stdin, stdout, stderr, and data for forwarded X11, TCP and .Ux Ns -domain connections). The compression algorithm is the same used by .Xr gzip 1 . Compression is desirable on modem lines and other slow connections, but will only slow down things on fast networks. The default value can be set on a host-by-host basis in the configuration files; see the .Cm Compression option in .Xr ssh_config 5 . .Pp .It Fl c Ar cipher_spec Selects the cipher specification for encrypting the session. .Ar cipher_spec is a comma-separated list of ciphers listed in order of preference. See the .Cm Ciphers keyword in .Xr ssh_config 5 for more information. .Pp .It Fl D Xo .Sm off .Oo Ar bind_address : Oc .Ar port .Sm on .Xc Specifies a local .Dq dynamic application-level port forwarding. This works by allocating a socket to listen to .Ar port on the local side, optionally bound to the specified .Ar bind_address . Whenever a connection is made to this port, the connection is forwarded over the secure channel, and the application protocol is then used to determine where to connect to from the remote machine. Currently the SOCKS4 and SOCKS5 protocols are supported, and .Nm will act as a SOCKS server. Only root can forward privileged ports. Dynamic port forwardings can also be specified in the configuration file. .Pp IPv6 addresses can be specified by enclosing the address in square brackets. Only the superuser can forward privileged ports. By default, the local port is bound in accordance with the .Cm GatewayPorts setting. However, an explicit .Ar bind_address may be used to bind the connection to a specific address. The .Ar bind_address of .Dq localhost indicates that the listening port be bound for local use only, while an empty address or .Sq * indicates that the port should be available from all interfaces. .Pp .It Fl E Ar log_file Append debug logs to .Ar log_file instead of standard error. .Pp .It Fl e Ar escape_char Sets the escape character for sessions with a pty (default: .Ql ~ ) . The escape character is only recognized at the beginning of a line. The escape character followed by a dot .Pq Ql \&. closes the connection; followed by control-Z suspends the connection; and followed by itself sends the escape character once. Setting the character to .Dq none disables any escapes and makes the session fully transparent. .Pp .It Fl F Ar configfile Specifies an alternative per-user configuration file. If a configuration file is given on the command line, the system-wide configuration file .Pq Pa /etc/ssh/ssh_config will be ignored. The default for the per-user configuration file is .Pa ~/.ssh/config . If set to .Dq none , no configuration files will be read. .Pp .It Fl f Requests .Nm to go to background just before command execution. This is useful if .Nm is going to ask for passwords or passphrases, but the user wants it in the background. This implies .Fl n . The recommended way to start X11 programs at a remote site is with something like .Ic ssh -f host xterm . .Pp If the .Cm ExitOnForwardFailure configuration option is set to .Dq yes , then a client started with .Fl f will wait for all remote port forwards to be successfully established before placing itself in the background. Refer to the description of .Cm ForkAfterAuthentication in .Xr ssh_config 5 for details. .Pp .It Fl G Causes .Nm to print its configuration after evaluating .Cm Host and .Cm Match blocks and exit. .Pp .It Fl g Allows remote hosts to connect to local forwarded ports. If used on a multiplexed connection, then this option must be specified on the master process. .Pp .It Fl I Ar pkcs11 Specify the PKCS#11 shared library .Nm should use to communicate with a PKCS#11 token providing keys for user authentication. .Pp .It Fl i Ar identity_file Selects a file from which the identity (private key) for public key authentication is read. You can also specify a public key file to use the corresponding private key that is loaded in .Xr ssh-agent 1 when the private key file is not present locally. The default is .Pa ~/.ssh/id_rsa , .Pa ~/.ssh/id_ecdsa , .Pa ~/.ssh/id_ecdsa_sk , .Pa ~/.ssh/id_ed25519 , .Pa ~/.ssh/id_ed25519_sk and .Pa ~/.ssh/id_dsa . Identity files may also be specified on a per-host basis in the configuration file. It is possible to have multiple .Fl i options (and multiple identities specified in configuration files). If no certificates have been explicitly specified by the .Cm CertificateFile directive, .Nm will also try to load certificate information from the filename obtained by appending .Pa -cert.pub to identity filenames. .Pp .It Fl J Ar destination Connect to the target host by first making an .Nm connection to the jump host described by .Ar destination and then establishing a TCP forwarding to the ultimate destination from there. Multiple jump hops may be specified separated by comma characters. This is a shortcut to specify a .Cm ProxyJump configuration directive. Note that configuration directives supplied on the command-line generally apply to the destination host and not any specified jump hosts. Use .Pa ~/.ssh/config to specify configuration for jump hosts. .Pp .It Fl K Enables GSSAPI-based authentication and forwarding (delegation) of GSSAPI credentials to the server. .Pp .It Fl k Disables forwarding (delegation) of GSSAPI credentials to the server. .Pp .It Fl L Xo .Sm off .Oo Ar bind_address : Oc .Ar port : host : hostport .Sm on .Xc .It Fl L Xo .Sm off .Oo Ar bind_address : Oc .Ar port : remote_socket .Sm on .Xc .It Fl L Xo .Sm off .Ar local_socket : host : hostport .Sm on .Xc .It Fl L Xo .Sm off .Ar local_socket : remote_socket .Sm on .Xc Specifies that connections to the given TCP port or Unix socket on the local (client) host are to be forwarded to the given host and port, or Unix socket, on the remote side. This works by allocating a socket to listen to either a TCP .Ar port on the local side, optionally bound to the specified .Ar bind_address , or to a Unix socket. Whenever a connection is made to the local port or socket, the connection is forwarded over the secure channel, and a connection is made to either .Ar host port .Ar hostport , or the Unix socket .Ar remote_socket , from the remote machine. .Pp Port forwardings can also be specified in the configuration file. Only the superuser can forward privileged ports. IPv6 addresses can be specified by enclosing the address in square brackets. .Pp By default, the local port is bound in accordance with the .Cm GatewayPorts setting. However, an explicit .Ar bind_address may be used to bind the connection to a specific address. The .Ar bind_address of .Dq localhost indicates that the listening port be bound for local use only, while an empty address or .Sq * indicates that the port should be available from all interfaces. .Pp .It Fl l Ar login_name Specifies the user to log in as on the remote machine. This also may be specified on a per-host basis in the configuration file. .Pp .It Fl M Places the .Nm client into .Dq master mode for connection sharing. Multiple .Fl M options places .Nm into .Dq master mode but with confirmation required using .Xr ssh-askpass 1 before each operation that changes the multiplexing state (e.g. opening a new session). Refer to the description of .Cm ControlMaster in .Xr ssh_config 5 for details. .Pp .It Fl m Ar mac_spec A comma-separated list of MAC (message authentication code) algorithms, specified in order of preference. See the .Cm MACs keyword in .Xr ssh_config 5 for more information. .Pp .It Fl N Do not execute a remote command. This is useful for just forwarding ports. Refer to the description of .Cm SessionType in .Xr ssh_config 5 for details. .Pp .It Fl n Redirects stdin from .Pa /dev/null (actually, prevents reading from stdin). This must be used when .Nm is run in the background. A common trick is to use this to run X11 programs on a remote machine. For example, .Ic ssh -n shadows.cs.hut.fi emacs & will start an emacs on shadows.cs.hut.fi, and the X11 connection will be automatically forwarded over an encrypted channel. The .Nm program will be put in the background. (This does not work if .Nm needs to ask for a password or passphrase; see also the .Fl f option.) Refer to the description of .Cm StdinNull in .Xr ssh_config 5 for details. .Pp .It Fl O Ar ctl_cmd Control an active connection multiplexing master process. When the .Fl O option is specified, the .Ar ctl_cmd argument is interpreted and passed to the master process. Valid commands are: .Dq check (check that the master process is running), .Dq forward (request forwardings without command execution), .Dq cancel (cancel forwardings), .Dq exit (request the master to exit), and .Dq stop (request the master to stop accepting further multiplexing requests). .Pp .It Fl o Ar option Can be used to give options in the format used in the configuration file. This is useful for specifying options for which there is no separate command-line flag. For full details of the options listed below, and their possible values, see .Xr ssh_config 5 . .Pp .Bl -tag -width Ds -offset indent -compact .It AddKeysToAgent .It AddressFamily .It BatchMode .It BindAddress .It CanonicalDomains .It CanonicalizeFallbackLocal .It CanonicalizeHostname .It CanonicalizeMaxDots .It CanonicalizePermittedCNAMEs .It CASignatureAlgorithms .It CertificateFile .It CheckHostIP .It Ciphers .It ClearAllForwardings .It Compression .It ConnectionAttempts .It ConnectTimeout .It ControlMaster .It ControlPath .It ControlPersist .It DynamicForward .It EnableEscapeCommandline .It EscapeChar .It ExitOnForwardFailure .It FingerprintHash .It ForkAfterAuthentication .It ForwardAgent .It ForwardX11 .It ForwardX11Timeout .It ForwardX11Trusted .It GatewayPorts .It GlobalKnownHostsFile .It GSSAPIAuthentication .It GSSAPIDelegateCredentials .It HashKnownHosts .It Host .It HostbasedAcceptedAlgorithms .It HostbasedAuthentication .It HostKeyAlgorithms .It HostKeyAlias .It Hostname .It IdentitiesOnly .It IdentityAgent .It IdentityFile .It IPQoS .It KbdInteractiveAuthentication .It KbdInteractiveDevices .It KexAlgorithms .It KnownHostsCommand .It LocalCommand .It LocalForward .It LogLevel .It MACs .It Match .It NoHostAuthenticationForLocalhost .It NumberOfPasswordPrompts .It PasswordAuthentication .It PermitLocalCommand .It PermitRemoteOpen .It PKCS11Provider .It Port .It PreferredAuthentications .It ProxyCommand .It ProxyJump .It ProxyUseFdpass .It PubkeyAcceptedAlgorithms .It PubkeyAuthentication .It RekeyLimit .It RemoteCommand .It RemoteForward .It RequestTTY .It RequiredRSASize .It SendEnv .It ServerAliveInterval .It ServerAliveCountMax .It SessionType .It SetEnv .It StdinNull .It StreamLocalBindMask .It StreamLocalBindUnlink .It StrictHostKeyChecking .It TCPKeepAlive .It Tunnel .It TunnelDevice .It UpdateHostKeys .It User .It UserKnownHostsFile .It VerifyHostKeyDNS .It VisualHostKey .It XAuthLocation .El .Pp .It Fl P Ar tag Specify a tag name that may be used to select configuration in .Xr ssh_config 5 . Refer to the .Cm Tag and .Cm Match keywords in .Xr ssh_config 5 for more information. .It Fl p Ar port Port to connect to on the remote host. This can be specified on a per-host basis in the configuration file. .Pp .It Fl Q Ar query_option Queries for the algorithms supported by one of the following features: .Ar cipher (supported symmetric ciphers), .Ar cipher-auth (supported symmetric ciphers that support authenticated encryption), .Ar help (supported query terms for use with the .Fl Q flag), .Ar mac (supported message integrity codes), .Ar kex (key exchange algorithms), .Ar key (key types), .Ar key-ca-sign (valid CA signature algorithms for certificates), .Ar key-cert (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. Causes most warning and diagnostic messages to be suppressed. .Pp .It Fl R Xo .Sm off .Oo Ar bind_address : Oc .Ar port : host : hostport .Sm on .Xc .It Fl R Xo .Sm off .Oo Ar bind_address : Oc .Ar port : local_socket .Sm on .Xc .It Fl R Xo .Sm off .Ar remote_socket : host : hostport .Sm on .Xc .It Fl R Xo .Sm off .Ar remote_socket : local_socket .Sm on .Xc .It Fl R Xo .Sm off .Oo Ar bind_address : Oc .Ar port .Sm on .Xc Specifies that connections to the given TCP port or Unix socket on the remote (server) host are to be forwarded to the local side. .Pp This works by allocating a socket to listen to either a TCP .Ar port or to a Unix socket on the remote side. Whenever a connection is made to this port or Unix socket, the connection is forwarded over the secure channel, and a connection is made from the local machine to either an explicit destination specified by .Ar host port .Ar hostport , or .Ar local_socket , or, if no explicit destination was specified, .Nm will act as a SOCKS 4/5 proxy and forward connections to the destinations requested by the remote SOCKS client. .Pp Port forwardings can also be specified in the configuration file. Privileged ports can be forwarded only when logging in as root on the remote machine. IPv6 addresses can be specified by enclosing the address in square brackets. .Pp By default, TCP listening sockets on the server will be bound to the loopback interface only. This may be overridden by specifying a .Ar bind_address . An empty .Ar bind_address , or the address .Ql * , indicates that the remote socket should listen on all interfaces. Specifying a remote .Ar bind_address will only succeed if the server's .Cm GatewayPorts option is enabled (see .Xr sshd_config 5 ) . .Pp If the .Ar port argument is .Ql 0 , the listen port will be dynamically allocated on the server and reported to the client at run time. When used together with .Ic -O forward , the allocated port will be printed to the standard output. .Pp .It Fl S Ar ctl_path Specifies the location of a control socket for connection sharing, or the string .Dq none to disable connection sharing. Refer to the description of .Cm ControlPath and .Cm ControlMaster in .Xr ssh_config 5 for details. .Pp .It Fl s May be used to request invocation of a subsystem on the remote system. Subsystems facilitate the use of SSH as a secure transport for other applications (e.g.\& .Xr sftp 1 ) . The subsystem is specified as the remote command. Refer to the description of .Cm SessionType in .Xr ssh_config 5 for details. .Pp .It Fl T Disable pseudo-terminal allocation. .Pp .It Fl t Force pseudo-terminal allocation. This can be used to execute arbitrary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services. Multiple .Fl t options force tty allocation, even if .Nm has no local tty. .Pp .It Fl V Display the version number and exit. .Pp .It Fl v Verbose mode. Causes .Nm to print debugging messages about its progress. This is helpful in debugging connection, authentication, and configuration problems. Multiple .Fl v options increase the verbosity. The maximum is 3. .Pp .It Fl W Ar host : Ns Ar port Requests that standard input and output on the client be forwarded to .Ar host on .Ar port over the secure channel. Implies .Fl N , .Fl T , .Cm ExitOnForwardFailure and .Cm ClearAllForwardings , though these can be overridden in the configuration file or using .Fl o command line options. .Pp .It Fl w Xo .Ar local_tun Ns Op : Ns Ar remote_tun .Xc Requests tunnel device forwarding with the specified .Xr tun 4 devices between the client .Pq Ar local_tun and the server .Pq Ar remote_tun . .Pp The devices may be specified by numerical ID or the keyword .Dq any , which uses the next available tunnel device. If .Ar remote_tun is not specified, it defaults to .Dq any . See also the .Cm Tunnel and .Cm TunnelDevice directives in .Xr ssh_config 5 . .Pp If the .Cm Tunnel directive is unset, it will be set to the default tunnel mode, which is .Dq point-to-point . If a different .Cm Tunnel forwarding mode it desired, then it should be specified before .Fl w . .Pp .It Fl X Enables X11 forwarding. This can also be specified on a per-host basis in a configuration file. .Pp X11 forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the user's X authorization database) can access the local X11 display through the forwarded connection. An attacker may then be able to perform activities such as keystroke monitoring. .Pp For this reason, X11 forwarding is subjected to X11 SECURITY extension restrictions by default. Refer to the .Nm .Fl Y option and the .Cm ForwardX11Trusted directive in .Xr ssh_config 5 for more information. .Pp .It Fl x Disables X11 forwarding. .Pp .It Fl Y Enables trusted X11 forwarding. Trusted X11 forwardings are not subjected to the X11 SECURITY extension controls. .Pp .It Fl y Send log information using the .Xr syslog 3 system module. By default this information is sent to stderr. .El .Pp .Nm may additionally obtain configuration data from a per-user configuration file and a system-wide configuration file. The file format and configuration options are described in .Xr ssh_config 5 . .Sh AUTHENTICATION The OpenSSH SSH client supports SSH protocol 2. .Pp The methods available for authentication are: GSSAPI-based authentication, host-based authentication, public key authentication, keyboard-interactive authentication, and password authentication. Authentication methods are tried in the order specified above, though .Cm PreferredAuthentications can be used to change the default order. .Pp Host-based authentication works as follows: If the machine the user logs in from is listed in .Pa /etc/hosts.equiv or .Pa /etc/shosts.equiv on the remote machine, the user is non-root and the user names are the same on both sides, or if the files .Pa ~/.rhosts or .Pa ~/.shosts exist in the user's home directory on the remote machine and contain a line containing the name of the client machine and the name of the user on that machine, the user is considered for login. Additionally, the server .Em must be able to verify the client's host key (see the description of .Pa /etc/ssh/ssh_known_hosts and .Pa ~/.ssh/known_hosts , below) for login to be permitted. This authentication method closes security holes due to IP spoofing, DNS spoofing, and routing spoofing. [Note to the administrator: .Pa /etc/hosts.equiv , .Pa ~/.rhosts , and the rlogin/rsh protocol in general, are inherently insecure and should be disabled if security is desired.] .Pp Public key authentication works as follows: The scheme is based on public-key cryptography, using cryptosystems where encryption and decryption are done using separate keys, and it is unfeasible to derive the decryption key from the encryption key. The idea is that each user creates a public/private key pair for authentication purposes. The server knows the public key, and only the user knows the private key. .Nm implements public key authentication protocol automatically, using one of the DSA, ECDSA, Ed25519 or RSA algorithms. The HISTORY section of .Xr ssl 8 contains a brief discussion of the DSA and RSA algorithms. .Pp The file .Pa ~/.ssh/authorized_keys lists the public keys that are permitted for logging in. When the user logs in, the .Nm program tells the server which key pair it would like to use for authentication. The client proves that it has access to the private key and the server checks that the corresponding public key is authorized to accept the account. .Pp The server may inform the client of errors that prevented public key authentication from succeeding after authentication completes using a different method. These may be viewed by increasing the .Cm LogLevel to .Cm DEBUG or higher (e.g. by using the .Fl v flag). .Pp The user creates their key pair by running .Xr ssh-keygen 1 . This stores the private key in .Pa ~/.ssh/id_dsa (DSA), .Pa ~/.ssh/id_ecdsa (ECDSA), .Pa ~/.ssh/id_ecdsa_sk (authenticator-hosted ECDSA), .Pa ~/.ssh/id_ed25519 (Ed25519), .Pa ~/.ssh/id_ed25519_sk (authenticator-hosted Ed25519), or .Pa ~/.ssh/id_rsa (RSA) and stores the public key in .Pa ~/.ssh/id_dsa.pub (DSA), .Pa ~/.ssh/id_ecdsa.pub (ECDSA), .Pa ~/.ssh/id_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) in the user's home directory. The user should then copy the public key to .Pa ~/.ssh/authorized_keys in their home directory on the remote machine. The .Pa authorized_keys file corresponds to the conventional .Pa ~/.rhosts file, and has one key per line, though the lines can be very long. After this, the user can log in without giving the password. .Pp A variation on public key authentication is available in the form of certificate authentication: instead of a set of public/private keys, signed certificates are used. This has the advantage that a single trusted certification authority can be used in place of many public/private keys. See the CERTIFICATES section of .Xr ssh-keygen 1 for more information. .Pp The most convenient way to use public key or certificate authentication may be with an authentication agent. See .Xr ssh-agent 1 and (optionally) the .Cm AddKeysToAgent directive in .Xr ssh_config 5 for more information. .Pp Keyboard-interactive authentication works as follows: The server sends an arbitrary .Qq challenge text and prompts for a response, possibly multiple times. Examples of keyboard-interactive authentication include .Bx Authentication (see .Xr login.conf 5 ) and PAM (some .Pf non- Ox systems). .Pp Finally, if other authentication methods fail, .Nm prompts the user for a password. The password is sent to the remote host for checking; however, since all communications are encrypted, the password cannot be seen by someone listening on the network. .Pp .Nm automatically maintains and checks a database containing identification for all hosts it has ever been used with. Host keys are stored in .Pa ~/.ssh/known_hosts in the user's home directory. Additionally, the file .Pa /etc/ssh/ssh_known_hosts is automatically checked for known hosts. Any new hosts are automatically added to the user's file. If a host's identification ever changes, .Nm warns about this and disables password authentication to prevent server spoofing or man-in-the-middle attacks, which could otherwise be used to circumvent the encryption. The .Cm StrictHostKeyChecking option can be used to control logins to machines whose host key is not known or has changed. .Pp When the user's identity has been accepted by the server, the server either executes the given command in a non-interactive session or, if no command has been specified, logs into the machine and gives the user a normal shell as an interactive session. All communication with the remote command or shell will be automatically encrypted. .Pp If an interactive session is requested, .Nm by default will only request a pseudo-terminal (pty) for interactive sessions when the client has one. The flags .Fl T and .Fl t can be used to override this behaviour. .Pp If a pseudo-terminal has been allocated, the user may use the escape characters noted below. .Pp If no pseudo-terminal has been allocated, the session is transparent and can be used to reliably transfer binary data. On most systems, setting the escape character to .Dq none will also make the session transparent even if a tty is used. .Pp The session terminates when the command or shell on the remote machine exits and all X11 and TCP connections have been closed. .Sh ESCAPE CHARACTERS When a pseudo-terminal has been requested, .Nm supports a number of functions through the use of an escape character. .Pp A single tilde character can be sent as .Ic ~~ or by following the tilde by a character other than those described below. The escape character must always follow a newline to be interpreted as special. The escape character can be changed in configuration files using the .Cm EscapeChar configuration directive or on the command line by the .Fl e option. .Pp The supported escapes (assuming the default .Ql ~ ) are: .Bl -tag -width Ds .It Cm ~. Disconnect. .It Cm ~^Z Background .Nm . .It Cm ~# List forwarded connections. .It Cm ~& Background .Nm at logout when waiting for forwarded connection / X11 sessions to terminate. .It Cm ~? Display a list of escape characters. .It Cm ~B Send a BREAK to the remote system (only useful if the peer supports it). .It Cm ~C Open command line. Currently this allows the addition of port forwardings using the .Fl L , .Fl R and .Fl D options (see above). It also allows the cancellation of existing port-forwardings with .Sm off .Fl KL Oo Ar bind_address : Oc Ar port .Sm on for local, .Sm off .Fl KR Oo Ar bind_address : Oc Ar port .Sm on for remote and .Sm off .Fl KD Oo Ar bind_address : Oc Ar port .Sm on for dynamic port-forwardings. .Ic !\& Ns Ar command allows the user to execute a local command if the .Ic PermitLocalCommand option is enabled in .Xr ssh_config 5 . Basic help is available, using the .Fl h option. .It Cm ~R Request rekeying of the connection (only useful if the peer supports it). .It Cm ~V Decrease the verbosity .Pq Ic LogLevel when errors are being written to stderr. .It Cm ~v Increase the verbosity .Pq Ic LogLevel when errors are being written to stderr. .El .Sh TCP FORWARDING Forwarding of arbitrary TCP connections over a secure channel can be specified either on the command line or in a configuration file. One possible application of TCP forwarding is a secure connection to a mail server; another is going through firewalls. .Pp In the example below, we look at encrypting communication for an IRC client, even though the IRC server it connects to does not directly support encrypted communication. This works as follows: the user connects to the remote host using .Nm , specifying the ports to be used to forward the connection. After that it is possible to start the program locally, and .Nm will encrypt and forward the connection to the remote server. .Pp The following example tunnels an IRC session from the client to an IRC server at .Dq server.example.com , joining channel .Dq #users , nickname .Dq pinky , using the standard IRC port, 6667: .Bd -literal -offset 4n $ ssh -f -L 6667:localhost:6667 server.example.com sleep 10 $ irc -c '#users' pinky IRC/127.0.0.1 .Ed .Pp The .Fl f option backgrounds .Nm and the remote command .Dq sleep 10 is specified to allow an amount of time (10 seconds, in the example) to start the program which is going to use the tunnel. If no connections are made within the time specified, .Nm will exit. .Sh X11 FORWARDING If the .Cm ForwardX11 variable is set to .Dq yes (or see the description of the .Fl X , .Fl x , and .Fl Y options above) and the user is using X11 (the .Ev DISPLAY environment variable is set), the connection to the X11 display is automatically forwarded to the remote side in such a way that any X11 programs started from the shell (or command) will go through the encrypted channel, and the connection to the real X server will be made from the local machine. The user should not manually set .Ev DISPLAY . Forwarding of X11 connections can be configured on the command line or in configuration files. .Pp The .Ev DISPLAY value set by .Nm will point to the server machine, but with a display number greater than zero. This is normal, and happens because .Nm creates a .Dq proxy X server on the server machine for forwarding the connections over the encrypted channel. .Pp .Nm will also automatically set up Xauthority data on the server machine. For this purpose, it will generate a random authorization cookie, store it in Xauthority on the server, and verify that any forwarded connections carry this cookie and replace it by the real cookie when the connection is opened. The real authentication cookie is never sent to the server machine (and no cookies are sent in the plain). .Pp If the .Cm ForwardAgent variable is set to .Dq yes (or see the description of the .Fl A and .Fl a options above) and the user is using an authentication agent, the connection to the agent is automatically forwarded to the remote side. .Sh VERIFYING HOST KEYS When connecting to a server for the first time, a fingerprint of the server's public key is presented to the user (unless the option .Cm StrictHostKeyChecking has been disabled). Fingerprints can be determined using .Xr ssh-keygen 1 : .Pp .Dl $ ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key .Pp If the fingerprint is already known, it can be matched and the key can be accepted or rejected. If only legacy (MD5) fingerprints for the server are available, the .Xr ssh-keygen 1 .Fl E option may be used to downgrade the fingerprint algorithm to match. .Pp Because of the difficulty of comparing host keys just by looking at fingerprint strings, there is also support to compare host keys visually, using .Em random art . By setting the .Cm VisualHostKey option to .Dq yes , a small ASCII graphic gets displayed on every login to a server, no matter if the session itself is interactive or not. By learning the pattern a known server produces, a user can easily find out that the host key has changed when a completely different pattern is displayed. Because these patterns are not unambiguous however, a pattern that looks similar to the pattern remembered only gives a good probability that the host key is the same, not guaranteed proof. .Pp To get a listing of the fingerprints along with their random art for all known hosts, the following command line can be used: .Pp .Dl $ ssh-keygen -lv -f ~/.ssh/known_hosts .Pp If the fingerprint is unknown, an alternative method of verification is available: SSH fingerprints verified by DNS. An additional resource record (RR), SSHFP, is added to a zonefile and the connecting client is able to match the fingerprint with that of the key presented. .Pp In this example, we are connecting a client to a server, .Dq host.example.com . The SSHFP resource records should first be added to the zonefile for host.example.com: .Bd -literal -offset indent $ ssh-keygen -r host.example.com. .Ed .Pp The output lines will have to be added to the zonefile. To check that the zone is answering fingerprint queries: .Pp .Dl $ dig -t SSHFP host.example.com .Pp Finally the client connects: .Bd -literal -offset indent $ ssh -o "VerifyHostKeyDNS ask" host.example.com [...] Matching host key fingerprint found in DNS. Are you sure you want to continue connecting (yes/no)? .Ed .Pp See the .Cm VerifyHostKeyDNS option in .Xr ssh_config 5 for more information. .Sh SSH-BASED VIRTUAL PRIVATE NETWORKS .Nm contains support for Virtual Private Network (VPN) tunnelling using the .Xr tun 4 network pseudo-device, allowing two networks to be joined securely. The .Xr sshd_config 5 configuration option .Cm PermitTunnel controls whether the server supports this, and at what level (layer 2 or 3 traffic). .Pp The following example would connect client network 10.0.50.0/24 with remote network 10.0.99.0/24 using a point-to-point connection from 10.1.1.1 to 10.1.1.2, provided that the SSH server running on the gateway to the remote network, at 192.168.1.15, allows it. .Pp On the client: .Bd -literal -offset indent # ssh -f -w 0:1 192.168.1.15 true # ifconfig tun0 10.1.1.1 10.1.1.2 netmask 255.255.255.252 # route add 10.0.99.0/24 10.1.1.2 .Ed .Pp On the server: .Bd -literal -offset indent # ifconfig tun1 10.1.1.2 10.1.1.1 netmask 255.255.255.252 # route add 10.0.50.0/24 10.1.1.1 .Ed .Pp Client access may be more finely tuned via the .Pa /root/.ssh/authorized_keys file (see below) and the .Cm PermitRootLogin server option. The following entry would permit connections on .Xr tun 4 device 1 from user .Dq jane and on tun device 2 from user .Dq john , if .Cm PermitRootLogin is set to .Dq forced-commands-only : .Bd -literal -offset 2n tunnel="1",command="sh /etc/netstart tun1" ssh-rsa ... jane tunnel="2",command="sh /etc/netstart tun2" ssh-rsa ... john .Ed .Pp Since an SSH-based setup entails a fair amount of overhead, it may be more suited to temporary setups, such as for wireless VPNs. More permanent VPNs are better provided by tools such as .Xr ipsecctl 8 and .Xr isakmpd 8 . .Sh ENVIRONMENT .Nm will normally set the following environment variables: .Bl -tag -width "SSH_ORIGINAL_COMMAND" .It Ev DISPLAY The .Ev DISPLAY variable indicates the location of the X11 server. It is automatically set by .Nm to point to a value of the form .Dq hostname:n , where .Dq hostname indicates the host where the shell runs, and .Sq n is an integer \*(Ge 1. .Nm uses this special value to forward X11 connections over the secure channel. The user should normally not set .Ev DISPLAY explicitly, as that will render the X11 connection insecure (and will require the user to manually copy any required authorization cookies). .It Ev HOME Set to the path of the user's home directory. .It Ev LOGNAME Synonym for .Ev USER ; set for compatibility with systems that use this variable. .It Ev MAIL Set to the path of the user's mailbox. .It Ev PATH Set to the default .Ev PATH , as specified when compiling .Nm . .It Ev SSH_ASKPASS If .Nm needs a passphrase, it will read the passphrase from the current terminal if it was run from a terminal. If .Nm does not have a terminal associated with it but .Ev DISPLAY and .Ev SSH_ASKPASS are set, it will execute the program specified by .Ev SSH_ASKPASS and open an X11 window to read the passphrase. This is particularly useful when calling .Nm from a .Pa .xsession or related script. (Note that on some machines it may be necessary to redirect the input from .Pa /dev/null to make this work.) .It Ev SSH_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_CONNECTION Identifies the client and server ends of the connection. The variable contains four space-separated values: client IP address, client port number, server IP address, and server port number. .It Ev SSH_ORIGINAL_COMMAND This variable contains the original command line if a forced command is executed. It can be used to extract the original arguments. .It Ev SSH_TTY This is set to the name of the tty (path to the device) associated with the current shell or command. If the current session has no tty, this variable is not set. .It Ev SSH_TUNNEL Optionally set by .Xr sshd 8 to contain the interface names assigned if tunnel forwarding was requested by the client. .It Ev SSH_USER_AUTH Optionally set by .Xr sshd 8 , this variable may contain a pathname to a file that lists the authentication methods successfully used when the session was established, including any public keys that were used. .It Ev TZ This variable is set to indicate the present time zone if it was set when the daemon was started (i.e. the daemon passes the value on to new connections). .It Ev USER Set to the name of the user logging in. .El .Pp Additionally, .Nm reads .Pa ~/.ssh/environment , and adds lines of the format .Dq VARNAME=value to the environment if the file exists and users are allowed to change their environment. For more information, see the .Cm PermitUserEnvironment option in .Xr sshd_config 5 . .Sh FILES .Bl -tag -width Ds -compact .It Pa ~/.rhosts This file is used for host-based authentication (see above). On some machines this file may need to be world-readable if the user's home directory is on an NFS partition, because .Xr sshd 8 reads it as root. Additionally, this file must be owned by the user, and must not have write permissions for anyone else. The recommended permission for most machines is read/write for the user, and not accessible by others. .Pp .It Pa ~/.shosts This file is used in exactly the same way as .Pa .rhosts , but allows host-based authentication without permitting login with rlogin/rsh. .Pp .It Pa ~/.ssh/ This directory is the default location for all user-specific configuration and authentication information. There is no general requirement to keep the entire contents of this directory secret, but the recommended permissions are read/write/execute for the user, and not accessible by others. .Pp .It Pa ~/.ssh/authorized_keys Lists the public keys (DSA, ECDSA, Ed25519, RSA) that can be used for logging in as this user. The format of this file is described in the .Xr sshd 8 manual page. This file is not highly sensitive, but the recommended permissions are read/write for the user, and not accessible by others. .Pp .It Pa ~/.ssh/config This is the per-user configuration file. The file format and configuration options are described in .Xr ssh_config 5 . Because of the potential for abuse, this file must have strict permissions: read/write for the user, and not writable by others. .Pp .It Pa ~/.ssh/environment Contains additional definitions for environment variables; see .Sx ENVIRONMENT , above. .Pp .It Pa ~/.ssh/id_dsa .It Pa ~/.ssh/id_ecdsa .It Pa ~/.ssh/id_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 contain sensitive data and should be readable by the user but not accessible by others (read/write/execute). .Nm will simply ignore a private key file if it is accessible by others. It is possible to specify a passphrase when generating the key which will be used to encrypt the sensitive part of this file using AES-128. .Pp .It Pa ~/.ssh/id_dsa.pub .It Pa ~/.ssh/id_ecdsa.pub .It Pa ~/.ssh/id_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 sensitive and can (but need not) be readable by anyone. .Pp .It Pa ~/.ssh/known_hosts Contains a list of host keys for all hosts the user has logged into that are not already in the systemwide list of known host keys. See .Xr sshd 8 for further details of the format of this file. .Pp .It Pa ~/.ssh/rc Commands in this file are executed by .Nm when the user logs in, just before the user's shell (or command) is started. See the .Xr sshd 8 manual page for more information. .Pp .It Pa /etc/hosts.equiv This file is for host-based authentication (see above). It should only be writable by root. .Pp .It Pa /etc/shosts.equiv This file is used in exactly the same way as .Pa hosts.equiv , but allows host-based authentication without permitting login with rlogin/rsh. .Pp .It Pa /etc/ssh/ssh_config Systemwide configuration file. The file format and configuration options are described in .Xr ssh_config 5 . .Pp .It Pa /etc/ssh/ssh_host_key .It Pa /etc/ssh/ssh_host_dsa_key .It Pa /etc/ssh/ssh_host_ecdsa_key .It Pa /etc/ssh/ssh_host_ed25519_key .It Pa /etc/ssh/ssh_host_rsa_key These files contain the private parts of the host keys and are used for host-based authentication. .Pp .It Pa /etc/ssh/ssh_known_hosts Systemwide list of known host keys. This file should be prepared by the system administrator to contain the public host keys of all machines in the organization. It should be world-readable. See .Xr sshd 8 for further details of the format of this file. .Pp .It Pa /etc/ssh/sshrc Commands in this file are executed by .Nm when the user logs in, just before the user's shell (or command) is started. See the .Xr sshd 8 manual page for more information. .El .Sh EXIT STATUS .Nm exits with the exit status of the remote command or with 255 if an error occurred. .Sh SEE ALSO .Xr scp 1 , .Xr sftp 1 , .Xr ssh-add 1 , .Xr ssh-agent 1 , .Xr ssh-keygen 1 , .Xr ssh-keyscan 1 , .Xr tun 4 , .Xr ssh_config 5 , .Xr ssh-keysign 8 , .Xr sshd 8 .Sh STANDARDS .Rs .%A S. Lehtinen .%A C. Lonvick .%D January 2006 .%R RFC 4250 .%T The Secure Shell (SSH) Protocol Assigned Numbers .Re .Pp .Rs .%A T. Ylonen .%A C. Lonvick .%D January 2006 .%R RFC 4251 .%T The Secure Shell (SSH) Protocol Architecture .Re .Pp .Rs .%A T. Ylonen .%A C. Lonvick .%D January 2006 .%R RFC 4252 .%T The Secure Shell (SSH) Authentication Protocol .Re .Pp .Rs .%A T. Ylonen .%A C. Lonvick .%D January 2006 .%R RFC 4253 .%T The Secure Shell (SSH) Transport Layer Protocol .Re .Pp .Rs .%A T. Ylonen .%A C. Lonvick .%D January 2006 .%R RFC 4254 .%T The Secure Shell (SSH) Connection Protocol .Re .Pp .Rs .%A J. Schlyter .%A W. Griffin .%D January 2006 .%R RFC 4255 .%T Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints .Re .Pp .Rs .%A F. Cusack .%A M. Forssen .%D January 2006 .%R RFC 4256 .%T Generic Message Exchange Authentication for the Secure Shell Protocol (SSH) .Re .Pp .Rs .%A J. Galbraith .%A P. Remaker .%D January 2006 .%R RFC 4335 .%T The Secure Shell (SSH) Session Channel Break Extension .Re .Pp .Rs .%A M. Bellare .%A T. Kohno .%A C. Namprempre .%D January 2006 .%R RFC 4344 .%T The Secure Shell (SSH) Transport Layer Encryption Modes .Re .Pp .Rs .%A B. Harris .%D January 2006 .%R RFC 4345 .%T Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol .Re .Pp .Rs .%A M. Friedl .%A N. Provos .%A W. Simpson .%D March 2006 .%R RFC 4419 .%T Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol .Re .Pp .Rs .%A J. Galbraith .%A R. Thayer .%D November 2006 .%R RFC 4716 .%T The Secure Shell (SSH) Public Key File Format .Re .Pp .Rs .%A D. Stebila .%A J. Green .%D December 2009 .%R RFC 5656 .%T Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer .Re .Pp .Rs .%A A. Perrig .%A D. Song .%D 1999 .%O International Workshop on Cryptographic Techniques and E-Commerce (CrypTEC '99) .%T Hash Visualization: a New Technique to improve Real-World Security .Re .Sh AUTHORS OpenSSH is a derivative of the original and free ssh 1.2.12 release by Tatu Ylonen. Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos, Theo de Raadt and Dug Song removed many bugs, re-added newer features and created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. diff --git a/crypto/openssh/ssh.c b/crypto/openssh/ssh.c index ec5c36091d29..6af2f279b8b5 100644 --- a/crypto/openssh/ssh.c +++ b/crypto/openssh/ssh.c @@ -1,2431 +1,2488 @@ -/* $OpenBSD: ssh.c,v 1.594 2023/09/03 23:59:32 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.599 2023/12/18 14:47:44 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Ssh client program. This program can be used to log into a remote machine. * The software supports strong authentication, encryption, and forwarding * of X11, TCP/IP, and authentication connections. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * Copyright (c) 1999 Niels Provos. All rights reserved. * Copyright (c) 2000, 2001, 2002, 2003 Markus Friedl. All rights reserved. * * Modified to work with SSLeay by Niels Provos * in Canada (German citizen). * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #ifdef HAVE_SYS_STAT_H # include #endif #include #include #include #include #include #include #include #include #ifdef HAVE_PATHS_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WITH_OPENSSL #include #include #endif #include "openbsd-compat/openssl-compat.h" #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "canohost.h" #include "compat.h" #include "cipher.h" #include "packet.h" #include "sshbuf.h" #include "channels.h" #include "sshkey.h" #include "authfd.h" #include "authfile.h" #include "pathnames.h" #include "dispatch.h" #include "clientloop.h" #include "log.h" #include "misc.h" #include "readconf.h" #include "sshconnect.h" #include "kex.h" #include "mac.h" #include "sshpty.h" #include "match.h" #include "msg.h" #include "version.h" #include "ssherr.h" #include "myproposal.h" #include "utf8.h" #ifdef ENABLE_PKCS11 #include "ssh-pkcs11.h" #endif extern char *__progname; /* Saves a copy of argv for setproctitle emulation */ #ifndef HAVE_SETPROCTITLE static char **saved_av; #endif /* Flag indicating whether debug mode is on. May be set on the command line. */ int debug_flag = 0; /* Flag indicating whether a tty should be requested */ int tty_flag = 0; /* * Flag indicating that the current process should be backgrounded and * a new mux-client launched in the foreground for ControlPersist. */ static int need_controlpersist_detach = 0; /* Copies of flags for ControlPersist foreground mux-client */ static int ostdin_null_flag, osession_type, otty_flag, orequest_tty; static int ofork_after_authentication; /* * General data structure for command line options and options configurable * in configuration files. See readconf.h. */ Options options; /* optional user configfile */ char *config = NULL; /* * Name of the host we are connecting to. This is the name given on the * command line, or the Hostname specified for the user-supplied name in a * configuration file. */ char *host; /* * 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; /* Private host keys. */ Sensitive sensitive_data; /* command to be executed */ struct sshbuf *command; /* # of replies received for global requests */ static int forward_confirms_pending = -1; /* mux.c */ extern int muxserver_sock; extern u_int muxclient_command; /* Prints a help message to the user. This function never returns. */ static void usage(void) { fprintf(stderr, "usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface] [-b bind_address]\n" " [-c cipher_spec] [-D [bind_address:]port] [-E log_file]\n" " [-e escape_char] [-F configfile] [-I pkcs11] [-i identity_file]\n" " [-J destination] [-L address] [-l login_name] [-m mac_spec]\n" -" [-O ctl_cmd] [-o option] [-P tag] [-p port] [-Q query_option]\n" -" [-R address] [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]]\n" +" [-O ctl_cmd] [-o option] [-P tag] [-p port] [-R address]\n" +" [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]]\n" " destination [command [argument ...]]\n" +" ssh [-Q query_option]\n" ); exit(255); } 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. */ static void tilde_expand_paths(char **paths, u_int num_paths) { u_int i; char *cp; for (i = 0; i < num_paths; i++) { cp = tilde_expand_filename(paths[i], getuid()); free(paths[i]); paths[i] = cp; } } /* * 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. * Returns NULL on failure. * NB. this function must operate with a options having undefined members. */ static struct addrinfo * resolve_host(const char *name, int port, int logerr, char *cname, size_t clen) { char strport[NI_MAXSERV]; const char *errstr = NULL; struct addrinfo hints, *res; int gaierr; LogLevel loglevel = SYSLOG_LEVEL_DEBUG1; if (port <= 0) port = default_ssh_port(); if (cname != NULL) *cname = '\0'; debug3_f("lookup %s:%d", name, port); snprintf(strport, sizeof strport, "%d", port); memset(&hints, 0, sizeof(hints)); hints.ai_family = options.address_family == -1 ? AF_UNSPEC : options.address_family; hints.ai_socktype = SOCK_STREAM; if (cname != NULL) hints.ai_flags = AI_CANONNAME; if ((gaierr = getaddrinfo(name, strport, &hints, &res)) != 0) { if (logerr || (gaierr != EAI_NONAME && gaierr != EAI_NODATA)) loglevel = SYSLOG_LEVEL_ERROR; do_log2(loglevel, "%s: Could not resolve hostname %.100s: %s", __progname, name, ssh_gai_strerror(gaierr)); return NULL; } if (cname != NULL && res->ai_canonname != NULL) { if (!valid_domain(res->ai_canonname, 0, &errstr)) { error("ignoring bad CNAME \"%s\" for host \"%s\": %s", res->ai_canonname, name, errstr); } else if (strlcpy(cname, res->ai_canonname, clen) >= clen) { error_f("host \"%s\" cname \"%s\" too long (max %lu)", name, res->ai_canonname, (u_long)clen); if (clen > 0) *cname = '\0'; } } return res; } /* Returns non-zero if name can only be an address and not a hostname */ static int is_addr_fast(const char *name) { return (strchr(name, '%') != NULL || strchr(name, ':') != NULL || strspn(name, "0123456789.") == strlen(name)); } /* Returns non-zero if name represents a valid, single address */ static int is_addr(const char *name) { char strport[NI_MAXSERV]; struct addrinfo hints, *res; if (is_addr_fast(name)) return 1; snprintf(strport, sizeof strport, "%u", default_ssh_port()); memset(&hints, 0, sizeof(hints)); hints.ai_family = options.address_family == -1 ? AF_UNSPEC : options.address_family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV; if (getaddrinfo(name, strport, &hints, &res) != 0) return 0; if (res == NULL || res->ai_next != NULL) { freeaddrinfo(res); return 0; } freeaddrinfo(res); return 1; } /* * Attempt to resolve a numeric host address / port to a single address. * Returns a canonical address string. * Returns NULL on failure. * NB. this function must operate with a options having undefined members. */ static struct addrinfo * resolve_addr(const char *name, int port, char *caddr, size_t clen) { char addr[NI_MAXHOST], strport[NI_MAXSERV]; struct addrinfo hints, *res; int gaierr; if (port <= 0) port = default_ssh_port(); snprintf(strport, sizeof strport, "%u", port); memset(&hints, 0, sizeof(hints)); hints.ai_family = options.address_family == -1 ? AF_UNSPEC : options.address_family; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV; if ((gaierr = getaddrinfo(name, strport, &hints, &res)) != 0) { debug2_f("could not resolve name %.100s as address: %s", name, ssh_gai_strerror(gaierr)); return NULL; } if (res == NULL) { debug_f("getaddrinfo %.100s returned no addresses", name); return NULL; } if (res->ai_next != NULL) { 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_f("Could not format address for name %.100s: %s", name, ssh_gai_strerror(gaierr)); goto fail; } if (strlcpy(caddr, addr, clen) >= clen) { error_f("host \"%s\" addr \"%s\" too long (max %lu)", name, addr, (u_long)clen); if (clen > 0) *caddr = '\0'; fail: freeaddrinfo(res); return NULL; } return res; } /* * Check whether the cname is a permitted replacement for the hostname * and perform the replacement if it is. * NB. this function must operate with a options having undefined members. */ static int check_follow_cname(int direct, char **namep, const char *cname) { int i; struct allowed_cname *rule; if (*cname == '\0' || !config_has_permitted_cnames(&options) || strcmp(*namep, cname) == 0) return 0; if (options.canonicalize_hostname == SSH_CANONICALISE_NO) return 0; /* * Don't attempt to canonicalize names that will be interpreted by * a proxy or jump host unless the user specifically requests so. */ if (!direct && options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS) return 0; debug3_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 || match_pattern_list(cname, rule->target_list, 1) != 1) continue; verbose("Canonicalized DNS aliased hostname " "\"%s\" => \"%s\"", *namep, cname); free(*namep); *namep = xstrdup(cname); return 1; } return 0; } /* * Attempt to resolve the supplied hostname after applying the user's * canonicalization rules. Returns the address list for the host or NULL * if no name was found after canonicalization. * NB. this function must operate with a options having undefined members. */ static struct addrinfo * resolve_canonicalize(char **hostp, int port) { int i, direct, ndots; char *cp, *fullhost, newname[NI_MAXHOST]; struct addrinfo *addrs; /* * Attempt to canonicalise addresses, regardless of * whether hostname canonicalisation was requested */ if ((addrs = resolve_addr(*hostp, port, newname, sizeof(newname))) != NULL) { debug2_f("hostname %.100s is address", *hostp); if (strcasecmp(*hostp, newname) != 0) { debug2_f("canonicalised address \"%s\" => \"%s\"", *hostp, newname); free(*hostp); *hostp = xstrdup(newname); } return addrs; } /* * If this looks like an address but didn't parse as one, it might * be an address with an invalid interface scope. Skip further * attempts at canonicalisation. */ if (is_addr_fast(*hostp)) { debug_f("hostname %.100s is an unrecognised address", *hostp); return NULL; } if (options.canonicalize_hostname == SSH_CANONICALISE_NO) return NULL; /* * Don't attempt to canonicalize names that will be interpreted by * a proxy unless the user specifically requests so. */ direct = option_clear_or_none(options.proxy_command) && option_clear_or_none(options.jump_host); if (!direct && options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS) return NULL; /* If domain name is anchored, then resolve it now */ if ((*hostp)[strlen(*hostp) - 1] == '.') { debug3_f("name is fully qualified"); fullhost = xstrdup(*hostp); if ((addrs = resolve_host(fullhost, port, 0, newname, sizeof(newname))) != NULL) goto found; free(fullhost); goto notfound; } /* Don't apply canonicalization to sufficiently-qualified hostnames */ ndots = 0; for (cp = *hostp; *cp != '\0'; cp++) { if (*cp == '.') ndots++; } if (ndots > options.canonicalize_max_dots) { debug3_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++) { if (strcasecmp(options.canonical_domains[i], "none") == 0) break; xasprintf(&fullhost, "%s.%s.", *hostp, options.canonical_domains[i]); debug3_f("attempting \"%s\" => \"%s\"", *hostp, fullhost); if ((addrs = resolve_host(fullhost, port, 0, newname, sizeof(newname))) == NULL) { free(fullhost); continue; } found: /* Remove trailing '.' */ fullhost[strlen(fullhost) - 1] = '\0'; /* Follow CNAME if requested */ if (!check_follow_cname(direct, &fullhost, newname)) { debug("Canonicalized hostname \"%s\" => \"%s\"", *hostp, fullhost); } free(*hostp); *hostp = fullhost; return addrs; } notfound: if (!options.canonicalize_fallback_local) fatal("%s: Could not resolve host \"%s\"", __progname, *hostp); debug2_f("host %s not found in any suffix", *hostp); return NULL; } /* * Check the result of hostkey loading, ignoring some errors and either * discarding the key or fatal()ing for others. */ static void check_load(int r, struct sshkey **k, const char *path, const char *message) { switch (r) { case 0: /* Check RSA keys size and discard if undersized */ if (k != NULL && *k != NULL && (r = sshkey_check_rsa_length(*k, options.required_rsa_size)) != 0) { error_r(r, "load %s \"%s\"", message, path); free(*k); *k = NULL; } break; case SSH_ERR_INTERNAL_ERROR: case SSH_ERR_ALLOC_FAIL: fatal_r(r, "load %s \"%s\"", message, path); case SSH_ERR_SYSTEM_ERROR: /* Ignore missing files */ if (errno == ENOENT) break; /* FALLTHROUGH */ default: error_r(r, "load %s \"%s\"", message, path); break; } } /* * Read per-user configuration file. Ignore the system wide config * file if the user specifies a config file on the command line. */ static void process_config_files(const char *host_name, struct passwd *pw, int final_pass, int *want_final_pass) { char buf[PATH_MAX]; int r; if (config != NULL) { if (strcasecmp(config, "none") != 0 && !read_config_file(config, pw, host, host_name, &options, SSHCONF_USERCONF | (final_pass ? SSHCONF_FINAL : 0), want_final_pass)) fatal("Can't open user config file %.100s: " "%.100s", config, strerror(errno)); } else { r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, _PATH_SSH_USER_CONFFILE); if (r > 0 && (size_t)r < sizeof(buf)) (void)read_config_file(buf, pw, host, host_name, &options, SSHCONF_CHECKPERM | SSHCONF_USERCONF | (final_pass ? SSHCONF_FINAL : 0), want_final_pass); /* Read systemwide configuration file after user config. */ (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, host, host_name, &options, final_pass ? SSHCONF_FINAL : 0, want_final_pass); } } /* Rewrite the port number in an addrinfo list of addresses */ static void set_addrinfo_port(struct addrinfo *addrs, int port) { struct addrinfo *addr; for (addr = addrs; addr != NULL; addr = addr->ai_next) { switch (addr->ai_family) { case AF_INET: ((struct sockaddr_in *)addr->ai_addr)-> sin_port = htons(port); break; case AF_INET6: ((struct sockaddr_in6 *)addr->ai_addr)-> sin6_port = htons(port); break; } } } 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->jmphost); free(cinfo); } +static int +valid_hostname(const char *s) +{ + size_t i; + + if (*s == '-') + return 0; + for (i = 0; s[i] != 0; i++) { + if (strchr("'`\"$\\;&<>|(){}", s[i]) != NULL || + isspace((u_char)s[i]) || iscntrl((u_char)s[i])) + return 0; + } + return 1; +} + +static int +valid_ruser(const char *s) +{ + size_t i; + + if (*s == '-') + return 0; + for (i = 0; s[i] != 0; i++) { + if (strchr("'`\";&<>|(){}", s[i]) != NULL) + return 0; + /* Disallow '-' after whitespace */ + if (isspace((u_char)s[i]) && s[i + 1] == '-') + return 0; + /* Disallow \ in last position */ + if (s[i] == '\\' && s[i + 1] == '\0') + return 0; + } + return 1; +} + /* * Main program for the ssh client. */ int main(int ac, char **av) { struct ssh *ssh = NULL; int i, r, opt, exit_status, use_syslog, direct, timeout_ms; int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0; char *p, *cp, *line, *argv0, *logfile; 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; 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(); /* * Discard other fds that are hanging around. These can cause problem * with backgrounded ssh processes started by ControlPersist. */ closefrom(STDERR_FILENO + 1); __progname = ssh_get_progname(av[0]); #ifndef HAVE_SETPROCTITLE /* Prepare for later setproctitle emulation */ /* Save argv so it isn't clobbered by setproctitle() emulation */ saved_av = xcalloc(ac + 1, sizeof(*saved_av)); for (i = 0; i < ac; i++) saved_av[i] = xstrdup(av[i]); saved_av[i] = NULL; compat_init_setproctitle(ac, av); av = saved_av; #endif seed_rng(); /* Get user data. */ pw = getpwuid(getuid()); if (!pw) { logit("No user exists for uid %lu", (u_long)getuid()); exit(255); } /* Take a copy of the returned structure. */ pw = pwcopy(pw); /* * Set our umask to something reasonable, as some files are created * with the default umask. This will make them world-readable but * writable only by the owner, which is ok for all files for which we * don't set the modes explicitly. */ umask(022 | umask(077)); msetlocale(); /* * Initialize option structure to indicate that no values have been * set. */ initialize_options(&options); /* * Prepare main ssh transport/connection structures */ if ((ssh = ssh_alloc_session_state()) == NULL) fatal("Couldn't allocate session state"); channel_init_channels(ssh); /* Parse command-line arguments. */ host = NULL; use_syslog = 0; logfile = NULL; argv0 = av[0]; again: while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" "AB:CD:E:F:GI:J:KL:MNO:P:Q:R:S:TVw:W:XYy")) != -1) { /* HUZdhjruz */ switch (opt) { case '1': fatal("SSH protocol v.1 is no longer supported"); break; case '2': /* Ignored */ break; case '4': options.address_family = AF_INET; break; case '6': options.address_family = AF_INET6; break; case 'n': options.stdin_null = 1; break; case 'f': options.fork_after_authentication = 1; options.stdin_null = 1; break; case 'x': options.forward_x11 = 0; break; case 'X': options.forward_x11 = 1; break; case 'y': use_syslog = 1; break; case 'E': logfile = optarg; break; case 'G': config_test = 1; break; case 'Y': options.forward_x11 = 1; options.forward_x11_trusted = 1; break; case 'g': options.fwd_opts.gateway_ports = 1; break; case 'O': if (options.stdio_forward_host != NULL) fatal("Cannot specify multiplexing " "command with -W"); else if (muxclient_command != 0) fatal("Multiplexing command already specified"); if (strcmp(optarg, "check") == 0) muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK; else if (strcmp(optarg, "forward") == 0) muxclient_command = SSHMUX_COMMAND_FORWARD; else if (strcmp(optarg, "exit") == 0) muxclient_command = SSHMUX_COMMAND_TERMINATE; else if (strcmp(optarg, "stop") == 0) muxclient_command = SSHMUX_COMMAND_STOP; else if (strcmp(optarg, "cancel") == 0) muxclient_command = SSHMUX_COMMAND_CANCEL_FWD; else if (strcmp(optarg, "proxy") == 0) muxclient_command = SSHMUX_COMMAND_PROXY; else fatal("Invalid multiplex command."); break; case 'P': if (options.tag == NULL) options.tag = xstrdup(optarg); break; case 'Q': cp = NULL; 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 || strcasecmp(optarg, "MACs") == 0) cp = mac_alg_list('\n'); 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'); else if (strcmp(optarg, "key-cert") == 0) cp = sshkey_alg_list(1, 0, 0, '\n'); else if (strcmp(optarg, "key-plain") == 0) cp = sshkey_alg_list(0, 1, 0, '\n'); else if (strcmp(optarg, "key-ca-sign") == 0 || strcasecmp(optarg, "CASignatureAlgorithms") == 0) cp = sshkey_alg_list(0, 1, 1, '\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, "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\ncompression\nkex\n" "key\nkey-cert\nkey-plain\nkey-sig\nmac\n" "protocol-version\nsig"); } if (cp == NULL) fatal("Unsupported query \"%s\"", optarg); printf("%s\n", cp); free(cp); exit(0); break; case 'a': options.forward_agent = 0; break; case 'A': options.forward_agent = 1; break; case 'k': options.gss_deleg_creds = 0; break; case 'K': options.gss_authentication = 1; options.gss_deleg_creds = 1; break; case 'i': p = tilde_expand_filename(optarg, getuid()); if (stat(p, &st) == -1) fprintf(stderr, "Warning: Identity file %s " "not accessible: %s.\n", p, strerror(errno)); else add_identity_file(&options, NULL, p, 1); free(p); break; case 'I': #ifdef ENABLE_PKCS11 free(options.pkcs11_provider); options.pkcs11_provider = xstrdup(optarg); #else fprintf(stderr, "no support for PKCS#11.\n"); #endif break; case 'J': if (options.jump_host != NULL) { fatal("Only a single -J option is permitted " "(use commas to separate multiple " "jump hops)"); } if (options.proxy_command != NULL) fatal("Cannot specify -J with ProxyCommand"); if (parse_jump(optarg, &options, 1) == -1) fatal("Invalid -J argument"); options.proxy_command = xstrdup("none"); break; case 't': if (options.request_tty == REQUEST_TTY_YES) options.request_tty = REQUEST_TTY_FORCE; else options.request_tty = REQUEST_TTY_YES; break; case 'v': if (debug_flag == 0) { debug_flag = 1; options.log_level = SYSLOG_LEVEL_DEBUG1; } else { if (options.log_level < SYSLOG_LEVEL_DEBUG3) { debug_flag++; options.log_level++; } } break; case 'V': fprintf(stderr, "%s, %s\n", SSH_RELEASE, SSH_OPENSSL_VERSION); exit(0); break; case 'w': if (options.tun_open == -1) options.tun_open = SSH_TUNMODE_DEFAULT; options.tun_local = a2tun(optarg, &options.tun_remote); if (options.tun_local == SSH_TUNID_ERR) { fprintf(stderr, "Bad tun device '%s'\n", optarg); exit(255); } break; case 'W': if (options.stdio_forward_host != NULL) fatal("stdio forward already specified"); if (muxclient_command != 0) fatal("Cannot specify stdio forward with -O"); if (parse_forward(&fwd, optarg, 1, 0)) { options.stdio_forward_host = fwd.listen_port == PORT_STREAMLOCAL ? fwd.listen_path : fwd.listen_host; options.stdio_forward_port = fwd.listen_port; free(fwd.connect_host); } else { fprintf(stderr, "Bad stdio forwarding specification '%s'\n", optarg); exit(255); } options.request_tty = REQUEST_TTY_NO; options.session_type = SESSION_TYPE_NONE; break; case 'q': options.log_level = SYSLOG_LEVEL_QUIET; break; case 'e': if (optarg[0] == '^' && optarg[2] == 0 && (u_char) optarg[1] >= 64 && (u_char) optarg[1] < 128) options.escape_char = (u_char) optarg[1] & 31; else if (strlen(optarg) == 1) options.escape_char = (u_char) optarg[0]; else if (strcmp(optarg, "none") == 0) options.escape_char = SSH_ESCAPECHAR_NONE; else { fprintf(stderr, "Bad escape character '%s'.\n", optarg); exit(255); } break; case 'c': if (!ciphers_valid(*optarg == '+' || *optarg == '^' ? optarg + 1 : optarg)) { fprintf(stderr, "Unknown cipher type '%s'\n", optarg); exit(255); } free(options.ciphers); options.ciphers = xstrdup(optarg); break; case 'm': if (mac_valid(optarg)) { free(options.macs); options.macs = xstrdup(optarg); } else { fprintf(stderr, "Unknown mac type '%s'\n", optarg); exit(255); } break; case 'M': if (options.control_master == SSHCTL_MASTER_YES) options.control_master = SSHCTL_MASTER_ASK; else options.control_master = SSHCTL_MASTER_YES; break; case 'p': if (options.port == -1) { options.port = a2port(optarg); if (options.port <= 0) { fprintf(stderr, "Bad port '%s'\n", optarg); exit(255); } } break; case 'l': if (options.user == NULL) options.user = optarg; break; case 'L': if (parse_forward(&fwd, optarg, 0, 0)) add_local_forward(&options, &fwd); else { fprintf(stderr, "Bad local forwarding specification '%s'\n", optarg); exit(255); } break; case 'R': if (parse_forward(&fwd, optarg, 0, 1) || parse_forward(&fwd, optarg, 1, 1)) { add_remote_forward(&options, &fwd); } else { fprintf(stderr, "Bad remote forwarding specification " "'%s'\n", optarg); exit(255); } break; case 'D': if (parse_forward(&fwd, optarg, 1, 0)) { add_local_forward(&options, &fwd); } else { fprintf(stderr, "Bad dynamic forwarding specification " "'%s'\n", optarg); exit(255); } break; case 'C': #ifdef WITH_ZLIB options.compression = 1; #else error("Compression not supported, disabling."); #endif break; case 'N': if (options.session_type != -1 && options.session_type != SESSION_TYPE_NONE) fatal("Cannot specify -N with -s/SessionType"); options.session_type = SESSION_TYPE_NONE; options.request_tty = REQUEST_TTY_NO; break; case 'T': options.request_tty = REQUEST_TTY_NO; break; case 'o': line = xstrdup(optarg); if (process_config_line(&options, pw, host ? host : "", host ? host : "", line, "command-line", 0, NULL, SSHCONF_USERCONF) != 0) exit(255); free(line); break; case 's': if (options.session_type != -1 && options.session_type != SESSION_TYPE_SUBSYSTEM) fatal("Cannot specify -s with -N/SessionType"); options.session_type = SESSION_TYPE_SUBSYSTEM; break; case 'S': free(options.control_path); options.control_path = xstrdup(optarg); break; case 'b': options.bind_address = optarg; break; case 'B': options.bind_interface = optarg; break; case 'F': config = optarg; break; default: usage(); } } if (optind > 1 && strcmp(av[optind - 1], "--") == 0) opt_terminated = 1; ac -= optind; av += optind; if (ac > 0 && !host) { int tport; char *tuser; switch (parse_ssh_uri(*av, &tuser, &host, &tport)) { case -1: usage(); break; case 0: if (options.user == NULL) { options.user = tuser; tuser = NULL; } free(tuser); if (options.port == -1 && tport != -1) options.port = tport; break; default: p = xstrdup(*av); cp = strrchr(p, '@'); if (cp != NULL) { if (cp == p) usage(); if (options.user == NULL) { options.user = p; p = NULL; } *cp++ = '\0'; host = xstrdup(cp); free(p); } else host = p; break; } if (ac > 1 && !opt_terminated) { optind = optreset = 1; goto again; } ac--, av++; } /* Check that we got a host name. */ if (!host) usage(); + if (!valid_hostname(host)) + fatal("hostname contains invalid characters"); + if (options.user != NULL && !valid_ruser(options.user)) + fatal("remote username contains invalid characters"); options.host_arg = xstrdup(host); /* Initialize the command to execute on remote host. */ if ((command = sshbuf_new()) == NULL) fatal("sshbuf_new failed"); /* * Save the command to execute on the remote host in a buffer. There * is no limit on the length of the command, except by the maximum * packet size. Also sets the tty flag if there is no command. */ if (!ac) { /* No command specified - execute shell on a tty. */ if (options.session_type == SESSION_TYPE_SUBSYSTEM) { fprintf(stderr, "You must specify a subsystem to invoke.\n"); usage(); } } else { /* A command has been specified. Store it into the buffer. */ for (i = 0; i < ac; i++) { if ((r = sshbuf_putf(command, "%s%s", i ? " " : "", av[i])) != 0) fatal_fr(r, "buffer error"); } } ssh_signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ /* * Initialize "log" output. Since we are the client all output * goes to stderr unless otherwise specified by -y or -E. */ if (use_syslog && logfile != NULL) fatal("Can't specify both -y and -E"); if (logfile != NULL) log_redirect_stderr_to(logfile); log_init(argv0, options.log_level == SYSLOG_LEVEL_NOT_SET ? SYSLOG_LEVEL_INFO : options.log_level, options.log_facility == SYSLOG_FACILITY_NOT_SET ? SYSLOG_FACILITY_USER : options.log_facility, !use_syslog); if (debug_flag) logit("%s, %s", SSH_RELEASE, SSH_OPENSSL_VERSION); /* Parse the configuration files */ process_config_files(options.host_arg, pw, 0, &want_final_pass); if (want_final_pass) debug("configuration requests final Match pass"); /* Hostname canonicalisation needs a few options filled. */ fill_default_options_for_canonicalization(&options); /* If the user has replaced the hostname then take it into use now */ if (options.hostname != NULL) { /* NB. Please keep in sync with readconf.c:match_cfg_line() */ cp = percent_expand(options.hostname, "h", host, (char *)NULL); free(host); host = cp; free(options.hostname); options.hostname = xstrdup(host); } /* Don't lowercase addresses, they will be explicitly canonicalised */ if ((was_addr = is_addr(host)) == 0) lowercase(host); /* * Try to canonicalize if requested by configuration or the * hostname is an address. */ if (options.canonicalize_hostname != SSH_CANONICALISE_NO || was_addr) addrs = resolve_canonicalize(&host, options.port); /* * If CanonicalizePermittedCNAMEs have been specified but * other canonicalization did not happen (by not being requested * or by failing with fallback) then the hostname may still be changed * as a result of CNAME following. * * Try to resolve the bare hostname name using the system resolver's * usual search rules and then apply the CNAME follow rules. * * Skip the lookup if a ProxyCommand is being used unless the user * has specifically requested canonicalisation for this case via * CanonicalizeHostname=always */ direct = option_clear_or_none(options.proxy_command) && option_clear_or_none(options.jump_host); if (addrs == NULL && config_has_permitted_cnames(&options) && (direct || options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) { if ((addrs = resolve_host(host, options.port, direct, cname, sizeof(cname))) == NULL) { /* Don't fatal proxied host names not in the DNS */ if (direct) cleanup_exit(255); /* logged in resolve_host */ } else check_follow_cname(direct, &host, cname); } /* * If canonicalisation is enabled then re-parse the configuration * files as new stanzas may match. */ if (options.canonicalize_hostname != 0 && !want_final_pass) { debug("hostname canonicalisation enabled, " "will re-parse configuration"); want_final_pass = 1; } if (want_final_pass) { debug("re-parsing configuration"); free(options.hostname); options.hostname = xstrdup(host); process_config_files(options.host_arg, pw, 1, NULL); /* * Address resolution happens early with canonicalisation * enabled and the port number may have changed since, so * reset it in address list */ if (addrs != NULL && options.port > 0) set_addrinfo_port(addrs, options.port); } /* Fill configuration defaults. */ 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 *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); /* * Try to use SSH indicated by argv[0], but fall back to * "ssh" if it appears unavailable. */ if (strchr(argv0, '/') != NULL && access(argv0, X_OK) != 0) sshbin = "ssh"; /* Consistency check */ if (options.proxy_command != NULL) fatal("inconsistent options: ProxyCommand+ProxyJump"); /* Never use FD passing for ProxyJump */ options.proxy_use_fdpass = 0; snprintf(port_s, sizeof(port_s), "%d", options.jump_port); xasprintf(&options.proxy_command, "%s%s%s%s%s%s%s%s%s%s%.*s -W '[%%h]:%%p' %s", sshbin, /* Optional "-l user" argument if jump_user set */ options.jump_user == NULL ? "" : " -l ", options.jump_user == NULL ? "" : options.jump_user, /* Optional "-p port" argument if jump_port set */ options.jump_port <= 0 ? "" : " -p ", options.jump_port <= 0 ? "" : port_s, /* Optional additional jump hosts ",..." */ options.jump_extra == NULL ? "" : " -J ", options.jump_extra == NULL ? "" : options.jump_extra, /* Optional "-F" argument if -F specified */ config == NULL ? "" : " -F ", config == NULL ? "" : config, /* Optional "-v" arguments if -v set */ debug_flag ? " -" : "", debug_flag, "vvv", /* Mandatory hostname */ options.jump_host); debug("Setting implicit ProxyCommand from ProxyJump: %s", options.proxy_command); } if (options.port == 0) options.port = default_ssh_port(); channel_set_af(ssh, options.address_family); /* Tidy and check options */ if (options.host_key_alias != NULL) lowercase(options.host_key_alias); if (options.proxy_command != NULL && strcmp(options.proxy_command, "-") == 0 && options.proxy_use_fdpass) fatal("ProxyCommand=- and ProxyUseFDPass are incompatible"); if (options.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"); if (sshbuf_len(command) != 0 && options.remote_command != NULL) fatal("Cannot execute command-line and remote command."); /* Cannot fork to background if no command. */ if (options.fork_after_authentication && sshbuf_len(command) == 0 && options.remote_command == NULL && options.session_type != SESSION_TYPE_NONE) fatal("Cannot fork into background without a command " "to execute."); /* reinit */ log_init(argv0, options.log_level, options.log_facility, !use_syslog); for (j = 0; j < options.num_log_verbose; j++) { if (strcasecmp(options.log_verbose[j], "none") == 0) break; log_verbose_add(options.log_verbose[j]); } if (options.request_tty == REQUEST_TTY_YES || options.request_tty == REQUEST_TTY_FORCE) tty_flag = 1; /* Allocate a tty by default if no command specified. */ if (sshbuf_len(command) == 0 && options.remote_command == NULL) tty_flag = options.request_tty != REQUEST_TTY_NO; /* Force no tty */ if (options.request_tty == REQUEST_TTY_NO || (muxclient_command && muxclient_command != SSHMUX_COMMAND_PROXY) || options.session_type == SESSION_TYPE_NONE) tty_flag = 0; /* Do not allocate a tty if stdin is not a tty. */ if ((!isatty(fileno(stdin)) || options.stdin_null) && options.request_tty != REQUEST_TTY_FORCE) { if (tty_flag) logit("Pseudo-terminal will not be allocated because " "stdin is not a terminal."); tty_flag = 0; } /* Set up strings used to percent_expand() arguments */ cinfo = xcalloc(1, sizeof(*cinfo)); if (gethostname(thishost, sizeof(thishost)) == -1) fatal("gethostname: %s", strerror(errno)); 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); cinfo->keyalias = xstrdup(options.host_key_alias ? options.host_key_alias : options.host_arg); - cinfo->conn_hash_hex = ssh_connection_hash(cinfo->thishost, host, - cinfo->portstr, options.user); cinfo->host_arg = xstrdup(options.host_arg); cinfo->remhost = xstrdup(host); cinfo->remuser = xstrdup(options.user); cinfo->homedir = xstrdup(pw->pw_dir); cinfo->locuser = xstrdup(pw->pw_name); + cinfo->jmphost = xstrdup(options.jump_host == NULL ? + "" : options.jump_host); + cinfo->conn_hash_hex = ssh_connection_hash(cinfo->thishost, + cinfo->remhost, cinfo->portstr, cinfo->remuser, cinfo->jmphost); /* Find canonic host name. */ if (strchr(host, '.') == NULL) { struct addrinfo hints; struct addrinfo *ai = NULL; int errgai; memset(&hints, 0, sizeof(hints)); hints.ai_family = options.address_family; hints.ai_flags = AI_CANONNAME; hints.ai_socktype = SOCK_STREAM; errgai = getaddrinfo(host, NULL, &hints, &ai); if (errgai == 0) { if (ai->ai_canonname != NULL) { free(host); host = xstrdup(ai->ai_canonname); } freeaddrinfo(ai); } } /* * Expand tokens in arguments. NB. LocalCommand is expanded later, * after port-forwarding is set up, so it may pick up any local * tunnel interface name allocated. */ if (options.remote_command != NULL) { debug3("expanding RemoteCommand: %s", options.remote_command); cp = options.remote_command; options.remote_command = 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_fr(r, "buffer error"); } if (options.control_path != NULL) { cp = tilde_expand_filename(options.control_path, getuid()); free(options.control_path); 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.revoked_host_keys != NULL) { p = tilde_expand_filename(options.revoked_host_keys, getuid()); cp = default_client_percent_dollar_expand(p, cinfo); free(p); free(options.revoked_host_keys); options.revoked_host_keys = 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) { int sock; if ((sock = muxclient(options.control_path)) >= 0) { ssh_packet_set_connection(ssh, sock, sock); ssh_packet_set_mux(ssh); goto skip_connect; } } /* * If hostname canonicalisation was not enabled, then we may not * have yet resolved the hostname. Do so now. */ if (addrs == NULL && options.proxy_command == NULL) { debug2("resolving \"%s\" port %d", host, options.port); if ((addrs = resolve_host(host, options.port, 1, cname, sizeof(cname))) == NULL) cleanup_exit(255); /* resolve_host logs the error */ } if (options.connection_timeout >= INT_MAX/1000) timeout_ms = INT_MAX; else timeout_ms = options.connection_timeout * 1000; + /* Apply channels timeouts, if set */ + channel_clear_timeouts(ssh); + for (j = 0; j < options.num_channel_timeouts; j++) { + debug3("applying channel timeout %s", + options.channel_timeouts[j]); + if (parse_pattern_interval(options.channel_timeouts[j], + &cp, &i) != 0) { + fatal_f("internal error: bad timeout %s", + options.channel_timeouts[j]); + } + channel_add_timeout(ssh, cp, i); + free(cp); + } + /* Open a connection to the remote host. */ if (ssh_connect(ssh, host, options.host_arg, addrs, &hostaddr, options.port, options.connection_attempts, &timeout_ms, options.tcp_keep_alive) != 0) exit(255); if (addrs != NULL) freeaddrinfo(addrs); ssh_packet_set_timeout(ssh, options.server_alive_interval, options.server_alive_count_max); if (timeout_ms > 0) debug3("timeout: %d ms remain after connect", timeout_ms); /* * If we successfully made the connection and we have hostbased auth * enabled, load the public keys so we can later use the ssh-keysign * helper to sign challenges. */ sensitive_data.nkeys = 0; sensitive_data.keys = NULL; if (options.hostbased_authentication) { int loaded = 0; sensitive_data.nkeys = 10; sensitive_data.keys = xcalloc(sensitive_data.nkeys, sizeof(*sensitive_data.keys)); /* XXX check errors? */ #define L_PUBKEY(p,o) do { \ if ((o) >= sensitive_data.nkeys) \ fatal_f("pubkey out of array bounds"); \ check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \ &(sensitive_data.keys[o]), p, "pubkey"); \ if (sensitive_data.keys[o] != NULL) { \ debug2("hostbased key %d: %s key from \"%s\"", o, \ sshkey_ssh_name(sensitive_data.keys[o]), p); \ loaded++; \ } \ } while (0) #define L_CERT(p,o) do { \ if ((o) >= sensitive_data.nkeys) \ fatal_f("cert out of array bounds"); \ check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), \ &(sensitive_data.keys[o]), p, "cert"); \ if (sensitive_data.keys[o] != NULL) { \ debug2("hostbased key %d: %s cert from \"%s\"", o, \ sshkey_ssh_name(sensitive_data.keys[o]), p); \ loaded++; \ } \ } while (0) if (options.hostbased_authentication == 1) { L_CERT(_PATH_HOST_ECDSA_KEY_FILE, 0); L_CERT(_PATH_HOST_ED25519_KEY_FILE, 1); L_CERT(_PATH_HOST_RSA_KEY_FILE, 2); L_CERT(_PATH_HOST_DSA_KEY_FILE, 3); L_PUBKEY(_PATH_HOST_ECDSA_KEY_FILE, 4); L_PUBKEY(_PATH_HOST_ED25519_KEY_FILE, 5); L_PUBKEY(_PATH_HOST_RSA_KEY_FILE, 6); L_PUBKEY(_PATH_HOST_DSA_KEY_FILE, 7); L_CERT(_PATH_HOST_XMSS_KEY_FILE, 8); L_PUBKEY(_PATH_HOST_XMSS_KEY_FILE, 9); if (loaded == 0) debug("HostbasedAuthentication enabled but no " "local public host keys could be loaded."); } } /* load options.identity_files */ load_public_identity_files(cinfo); /* optionally set the SSH_AUTHSOCKET_ENV_NAME variable */ if (options.identity_agent && strcmp(options.identity_agent, SSH_AUTHSOCKET_ENV_NAME) != 0) { if (strcmp(options.identity_agent, "none") == 0) { unsetenv(SSH_AUTHSOCKET_ENV_NAME); } else { 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); } if ((p = getenv(cp + 1)) == NULL) unsetenv(SSH_AUTHSOCKET_ENV_NAME); else setenv(SSH_AUTHSOCKET_ENV_NAME, p, 1); } else { /* identity_agent specifies a path directly */ setenv(SSH_AUTHSOCKET_ENV_NAME, cp, 1); } } } 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 = xstrdup(p); else options.forward_agent = 0; free(cp); } else { forward_agent_sock_path = cp; } } /* Expand ~ in known host file names. */ tilde_expand_paths(options.system_hostfiles, options.num_system_hostfiles); tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles); 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, cinfo); /* We no longer need the private host keys. Clear them now. */ if (sensitive_data.nkeys != 0) { for (i = 0; i < sensitive_data.nkeys; i++) { if (sensitive_data.keys[i] != NULL) { /* Destroys contents safely */ debug3("clear hostkey %d", i); sshkey_free(sensitive_data.keys[i]); sensitive_data.keys[i] = NULL; } } free(sensitive_data.keys); } for (i = 0; i < options.num_identity_files; i++) { free(options.identity_files[i]); options.identity_files[i] = NULL; if (options.identity_keys[i]) { sshkey_free(options.identity_keys[i]); options.identity_keys[i] = NULL; } } for (i = 0; i < options.num_certificate_files; i++) { free(options.certificate_files[i]); options.certificate_files[i] = NULL; } #ifdef ENABLE_PKCS11 (void)pkcs11_del_provider(options.pkcs11_provider); #endif skip_connect: exit_status = ssh_session2(ssh, cinfo); ssh_conn_info_free(cinfo); ssh_packet_close(ssh); if (options.control_path != NULL && muxserver_sock != -1) unlink(options.control_path); /* Kill ProxyCommand if it is running. */ ssh_kill_proxy_command(); return exit_status; } static void control_persist_detach(void) { pid_t pid; debug_f("backgrounding master process"); /* * master (current process) into the background, and make the * foreground process a client of the backgrounded master. */ switch ((pid = fork())) { case -1: fatal_f("fork: %s", strerror(errno)); case 0: /* Child: master process continues mainloop */ break; default: /* * Parent: set up mux client to connect to backgrounded * master. */ debug2_f("background process is %ld", (long)pid); options.stdin_null = ostdin_null_flag; options.request_tty = orequest_tty; tty_flag = otty_flag; options.fork_after_authentication = ofork_after_authentication; options.session_type = osession_type; close(muxserver_sock); muxserver_sock = -1; options.control_master = SSHCTL_MASTER_NO; (void)muxclient(options.control_path); /* muxclient() doesn't return on success. */ fatal("Failed to connect to new control master"); } 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); } /* Do fork() after authentication. Used by "ssh -f" */ static void fork_postauth(void) { if (need_controlpersist_detach) control_persist_detach(); debug("forking to background"); options.fork_after_authentication = 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 (options.fork_after_authentication) fork_postauth(); } else { debug2_f("%d expected forwarding replies remaining", forward_confirms_pending); } } /* Callback for remote forward global requests */ static void ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) { struct Forward *rfwd = (struct Forward *)ctxt; u_int port; int r; /* XXX verbose() on failure? */ debug("remote forward %s for: listen %s%s%d, connect %s:%d", type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", rfwd->listen_path ? rfwd->listen_path : rfwd->listen_host ? rfwd->listen_host : "", (rfwd->listen_path || rfwd->listen_host) ? ":" : "", rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path : rfwd->connect_host, rfwd->connect_port); if (rfwd->listen_path == NULL && rfwd->listen_port == 0) { if (type == SSH2_MSG_REQUEST_SUCCESS) { if ((r = sshpkt_get_u32(ssh, &port)) != 0) fatal_fr(r, "parse packet"); if (port > 65535) { error("Invalid allocated port %u for remote " "forward to %s:%d", port, rfwd->connect_host, rfwd->connect_port); /* Ensure failure processing runs below */ type = SSH2_MSG_REQUEST_FAILURE; channel_update_permission(ssh, rfwd->handle, -1); } else { rfwd->allocated_port = (int)port; logit("Allocated port %u for remote " "forward to %s:%d", rfwd->allocated_port, rfwd->connect_path ? rfwd->connect_path : rfwd->connect_host, rfwd->connect_port); channel_update_permission(ssh, rfwd->handle, rfwd->allocated_port); } } else { channel_update_permission(ssh, rfwd->handle, -1); } } if (type == SSH2_MSG_REQUEST_FAILURE) { if (options.exit_on_forward_failure) { if (rfwd->listen_path != NULL) fatal("Error: remote port forwarding failed " "for listen path %s", rfwd->listen_path); else fatal("Error: remote port forwarding failed " "for listen port %d", rfwd->listen_port); } else { if (rfwd->listen_path != NULL) logit("Warning: remote port forwarding failed " "for listen path %s", rfwd->listen_path); else logit("Warning: remote port forwarding failed " "for listen port %d", rfwd->listen_port); } } forwarding_success(); } static void client_cleanup_stdio_fwd(struct ssh *ssh, int id, int force, void *arg) { debug("stdio forwarding: done"); cleanup_exit(0); } static void ssh_stdio_confirm(struct ssh *ssh, int id, int success, void *arg) { if (!success) fatal("stdio forwarding failed"); } static void ssh_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) { Channel *c; int in, out; if (options.stdio_forward_host == NULL) return; debug3_f("%s:%d", options.stdio_forward_host, options.stdio_forward_port); if ((in = dup(STDIN_FILENO)) == -1 || (out = dup(STDOUT_FILENO)) == -1) fatal_f("dup() in/out failed"); if ((c = channel_connect_stdio_fwd(ssh, options.stdio_forward_host, options.stdio_forward_port, in, out, CHANNEL_NONBLOCK_STDIO)) == NULL) 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; 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]); addr = hpdelim(&arg); if (addr == NULL) 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 " "address %.200s:%d", (options.local_forwards[i].listen_path != NULL) ? options.local_forwards[i].listen_path : (options.local_forwards[i].listen_host == NULL) ? (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") : options.local_forwards[i].listen_host, options.local_forwards[i].listen_port, (options.local_forwards[i].connect_path != NULL) ? options.local_forwards[i].connect_path : options.local_forwards[i].connect_host, options.local_forwards[i].connect_port); success += channel_setup_local_fwd_listener(ssh, &options.local_forwards[i], &options.fwd_opts); } if (i > 0 && success != i && options.exit_on_forward_failure) fatal("Could not request local forwarding."); if (i > 0 && success == 0) error("Could not request local forwarding."); /* Initiate remote TCP/IP port forwardings. */ for (i = 0; i < options.num_remote_forwards; i++) { debug("Remote connections from %.200s:%d forwarded to " "local address %.200s:%d", (options.remote_forwards[i].listen_path != NULL) ? options.remote_forwards[i].listen_path : (options.remote_forwards[i].listen_host == NULL) ? "LOCALHOST" : options.remote_forwards[i].listen_host, options.remote_forwards[i].listen_port, (options.remote_forwards[i].connect_path != NULL) ? options.remote_forwards[i].connect_path : options.remote_forwards[i].connect_host, options.remote_forwards[i].connect_port); if ((options.remote_forwards[i].handle = channel_request_remote_forwarding(ssh, &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, 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); } } static void check_agent_present(void) { int r; if (options.forward_agent) { /* Clear agent forwarding if we don't have an agent. */ if ((r = ssh_get_authentication_socket(NULL)) != 0) { options.forward_agent = 0; if (r != SSH_ERR_AGENT_NOT_PRESENT) debug_r(r, "ssh_get_authentication_socket"); } } } static void ssh_session2_setup(struct ssh *ssh, int id, int success, void *arg) { extern char **environ; const char *display, *term; int r, interactive = tty_flag; char *proto = NULL, *data = NULL; if (!success) return; /* No need for error message, channels code sends one */ display = getenv("DISPLAY"); if (display == NULL && options.forward_x11) debug("X11 forwarding requested but DISPLAY not set"); if (options.forward_x11 && client_x11_get_proto(ssh, display, options.xauth_location, options.forward_x11_trusted, options.forward_x11_timeout, &proto, &data) == 0) { /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication " "spoofing."); x11_request_forwarding_with_spoofing(ssh, id, display, proto, data, 1); client_expect_confirm(ssh, id, "X11 forwarding", CONFIRM_WARN); /* XXX exit_on_forward_failure */ interactive = 1; } check_agent_present(); if (options.forward_agent) { debug("Requesting authentication agent forwarding."); channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0); if ((r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); } /* Tell the packet module whether this is an interactive session. */ ssh_packet_set_interactive(ssh, interactive, options.ip_qos_interactive, options.ip_qos_bulk); if ((term = lookup_env_in_list("TERM", options.setenv, options.num_setenv)) == NULL || *term == '\0') term = getenv("TERM"); client_session2_setup(ssh, id, tty_flag, options.session_type == SESSION_TYPE_SUBSYSTEM, term, NULL, fileno(stdin), command, environ); } /* open new channel for a session */ static int ssh_session2_open(struct ssh *ssh) { Channel *c; int window, packetmax, in, out, err; if (options.stdin_null) { in = open(_PATH_DEVNULL, O_RDONLY); } else { in = dup(STDIN_FILENO); } out = dup(STDOUT_FILENO); err = dup(STDERR_FILENO); if (in == -1 || out == -1 || err == -1) fatal("dup() in/out/err failed"); window = CHAN_SES_WINDOW_DEFAULT; packetmax = CHAN_SES_PACKET_DEFAULT; if (tty_flag) { window >>= 1; packetmax >>= 1; } c = channel_new(ssh, "session", SSH_CHANNEL_OPENING, in, out, err, window, packetmax, CHAN_EXTENDED_WRITE, "client-session", CHANNEL_NONBLOCK_STDIO); debug3_f("channel_new: %d", c->self); channel_send_open(ssh, c->self); if (options.session_type != SESSION_TYPE_NONE) channel_register_open_confirm(ssh, c->self, ssh_session2_setup, NULL); return c->self; } static int ssh_session2(struct ssh *ssh, const struct ssh_conn_info *cinfo) { int r, interactive, id = -1; char *cp, *tun_fwd_ifname = NULL; /* XXX should be pre-session */ if (!options.control_persist) ssh_init_stdio_forwarding(ssh); ssh_init_forwarding(ssh, &tun_fwd_ifname); if (options.local_command != NULL) { debug3("expanding LocalCommand: %s", options.local_command); cp = options.local_command; options.local_command = percent_expand(cp, DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo), "T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname, (char *)NULL); debug3("expanded LocalCommand: %s", options.local_command); free(cp); } /* Start listening for multiplex clients */ if (!ssh_packet_get_mux(ssh)) muxserver_listen(ssh); /* * If we are in control persist mode and have a working mux listen * socket, then prepare to background ourselves and have a foreground * client attach as a control client. * NB. we must save copies of the flags that we override for * 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). */ if (options.control_persist && muxserver_sock != -1) { ostdin_null_flag = options.stdin_null; osession_type = options.session_type; orequest_tty = options.request_tty; otty_flag = tty_flag; ofork_after_authentication = options.fork_after_authentication; options.stdin_null = 1; options.session_type = SESSION_TYPE_NONE; tty_flag = 0; if ((osession_type != SESSION_TYPE_NONE || options.stdio_forward_host != NULL)) need_controlpersist_detach = 1; options.fork_after_authentication = 1; } /* * ControlPersist mux listen socket setup failed, attempt the * stdio forward setup that we skipped earlier. */ if (options.control_persist && muxserver_sock == -1) ssh_init_stdio_forwarding(ssh); if (options.session_type != SESSION_TYPE_NONE) id = ssh_session2_open(ssh); else { interactive = options.control_master == SSHCTL_MASTER_NO; /* ControlPersist may have clobbered ControlMaster, so check */ if (need_controlpersist_detach) interactive = otty_flag != 0; ssh_packet_set_interactive(ssh, interactive, options.ip_qos_interactive, options.ip_qos_bulk); } /* If we don't expect to open a new session, then disallow it */ if (options.control_master == SSHCTL_MASTER_NO && (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_fr(r, "send packet"); } /* Execute a local command */ if (options.local_command != NULL && options.permit_local_command) ssh_local_cmd(options.local_command); /* * stdout is now owned by the session channel; clobber it here * so future channel closes are propagated to the local fd. * NB. this can only happen after LocalCommand has completed, * as it may want to write to stdout. */ if (!need_controlpersist_detach && stdfd_devnull(0, 1, 0) == -1) error_f("stdfd_devnull failed"); /* * If requested and we are not interested in replies to remote * forwarding requests, then let ssh continue in the background. */ if (options.fork_after_authentication) { if (options.exit_on_forward_failure && options.num_remote_forwards > 0) { debug("deferring postauth fork until remote forward " "confirmation received"); } else fork_postauth(); } return client_loop(ssh, tty_flag, tty_flag ? options.escape_char : SSH_ESCAPECHAR_NONE, id); } /* Loads all IdentityFile and CertificateFile keys */ static void load_public_identity_files(const struct ssh_conn_info *cinfo) { char *filename, *cp; struct sshkey *public; int i; u_int n_ids, n_certs; char *identity_files[SSH_MAX_IDENTITY_FILES]; struct sshkey *identity_keys[SSH_MAX_IDENTITY_FILES]; int identity_file_userprovided[SSH_MAX_IDENTITY_FILES]; char *certificate_files[SSH_MAX_CERTIFICATE_FILES]; struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; #ifdef ENABLE_PKCS11 struct sshkey **keys = NULL; char **comments = NULL; int nkeys; #endif /* PKCS11 */ n_ids = n_certs = 0; memset(identity_files, 0, sizeof(identity_files)); memset(identity_keys, 0, sizeof(identity_keys)); memset(identity_file_userprovided, 0, sizeof(identity_file_userprovided)); memset(certificate_files, 0, sizeof(certificate_files)); memset(certificates, 0, sizeof(certificates)); memset(certificate_file_userprovided, 0, sizeof(certificate_file_userprovided)); #ifdef ENABLE_PKCS11 if (options.pkcs11_provider != NULL && options.num_identity_files < SSH_MAX_IDENTITY_FILES && (pkcs11_init(!options.batch_mode) == 0) && (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL, &keys, &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] = comments[i]; /* transferred */ n_ids++; } free(keys); free(comments); } #endif /* ENABLE_PKCS11 */ for (i = 0; i < options.num_identity_files; i++) { if (n_ids >= SSH_MAX_IDENTITY_FILES || strcasecmp(options.identity_files[i], "none") == 0) { free(options.identity_files[i]); options.identity_files[i] = NULL; continue; } cp = tilde_expand_filename(options.identity_files[i], getuid()); filename = default_client_percent_dollar_expand(cp, cinfo); free(cp); check_load(sshkey_load_public(filename, &public, NULL), &public, filename, "pubkey"); debug("identity file %s type %d", filename, public ? public->type : -1); free(options.identity_files[i]); identity_files[n_ids] = filename; identity_keys[n_ids] = public; identity_file_userprovided[n_ids] = options.identity_file_userprovided[i]; if (++n_ids >= SSH_MAX_IDENTITY_FILES) continue; /* * If no certificates have been explicitly listed then try * to add the default certificate variant too. */ if (options.num_certificate_files != 0) continue; xasprintf(&cp, "%s-cert", filename); check_load(sshkey_load_public(cp, &public, NULL), &public, filename, "pubkey"); debug("identity file %s type %d", cp, public ? public->type : -1); if (public == NULL) { free(cp); continue; } if (!sshkey_is_cert(public)) { debug_f("key %s type %s is not a certificate", cp, sshkey_type(public)); sshkey_free(public); free(cp); continue; } /* NB. leave filename pointing to private key */ identity_files[n_ids] = xstrdup(filename); identity_keys[n_ids] = public; identity_file_userprovided[n_ids] = options.identity_file_userprovided[i]; n_ids++; } if (options.num_certificate_files > SSH_MAX_CERTIFICATE_FILES) fatal_f("too many certificates"); for (i = 0; i < options.num_certificate_files; i++) { cp = tilde_expand_filename(options.certificate_files[i], getuid()); filename = default_client_percent_dollar_expand(cp, cinfo); free(cp); check_load(sshkey_load_public(filename, &public, NULL), &public, filename, "certificate"); debug("certificate file %s type %d", filename, public ? public->type : -1); free(options.certificate_files[i]); options.certificate_files[i] = NULL; if (public == NULL) { free(filename); continue; } if (!sshkey_is_cert(public)) { debug_f("key %s type %s is not a certificate", filename, sshkey_type(public)); sshkey_free(public); free(filename); continue; } certificate_files[n_certs] = filename; certificates[n_certs] = public; certificate_file_userprovided[n_certs] = options.certificate_file_userprovided[i]; ++n_certs; } options.num_identity_files = n_ids; memcpy(options.identity_files, identity_files, sizeof(identity_files)); memcpy(options.identity_keys, identity_keys, sizeof(identity_keys)); memcpy(options.identity_file_userprovided, identity_file_userprovided, sizeof(identity_file_userprovided)); options.num_certificate_files = n_certs; memcpy(options.certificate_files, certificate_files, sizeof(certificate_files)); memcpy(options.certificates, certificates, sizeof(certificates)); memcpy(options.certificate_file_userprovided, certificate_file_userprovided, sizeof(certificate_file_userprovided)); } static void main_sigchld_handler(int sig) { int save_errno = errno; pid_t pid; int status; while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || (pid == -1 && errno == EINTR)) ; errno = save_errno; } diff --git a/crypto/openssh/ssh2.h b/crypto/openssh/ssh2.h index 0d48d052782f..836eeda7c39a 100644 --- a/crypto/openssh/ssh2.h +++ b/crypto/openssh/ssh2.h @@ -1,179 +1,180 @@ -/* $OpenBSD: ssh2.h,v 1.21 2023/08/28 03:28:43 djm Exp $ */ +/* $OpenBSD: ssh2.h,v 1.22 2023/10/10 03:57:45 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * RFC4251: * * Transport layer protocol: * * 1-19 Transport layer generic (e.g. disconnect, ignore, debug, * etc) * 20-29 Algorithm negotiation * 30-49 Key exchange method specific (numbers can be reused for * different authentication methods) * * User authentication protocol: * * 50-59 User authentication generic * 60-79 User authentication method specific (numbers can be reused * for different authentication methods) * * Connection protocol: * * 80-89 Connection protocol generic * 90-127 Channel related messages * * Reserved for client protocols: * * 128-191 Reserved * * Local extensions: * * 192-255 Local extensions + * 248-255 Local extensions (OpenSSH will never use numbers in this range) */ /* special marker for no message */ #define SSH_MSG_NONE 0 /* ranges */ #define SSH2_MSG_TRANSPORT_MIN 1 #define SSH2_MSG_TRANSPORT_MAX 49 #define SSH2_MSG_USERAUTH_MIN 50 #define SSH2_MSG_USERAUTH_MAX 79 #define SSH2_MSG_USERAUTH_PER_METHOD_MIN 60 #define SSH2_MSG_USERAUTH_PER_METHOD_MAX SSH2_MSG_USERAUTH_MAX #define SSH2_MSG_CONNECTION_MIN 80 #define SSH2_MSG_CONNECTION_MAX 127 #define SSH2_MSG_RESERVED_MIN 128 #define SSH2_MSG_RESERVED_MAX 191 #define SSH2_MSG_LOCAL_MIN 192 #define SSH2_MSG_LOCAL_MAX 255 #define SSH2_MSG_MIN 1 #define SSH2_MSG_MAX 255 /* transport layer: generic */ #define SSH2_MSG_DISCONNECT 1 #define SSH2_MSG_IGNORE 2 #define SSH2_MSG_UNIMPLEMENTED 3 #define SSH2_MSG_DEBUG 4 #define SSH2_MSG_SERVICE_REQUEST 5 #define SSH2_MSG_SERVICE_ACCEPT 6 #define SSH2_MSG_EXT_INFO 7 #define SSH2_MSG_NEWCOMPRESS 8 /* transport layer: alg negotiation */ #define SSH2_MSG_KEXINIT 20 #define SSH2_MSG_NEWKEYS 21 /* transport layer: kex specific messages, can be reused */ #define SSH2_MSG_KEXDH_INIT 30 #define SSH2_MSG_KEXDH_REPLY 31 /* dh-group-exchange */ #define SSH2_MSG_KEX_DH_GEX_REQUEST_OLD 30 #define SSH2_MSG_KEX_DH_GEX_GROUP 31 #define SSH2_MSG_KEX_DH_GEX_INIT 32 #define SSH2_MSG_KEX_DH_GEX_REPLY 33 #define SSH2_MSG_KEX_DH_GEX_REQUEST 34 /* ecdh */ #define SSH2_MSG_KEX_ECDH_INIT 30 #define SSH2_MSG_KEX_ECDH_REPLY 31 /* transport layer: OpenSSH extensions */ #define SSH2_MSG_PING 192 #define SSH2_MSG_PONG 193 /* user authentication: generic */ #define SSH2_MSG_USERAUTH_REQUEST 50 #define SSH2_MSG_USERAUTH_FAILURE 51 #define SSH2_MSG_USERAUTH_SUCCESS 52 #define SSH2_MSG_USERAUTH_BANNER 53 /* user authentication: method specific, can be reused */ #define SSH2_MSG_USERAUTH_PK_OK 60 #define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60 #define SSH2_MSG_USERAUTH_INFO_REQUEST 60 #define SSH2_MSG_USERAUTH_INFO_RESPONSE 61 /* connection protocol: generic */ #define SSH2_MSG_GLOBAL_REQUEST 80 #define SSH2_MSG_REQUEST_SUCCESS 81 #define SSH2_MSG_REQUEST_FAILURE 82 /* channel related messages */ #define SSH2_MSG_CHANNEL_OPEN 90 #define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION 91 #define SSH2_MSG_CHANNEL_OPEN_FAILURE 92 #define SSH2_MSG_CHANNEL_WINDOW_ADJUST 93 #define SSH2_MSG_CHANNEL_DATA 94 #define SSH2_MSG_CHANNEL_EXTENDED_DATA 95 #define SSH2_MSG_CHANNEL_EOF 96 #define SSH2_MSG_CHANNEL_CLOSE 97 #define SSH2_MSG_CHANNEL_REQUEST 98 #define SSH2_MSG_CHANNEL_SUCCESS 99 #define SSH2_MSG_CHANNEL_FAILURE 100 /* disconnect reason code */ #define SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1 #define SSH2_DISCONNECT_PROTOCOL_ERROR 2 #define SSH2_DISCONNECT_KEY_EXCHANGE_FAILED 3 #define SSH2_DISCONNECT_HOST_AUTHENTICATION_FAILED 4 #define SSH2_DISCONNECT_RESERVED 4 #define SSH2_DISCONNECT_MAC_ERROR 5 #define SSH2_DISCONNECT_COMPRESSION_ERROR 6 #define SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE 7 #define SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8 #define SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9 #define SSH2_DISCONNECT_CONNECTION_LOST 10 #define SSH2_DISCONNECT_BY_APPLICATION 11 #define SSH2_DISCONNECT_TOO_MANY_CONNECTIONS 12 #define SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER 13 #define SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14 #define SSH2_DISCONNECT_ILLEGAL_USER_NAME 15 /* misc */ #define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED 1 #define SSH2_OPEN_CONNECT_FAILED 2 #define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE 3 #define SSH2_OPEN_RESOURCE_SHORTAGE 4 #define SSH2_EXTENDED_DATA_STDERR 1 /* Certificate types for OpenSSH certificate keys extension */ #define SSH2_CERT_TYPE_USER 1 #define SSH2_CERT_TYPE_HOST 2 diff --git a/crypto/openssh/ssh_config.5 b/crypto/openssh/ssh_config.5 index e50c17728967..dead70fa9868 100644 --- a/crypto/openssh/ssh_config.5 +++ b/crypto/openssh/ssh_config.5 @@ -1,2274 +1,2347 @@ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland .\" All rights reserved .\" .\" As far as I am concerned, the code I have written for this software .\" can be used freely for any purpose. Any derived versions of this .\" software must be clearly marked as such, and if the derived work is .\" incompatible with the protocol description in the RFC file, it must be .\" called by a name other than "ssh" or "Secure Shell". .\" .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh_config.5,v 1.387 2023/10/04 04:03:50 djm Exp $ -.Dd $Mdocdate: October 4 2023 $ +.\" $OpenBSD: ssh_config.5,v 1.391 2023/10/12 02:18:18 djm Exp $ +.Dd $Mdocdate: October 12 2023 $ .Dt SSH_CONFIG 5 .Os .Sh NAME .Nm ssh_config .Nd OpenSSH client configuration file .Sh DESCRIPTION .Xr ssh 1 obtains configuration data from the following sources in the following order: .Pp .Bl -enum -offset indent -compact .It command-line options .It user's configuration file .Pq Pa ~/.ssh/config .It system-wide configuration file .Pq Pa /etc/ssh/ssh_config .El .Pp Unless noted otherwise, for each parameter, the first obtained value will be used. The configuration files contain sections separated by .Cm Host specifications, and that section is only applied for hosts that match one of the patterns given in the specification. The matched host name is usually the one given on the command line (see the .Cm CanonicalizeHostname option for exceptions). .Pp Since the first obtained value for each parameter is used, more host-specific declarations should be given near the beginning of the file, and general defaults at the end. .Pp The file contains keyword-argument pairs, one per line. Lines starting with .Ql # and empty lines are interpreted as comments. Arguments may optionally be enclosed in double quotes .Pq \&" in order to represent arguments containing spaces. Configuration options may be separated by whitespace or optional whitespace and exactly one .Ql = ; the latter format is useful to avoid the need to quote whitespace when specifying configuration options using the .Nm ssh , .Nm scp , and .Nm sftp .Fl o option. .Pp The possible keywords and their meanings are as follows (note that keywords are case-insensitive and arguments are case-sensitive): .Bl -tag -width Ds .It Cm Host Restricts the following declarations (up to the next .Cm Host or .Cm Match keyword) to be only for those hosts that match one of the patterns given after the keyword. If more than one pattern is provided, they should be separated by whitespace. A single .Ql * as a pattern can be used to provide global defaults for all hosts. The host is usually the .Ar hostname argument given on the command line (see the .Cm CanonicalizeHostname keyword for exceptions). .Pp A pattern entry may be negated by prefixing it with an exclamation mark .Pq Sq !\& . If a negated entry is matched, then the .Cm Host entry is ignored, regardless of whether any other patterns on the line match. Negated matches are therefore useful to provide exceptions for wildcard matches. .Pp See .Sx PATTERNS for more information on patterns. .It Cm Match Restricts the following declarations (up to the next .Cm Host or .Cm Match keyword) to be used only when the conditions following the .Cm Match keyword are satisfied. Match conditions are specified using one or more criteria or the single token .Cm all which always matches. The available criteria keywords are: .Cm canonical , .Cm final , .Cm exec , .Cm localnetwork , .Cm host , .Cm originalhost , .Cm Tag , .Cm user , and .Cm localuser . The .Cm all criteria must appear alone or immediately after .Cm canonical or .Cm final . Other criteria may be combined arbitrarily. All criteria but .Cm all , .Cm canonical , and .Cm final require an argument. Criteria may be negated by prepending an exclamation mark .Pq Sq !\& . .Pp The .Cm canonical keyword matches only when the configuration file is being re-parsed after hostname canonicalization (see the .Cm CanonicalizeHostname option). This may be useful to specify conditions that work with canonical host names only. .Pp The .Cm final keyword requests that the configuration be re-parsed (regardless of whether .Cm CanonicalizeHostname is enabled), and matches only during this final pass. If .Cm CanonicalizeHostname is enabled, then .Cm canonical and .Cm final match during the same pass. .Pp The .Cm exec keyword executes the specified command under the user's shell. If the command returns a zero exit status then the condition is considered true. Commands containing whitespace characters must be quoted. Arguments to .Cm exec accept the tokens described in the .Sx TOKENS section. .Pp The .Cm localnetwork keyword matches the addresses of active local network interfaces against the supplied list of networks in CIDR format. This may be convenient for varying the effective configuration on devices that roam between networks. Note that network address is not a trustworthy criteria in many situations (e.g. when the network is automatically configured using DHCP) and so caution should be applied if using it to control security-sensitive configuration. .Pp The other keywords' criteria must be single entries or comma-separated lists and may use the wildcard and negation operators described in the .Sx PATTERNS section. The criteria for the .Cm host keyword are matched against the target hostname, after any substitution by the .Cm Hostname or .Cm CanonicalizeHostname options. The .Cm originalhost keyword matches against the hostname as it was specified on the command-line. The .Cm tagged keyword matches a tag name specified by a prior .Cm Tag directive or on the .Xr ssh 1 command-line using the .Fl P flag. The .Cm user keyword matches against the target username on the remote host. The .Cm localuser keyword matches against the name of the local user running .Xr ssh 1 (this keyword may be useful in system-wide .Nm files). .It Cm AddKeysToAgent Specifies whether keys should be automatically added to a running .Xr ssh-agent 1 . If this option is set to .Cm yes and a key is loaded from a file, the key and its passphrase are added to the agent with the default lifetime, as if by .Xr ssh-add 1 . If this option is set to .Cm ask , .Xr ssh 1 will require confirmation using the .Ev SSH_ASKPASS program before adding a key (see .Xr ssh-add 1 for details). If this option is set to .Cm confirm , each use of the key must be confirmed, as if the .Fl c option was specified to .Xr ssh-add 1 . If this option is set to .Cm no , no keys are added to the agent. 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 no (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 .Cm any (the default), .Cm inet (use IPv4 only), or .Cm inet6 (use IPv6 only). .It Cm BatchMode If set to .Cm yes , 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 interact with .Xr ssh 1 . The argument must be .Cm yes or .Cm no (the default). .It Cm BindAddress Use the specified address on the local machine as the source address of the connection. Only useful on systems with more than one address. .It Cm BindInterface Use the address of the specified interface on the local machine as the source address of the connection. .It Cm CanonicalDomains When .Cm CanonicalizeHostname is enabled, this option specifies the list of domain suffixes in which to search for the specified destination host. .It Cm CanonicalizeFallbackLocal Specifies whether to fail with an error when hostname canonicalization fails. The default, .Cm yes , will attempt to look up the unqualified hostname using the system resolver's search rules. A value of .Cm no will cause .Xr ssh 1 to fail instantly if .Cm CanonicalizeHostname is enabled and the target hostname cannot be found in any of the domains specified by .Cm CanonicalDomains . .It Cm CanonicalizeHostname Controls whether explicit hostname canonicalization is performed. The default, .Cm no , is not to perform any name rewriting and let the system resolver handle all hostname lookups. If set to .Cm yes then, for connections that do not use a .Cm ProxyCommand or .Cm ProxyJump , .Xr ssh 1 will attempt to canonicalize the hostname specified on the command line using the .Cm CanonicalDomains suffixes and .Cm CanonicalizePermittedCNAMEs rules. If .Cm CanonicalizeHostname is set to .Cm always , then canonicalization is applied to proxied connections too. .Pp If this option is enabled, then the configuration files are processed again using the new target name to pick up any new configuration in matching .Cm Host and .Cm Match stanzas. A value of .Cm none disables the use of a .Cm ProxyJump host. .It Cm CanonicalizeMaxDots Specifies the maximum number of dot characters in a hostname before canonicalization is disabled. The default, 1, allows a single dot (i.e. hostname.subdomain). .It Cm CanonicalizePermittedCNAMEs Specifies rules to determine whether CNAMEs should be followed when canonicalizing hostnames. The rules consist of one or more arguments of .Ar source_domain_list : Ns Ar target_domain_list , where .Ar source_domain_list is a pattern-list of domains that may follow CNAMEs in canonicalization, and .Ar target_domain_list is a pattern-list of domains that they may resolve to. .Pp For example, .Qq *.a.example.com:*.b.example.com,*.c.example.com will allow hostnames matching .Qq *.a.example.com to be canonicalized to names in the .Qq *.b.example.com or .Qq *.c.example.com domains. .Pp A single argument of .Qq none causes no CNAMEs to be considered for canonicalization. This is the default behaviour. .It Cm CASignatureAlgorithms Specifies which algorithms are allowed for signing of certificates by certificate authorities (CAs). The default is: .Bd -literal -offset indent 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 .Ed .Pp If the specified list begins with a .Sq + 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 algorithms (including wildcards) will be removed from the default set instead of replacing them. .Pp .Xr ssh 1 will not accept host certificates signed using algorithms other than those specified. .It Cm CertificateFile Specifies a file from which the user's certificate is read. A corresponding private key must be provided separately in order to use this certificate either from an .Cm IdentityFile directive or .Fl i flag to .Xr ssh 1 , via .Xr ssh-agent 1 , or via a .Cm PKCS11Provider or .Cm SecurityKeyProvider . .Pp Arguments to .Cm CertificateFile 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 configuration files; these certificates will be tried in sequence. Multiple .Cm CertificateFile directives will add to the list of certificates used for authentication. +.It Cm ChannelTimeout +Specifies whether and how quickly +.Xr ssh 1 +should close inactive channels. +Timeouts are specified as one or more +.Dq type=interval +pairs separated by whitespace, where the +.Dq type +must be a channel type name (as described in the table below), optionally +containing wildcard characters. +.Pp +The timeout value +.Dq interval +is specified in seconds or may use any of the units documented in the +.Sx TIME FORMATS +section. +For example, +.Dq session=5m +would cause the interactive session to terminate after five minutes of +inactivity. +Specifying a zero value disables the inactivity timeout. +.Pp +The available channel types include: +.Bl -tag -width Ds +.It Cm agent-connection +Open connections to +.Xr ssh-agent 1 . +.It Cm direct-tcpip , Cm direct-streamlocal@openssh.com +Open TCP or Unix socket (respectively) connections that have +been established from a +.Xr ssh 1 +local forwarding, i.e.\& +.Cm LocalForward +or +.Cm DynamicForward . +.It Cm forwarded-tcpip , Cm forwarded-streamlocal@openssh.com +Open TCP or Unix socket (respectively) connections that have been +established to a +.Xr sshd 8 +listening on behalf of a +.Xr ssh 1 +remote forwarding, i.e.\& +.Cm RemoteForward . +.It Cm session +The interactive main session, including shell session, command execution, +.Xr scp 1 , +.Xr sftp 1 , +etc. +.It Cm tun-connection +Open +.Cm TunnelForward +connections. +.It Cm x11-connection +Open X11 forwarding sessions. +.El +.Pp +Note that in all the above cases, terminating an inactive session does not +guarantee to remove all resources associated with the session, e.g. shell +processes or X11 clients relating to the session may continue to execute. +.Pp +Moreover, terminating an inactive channel or session does not necessarily +close the SSH connection, nor does it prevent a client from +requesting another channel of the same type. +In particular, expiring an inactive forwarding session does not prevent +another identical forwarding from being subsequently created. +.Pp +The default is not to expire channels of any type for inactivity. .It Cm CheckHostIP If set to .Cm yes , .Xr ssh 1 will additionally check the host IP address in the .Pa known_hosts file. This allows it to detect if a host key changed due to DNS spoofing and will add addresses of destination hosts to .Pa ~/.ssh/known_hosts in the process, regardless of the setting of .Cm StrictHostKeyChecking . If the option is set to .Cm no (the default), the check will not be executed. The default is .Cm no . .It Cm Ciphers Specifies the ciphers allowed and their order of preference. Multiple ciphers must be comma-separated. If the specified list begins with a .Sq + character, then the specified ciphers will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - character, then the specified ciphers (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 ciphers will be placed at the head of the default set. .Pp The supported ciphers are: .Bd -literal -offset indent 3des-cbc aes128-cbc aes192-cbc aes256-cbc aes128-ctr aes192-ctr aes256-ctr aes128-gcm@openssh.com aes256-gcm@openssh.com chacha20-poly1305@openssh.com .Ed .Pp The default is: .Bd -literal -offset indent chacha20-poly1305@openssh.com, aes128-ctr,aes192-ctr,aes256-ctr, aes128-gcm@openssh.com,aes256-gcm@openssh.com .Ed .Pp The list of available ciphers may also be obtained using .Qq ssh -Q cipher . .It Cm ClearAllForwardings Specifies that all local, remote, and dynamic port forwardings specified in the configuration files or on the command line be cleared. This option is primarily useful when used from the .Xr ssh 1 command line to clear port forwardings set in configuration files, and is automatically set by .Xr scp 1 and .Xr sftp 1 . The argument must be .Cm yes or .Cm no (the default). .It Cm Compression Specifies whether to use compression. The argument must be .Cm yes or .Cm no (the default). .It Cm ConnectionAttempts Specifies the number of tries (one per second) to make before exiting. The argument must be an integer. This may be useful in scripts if the connection sometimes fails. The default is 1. .It Cm ConnectTimeout Specifies the timeout (in seconds) used when connecting to the SSH server, instead of using the default system TCP timeout. This timeout is applied both to establishing the connection and to performing the initial SSH protocol handshake and key exchange. .It Cm ControlMaster Enables the sharing of multiple sessions over a single network connection. When set to .Cm yes , .Xr ssh 1 will listen for connections on a control socket specified using the .Cm ControlPath argument. Additional sessions can connect to this socket using the same .Cm ControlPath with .Cm ControlMaster set to .Cm no (the default). These sessions will try to reuse the master instance's network connection rather than initiating new ones, but will fall back to connecting normally if the control socket does not exist, or is not listening. .Pp Setting this to .Cm ask will cause .Xr ssh 1 to listen for control connections, but require confirmation using .Xr ssh-askpass 1 . If the .Cm ControlPath cannot be opened, .Xr ssh 1 will continue without connecting to a master instance. .Pp X11 and .Xr ssh-agent 1 forwarding is supported over these multiplexed connections, however the display and agent forwarded will be the one belonging to the master connection i.e. it is not possible to forward multiple displays or agents. .Pp Two additional options allow for opportunistic multiplexing: try to use a master connection but fall back to creating a new one if one does not already exist. These options are: .Cm auto and .Cm autoask . The latter requires confirmation like the .Cm ask option. .It Cm ControlPath Specify the path to the control socket used for connection sharing as described in the .Cm ControlMaster section above or the string .Cm none to disable connection sharing. Arguments to .Cm ControlPath may use the tilde syntax to refer to a user's home directory, 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 used for opportunistic connection sharing include at least %h, %p, and %r (or alternatively %C) and be placed in a directory that is not writable by other users. This ensures that shared connections are uniquely identified. .It Cm ControlPersist When used in conjunction with .Cm ControlMaster , specifies that the master connection should remain open in the background (waiting for future client connections) after the initial client connection has been closed. If set to .Cm no (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 .Cm yes or 0, then the master connection will remain in the background indefinitely (until killed or closed via a mechanism such as the .Qq ssh -O exit ) . If set to a time in seconds, or a time in any of the formats documented in .Xr sshd_config 5 , then the backgrounded master connection will automatically terminate after it has remained idle (with no client connections) for the specified time. .It Cm DynamicForward Specifies that a TCP port on the local machine be forwarded over the secure channel, and the application protocol is then used to determine where to connect to from the remote machine. .Pp The argument must be .Sm off .Oo Ar bind_address : Oc Ar port . .Sm on IPv6 addresses can be specified by enclosing addresses in square brackets. By default, the local port is bound in accordance with the .Cm GatewayPorts setting. However, an explicit .Ar bind_address may be used to bind the connection to a specific address. The .Ar bind_address of .Cm localhost indicates that the listening port be bound for local use only, while an empty address or .Sq * indicates that the port should be available from all interfaces. .Pp Currently the SOCKS4 and SOCKS5 protocols are supported, and .Xr ssh 1 will act as a SOCKS server. Multiple forwardings may be specified, and additional forwardings can be given on the command line. Only the superuser can forward privileged ports. .It Cm EnableEscapeCommandline Enables the command line option in the .Cm EscapeChar menu for interactive sessions (default .Ql ~C ) . By default, the command line is disabled. .It Cm EnableSSHKeysign Setting this option to .Cm yes in the global client configuration file .Pa /etc/ssh/ssh_config enables the use of the helper program .Xr ssh-keysign 8 during .Cm HostbasedAuthentication . The argument must be .Cm yes or .Cm no (the default). This option should be placed in the non-hostspecific section. See .Xr ssh-keysign 8 for more information. .It Cm EscapeChar Sets the escape character (default: .Ql ~ ) . The escape character can also be set on the command line. The argument should be a single character, .Ql ^ followed by a letter, or .Cm none to disable the escape character entirely (making the connection transparent for binary data). .It Cm ExitOnForwardFailure Specifies whether .Xr ssh 1 should terminate the connection if it cannot set up all requested dynamic, tunnel, local, and remote port forwardings, (e.g.\& if either end is unable to bind and listen on a specified port). Note that .Cm ExitOnForwardFailure does not apply to connections made over port forwardings and will not, for example, cause .Xr ssh 1 to exit if TCP connections to the ultimate forwarding destination fail. The argument must be .Cm yes or .Cm no (the default). .It Cm FingerprintHash Specifies the hash algorithm used when displaying key fingerprints. Valid options are: .Cm md5 and .Cm sha256 (the default). .It Cm ForkAfterAuthentication Requests .Nm ssh to go to background just before command execution. This is useful if .Nm ssh is going to ask for passwords or passphrases, but the user wants it in the background. This implies the .Cm StdinNull configuration option being set to .Dq yes . The recommended way to start X11 programs at a remote site is with something like .Ic ssh -f host xterm , which is the same as .Ic ssh host xterm if the .Cm ForkAfterAuthentication configuration option is set to .Dq yes . .Pp If the .Cm ExitOnForwardFailure configuration option is set to .Dq yes , then a client started with the .Cm ForkAfterAuthentication configuration option being set to .Dq yes will wait for all remote port forwards to be successfully established before placing itself in the background. The argument to this keyword must be .Cm yes (same as the .Fl f option) or .Cm no (the default). .It Cm ForwardAgent Specifies whether the connection to the authentication agent (if any) will be forwarded to the remote machine. The argument may be .Cm yes , .Cm no (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 (for the agent's Unix-domain socket) can access the local agent through the forwarded connection. An attacker cannot obtain key material from the agent, however they can perform operations on the keys that enable them to authenticate using the identities loaded into the agent. .It Cm ForwardX11 Specifies whether X11 connections will be automatically redirected over the secure channel and .Ev DISPLAY set. The argument must be .Cm yes or .Cm no (the default). .Pp X11 forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the user's X11 authorization database) can access the local X11 display through the forwarded connection. An attacker may then be able to perform activities such as keystroke monitoring if the .Cm ForwardX11Trusted option is also enabled. .It Cm ForwardX11Timeout Specify a timeout for untrusted X11 forwarding using the format described in the .Sx TIME FORMATS section of .Xr sshd_config 5 . X11 connections received by .Xr ssh 1 after this time will be refused. Setting .Cm ForwardX11Timeout to zero will disable the timeout and permit X11 forwarding for the life of the connection. The default is to disable untrusted X11 forwarding after twenty minutes has elapsed. .It Cm ForwardX11Trusted If this option is set to .Cm yes , remote X11 clients will have full access to the original X11 display. .Pp If this option is set to .Cm no (the default), remote X11 clients will be considered untrusted and prevented from stealing or tampering with data belonging to trusted X11 clients. Furthermore, the .Xr xauth 1 token used for the session will be set to expire after 20 minutes. Remote clients will be refused access after this time. .Pp See the X11 SECURITY extension specification for full details on the restrictions imposed on untrusted clients. .It Cm GatewayPorts Specifies whether remote hosts are allowed to connect to local forwarded ports. By default, .Xr ssh 1 binds local port forwardings to the loopback address. This prevents other remote hosts from connecting to forwarded ports. .Cm GatewayPorts can be used to specify that ssh should bind local port forwardings to the wildcard address, thus allowing remote hosts to connect to forwarded ports. The argument must be .Cm yes or .Cm no (the default). .It Cm GlobalKnownHostsFile Specifies one or more files to use for the global host key database, separated by whitespace. The default is .Pa /etc/ssh/ssh_known_hosts , .Pa /etc/ssh/ssh_known_hosts2 . .It Cm GSSAPIAuthentication Specifies whether user authentication based on GSSAPI is allowed. The default is .Cm no . .It Cm GSSAPIDelegateCredentials Forward (delegate) credentials to the server. The default is .Cm no . .It Cm HashKnownHosts Indicates that .Xr ssh 1 should hash host names and addresses when they are added to .Pa ~/.ssh/known_hosts . These hashed names may be used normally by .Xr ssh 1 and .Xr sshd 8 , but they do not 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-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 .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. The argument must be .Cm yes or .Cm no (the default). .It Cm HostKeyAlgorithms 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 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-ed25519, ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, sk-ecdsa-sha2-nistp256@openssh.com, sk-ssh-ed25519@openssh.com, rsa-sha2-512,rsa-sha2-256 .Ed .Pp If hostkeys are known for the destination host then this default is modified to prefer their algorithms. .Pp 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 in the host key database files and when validating host certificates. This option is useful for tunneling SSH connections or for multiple servers running on a single host. .It Cm Hostname Specifies the real host name to log into. This can be used to specify nicknames or abbreviations for hosts. Arguments to .Cm Hostname accept the tokens described in the .Sx TOKENS section. Numeric IP addresses are also permitted (both on the command line and in .Cm Hostname specifications). The default is the name given on the command line. .It Cm IdentitiesOnly Specifies that .Xr ssh 1 should only use the configured authentication identity and certificate files (either the default files, or those explicitly configured in the .Nm files or passed on the .Xr ssh 1 command-line), even if .Xr ssh-agent 1 or a .Cm PKCS11Provider or .Cm SecurityKeyProvider offers more identities. The argument to this keyword must be .Cm yes or .Cm no (the default). This option is intended for situations where ssh-agent offers many different identities. .It Cm IdentityAgent Specifies the .Ux Ns -domain socket used to communicate with the authentication agent. .Pp This option overrides the .Ev SSH_AUTH_SOCK environment variable and can be used to select a specific agent. Setting the socket name to .Cm none disables the use of an authentication agent. If the string .Qq SSH_AUTH_SOCK is specified, the location of the socket will be read from the .Ev SSH_AUTH_SOCK environment variable. Otherwise if the specified value begins with a .Sq $ character, then it will be treated as an environment variable containing the location of the socket. .Pp Arguments to .Cm IdentityAgent may use the tilde syntax to refer to a user's home directory, 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, authenticator-hosted ECDSA, Ed25519, authenticator-hosted Ed25519 or RSA authentication identity is read. You can also specify a public key file to use the corresponding private key that is loaded in .Xr ssh-agent 1 when the private key file is not present locally. The default is .Pa ~/.ssh/id_rsa , .Pa ~/.ssh/id_ecdsa , .Pa ~/.ssh/id_ecdsa_sk , .Pa ~/.ssh/id_ed25519 , .Pa ~/.ssh/id_ed25519_sk and .Pa ~/.ssh/id_dsa . Additionally, any identities represented by the authentication agent will be used for authentication unless .Cm IdentitiesOnly is set. If no certificates have been explicitly specified by .Cm CertificateFile , .Xr ssh 1 will try to load certificate information from the filename obtained by appending .Pa -cert.pub to the path of a specified .Cm IdentityFile . .Pp Arguments to .Cm IdentityFile may use the tilde syntax to refer to a user's home directory or the tokens described in the .Sx TOKENS section. +Alternately an argument of +.Cm none +may be used to indicate no identity files should be loaded. .Pp It is possible to have multiple identity files specified in configuration files; all these identities will be tried in sequence. Multiple .Cm IdentityFile directives will add to the list of identities tried (this behaviour differs from that of other configuration directives). .Pp .Cm IdentityFile may be used in conjunction with .Cm IdentitiesOnly to select which identities in an agent are offered during authentication. .Cm IdentityFile may also be used in conjunction with .Cm CertificateFile in order to provide any certificate also needed for authentication with the identity. .It Cm IgnoreUnknown Specifies a pattern-list of unknown options to be ignored if they are encountered in configuration parsing. This may be used to suppress errors if .Nm contains options that are unrecognised by .Xr ssh 1 . It is recommended that .Cm IgnoreUnknown be listed early in the configuration file as it will not be applied to unknown options that appear before it. .It Cm Include Include the specified configuration file(s). Multiple pathnames may be specified and each pathname may contain .Xr glob 7 wildcards and, for user configurations, shell-like .Sq ~ references to user home directories. 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 .Pa /etc/ssh if included from the system configuration file. .Cm Include directive may appear inside a .Cm Match or .Cm Host block to perform conditional inclusion. .It Cm IPQoS Specifies the IPv4 type-of-service or DSCP class for connections. Accepted values are .Cm af11 , .Cm af12 , .Cm af13 , .Cm af21 , .Cm af22 , .Cm af23 , .Cm af31 , .Cm af32 , .Cm af33 , .Cm af41 , .Cm af42 , .Cm af43 , .Cm cs0 , .Cm cs1 , .Cm cs2 , .Cm cs3 , .Cm cs4 , .Cm cs5 , .Cm cs6 , .Cm cs7 , .Cm ef , .Cm le , .Cm lowdelay , .Cm throughput , .Cm reliability , a numeric value, or .Cm none to use the operating system default. This option may take one or two arguments, separated by whitespace. If one argument is specified, it is used as the packet class unconditionally. If two values are specified, the first is automatically selected for interactive sessions and the second for non-interactive sessions. The default is .Cm af21 (Low-Latency Data) for interactive sessions and .Cm cs1 (Lower Effort) for non-interactive sessions. .It Cm KbdInteractiveAuthentication Specifies whether to use keyboard-interactive authentication. The argument to this keyword must be .Cm yes (the default) or .Cm no . .Cm ChallengeResponseAuthentication is a deprecated alias for this. .It Cm KbdInteractiveDevices Specifies the list of methods to use in keyboard-interactive authentication. Multiple method names must be comma-separated. The default is to use the server specified list. The methods available vary depending on what the server supports. For an OpenSSH server, it may be zero or more of: .Cm bsdauth and .Cm pam . .It Cm KexAlgorithms Specifies the available KEX (Key Exchange) algorithms. Multiple algorithms must be comma-separated. If the specified list begins with a .Sq + 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 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 algorithms will be placed at the head of the default set. The default is: .Bd -literal -offset indent sntrup761x25519-sha512@openssh.com, 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 .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. The command string extends to the end of the line, and is executed with the user's shell. Arguments to .Cm LocalCommand accept the tokens described in the .Sx TOKENS section. .Pp The command is run synchronously and does not have access to the session of the .Xr ssh 1 that spawned it. It should not be used for interactive commands. .Pp This directive is ignored unless .Cm PermitLocalCommand has been enabled. .It Cm LocalForward Specifies that a TCP port on the local machine be forwarded over the secure channel to the specified host and port from the remote machine. The first argument specifies the listener and may be .Sm off .Oo Ar bind_address : Oc Ar port .Sm on 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. Only the superuser can forward privileged ports. By default, the local port is bound in accordance with the .Cm GatewayPorts setting. However, an explicit .Ar bind_address may be used to bind the connection to a specific address. The .Ar bind_address of .Cm localhost indicates that the listening port be bound for local use only, while an empty address or .Sq * indicates that the port should be available from all interfaces. 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 . The possible values are: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify higher levels of verbose output. .It Cm 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. The MAC algorithm is used for data integrity protection. Multiple algorithms must be comma-separated. If the specified list begins with a .Sq + 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 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 algorithms will be placed at the head of the default set. .Pp The algorithms that contain .Qq -etm calculate the MAC after encryption (encrypt-then-mac). These are considered safer and their use recommended. .Pp The default is: .Bd -literal -offset indent umac-64-etm@openssh.com,umac-128-etm@openssh.com, hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, hmac-sha1-etm@openssh.com, umac-64@openssh.com,umac-128@openssh.com, hmac-sha2-256,hmac-sha2-512,hmac-sha1 .Ed .Pp The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . .It Cm NoHostAuthenticationForLocalhost Disable host authentication for localhost (loopback addresses). The argument to this keyword must be .Cm yes or .Cm no (the default). .It Cm NumberOfPasswordPrompts Specifies the number of password prompts before giving up. The argument to this keyword must be an integer. The default is 3. .It Cm ObscureKeystrokeTiming Specifies whether .Xr ssh 1 should try to obscure inter-keystroke timings from passive observers of network traffic. If enabled, then for interactive sessions, .Xr ssh 1 will send keystrokes at fixed intervals of a few tens of milliseconds and will send fake keystroke packets for some time after typing ceases. The argument to this keyword must be .Cm yes , .Cm no or an interval specifier of the form .Cm interval:milliseconds (e.g.\& .Cm interval:80 for 80 milliseconds). The default is to obscure keystrokes using a 20ms packet interval. Note that smaller intervals will result in higher fake keystroke packet rates. .It Cm PasswordAuthentication Specifies whether to use password authentication. The argument to this keyword must be .Cm yes (the default) or .Cm no . .It Cm PermitLocalCommand Allow local command execution via the .Ic LocalCommand option or using the .Ic !\& Ns Ar command escape sequence in .Xr ssh 1 . The argument must be .Cm yes or .Cm no (the default). .It Cm 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 to indicate that no provider should be used (the default). The argument to this keyword is a path to the PKCS#11 shared library .Xr ssh 1 should use to communicate with a PKCS#11 token providing keys for user authentication. .It Cm Port Specifies the port number to connect on the remote host. The default is 22. .It Cm PreferredAuthentications Specifies the order in which the client should try authentication methods. This allows a client to prefer one method (e.g.\& .Cm keyboard-interactive ) over another method (e.g.\& .Cm password ) . The default is: .Bd -literal -offset indent gssapi-with-mic,hostbased,publickey, keyboard-interactive,password .Ed .It Cm ProxyCommand Specifies the command to use to connect to the server. The command string extends to the end of the line, and is executed using the user's shell .Ql exec directive to avoid a lingering shell process. .Pp Arguments to .Cm ProxyCommand accept the tokens described in the .Sx TOKENS section. The command can be basically anything, and should read from its standard input and write to its standard output. It should eventually connect an .Xr sshd 8 server running on some machine, or execute .Ic sshd -i somewhere. Host key management will be done using the .Cm Hostname of the host being connected (defaulting to the name typed by the user). Setting the command to .Cm none disables this option entirely. Note that .Cm CheckHostIP is not available for connects with a proxy command. .Pp This directive is useful in conjunction with .Xr nc 1 and its proxy support. For example, the following directive would connect via an HTTP proxy at 192.0.2.0: .Bd -literal -offset 3n ProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p .Ed .It Cm ProxyJump Specifies one or more jump proxies as either .Xo .Sm off .Op Ar user No @ .Ar host .Op : Ns Ar port .Sm on or an ssh URI .Xc . Multiple proxies may be separated by comma characters and will be visited sequentially. Setting this option will cause .Xr ssh 1 to connect to the target host by first making a .Xr ssh 1 connection to the specified .Cm ProxyJump host and then establishing a TCP forwarding to the ultimate target from there. Setting the host to .Cm none disables this option entirely. .Pp Note that this option will compete with the .Cm ProxyCommand option - whichever is specified first will prevent later instances of the other from taking effect. .Pp Note also that the configuration for the destination host (either supplied via the command-line or the configuration file) is not generally applied to jump hosts. .Pa ~/.ssh/config should be used if specific configuration is required for jump hosts. .It Cm ProxyUseFdpass Specifies that .Cm ProxyCommand will pass a connected file descriptor back to .Xr ssh 1 instead of continuing to execute and pass data. The default is .Cm no . .It Cm 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 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 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 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-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 .Ed .Pp 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 .Cm yes (the default), .Cm no , .Cm unbound or .Cm host-bound . The final two options enable public key authentication while respectively disabling or enabling the OpenSSH host-bound authentication protocol extension required for restricted .Xr ssh-agent 1 forwarding. .It Cm RekeyLimit Specifies the maximum amount of data that may be transmitted or received before the 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 , .Sq M , or .Sq G to indicate Kilobytes, Megabytes, or Gigabytes, respectively. The default is between .Sq 1G and .Sq 4G , depending on the cipher. The optional second value is specified in seconds and may use any of the units documented in the TIME FORMATS section of .Xr sshd_config 5 . The default value for .Cm RekeyLimit is .Cm default none , which means that rekeying is performed after the cipher's default amount of data has been sent or received and no time based rekeying is done. .It Cm RemoteCommand Specifies a command to execute on the remote machine after successfully connecting to the server. The command string extends to the end of the line, and is executed with the user's shell. Arguments to .Cm RemoteCommand accept the tokens described in the .Sx TOKENS section. .It Cm RemoteForward Specifies that a TCP port on the remote machine be forwarded over the secure channel. The remote port may either be forwarded to a specified host and port from the local machine, or may act as a SOCKS 4/5 proxy that allows a remote client to connect to arbitrary destinations from the local machine. The first argument 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 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 argument is 0, the listen port will be dynamically allocated on the server and reported to the client at run time. .Pp If the .Ar bind_address is not specified, the default is to only bind to loopback addresses. If the .Ar bind_address is .Ql * or an empty string, then the forwarding is requested to listen on all interfaces. Specifying a remote .Ar bind_address will only succeed if the server's .Cm GatewayPorts option is enabled (see .Xr sshd_config 5 ) . .It Cm RequestTTY Specifies whether to request a pseudo-tty for the session. The argument may be one of: .Cm no (never request a TTY), .Cm yes (always request a TTY when standard input is a TTY), .Cm force (always request a TTY) or .Cm auto (request a TTY when opening a login session). This option mirrors the .Fl t and .Fl T flags for .Xr ssh 1 . .It Cm RequiredRSASize Specifies the minimum RSA key size (in bits) that .Xr ssh 1 will accept. User authentication keys smaller than this limit will be ignored. Servers that present host keys smaller than this limit will cause the connection to be terminated. The default is .Cm 1024 bits. Note that this limit may only be raised from the default. .It Cm RevokedHostKeys Specifies revoked host public keys. Keys listed in this file will be refused for host authentication. Note that if this file does not exist or is not readable, then host authentication will be refused for all hosts. Keys may be specified as a text file, listing one public key per line, or as an OpenSSH Key Revocation List (KRL) as generated by .Xr ssh-keygen 1 . For more information on KRLs, see the KEY REVOCATION LISTS section in .Xr ssh-keygen 1 . Arguments to .Cm RevokedHostKeys 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 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 should be sent to the server. The server must also support it, and the server must be configured to accept these environment variables. Note that the .Ev TERM environment variable is always sent whenever a pseudo-terminal is requested as it is required by the protocol. Refer to .Cm AcceptEnv in .Xr sshd_config 5 for how to configure the server. Variables are specified by name, which may contain wildcard characters. Multiple environment variables may be separated by whitespace or spread across multiple .Cm SendEnv directives. .Pp See .Sx PATTERNS for more information on patterns. .Pp It is possible to clear previously set .Cm SendEnv variable names by prefixing patterns with .Pa - . The default is not to send any environment variables. .It Cm ServerAliveCountMax Sets the number of server alive messages (see below) which may be sent without .Xr ssh 1 receiving any messages back from the server. If this threshold is reached while server alive messages are being sent, ssh will disconnect from the server, terminating the session. It is important to note that the use of server alive messages is very different from .Cm TCPKeepAlive (below). The server alive messages are sent through the encrypted channel and therefore will not be spoofable. The TCP keepalive option enabled by .Cm TCPKeepAlive is spoofable. The server alive mechanism is valuable when the client or server depend on knowing when a connection has become unresponsive. .Pp The default value is 3. If, for example, .Cm ServerAliveInterval (see below) is set to 15 and .Cm ServerAliveCountMax is left at the default, if the server becomes unresponsive, ssh will disconnect after approximately 45 seconds. .It Cm ServerAliveInterval Sets a timeout interval in seconds after which if no data has been received from the server, .Xr ssh 1 will send a message through the encrypted channel to request a response from the server. The default is 0, indicating that these messages will not be sent to the server. .It Cm SessionType May be used to either request invocation of a subsystem on the remote system, or to prevent the execution of a remote command at all. The latter is useful for just forwarding ports. The argument to this keyword must be .Cm none (same as the .Fl N option), .Cm subsystem (same as the .Fl s option) or .Cm default (shell or command execution). .It Cm SetEnv Directly specify one or more environment variables and their contents to be sent to the server. Similarly to .Cm SendEnv , with the exception of the .Ev TERM variable, the server must be prepared to accept the environment variable. .It Cm StdinNull Redirects stdin from .Pa /dev/null (actually, prevents reading from stdin). Either this or the equivalent .Fl n option must be used when .Nm ssh is run in the background. The argument to this keyword must be .Cm yes (same as the .Fl n option) or .Cm no (the default). .It Cm StreamLocalBindMask Sets the octal file creation mode mask .Pq umask used when creating a Unix-domain socket file for local or remote port forwarding. This option is only used for port forwarding to a Unix-domain socket file. .Pp The default value is 0177, which creates a Unix-domain socket file that is readable and writable only by the owner. Note that not all operating systems honor the file mode on Unix-domain socket files. .It Cm StreamLocalBindUnlink Specifies whether to remove an existing Unix-domain socket file for local or remote port forwarding before creating a new one. If the socket file already exists and .Cm StreamLocalBindUnlink is not enabled, .Nm ssh will be unable to forward the port to the Unix-domain socket file. This option is only used for port forwarding to a Unix-domain socket file. .Pp The argument must be .Cm yes or .Cm no (the default). .It Cm StrictHostKeyChecking If this flag is set to .Cm yes , .Xr ssh 1 will never automatically add host keys to the .Pa ~/.ssh/known_hosts file, and refuses to connect to hosts whose host key has changed. This provides maximum protection against man-in-the-middle (MITM) attacks, though it can be annoying when the .Pa /etc/ssh/ssh_known_hosts file is poorly maintained or when connections to new hosts are frequently made. This option forces the user to manually add all new hosts. .Pp If this flag is set to .Cm accept-new then ssh will automatically add new host keys to the user's .Pa known_hosts file, but will not permit connections to hosts with changed host keys. If this flag is set to .Cm no or .Cm off , ssh will automatically add new host keys to the user known hosts files and allow connections to hosts with changed hostkeys to proceed, subject to some restrictions. If this flag is set to .Cm ask (the default), new host keys will be added to the user known host files only after the user has confirmed that is what they really want to do, and ssh will refuse to connect to hosts whose host key has changed. The host keys of known hosts will be verified automatically in all cases. .It Cm SyslogFacility Gives the facility code that is used when logging messages from .Xr ssh 1 . The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The default is USER. .It Cm TCPKeepAlive Specifies whether the system should send TCP keepalive messages to the other side. If they are sent, death of the connection or crash of one of the machines will be properly noticed. However, this means that connections will die if the route is down temporarily, and some people find it annoying. .Pp The default is .Cm yes (to send TCP keepalive messages), and the client will notice if the network goes down or the remote host dies. This is important in scripts, and many users want it too. .Pp To disable TCP keepalive messages, the value should be set to .Cm no . See also .Cm ServerAliveInterval for protocol-level keepalives. .It Cm Tag Specify a configuration tag name that may be later used by a .Cm Match directive to select a block of configuration. .It Cm Tunnel Request .Xr tun 4 device forwarding between the client and the server. The argument must be .Cm yes , .Cm point-to-point (layer 3), .Cm ethernet (layer 2), or .Cm no (the default). Specifying .Cm yes requests the default tunnel mode, which is .Cm point-to-point . .It Cm TunnelDevice Specifies the .Xr tun 4 devices to open on the client .Pq Ar local_tun and the server .Pq Ar remote_tun . .Pp The argument must be .Sm off .Ar local_tun Op : Ar remote_tun . .Sm on The devices may be specified by numerical ID or the keyword .Cm any , which uses the next available tunnel device. If .Ar remote_tun is not specified, it defaults to .Cm any . The default is .Cm any:any . .It Cm UpdateHostKeys Specifies whether .Xr ssh 1 should accept notifications of additional hostkeys from the server sent after authentication has completed and add them to .Cm UserKnownHostsFile . The argument must be .Cm yes , .Cm no or .Cm ask . 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, 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 .Cm ask , then the user is asked to confirm the modifications to the known_hosts file. Confirmation is currently incompatible with .Cm ControlPersist , and will be disabled if it is enabled. .Pp Presently, only .Xr sshd 8 from OpenSSH 6.8 and greater support the .Qq hostkeys@openssh.com protocol extension used to inform the client of all the server's hostkeys. .It Cm User Specifies the user to log in as. This can be useful when a different user name is used on different machines. This saves the trouble of having to remember to give the user name on the command line. .It Cm UserKnownHostsFile Specifies one or more files to use for the user host key database, separated by whitespace. 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. A value of .Cm none causes .Xr ssh 1 to ignore any user-specific known hosts files. The default is .Pa ~/.ssh/known_hosts , .Pa ~/.ssh/known_hosts2 . .It Cm VerifyHostKeyDNS Specifies whether to verify the remote key using DNS and SSHFP resource records. If this option is set to .Cm yes , the client will implicitly trust keys that match a secure fingerprint from DNS. Insecure fingerprints will be handled as if this option was set to .Cm ask . If this option is set to .Cm ask , information on fingerprint match will be displayed, but the user will still need to confirm new host keys according to the .Cm StrictHostKeyChecking option. The default is .Cm no . .Pp See also .Sx VERIFYING HOST KEYS in .Xr ssh 1 . .It Cm VisualHostKey If this flag is set to .Cm yes , an ASCII art representation of the remote host key fingerprint is printed in addition to the fingerprint string at login and for unknown host keys. If this flag is set to .Cm no (the default), no fingerprint strings are printed at login and only the fingerprint string will be printed for unknown host keys. .It Cm XAuthLocation Specifies the full pathname of the .Xr xauth 1 program. The default is .Pa /usr/local/bin/xauth . .El .Sh PATTERNS A .Em pattern consists of zero or more non-whitespace characters, .Sq * (a wildcard that matches zero or more characters), or .Sq ?\& (a wildcard that matches exactly one character). For example, to specify a set of declarations for any host in the .Qq .co.uk set of domains, the following pattern could be used: .Pp .Dl Host *.co.uk .Pp The following pattern would match any host in the 192.168.0.[0-9] network range: .Pp .Dl Host 192.168.0.? .Pp A .Em pattern-list is a comma-separated list of patterns. Patterns within pattern-lists may be negated by preceding them with an exclamation mark .Pq Sq !\& . For example, to allow a key to be used from anywhere within an organization except from the .Qq dialup pool, the following entry (in authorized_keys) could be used: .Pp .Dl from=\&"!*.dialup.example.com,*.example.com\&" .Pp Note that a negated match will never produce a positive result by itself. For example, attempting to match .Qq host3 against the following pattern-list will fail: .Pp .Dl from=\&"!host1,!host2\&" .Pp The solution here is to include a term that will yield a positive match, such as a wildcard: .Pp .Dl from=\&"!host1,!host2,*\&" .Sh TOKENS Arguments to some keywords can make use of tokens, which are expanded at runtime: .Pp .Bl -tag -width XXXX -offset indent -compact .It %% A literal .Sq % . .It \&%C -Hash of %l%h%p%r. +Hash of %l%h%p%r%j. .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 %j +The contents of the ProxyJump option, or the empty string if this +option is unset. .It %K The base64 encoded host key. .It %k The host key alias if specified, otherwise the original remote hostname given on the command line. .It %L The local hostname. .It %l The local hostname, including the domain name. .It %n The original remote hostname, as given on the command line. .It %p The remote port. .It %r The remote username. .It \&%T The local .Xr tun 4 or .Xr tap 4 network interface assigned if tunnel forwarding was requested, or .Qq NONE otherwise. .It %t The type of the server host key, e.g. .Cm ssh-ed25519 . .It %u The local username. .El .Pp .Cm CertificateFile , .Cm ControlPath , .Cm IdentityAgent , .Cm IdentityFile , .Cm KnownHostsCommand , .Cm LocalForward , .Cm Match exec , .Cm RemoteCommand , .Cm RemoteForward , .Cm RevokedHostKeys , and .Cm UserKnownHostsFile -accept the tokens %%, %C, %d, %h, %i, %k, %L, %l, %n, %p, %r, and %u. +accept the tokens %%, %C, %d, %h, %i, %j, %k, %L, %l, %n, %p, %r, and %u. .Pp .Cm KnownHostsCommand additionally accepts the tokens %f, %H, %I, %K and %t. .Pp .Cm Hostname accepts the tokens %% and %h. .Pp .Cm LocalCommand accepts all tokens. .Pp .Cm ProxyCommand and .Cm ProxyJump accept the tokens %%, %h, %n, %p, and %r. .Pp Note that some of these directives build commands for execution via the shell. Because .Xr ssh 1 performs no filtering or escaping of characters that have special meaning in -shell commands (e.g. quotes), it is the user's reposibility to ensure that +shell commands (e.g. quotes), it is the user's responsibility to ensure that the arguments passed to .Xr ssh 1 do not contain such characters and that tokens are appropriately quoted when used. .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 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 This is the per-user configuration file. The format of this file is described above. This file is used by the SSH client. Because of the potential for abuse, this file must have strict permissions: read/write for the user, and not writable by others. .It Pa /etc/ssh/ssh_config Systemwide configuration file. This file provides defaults for those values that are not specified in the user's configuration file, and for those users who do not have a configuration file. This file must be world-readable. .El .Sh SEE ALSO .Xr ssh 1 .Sh AUTHORS .An -nosplit OpenSSH is a derivative of the original and free ssh 1.2.12 release by .An Tatu Ylonen . .An Aaron Campbell , Bob Beck , Markus Friedl , .An Niels Provos , Theo de Raadt and .An Dug Song removed many bugs, re-added newer features and created OpenSSH. .An Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. diff --git a/crypto/openssh/ssh_namespace.h b/crypto/openssh/ssh_namespace.h index 083f73ca200f..5d1fa0d5ca19 100644 --- a/crypto/openssh/ssh_namespace.h +++ b/crypto/openssh/ssh_namespace.h @@ -1,1019 +1,1022 @@ /* * This file was machine-@generated. Do not edit manually. * Run crypto/openssh/freebsd-namespace.sh to regenerate. */ #define Blowfish_decipher Fssh_Blowfish_decipher #define Blowfish_encipher Fssh_Blowfish_encipher #define Blowfish_expand0state Fssh_Blowfish_expand0state #define Blowfish_expandstate Fssh_Blowfish_expandstate #define Blowfish_initstate Fssh_Blowfish_initstate #define Blowfish_stream2word Fssh_Blowfish_stream2word #define Decode Fssh_Decode #define EVP_CIPHER_CTX_get_iv Fssh_EVP_CIPHER_CTX_get_iv #define EVP_CIPHER_CTX_set_iv Fssh_EVP_CIPHER_CTX_set_iv #define Encode Fssh_Encode #define Hide Fssh_Hide #define Rq_mult_small Fssh_Rq_mult_small #define Short_random Fssh_Short_random #define _ssh__compat_glob Fssh__ssh__compat_glob #define _ssh__compat_globfree Fssh__ssh__compat_globfree #define _ssh_exchange_banner Fssh__ssh_exchange_banner #define _ssh_host_key_sign Fssh__ssh_host_key_sign #define _ssh_host_private_key Fssh__ssh_host_private_key #define _ssh_host_public_key Fssh__ssh_host_public_key #define _ssh_mkstemp Fssh__ssh_mkstemp #define _ssh_order_hostkeyalgs Fssh__ssh_order_hostkeyalgs #define _ssh_read_banner Fssh__ssh_read_banner #define _ssh_send_banner Fssh__ssh_send_banner #define _ssh_verify_host_key Fssh__ssh_verify_host_key #define a2port Fssh_a2port #define a2tun Fssh_a2tun #define add_host_to_hostfile Fssh_add_host_to_hostfile #define add_p1p1 Fssh_add_p1p1 #define addargs Fssh_addargs #define addr_and Fssh_addr_and #define addr_cmp Fssh_addr_cmp #define addr_host_is_all0s Fssh_addr_host_is_all0s #define addr_host_to_all1s Fssh_addr_host_to_all1s #define addr_hostmask Fssh_addr_hostmask #define addr_increment Fssh_addr_increment #define addr_invert Fssh_addr_invert #define addr_is_all0s Fssh_addr_is_all0s #define addr_match_cidr_list Fssh_addr_match_cidr_list #define addr_match_list Fssh_addr_match_list #define addr_netmask Fssh_addr_netmask #define addr_netmatch Fssh_addr_netmatch #define addr_ntop Fssh_addr_ntop #define addr_or Fssh_addr_or #define addr_pton Fssh_addr_pton #define addr_pton_cidr Fssh_addr_pton_cidr #define addr_sa_pton Fssh_addr_sa_pton #define addr_sa_to_xaddr Fssh_addr_sa_to_xaddr #define addr_unicast_masklen Fssh_addr_unicast_masklen #define addr_xaddr_to_sa Fssh_addr_xaddr_to_sa #define argv_assemble Fssh_argv_assemble #define argv_consume Fssh_argv_consume #define argv_free Fssh_argv_free #define argv_next Fssh_argv_next #define argv_split Fssh_argv_split #define ask_permission Fssh_ask_permission #define asmprintf Fssh_asmprintf #define atoi_err Fssh_atoi_err #define atomicio Fssh_atomicio #define atomicio6 Fssh_atomicio6 #define atomiciov Fssh_atomiciov #define atomiciov6 Fssh_atomiciov6 #define bandwidth_limit Fssh_bandwidth_limit #define bandwidth_limit_init Fssh_bandwidth_limit_init #define barrett_reduce Fssh_barrett_reduce #define baud_to_speed Fssh_baud_to_speed #define bcrypt_hash Fssh_bcrypt_hash #define bcrypt_pbkdf Fssh_bcrypt_pbkdf #define bitmap_clear_bit Fssh_bitmap_clear_bit #define bitmap_free Fssh_bitmap_free #define bitmap_from_string Fssh_bitmap_from_string #define bitmap_nbits Fssh_bitmap_nbits #define bitmap_nbytes Fssh_bitmap_nbytes #define bitmap_new Fssh_bitmap_new #define bitmap_set_bit Fssh_bitmap_set_bit #define bitmap_test_bit Fssh_bitmap_test_bit #define bitmap_to_string Fssh_bitmap_to_string #define bitmap_zero Fssh_bitmap_zero #define blf_cbc_decrypt Fssh_blf_cbc_decrypt #define blf_cbc_encrypt Fssh_blf_cbc_encrypt #define blf_dec Fssh_blf_dec #define blf_ecb_decrypt Fssh_blf_ecb_decrypt #define blf_ecb_encrypt Fssh_blf_ecb_encrypt #define blf_enc Fssh_blf_enc #define blf_key Fssh_blf_key #define blob_section Fssh_blob_section #define cert_free Fssh_cert_free #define cert_parse Fssh_cert_parse #define chacha_encrypt_bytes Fssh_chacha_encrypt_bytes #define chacha_ivsetup Fssh_chacha_ivsetup #define chacha_keysetup Fssh_chacha_keysetup #define chachapoly_crypt Fssh_chachapoly_crypt #define chachapoly_free Fssh_chachapoly_free #define chachapoly_get_length Fssh_chachapoly_get_length #define chachapoly_new Fssh_chachapoly_new #define chan_ibuf_empty Fssh_chan_ibuf_empty #define chan_is_dead Fssh_chan_is_dead #define chan_mark_dead Fssh_chan_mark_dead #define chan_obuf_empty Fssh_chan_obuf_empty #define chan_rcvd_eow Fssh_chan_rcvd_eow #define chan_rcvd_ieof Fssh_chan_rcvd_ieof #define chan_rcvd_oclose Fssh_chan_rcvd_oclose #define chan_read_failed Fssh_chan_read_failed #define chan_send_close2 Fssh_chan_send_close2 #define chan_send_eof2 Fssh_chan_send_eof2 #define chan_shutdown_extended_read Fssh_chan_shutdown_extended_read #define chan_shutdown_read Fssh_chan_shutdown_read #define chan_shutdown_write Fssh_chan_shutdown_write #define chan_write_failed Fssh_chan_write_failed #define channel_add_permission Fssh_channel_add_permission #define channel_add_timeout Fssh_channel_add_timeout #define channel_after_poll Fssh_channel_after_poll #define channel_by_id Fssh_channel_by_id #define channel_by_remote_id Fssh_channel_by_remote_id #define channel_cancel_cleanup Fssh_channel_cancel_cleanup #define channel_cancel_lport_listener Fssh_channel_cancel_lport_listener #define channel_cancel_rport_listener Fssh_channel_cancel_rport_listener #define channel_clear_permission Fssh_channel_clear_permission #define channel_clear_timeouts Fssh_channel_clear_timeouts #define channel_close_all Fssh_channel_close_all #define channel_close_fd Fssh_channel_close_fd #define channel_connect_by_listen_address Fssh_channel_connect_by_listen_address #define channel_connect_by_listen_path Fssh_channel_connect_by_listen_path #define channel_connect_stdio_fwd Fssh_channel_connect_stdio_fwd #define channel_connect_to_path Fssh_channel_connect_to_path #define channel_connect_to_port Fssh_channel_connect_to_port #define channel_decode_socks4 Fssh_channel_decode_socks4 #define channel_decode_socks5 Fssh_channel_decode_socks5 #define channel_disable_admin Fssh_channel_disable_admin #define channel_find_open Fssh_channel_find_open #define channel_force_close Fssh_channel_force_close #define channel_format_extended_usage Fssh_channel_format_extended_usage #define channel_free Fssh_channel_free #define channel_free_all Fssh_channel_free_all #define channel_fwd_bind_addr Fssh_channel_fwd_bind_addr #define channel_handler Fssh_channel_handler #define channel_init_channels Fssh_channel_init_channels #define channel_input_data Fssh_channel_input_data #define channel_input_extended_data Fssh_channel_input_extended_data #define channel_input_ieof Fssh_channel_input_ieof #define channel_input_oclose Fssh_channel_input_oclose #define channel_input_open_confirmation Fssh_channel_input_open_confirmation #define channel_input_open_failure Fssh_channel_input_open_failure #define channel_input_status_confirm Fssh_channel_input_status_confirm #define channel_input_window_adjust Fssh_channel_input_window_adjust #define channel_lookup Fssh_channel_lookup #define channel_new Fssh_channel_new #define channel_not_very_much_buffered_data Fssh_channel_not_very_much_buffered_data #define channel_open_message Fssh_channel_open_message #define channel_output_poll Fssh_channel_output_poll #define channel_parse_id Fssh_channel_parse_id #define channel_permit_all Fssh_channel_permit_all #define channel_post_auth_listener Fssh_channel_post_auth_listener #define channel_post_connecting Fssh_channel_post_connecting #define channel_post_mux_client Fssh_channel_post_mux_client #define channel_post_mux_listener Fssh_channel_post_mux_listener #define channel_post_open Fssh_channel_post_open #define channel_post_port_listener Fssh_channel_post_port_listener #define channel_post_x11_listener Fssh_channel_post_x11_listener #define channel_pre_connecting Fssh_channel_pre_connecting #define channel_pre_dynamic Fssh_channel_pre_dynamic #define channel_pre_listener Fssh_channel_pre_listener #define channel_pre_mux_client Fssh_channel_pre_mux_client #define channel_pre_open Fssh_channel_pre_open #define channel_pre_x11_open Fssh_channel_pre_x11_open #define channel_prepare_poll Fssh_channel_prepare_poll #define channel_proxy_downstream Fssh_channel_proxy_downstream #define channel_proxy_upstream Fssh_channel_proxy_upstream #define channel_register_cleanup Fssh_channel_register_cleanup #define channel_register_fds Fssh_channel_register_fds #define channel_register_filter Fssh_channel_register_filter #define channel_register_open_confirm Fssh_channel_register_open_confirm #define channel_register_status_confirm Fssh_channel_register_status_confirm #define channel_request_remote_forwarding Fssh_channel_request_remote_forwarding #define channel_request_rforward_cancel Fssh_channel_request_rforward_cancel #define channel_request_start Fssh_channel_request_start #define channel_send_open Fssh_channel_send_open #define channel_send_window_changes Fssh_channel_send_window_changes #define channel_set_af Fssh_channel_set_af #define channel_set_fds Fssh_channel_set_fds #define channel_set_x11_refuse_time Fssh_channel_set_x11_refuse_time #define channel_set_xtype Fssh_channel_set_xtype #define channel_setup_fwd_listener_streamlocal Fssh_channel_setup_fwd_listener_streamlocal #define channel_setup_fwd_listener_tcpip Fssh_channel_setup_fwd_listener_tcpip #define channel_setup_local_fwd_listener Fssh_channel_setup_local_fwd_listener #define channel_setup_remote_fwd_listener Fssh_channel_setup_remote_fwd_listener #define channel_still_open Fssh_channel_still_open #define channel_stop_listening Fssh_channel_stop_listening +#define channel_tty_open Fssh_channel_tty_open #define channel_update_permission Fssh_channel_update_permission #define check_hostkeys_by_key_or_type Fssh_check_hostkeys_by_key_or_type #define check_key_in_hostkeys Fssh_check_key_in_hostkeys #define child_set_env Fssh_child_set_env #define choose_dh Fssh_choose_dh #define choose_t Fssh_choose_t #define chop Fssh_chop #define cipher_alg_list Fssh_cipher_alg_list #define cipher_authlen Fssh_cipher_authlen #define cipher_blocksize Fssh_cipher_blocksize #define cipher_by_name Fssh_cipher_by_name #define cipher_crypt Fssh_cipher_crypt #define cipher_ctx_is_plaintext Fssh_cipher_ctx_is_plaintext #define cipher_free Fssh_cipher_free #define cipher_get_keyiv Fssh_cipher_get_keyiv -#define cipher_get_keyiv_len Fssh_cipher_get_keyiv_len #define cipher_get_length Fssh_cipher_get_length #define cipher_init Fssh_cipher_init #define cipher_is_cbc Fssh_cipher_is_cbc #define cipher_ivlen Fssh_cipher_ivlen #define cipher_keylen Fssh_cipher_keylen #define cipher_seclen Fssh_cipher_seclen #define cipher_set_keyiv Fssh_cipher_set_keyiv #define cipher_warning_message Fssh_cipher_warning_message #define ciphers_valid Fssh_ciphers_valid #define cleanhostname Fssh_cleanhostname #define cleanup_exit Fssh_cleanup_exit #define client_converse Fssh_client_converse #define colon Fssh_colon #define compare Fssh_compare #define compare_gps Fssh_compare_gps #define compat_banner Fssh_compat_banner #define compat_kex_proposal Fssh_compat_kex_proposal #define compression_alg_list Fssh_compression_alg_list #define connect_next Fssh_connect_next #define connect_to Fssh_connect_to #define connect_to_helper Fssh_connect_to_helper #define convtime Fssh_convtime #define crypto_hash_sha512 Fssh_crypto_hash_sha512 #define crypto_kem_sntrup761_dec Fssh_crypto_kem_sntrup761_dec #define crypto_kem_sntrup761_enc Fssh_crypto_kem_sntrup761_enc #define crypto_kem_sntrup761_keypair Fssh_crypto_kem_sntrup761_keypair #define crypto_scalarmult_curve25519 Fssh_crypto_scalarmult_curve25519 #define crypto_sign_ed25519 Fssh_crypto_sign_ed25519 #define crypto_sign_ed25519_keypair Fssh_crypto_sign_ed25519_keypair #define crypto_sign_ed25519_open Fssh_crypto_sign_ed25519_open #define crypto_sign_ed25519_ref_fe25519_getparity Fssh_crypto_sign_ed25519_ref_fe25519_getparity #define crypto_sign_ed25519_ref_fe25519_iseq_vartime Fssh_crypto_sign_ed25519_ref_fe25519_iseq_vartime #define crypto_sign_ed25519_ref_fe25519_mul Fssh_crypto_sign_ed25519_ref_fe25519_mul #define crypto_sign_ed25519_ref_isneutral_vartime Fssh_crypto_sign_ed25519_ref_isneutral_vartime #define crypto_sign_ed25519_ref_pack Fssh_crypto_sign_ed25519_ref_pack #define crypto_sign_ed25519_ref_scalarmult_base Fssh_crypto_sign_ed25519_ref_scalarmult_base #define crypto_sign_ed25519_ref_unpackneg_vartime Fssh_crypto_sign_ed25519_ref_unpackneg_vartime #define daemonized Fssh_daemonized #define dangerous_locale Fssh_dangerous_locale #define dbl_p1p1 Fssh_dbl_p1p1 #define default_key_sign Fssh_default_key_sign #define deserialise_identity2 Fssh_deserialise_identity2 #define dh_estimate Fssh_dh_estimate #define dh_gen_key Fssh_dh_gen_key #define dh_new_group Fssh_dh_new_group #define dh_new_group1 Fssh_dh_new_group1 #define dh_new_group14 Fssh_dh_new_group14 #define dh_new_group16 Fssh_dh_new_group16 #define dh_new_group18 Fssh_dh_new_group18 #define dh_new_group_asc Fssh_dh_new_group_asc #define dh_new_group_fallback Fssh_dh_new_group_fallback #define dh_pub_is_valid Fssh_dh_pub_is_valid #define dh_set_moduli_file Fssh_dh_set_moduli_file #define dispatch_protocol_error Fssh_dispatch_protocol_error #define dispatch_protocol_ignore Fssh_dispatch_protocol_ignore #define do_log Fssh_do_log #define dollar_expand Fssh_dollar_expand #define ecdsa_do_sign Fssh_ecdsa_do_sign #define encode_constraints Fssh_encode_constraints #define encode_dest_constraint_hop Fssh_encode_dest_constraint_hop #define exited_cleanly Fssh_exited_cleanly #define export_dns_rr Fssh_export_dns_rr #define extension_section Fssh_extension_section #define fd_ready Fssh_fd_ready #define fe25519_reduce_add_sub Fssh_fe25519_reduce_add_sub #define filter_list Fssh_filter_list #define fingerprint_b64 Fssh_fingerprint_b64 #define fingerprint_hex Fssh_fingerprint_hex #define fmprintf Fssh_fmprintf #define fmt_scaled Fssh_fmt_scaled #define fmt_timeframe Fssh_fmt_timeframe #define format_absolute_time Fssh_format_absolute_time #define format_timestamp Fssh_format_timestamp #define forward_equals Fssh_forward_equals #define free_hostkeys Fssh_free_hostkeys #define freeargs Fssh_freeargs #define freerrset Fssh_freerrset #define freezero Fssh_freezero #define fwd_ident Fssh_fwd_ident #define g_opendir Fssh_g_opendir #define g_stat Fssh_g_stat #define gen_candidates Fssh_gen_candidates #define get_local_ipaddr Fssh_get_local_ipaddr #define get_local_name Fssh_get_local_name #define get_local_port Fssh_get_local_port #define get_peer_ipaddr Fssh_get_peer_ipaddr #define get_peer_port Fssh_get_peer_port #define get_rdomain Fssh_get_rdomain #define get_sock_af Fssh_get_sock_af #define get_sock_port Fssh_get_sock_port #define get_socket_address Fssh_get_socket_address #define get_u16 Fssh_get_u16 #define get_u32 Fssh_get_u32 #define get_u32_le Fssh_get_u32_le #define get_u64 Fssh_get_u64 #define getrrsetbyname Fssh_getrrsetbyname #define glob0 Fssh_glob0 #define glob2 Fssh_glob2 #define globexp1 Fssh_globexp1 #define globextend Fssh_globextend #define host_delete Fssh_host_delete #define host_hash Fssh_host_hash #define hostfile_create_user_ssh_dir Fssh_hostfile_create_user_ssh_dir #define hostfile_read_key Fssh_hostfile_read_key #define hostfile_replace_entries Fssh_hostfile_replace_entries #define hostkeys_foreach Fssh_hostkeys_foreach #define hostkeys_foreach_file Fssh_hostkeys_foreach_file #define hpdelim Fssh_hpdelim #define hpdelim2 Fssh_hpdelim2 #define init_hostkeys Fssh_init_hostkeys #define input_kex_dh_gex_group Fssh_input_kex_dh_gex_group #define input_kex_dh_gex_init Fssh_input_kex_dh_gex_init #define input_kex_dh_gex_reply Fssh_input_kex_dh_gex_reply #define input_kex_dh_gex_request Fssh_input_kex_dh_gex_request #define input_kex_gen_init Fssh_input_kex_gen_init #define input_kex_gen_reply Fssh_input_kex_gen_reply #define iptos2str Fssh_iptos2str #define ipv64_normalise_mapped Fssh_ipv64_normalise_mapped #define is_cert_revoked Fssh_is_cert_revoked #define is_key_revoked Fssh_is_key_revoked #define kex_alg_by_name Fssh_kex_alg_by_name #define kex_alg_list Fssh_kex_alg_list #define kex_assemble_names Fssh_kex_assemble_names #define kex_buf2prop Fssh_kex_buf2prop #define kex_c25519_dec Fssh_kex_c25519_dec #define kex_c25519_enc Fssh_kex_c25519_enc #define kex_c25519_keypair Fssh_kex_c25519_keypair #define kex_choose_conf Fssh_kex_choose_conf #define kex_derive_keys Fssh_kex_derive_keys #define kex_dh_compute_key Fssh_kex_dh_compute_key #define kex_dh_dec Fssh_kex_dh_dec #define kex_dh_enc Fssh_kex_dh_enc #define kex_dh_keygen Fssh_kex_dh_keygen #define kex_dh_keypair Fssh_kex_dh_keypair #define kex_ecdh_dec Fssh_kex_ecdh_dec #define kex_ecdh_dec_key_group Fssh_kex_ecdh_dec_key_group #define kex_ecdh_enc Fssh_kex_ecdh_enc #define kex_ecdh_keypair Fssh_kex_ecdh_keypair #define kex_exchange_identification Fssh_kex_exchange_identification #define kex_ext_info_check_ver Fssh_kex_ext_info_check_ver #define kex_free Fssh_kex_free #define kex_free_newkeys Fssh_kex_free_newkeys #define kex_gen_client Fssh_kex_gen_client #define kex_gen_hash Fssh_kex_gen_hash #define kex_gen_server Fssh_kex_gen_server #define kex_input_ext_info Fssh_kex_input_ext_info #define kex_input_kexinit Fssh_kex_input_kexinit #define kex_input_newkeys Fssh_kex_input_newkeys #define kex_kem_sntrup761x25519_dec Fssh_kex_kem_sntrup761x25519_dec #define kex_kem_sntrup761x25519_enc Fssh_kex_kem_sntrup761x25519_enc #define kex_kem_sntrup761x25519_keypair Fssh_kex_kem_sntrup761x25519_keypair #define kex_load_hostkey Fssh_kex_load_hostkey #define kex_names_cat Fssh_kex_names_cat #define kex_names_valid Fssh_kex_names_valid #define kex_new Fssh_kex_new #define kex_prop2buf Fssh_kex_prop2buf #define kex_prop_free Fssh_kex_prop_free #define kex_proposal_free_entries Fssh_kex_proposal_free_entries #define kex_proposal_populate_entries Fssh_kex_proposal_populate_entries #define kex_protocol_error Fssh_kex_protocol_error #define kex_ready Fssh_kex_ready #define kex_send_kexinit Fssh_kex_send_kexinit #define kex_send_newkeys Fssh_kex_send_newkeys +#define kex_server_update_ext_info Fssh_kex_server_update_ext_info +#define kex_set_server_sig_algs Fssh_kex_set_server_sig_algs #define kex_setup Fssh_kex_setup #define kex_start_rekex Fssh_kex_start_rekex #define kex_verify_host_key Fssh_kex_verify_host_key #define kexc25519_keygen Fssh_kexc25519_keygen #define kexc25519_shared_key Fssh_kexc25519_shared_key #define kexc25519_shared_key_ext Fssh_kexc25519_shared_key_ext #define kexgex_client Fssh_kexgex_client #define kexgex_hash Fssh_kexgex_hash #define kexgex_server Fssh_kexgex_server #define krl_dump Fssh_krl_dump #define lib_contains_symbol Fssh_lib_contains_symbol #define load_hostkeys Fssh_load_hostkeys #define load_hostkeys_file Fssh_load_hostkeys_file #define log_change_level Fssh_log_change_level #define log_facility_name Fssh_log_facility_name #define log_facility_number Fssh_log_facility_number #define log_init Fssh_log_init #define log_is_on_stderr Fssh_log_is_on_stderr #define log_level_get Fssh_log_level_get #define log_level_name Fssh_log_level_name #define log_level_number Fssh_log_level_number #define log_redirect_stderr_to Fssh_log_redirect_stderr_to #define log_verbose_add Fssh_log_verbose_add #define log_verbose_reset Fssh_log_verbose_reset #define lookup_env_in_list Fssh_lookup_env_in_list #define lookup_key_in_hostkeys_by_type Fssh_lookup_key_in_hostkeys_by_type #define lookup_marker_in_hostkeys Fssh_lookup_marker_in_hostkeys #define lookup_setenv_in_list Fssh_lookup_setenv_in_list #define lowercase Fssh_lowercase #define mac_alg_list Fssh_mac_alg_list #define mac_check Fssh_mac_check #define mac_clear Fssh_mac_clear #define mac_compute Fssh_mac_compute #define mac_init Fssh_mac_init #define mac_setup Fssh_mac_setup #define mac_valid Fssh_mac_valid #define match_filter_allowlist Fssh_match_filter_allowlist #define match_filter_denylist Fssh_match_filter_denylist #define match_host_and_ip Fssh_match_host_and_ip #define match_hostname Fssh_match_hostname #define match_list Fssh_match_list #define match_maybe_hashed Fssh_match_maybe_hashed #define match_pattern Fssh_match_pattern #define match_pattern_list Fssh_match_pattern_list #define match_user Fssh_match_user #define match_usergroup_pattern_list Fssh_match_usergroup_pattern_list #define mktemp_proto Fssh_mktemp_proto #define mm_choose_dh Fssh_mm_choose_dh #define mm_receive_fd Fssh_mm_receive_fd #define mm_send_fd Fssh_mm_send_fd #define mm_sshkey_sign Fssh_mm_sshkey_sign #define monotime Fssh_monotime #define monotime_double Fssh_monotime_double #define monotime_ts Fssh_monotime_ts #define monotime_tv Fssh_monotime_tv #define mprintf Fssh_mprintf #define ms_subtract_diff Fssh_ms_subtract_diff #define ms_to_timespec Fssh_ms_to_timespec #define msetlocale Fssh_msetlocale #define newkeys_from_blob Fssh_newkeys_from_blob #define newkeys_to_blob Fssh_newkeys_to_blob #define nh_aux Fssh_nh_aux #define nh_final Fssh_nh_final #define note_key Fssh_note_key #define notify_complete Fssh_notify_complete #define notify_start Fssh_notify_start #define open_preamble Fssh_open_preamble #define openssh_RSA_verify Fssh_openssh_RSA_verify #define opt_array_append Fssh_opt_array_append #define opt_array_append2 Fssh_opt_array_append2 #define opt_dequote Fssh_opt_dequote #define opt_flag Fssh_opt_flag #define opt_match Fssh_opt_match #define ossl_error Fssh_ossl_error #define parse_absolute_time Fssh_parse_absolute_time #define parse_ipqos Fssh_parse_ipqos +#define parse_pattern_interval Fssh_parse_pattern_interval #define parse_prime Fssh_parse_prime #define parse_revoked_certs Fssh_parse_revoked_certs #define parse_uri Fssh_parse_uri #define parse_user_host_path Fssh_parse_user_host_path #define parse_user_host_port Fssh_parse_user_host_port #define path_absolute Fssh_path_absolute #define pem_passphrase_cb Fssh_pem_passphrase_cb #define percent_dollar_expand Fssh_percent_dollar_expand #define percent_expand Fssh_percent_expand #define permission_set_add Fssh_permission_set_add #define permitopen_port Fssh_permitopen_port #define pkcs11_add_provider Fssh_pkcs11_add_provider #define pkcs11_del_provider Fssh_pkcs11_del_provider #define pkcs11_ecdsa_wrap Fssh_pkcs11_ecdsa_wrap #define pkcs11_fetch_certs Fssh_pkcs11_fetch_certs #define pkcs11_fetch_keys Fssh_pkcs11_fetch_keys #define pkcs11_find Fssh_pkcs11_find #define pkcs11_get_key Fssh_pkcs11_get_key #define pkcs11_init Fssh_pkcs11_init #define pkcs11_k11_free Fssh_pkcs11_k11_free #define pkcs11_login_slot Fssh_pkcs11_login_slot #define pkcs11_provider_finalize Fssh_pkcs11_provider_finalize #define pkcs11_provider_unref Fssh_pkcs11_provider_unref #define pkcs11_rsa_private_decrypt Fssh_pkcs11_rsa_private_decrypt #define pkcs11_rsa_private_encrypt Fssh_pkcs11_rsa_private_encrypt #define pkcs11_rsa_wrap Fssh_pkcs11_rsa_wrap #define pkcs11_terminate Fssh_pkcs11_terminate #define plain_key_blob Fssh_plain_key_blob #define platform_disable_tracing Fssh_platform_disable_tracing #define platform_pledge_agent Fssh_platform_pledge_agent #define platform_pledge_mux Fssh_platform_pledge_mux #define platform_pledge_sftp_server Fssh_platform_pledge_sftp_server #define platform_sys_dir_uid Fssh_platform_sys_dir_uid #define pledge Fssh_pledge #define poly1305_auth Fssh_poly1305_auth #define poly_hash Fssh_poly_hash #define port_open_helper Fssh_port_open_helper #define prime_test Fssh_prime_test #define private2_check_padding Fssh_private2_check_padding #define private2_uudecode Fssh_private2_uudecode #define proposals_match Fssh_proposals_match #define ptimeout_deadline_monotime Fssh_ptimeout_deadline_monotime #define ptimeout_deadline_monotime_tsp Fssh_ptimeout_deadline_monotime_tsp #define ptimeout_deadline_ms Fssh_ptimeout_deadline_ms #define ptimeout_deadline_sec Fssh_ptimeout_deadline_sec #define ptimeout_get_ms Fssh_ptimeout_get_ms #define ptimeout_get_tsp Fssh_ptimeout_get_tsp #define ptimeout_init Fssh_ptimeout_init #define ptimeout_isset Fssh_ptimeout_isset #define put_bitmap Fssh_put_bitmap #define put_host_port Fssh_put_host_port #define put_u16 Fssh_put_u16 #define put_u32 Fssh_put_u32 #define put_u32_le Fssh_put_u32_le #define put_u64 Fssh_put_u64 #define pwcopy Fssh_pwcopy #define qfileout Fssh_qfileout #define read_mux Fssh_read_mux #define read_passphrase Fssh_read_passphrase #define recallocarray Fssh_recallocarray #define record_hostkey Fssh_record_hostkey #define refresh_progress_meter Fssh_refresh_progress_meter #define replacearg Fssh_replacearg #define revoke_blob Fssh_revoke_blob #define revoked_blob_tree_RB_FIND Fssh_revoked_blob_tree_RB_FIND #define revoked_blob_tree_RB_NEXT Fssh_revoked_blob_tree_RB_NEXT #define revoked_blob_tree_RB_REMOVE Fssh_revoked_blob_tree_RB_REMOVE #define revoked_certs_for_ca_key Fssh_revoked_certs_for_ca_key #define revoked_certs_generate Fssh_revoked_certs_generate #define revoked_serial_tree_RB_REMOVE Fssh_revoked_serial_tree_RB_REMOVE #define rijndaelEncrypt Fssh_rijndaelEncrypt #define rijndaelKeySetupEnc Fssh_rijndaelKeySetupEnc #define rsa_hash_id_from_keyname Fssh_rsa_hash_id_from_keyname #define rtrim Fssh_rtrim #define safe_path Fssh_safe_path #define safe_path_fd Fssh_safe_path_fd #define sanitise_stdfd Fssh_sanitise_stdfd #define scan_scaled Fssh_scan_scaled #define seed_rng Fssh_seed_rng #define send_error Fssh_send_error #define set_log_handler Fssh_set_log_handler #define set_nodelay Fssh_set_nodelay #define set_nonblock Fssh_set_nonblock #define set_rdomain Fssh_set_rdomain #define set_reuseaddr Fssh_set_reuseaddr #define set_sock_tos Fssh_set_sock_tos #define sftp_realpath Fssh_sftp_realpath #define shadow_pw Fssh_shadow_pw #define sieve_large Fssh_sieve_large #define sig_alarm Fssh_sig_alarm #define sig_winch Fssh_sig_winch #define skip_space Fssh_skip_space #define snmprintf Fssh_snmprintf #define sock_set_v6only Fssh_sock_set_v6only #define speed_to_baud Fssh_speed_to_baud #define square Fssh_square #define ssh_add_hostkey Fssh_ssh_add_hostkey #define ssh_add_identity_constrained Fssh_ssh_add_identity_constrained #define ssh_agent_bind_hostkey Fssh_ssh_agent_bind_hostkey #define ssh_agent_has_key Fssh_ssh_agent_has_key #define ssh_agent_sign Fssh_ssh_agent_sign #define ssh_alloc_session_state Fssh_ssh_alloc_session_state #define ssh_clear_newkeys Fssh_ssh_clear_newkeys #define ssh_close_authentication_socket Fssh_ssh_close_authentication_socket #define ssh_compatible_openssl Fssh_ssh_compatible_openssl #define ssh_digest_alg_by_name Fssh_ssh_digest_alg_by_name #define ssh_digest_alg_name Fssh_ssh_digest_alg_name #define ssh_digest_blocksize Fssh_ssh_digest_blocksize #define ssh_digest_buffer Fssh_ssh_digest_buffer #define ssh_digest_bytes Fssh_ssh_digest_bytes #define ssh_digest_copy_state Fssh_ssh_digest_copy_state #define ssh_digest_final Fssh_ssh_digest_final #define ssh_digest_free Fssh_ssh_digest_free #define ssh_digest_memory Fssh_ssh_digest_memory #define ssh_digest_start Fssh_ssh_digest_start #define ssh_digest_update Fssh_ssh_digest_update #define ssh_digest_update_buffer Fssh_ssh_digest_update_buffer #define ssh_dispatch_init Fssh_ssh_dispatch_init #define ssh_dispatch_range Fssh_ssh_dispatch_range #define ssh_dispatch_run Fssh_ssh_dispatch_run #define ssh_dispatch_run_fatal Fssh_ssh_dispatch_run_fatal #define ssh_dispatch_set Fssh_ssh_dispatch_set #define ssh_dss_alloc Fssh_ssh_dss_alloc #define ssh_dss_cleanup Fssh_ssh_dss_cleanup #define ssh_dss_copy_public Fssh_ssh_dss_copy_public #define ssh_dss_deserialize_private Fssh_ssh_dss_deserialize_private #define ssh_dss_deserialize_public Fssh_ssh_dss_deserialize_public #define ssh_dss_equal Fssh_ssh_dss_equal #define ssh_dss_generate Fssh_ssh_dss_generate #define ssh_dss_serialize_private Fssh_ssh_dss_serialize_private #define ssh_dss_serialize_public Fssh_ssh_dss_serialize_public #define ssh_dss_sign Fssh_ssh_dss_sign #define ssh_dss_size Fssh_ssh_dss_size #define ssh_dss_verify Fssh_ssh_dss_verify #define ssh_ecdsa_cleanup Fssh_ssh_ecdsa_cleanup #define ssh_ecdsa_copy_public Fssh_ssh_ecdsa_copy_public #define ssh_ecdsa_deserialize_private Fssh_ssh_ecdsa_deserialize_private #define ssh_ecdsa_deserialize_public Fssh_ssh_ecdsa_deserialize_public #define ssh_ecdsa_equal Fssh_ssh_ecdsa_equal #define ssh_ecdsa_generate Fssh_ssh_ecdsa_generate #define ssh_ecdsa_serialize_private Fssh_ssh_ecdsa_serialize_private #define ssh_ecdsa_serialize_public Fssh_ssh_ecdsa_serialize_public #define ssh_ecdsa_sign Fssh_ssh_ecdsa_sign #define ssh_ecdsa_size Fssh_ssh_ecdsa_size #define ssh_ecdsa_sk_cleanup Fssh_ssh_ecdsa_sk_cleanup #define ssh_ecdsa_sk_copy_public Fssh_ssh_ecdsa_sk_copy_public #define ssh_ecdsa_sk_deserialize_private Fssh_ssh_ecdsa_sk_deserialize_private #define ssh_ecdsa_sk_deserialize_public Fssh_ssh_ecdsa_sk_deserialize_public #define ssh_ecdsa_sk_equal Fssh_ssh_ecdsa_sk_equal #define ssh_ecdsa_sk_serialize_private Fssh_ssh_ecdsa_sk_serialize_private #define ssh_ecdsa_sk_serialize_public Fssh_ssh_ecdsa_sk_serialize_public #define ssh_ecdsa_sk_verify Fssh_ssh_ecdsa_sk_verify #define ssh_ecdsa_verify Fssh_ssh_ecdsa_verify #define ssh_ed25519_cleanup Fssh_ssh_ed25519_cleanup #define ssh_ed25519_copy_public Fssh_ssh_ed25519_copy_public #define ssh_ed25519_deserialize_private Fssh_ssh_ed25519_deserialize_private #define ssh_ed25519_deserialize_public Fssh_ssh_ed25519_deserialize_public #define ssh_ed25519_equal Fssh_ssh_ed25519_equal #define ssh_ed25519_generate Fssh_ssh_ed25519_generate #define ssh_ed25519_serialize_private Fssh_ssh_ed25519_serialize_private #define ssh_ed25519_serialize_public Fssh_ssh_ed25519_serialize_public #define ssh_ed25519_sign Fssh_ssh_ed25519_sign #define ssh_ed25519_sk_cleanup Fssh_ssh_ed25519_sk_cleanup #define ssh_ed25519_sk_copy_public Fssh_ssh_ed25519_sk_copy_public #define ssh_ed25519_sk_deserialize_private Fssh_ssh_ed25519_sk_deserialize_private #define ssh_ed25519_sk_deserialize_public Fssh_ssh_ed25519_sk_deserialize_public #define ssh_ed25519_sk_equal Fssh_ssh_ed25519_sk_equal #define ssh_ed25519_sk_serialize_private Fssh_ssh_ed25519_sk_serialize_private #define ssh_ed25519_sk_serialize_public Fssh_ssh_ed25519_sk_serialize_public #define ssh_ed25519_sk_verify Fssh_ssh_ed25519_sk_verify #define ssh_ed25519_verify Fssh_ssh_ed25519_verify #define ssh_err Fssh_ssh_err #define ssh_fetch_identitylist Fssh_ssh_fetch_identitylist #define ssh_free Fssh_ssh_free #define ssh_free_identitylist Fssh_ssh_free_identitylist #define ssh_gai_strerror Fssh_ssh_gai_strerror #define ssh_get_app_data Fssh_ssh_get_app_data #define ssh_get_authentication_socket Fssh_ssh_get_authentication_socket #define ssh_get_authentication_socket_path Fssh_ssh_get_authentication_socket_path #define ssh_get_progname Fssh_ssh_get_progname #define ssh_hmac_bytes Fssh_ssh_hmac_bytes #define ssh_hmac_final Fssh_ssh_hmac_final #define ssh_hmac_free Fssh_ssh_hmac_free #define ssh_hmac_init Fssh_ssh_hmac_init #define ssh_hmac_start Fssh_ssh_hmac_start #define ssh_hmac_update Fssh_ssh_hmac_update #define ssh_hmac_update_buffer Fssh_ssh_hmac_update_buffer #define ssh_init Fssh_ssh_init #define ssh_input_append Fssh_ssh_input_append #define ssh_input_space Fssh_ssh_input_space #define ssh_krl_check_key Fssh_ssh_krl_check_key #define ssh_krl_file_contains_key Fssh_ssh_krl_file_contains_key #define ssh_krl_free Fssh_ssh_krl_free #define ssh_krl_from_blob Fssh_ssh_krl_from_blob #define ssh_krl_init Fssh_ssh_krl_init #define ssh_krl_revoke_cert_by_key_id Fssh_ssh_krl_revoke_cert_by_key_id #define ssh_krl_revoke_cert_by_serial Fssh_ssh_krl_revoke_cert_by_serial #define ssh_krl_revoke_cert_by_serial_range Fssh_ssh_krl_revoke_cert_by_serial_range #define ssh_krl_revoke_key Fssh_ssh_krl_revoke_key #define ssh_krl_revoke_key_explicit Fssh_ssh_krl_revoke_key_explicit #define ssh_krl_revoke_key_sha1 Fssh_ssh_krl_revoke_key_sha1 #define ssh_krl_revoke_key_sha256 Fssh_ssh_krl_revoke_key_sha256 #define ssh_krl_set_comment Fssh_ssh_krl_set_comment #define ssh_krl_set_version Fssh_ssh_krl_set_version #define ssh_krl_to_blob Fssh_ssh_krl_to_blob #define ssh_libcrypto_init Fssh_ssh_libcrypto_init #define ssh_local_ipaddr Fssh_ssh_local_ipaddr #define ssh_local_port Fssh_ssh_local_port #define ssh_lock_agent Fssh_ssh_lock_agent #define ssh_msg_recv Fssh_ssh_msg_recv #define ssh_msg_send Fssh_ssh_msg_send #define ssh_output_consume Fssh_ssh_output_consume #define ssh_output_ptr Fssh_ssh_output_ptr #define ssh_output_space Fssh_ssh_output_space #define ssh_packet_check_rekey Fssh_ssh_packet_check_rekey #define ssh_packet_clear_keys Fssh_ssh_packet_clear_keys #define ssh_packet_close Fssh_ssh_packet_close #define ssh_packet_close_internal Fssh_ssh_packet_close_internal #define ssh_packet_connection_af Fssh_ssh_packet_connection_af #define ssh_packet_connection_is_on_socket Fssh_ssh_packet_connection_is_on_socket #define ssh_packet_disconnect Fssh_ssh_packet_disconnect #define ssh_packet_enable_delayed_compress Fssh_ssh_packet_enable_delayed_compress #define ssh_packet_get_bytes Fssh_ssh_packet_get_bytes #define ssh_packet_get_connection_in Fssh_ssh_packet_get_connection_in #define ssh_packet_get_connection_out Fssh_ssh_packet_get_connection_out #define ssh_packet_get_input Fssh_ssh_packet_get_input #define ssh_packet_get_maxsize Fssh_ssh_packet_get_maxsize #define ssh_packet_get_mux Fssh_ssh_packet_get_mux #define ssh_packet_get_output Fssh_ssh_packet_get_output #define ssh_packet_get_protocol_flags Fssh_ssh_packet_get_protocol_flags #define ssh_packet_get_rekey_timeout Fssh_ssh_packet_get_rekey_timeout #define ssh_packet_get_state Fssh_ssh_packet_get_state #define ssh_packet_have_data_to_write Fssh_ssh_packet_have_data_to_write #define ssh_packet_inc_alive_timeouts Fssh_ssh_packet_inc_alive_timeouts #define ssh_packet_interactive_data_to_write Fssh_ssh_packet_interactive_data_to_write #define ssh_packet_is_interactive Fssh_ssh_packet_is_interactive #define ssh_packet_is_rekeying Fssh_ssh_packet_is_rekeying #define ssh_packet_log_type Fssh_ssh_packet_log_type #define ssh_packet_need_rekeying Fssh_ssh_packet_need_rekeying #define ssh_packet_next Fssh_ssh_packet_next #define ssh_packet_not_very_much_data_to_write Fssh_ssh_packet_not_very_much_data_to_write #define ssh_packet_payload Fssh_ssh_packet_payload #define ssh_packet_process_incoming Fssh_ssh_packet_process_incoming #define ssh_packet_process_read Fssh_ssh_packet_process_read #define ssh_packet_put Fssh_ssh_packet_put #define ssh_packet_rdomain_in Fssh_ssh_packet_rdomain_in #define ssh_packet_read Fssh_ssh_packet_read -#define ssh_packet_read_expect Fssh_ssh_packet_read_expect #define ssh_packet_read_poll2 Fssh_ssh_packet_read_poll2 #define ssh_packet_read_poll_seqnr Fssh_ssh_packet_read_poll_seqnr #define ssh_packet_read_seqnr Fssh_ssh_packet_read_seqnr #define ssh_packet_remaining Fssh_ssh_packet_remaining #define ssh_packet_send2 Fssh_ssh_packet_send2 #define ssh_packet_send2_wrapped Fssh_ssh_packet_send2_wrapped #define ssh_packet_send_debug Fssh_ssh_packet_send_debug +#define ssh_packet_send_mux Fssh_ssh_packet_send_mux #define ssh_packet_set_alive_timeouts Fssh_ssh_packet_set_alive_timeouts #define ssh_packet_set_authenticated Fssh_ssh_packet_set_authenticated #define ssh_packet_set_connection Fssh_ssh_packet_set_connection #define ssh_packet_set_input_hook Fssh_ssh_packet_set_input_hook #define ssh_packet_set_interactive Fssh_ssh_packet_set_interactive #define ssh_packet_set_log_preamble Fssh_ssh_packet_set_log_preamble #define ssh_packet_set_maxsize Fssh_ssh_packet_set_maxsize #define ssh_packet_set_mux Fssh_ssh_packet_set_mux #define ssh_packet_set_nonblocking Fssh_ssh_packet_set_nonblocking #define ssh_packet_set_postauth Fssh_ssh_packet_set_postauth #define ssh_packet_set_protocol_flags Fssh_ssh_packet_set_protocol_flags #define ssh_packet_set_rekey_limits Fssh_ssh_packet_set_rekey_limits #define ssh_packet_set_server Fssh_ssh_packet_set_server #define ssh_packet_set_state Fssh_ssh_packet_set_state #define ssh_packet_set_timeout Fssh_ssh_packet_set_timeout #define ssh_packet_set_tos Fssh_ssh_packet_set_tos #define ssh_packet_start_discard Fssh_ssh_packet_start_discard #define ssh_packet_stop_discard Fssh_ssh_packet_stop_discard #define ssh_packet_write_poll Fssh_ssh_packet_write_poll #define ssh_packet_write_wait Fssh_ssh_packet_write_wait #define ssh_remote_ipaddr Fssh_ssh_remote_ipaddr #define ssh_remote_port Fssh_ssh_remote_port #define ssh_remove_all_identities Fssh_ssh_remove_all_identities #define ssh_remove_identity Fssh_ssh_remove_identity #define ssh_request_reply Fssh_ssh_request_reply #define ssh_request_reply_decode Fssh_ssh_request_reply_decode #define ssh_rsa_alloc Fssh_ssh_rsa_alloc #define ssh_rsa_cleanup Fssh_ssh_rsa_cleanup #define ssh_rsa_complete_crt_parameters Fssh_ssh_rsa_complete_crt_parameters #define ssh_rsa_copy_public Fssh_ssh_rsa_copy_public #define ssh_rsa_deserialize_private Fssh_ssh_rsa_deserialize_private #define ssh_rsa_deserialize_public Fssh_ssh_rsa_deserialize_public #define ssh_rsa_equal Fssh_ssh_rsa_equal #define ssh_rsa_generate Fssh_ssh_rsa_generate #define ssh_rsa_serialize_private Fssh_ssh_rsa_serialize_private #define ssh_rsa_serialize_public Fssh_ssh_rsa_serialize_public #define ssh_rsa_sign Fssh_ssh_rsa_sign #define ssh_rsa_size Fssh_ssh_rsa_size #define ssh_rsa_verify Fssh_ssh_rsa_verify #define ssh_set_app_data Fssh_ssh_set_app_data #define ssh_set_newkeys Fssh_ssh_set_newkeys #define ssh_set_verify_host_key_callback Fssh_ssh_set_verify_host_key_callback #define ssh_signal Fssh_ssh_signal #define ssh_tty_make_modes Fssh_ssh_tty_make_modes #define ssh_tty_parse_modes Fssh_ssh_tty_parse_modes #define ssh_update_card Fssh_ssh_update_card #define sshbuf_alloc Fssh_sshbuf_alloc #define sshbuf_allocate Fssh_sshbuf_allocate #define sshbuf_avail Fssh_sshbuf_avail #define sshbuf_b64tod Fssh_sshbuf_b64tod #define sshbuf_check_reserve Fssh_sshbuf_check_reserve #define sshbuf_cmp Fssh_sshbuf_cmp #define sshbuf_consume Fssh_sshbuf_consume #define sshbuf_consume_end Fssh_sshbuf_consume_end #define sshbuf_dtob16 Fssh_sshbuf_dtob16 #define sshbuf_dtob64 Fssh_sshbuf_dtob64 #define sshbuf_dtob64_string Fssh_sshbuf_dtob64_string #define sshbuf_dtourlb64 Fssh_sshbuf_dtourlb64 #define sshbuf_dump Fssh_sshbuf_dump #define sshbuf_dump_data Fssh_sshbuf_dump_data #define sshbuf_dup_string Fssh_sshbuf_dup_string #define sshbuf_find Fssh_sshbuf_find #define sshbuf_free Fssh_sshbuf_free #define sshbuf_from Fssh_sshbuf_from #define sshbuf_fromb Fssh_sshbuf_fromb #define sshbuf_froms Fssh_sshbuf_froms #define sshbuf_get Fssh_sshbuf_get #define sshbuf_get_bignum2 Fssh_sshbuf_get_bignum2 #define sshbuf_get_bignum2_bytes_direct Fssh_sshbuf_get_bignum2_bytes_direct #define sshbuf_get_cstring Fssh_sshbuf_get_cstring #define sshbuf_get_ec Fssh_sshbuf_get_ec #define sshbuf_get_eckey Fssh_sshbuf_get_eckey #define sshbuf_get_string Fssh_sshbuf_get_string #define sshbuf_get_string_direct Fssh_sshbuf_get_string_direct #define sshbuf_get_stringb Fssh_sshbuf_get_stringb #define sshbuf_get_u16 Fssh_sshbuf_get_u16 #define sshbuf_get_u32 Fssh_sshbuf_get_u32 #define sshbuf_get_u64 Fssh_sshbuf_get_u64 #define sshbuf_get_u8 Fssh_sshbuf_get_u8 #define sshbuf_len Fssh_sshbuf_len #define sshbuf_load_fd Fssh_sshbuf_load_fd #define sshbuf_load_file Fssh_sshbuf_load_file #define sshbuf_max_size Fssh_sshbuf_max_size #define sshbuf_maybe_pack Fssh_sshbuf_maybe_pack #define sshbuf_mutable_ptr Fssh_sshbuf_mutable_ptr #define sshbuf_new Fssh_sshbuf_new #define sshbuf_parent Fssh_sshbuf_parent #define sshbuf_peek_string_direct Fssh_sshbuf_peek_string_direct #define sshbuf_peek_u16 Fssh_sshbuf_peek_u16 #define sshbuf_peek_u32 Fssh_sshbuf_peek_u32 #define sshbuf_peek_u64 Fssh_sshbuf_peek_u64 #define sshbuf_peek_u8 Fssh_sshbuf_peek_u8 #define sshbuf_poke Fssh_sshbuf_poke #define sshbuf_poke_u16 Fssh_sshbuf_poke_u16 #define sshbuf_poke_u32 Fssh_sshbuf_poke_u32 #define sshbuf_poke_u64 Fssh_sshbuf_poke_u64 #define sshbuf_poke_u8 Fssh_sshbuf_poke_u8 #define sshbuf_ptr Fssh_sshbuf_ptr #define sshbuf_put Fssh_sshbuf_put #define sshbuf_put_bignum2 Fssh_sshbuf_put_bignum2 #define sshbuf_put_bignum2_bytes Fssh_sshbuf_put_bignum2_bytes #define sshbuf_put_cstring Fssh_sshbuf_put_cstring #define sshbuf_put_ec Fssh_sshbuf_put_ec #define sshbuf_put_eckey Fssh_sshbuf_put_eckey #define sshbuf_put_string Fssh_sshbuf_put_string #define sshbuf_put_stringb Fssh_sshbuf_put_stringb #define sshbuf_put_u16 Fssh_sshbuf_put_u16 #define sshbuf_put_u32 Fssh_sshbuf_put_u32 #define sshbuf_put_u64 Fssh_sshbuf_put_u64 #define sshbuf_put_u8 Fssh_sshbuf_put_u8 #define sshbuf_putb Fssh_sshbuf_putb #define sshbuf_putf Fssh_sshbuf_putf #define sshbuf_putfv Fssh_sshbuf_putfv #define sshbuf_read Fssh_sshbuf_read #define sshbuf_refcount Fssh_sshbuf_refcount #define sshbuf_reserve Fssh_sshbuf_reserve #define sshbuf_reset Fssh_sshbuf_reset #define sshbuf_set_max_size Fssh_sshbuf_set_max_size #define sshbuf_set_parent Fssh_sshbuf_set_parent #define sshbuf_write_file Fssh_sshbuf_write_file #define sshfatal Fssh_sshfatal #define sshkey_advance_past_options Fssh_sshkey_advance_past_options #define sshkey_alg_list Fssh_sshkey_alg_list #define sshkey_cert_check_authority Fssh_sshkey_cert_check_authority #define sshkey_cert_check_authority_now Fssh_sshkey_cert_check_authority_now #define sshkey_cert_check_host Fssh_sshkey_cert_check_host #define sshkey_cert_copy Fssh_sshkey_cert_copy #define sshkey_cert_type Fssh_sshkey_cert_type #define sshkey_certify Fssh_sshkey_certify #define sshkey_certify_custom Fssh_sshkey_certify_custom #define sshkey_check_cert_sigtype Fssh_sshkey_check_cert_sigtype #define sshkey_check_revoked Fssh_sshkey_check_revoked #define sshkey_check_rsa_length Fssh_sshkey_check_rsa_length #define sshkey_check_sigtype Fssh_sshkey_check_sigtype #define sshkey_copy_public_sk Fssh_sshkey_copy_public_sk #define sshkey_curve_name_to_nid Fssh_sshkey_curve_name_to_nid #define sshkey_curve_nid_to_bits Fssh_sshkey_curve_nid_to_bits #define sshkey_curve_nid_to_name Fssh_sshkey_curve_nid_to_name #define sshkey_deserialize_sk Fssh_sshkey_deserialize_sk #define sshkey_drop_cert Fssh_sshkey_drop_cert #define sshkey_dump_ec_key Fssh_sshkey_dump_ec_key #define sshkey_dump_ec_point Fssh_sshkey_dump_ec_point #define sshkey_ec_nid_to_hash_alg Fssh_sshkey_ec_nid_to_hash_alg #define sshkey_ec_validate_private Fssh_sshkey_ec_validate_private #define sshkey_ec_validate_public Fssh_sshkey_ec_validate_public #define sshkey_ecdsa_bits_to_nid Fssh_sshkey_ecdsa_bits_to_nid #define sshkey_ecdsa_key_to_nid Fssh_sshkey_ecdsa_key_to_nid #define sshkey_ecdsa_nid_from_name Fssh_sshkey_ecdsa_nid_from_name #define sshkey_enable_maxsign Fssh_sshkey_enable_maxsign #define sshkey_equal Fssh_sshkey_equal #define sshkey_equal_public Fssh_sshkey_equal_public #define sshkey_fingerprint Fssh_sshkey_fingerprint #define sshkey_fingerprint_raw Fssh_sshkey_fingerprint_raw #define sshkey_format_cert_validity Fssh_sshkey_format_cert_validity #define sshkey_format_text Fssh_sshkey_format_text #define sshkey_free Fssh_sshkey_free #define sshkey_free_contents Fssh_sshkey_free_contents #define sshkey_from_blob Fssh_sshkey_from_blob #define sshkey_from_blob_internal Fssh_sshkey_from_blob_internal #define sshkey_from_private Fssh_sshkey_from_private #define sshkey_fromb Fssh_sshkey_fromb #define sshkey_froms Fssh_sshkey_froms #define sshkey_generate Fssh_sshkey_generate #define sshkey_get_sigtype Fssh_sshkey_get_sigtype #define sshkey_impl_from_type Fssh_sshkey_impl_from_type #define sshkey_in_file Fssh_sshkey_in_file #define sshkey_is_cert Fssh_sshkey_is_cert #define sshkey_is_shielded Fssh_sshkey_is_shielded #define sshkey_is_sk Fssh_sshkey_is_sk #define sshkey_load_cert Fssh_sshkey_load_cert #define sshkey_load_private Fssh_sshkey_load_private #define sshkey_load_private_cert Fssh_sshkey_load_private_cert #define sshkey_load_private_type Fssh_sshkey_load_private_type #define sshkey_load_private_type_fd Fssh_sshkey_load_private_type_fd #define sshkey_load_public Fssh_sshkey_load_public #define sshkey_match_keyname_to_sigalgs Fssh_sshkey_match_keyname_to_sigalgs #define sshkey_names_valid2 Fssh_sshkey_names_valid2 #define sshkey_new Fssh_sshkey_new #define sshkey_parse_private2 Fssh_sshkey_parse_private2 #define sshkey_parse_private_fileblob Fssh_sshkey_parse_private_fileblob #define sshkey_parse_private_fileblob_type Fssh_sshkey_parse_private_fileblob_type #define sshkey_parse_pubkey_from_private_fileblob_type Fssh_sshkey_parse_pubkey_from_private_fileblob_type #define sshkey_perm_ok Fssh_sshkey_perm_ok #define sshkey_plain_to_blob Fssh_sshkey_plain_to_blob #define sshkey_private_deserialize Fssh_sshkey_private_deserialize #define sshkey_private_deserialize_sk Fssh_sshkey_private_deserialize_sk #define sshkey_private_serialize Fssh_sshkey_private_serialize #define sshkey_private_serialize_maxsign Fssh_sshkey_private_serialize_maxsign #define sshkey_private_serialize_opt Fssh_sshkey_private_serialize_opt #define sshkey_private_to_blob2 Fssh_sshkey_private_to_blob2 #define sshkey_private_to_fileblob Fssh_sshkey_private_to_fileblob #define sshkey_putb Fssh_sshkey_putb #define sshkey_putb_plain Fssh_sshkey_putb_plain #define sshkey_puts Fssh_sshkey_puts #define sshkey_puts_opts Fssh_sshkey_puts_opts #define sshkey_read Fssh_sshkey_read #define sshkey_save_private Fssh_sshkey_save_private #define sshkey_save_public Fssh_sshkey_save_public #define sshkey_serialize_private_sk Fssh_sshkey_serialize_private_sk #define sshkey_serialize_sk Fssh_sshkey_serialize_sk #define sshkey_set_filename Fssh_sshkey_set_filename #define sshkey_shield_private Fssh_sshkey_shield_private #define sshkey_sig_details_free Fssh_sshkey_sig_details_free #define sshkey_sigalg_by_name Fssh_sshkey_sigalg_by_name #define sshkey_sign Fssh_sshkey_sign #define sshkey_signatures_left Fssh_sshkey_signatures_left #define sshkey_size Fssh_sshkey_size #define sshkey_sk_cleanup Fssh_sshkey_sk_cleanup #define sshkey_sk_fields_equal Fssh_sshkey_sk_fields_equal #define sshkey_ssh_name Fssh_sshkey_ssh_name #define sshkey_ssh_name_plain Fssh_sshkey_ssh_name_plain #define sshkey_to_base64 Fssh_sshkey_to_base64 #define sshkey_to_blob Fssh_sshkey_to_blob #define sshkey_to_certified Fssh_sshkey_to_certified #define sshkey_try_load_public Fssh_sshkey_try_load_public #define sshkey_type Fssh_sshkey_type #define sshkey_type_from_name Fssh_sshkey_type_from_name #define sshkey_type_is_cert Fssh_sshkey_type_is_cert #define sshkey_type_plain Fssh_sshkey_type_plain #define sshkey_unshield_private Fssh_sshkey_unshield_private #define sshkey_verify Fssh_sshkey_verify #define sshkey_write Fssh_sshkey_write #define sshlog Fssh_sshlog #define sshlogdie Fssh_sshlogdie #define sshlogdirect Fssh_sshlogdirect #define sshlogv Fssh_sshlogv #define sshpkt_add_padding Fssh_sshpkt_add_padding #define sshpkt_disconnect Fssh_sshpkt_disconnect #define sshpkt_fatal Fssh_sshpkt_fatal #define sshpkt_fmt_connection_id Fssh_sshpkt_fmt_connection_id #define sshpkt_get Fssh_sshpkt_get #define sshpkt_get_bignum2 Fssh_sshpkt_get_bignum2 #define sshpkt_get_cstring Fssh_sshpkt_get_cstring #define sshpkt_get_ec Fssh_sshpkt_get_ec #define sshpkt_get_end Fssh_sshpkt_get_end #define sshpkt_get_string Fssh_sshpkt_get_string #define sshpkt_get_string_direct Fssh_sshpkt_get_string_direct #define sshpkt_get_u32 Fssh_sshpkt_get_u32 #define sshpkt_get_u64 Fssh_sshpkt_get_u64 #define sshpkt_get_u8 Fssh_sshpkt_get_u8 #define sshpkt_getb_froms Fssh_sshpkt_getb_froms #define sshpkt_msg_ignore Fssh_sshpkt_msg_ignore #define sshpkt_peek_string_direct Fssh_sshpkt_peek_string_direct #define sshpkt_ptr Fssh_sshpkt_ptr #define sshpkt_put Fssh_sshpkt_put #define sshpkt_put_bignum2 Fssh_sshpkt_put_bignum2 #define sshpkt_put_cstring Fssh_sshpkt_put_cstring #define sshpkt_put_ec Fssh_sshpkt_put_ec #define sshpkt_put_string Fssh_sshpkt_put_string #define sshpkt_put_stringb Fssh_sshpkt_put_stringb #define sshpkt_put_u32 Fssh_sshpkt_put_u32 #define sshpkt_put_u64 Fssh_sshpkt_put_u64 #define sshpkt_put_u8 Fssh_sshpkt_put_u8 #define sshpkt_putb Fssh_sshpkt_putb #define sshpkt_send Fssh_sshpkt_send #define sshpkt_start Fssh_sshpkt_start #define sshpkt_vfatal Fssh_sshpkt_vfatal #define sshsigdie Fssh_sshsigdie #define sshsk_enroll Fssh_sshsk_enroll #define sshsk_free_resident_keys Fssh_sshsk_free_resident_keys #define sshsk_load_resident Fssh_sshsk_load_resident #define sshsk_sign Fssh_sshsk_sign #define start_compression_in Fssh_start_compression_in #define start_compression_out Fssh_start_compression_out #define start_progress_meter Fssh_start_progress_meter #define stdfd_devnull Fssh_stdfd_devnull #define stop_progress_meter Fssh_stop_progress_meter #define stravis Fssh_stravis #define strdelim Fssh_strdelim #define strdelim_internal Fssh_strdelim_internal #define strdelimw Fssh_strdelimw #define strnvis Fssh_strnvis #define strvis Fssh_strvis #define strvisx Fssh_strvisx #define subprocess Fssh_subprocess #define sys_tun_open Fssh_sys_tun_open #define tilde_expand Fssh_tilde_expand #define tilde_expand_filename Fssh_tilde_expand_filename #define timeout_connect Fssh_timeout_connect #define to_blob Fssh_to_blob #define to_blob_buf Fssh_to_blob_buf #define tohex Fssh_tohex #define tun_open Fssh_tun_open #define umac128_delete Fssh_umac128_delete #define umac128_final Fssh_umac128_final #define umac128_new Fssh_umac128_new #define umac128_update Fssh_umac128_update #define umac_delete Fssh_umac_delete #define umac_final Fssh_umac_final #define umac_new Fssh_umac_new #define umac_update Fssh_umac_update #define uncompress_buffer Fssh_uncompress_buffer #define unix_listener Fssh_unix_listener #define unset_nonblock Fssh_unset_nonblock #define urldecode Fssh_urldecode #define valid_domain Fssh_valid_domain #define valid_env_name Fssh_valid_env_name #define vasnmprintf Fssh_vasnmprintf #define vdollar_percent_expand Fssh_vdollar_percent_expand #define verify_host_key_dns Fssh_verify_host_key_dns #define vfmprintf Fssh_vfmprintf #define vis Fssh_vis #define waitfd Fssh_waitfd #define waitrfd Fssh_waitrfd #define webauthn_check_prepare_hash Fssh_webauthn_check_prepare_hash #define write_host_entry Fssh_write_host_entry #define x11_connect_display Fssh_x11_connect_display #define x11_create_display_inet Fssh_x11_create_display_inet #define x11_request_forwarding_with_spoofing Fssh_x11_request_forwarding_with_spoofing #define xasprintf Fssh_xasprintf #define xcalloc Fssh_xcalloc #define xcrypt Fssh_xcrypt #define xextendf Fssh_xextendf #define xmalloc Fssh_xmalloc #define xreallocarray Fssh_xreallocarray #define xrecallocarray Fssh_xrecallocarray #define xstrdup Fssh_xstrdup #define xvasprintf Fssh_xvasprintf diff --git a/crypto/openssh/sshconnect.c b/crypto/openssh/sshconnect.c index e6012f01e4d9..bd077c75c137 100644 --- a/crypto/openssh/sshconnect.c +++ b/crypto/openssh/sshconnect.c @@ -1,1721 +1,1729 @@ -/* $OpenBSD: sshconnect.c,v 1.363 2023/03/10 07:17:08 dtucker Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.365 2023/11/20 02:50:00 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * Code to connect to a remote host, and to perform the client side of the * login (authentication) dialog. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */ #include "includes.h" #include #include #include #include #ifdef HAVE_SYS_TIME_H # include #endif #include #include #include #include #include #include #include #include #ifdef HAVE_PATHS_H #include #endif #include #ifdef HAVE_POLL_H #include #endif #include #include #include #include #include #include #ifdef HAVE_IFADDRS_H # include #endif #include "xmalloc.h" #include "hostfile.h" #include "ssh.h" #include "sshbuf.h" #include "packet.h" #include "sshkey.h" #include "sshconnect.h" #include "log.h" #include "misc.h" #include "readconf.h" #include "atomicio.h" #include "dns.h" #include "monitor_fdpass.h" #include "ssh2.h" #include "version.h" #include "authfile.h" #include "ssherr.h" #include "authfd.h" #include "kex.h" struct sshkey *previous_host_key = NULL; static int matching_host_key_dns = 0; static pid_t proxy_command_pid = 0; /* import */ extern int debug_flag; extern Options options; extern char *__progname; static int show_other_keys(struct hostkeys *, struct sshkey *); static void warn_changed_key(struct sshkey *); /* Expand a proxy command */ static char * expand_proxy_command(const char *proxy_command, const char *user, const char *host, 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, (char *)NULL); free(tmp); return ret; } /* * Connect to the given ssh server using a proxy command that passes a * a connected fd back to us. */ static int ssh_proxy_fdpass_connect(struct ssh *ssh, const char *host, const char *host_arg, u_short port, const char *proxy_command) { char *command_string; int sp[2], sock; pid_t pid; char *shell; if ((shell = getenv("SHELL")) == NULL) shell = _PATH_BSHELL; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == -1) fatal("Could not create socketpair to communicate with " "proxy dialer: %.100s", strerror(errno)); command_string = expand_proxy_command(proxy_command, options.user, host, host_arg, port); debug("Executing proxy dialer command: %.500s", command_string); /* Fork and execute the proxy command. */ if ((pid = fork()) == 0) { char *argv[10]; close(sp[1]); /* Redirect stdin and stdout. */ if (sp[0] != 0) { if (dup2(sp[0], 0) == -1) perror("dup2 stdin"); } if (sp[0] != 1) { if (dup2(sp[0], 1) == -1) perror("dup2 stdout"); } if (sp[0] >= 2) close(sp[0]); /* * Stderr is left for non-ControlPersist connections is so * error messages may be printed on the user's terminal. */ if (!debug_flag && options.control_path != NULL && options.control_persist && stdfd_devnull(0, 0, 1) == -1) error_f("stdfd_devnull failed"); argv[0] = shell; argv[1] = "-c"; argv[2] = command_string; argv[3] = NULL; /* * Execute the proxy command. * Note that we gave up any extra privileges above. */ execv(argv[0], argv); perror(argv[0]); exit(1); } /* Parent. */ if (pid == -1) fatal("fork failed: %.100s", strerror(errno)); close(sp[0]); free(command_string); if ((sock = mm_receive_fd(sp[1])) == -1) fatal("proxy dialer did not pass back a connection"); close(sp[1]); while (waitpid(pid, NULL, 0) == -1) if (errno != EINTR) fatal("Couldn't wait for child: %s", strerror(errno)); /* Set the connection file descriptors. */ if (ssh_packet_set_connection(ssh, sock, sock) == NULL) return -1; /* ssh_packet_set_connection logs error */ return 0; } /* * Connect to the given ssh server using a proxy command. */ static int ssh_proxy_connect(struct ssh *ssh, const char *host, const char *host_arg, u_short port, const char *proxy_command) { char *command_string; int pin[2], pout[2]; pid_t pid; char *shell; if ((shell = getenv("SHELL")) == NULL || *shell == '\0') shell = _PATH_BSHELL; /* Create pipes for communicating with the proxy. */ if (pipe(pin) == -1 || pipe(pout) == -1) fatal("Could not create pipes to communicate with the proxy: %.100s", strerror(errno)); command_string = expand_proxy_command(proxy_command, options.user, host, host_arg, port); debug("Executing proxy command: %.500s", command_string); /* Fork and execute the proxy command. */ if ((pid = fork()) == 0) { char *argv[10]; /* Redirect stdin and stdout. */ close(pin[1]); if (pin[0] != 0) { if (dup2(pin[0], 0) == -1) perror("dup2 stdin"); close(pin[0]); } close(pout[0]); if (dup2(pout[1], 1) == -1) perror("dup2 stdout"); /* Cannot be 1 because pin allocated two descriptors. */ close(pout[1]); /* * Stderr is left for non-ControlPersist connections is so * error messages may be printed on the user's terminal. */ if (!debug_flag && options.control_path != NULL && options.control_persist && stdfd_devnull(0, 0, 1) == -1) error_f("stdfd_devnull failed"); argv[0] = shell; argv[1] = "-c"; argv[2] = command_string; argv[3] = NULL; /* * Execute the proxy command. Note that we gave up any * extra privileges above. */ ssh_signal(SIGPIPE, SIG_DFL); execv(argv[0], argv); perror(argv[0]); exit(1); } /* Parent. */ if (pid == -1) fatal("fork failed: %.100s", strerror(errno)); else proxy_command_pid = pid; /* save pid to clean up later */ /* Close child side of the descriptors. */ close(pin[0]); close(pout[1]); /* Free the command name. */ free(command_string); /* Set the connection file descriptors. */ if (ssh_packet_set_connection(ssh, pout[0], pin[1]) == NULL) return -1; /* ssh_packet_set_connection logs error */ return 0; } void ssh_kill_proxy_command(void) { /* * Send SIGHUP to proxy command if used. We don't wait() in * case it hangs and instead rely on init to reap the child */ if (proxy_command_pid > 1) kill(proxy_command_pid, SIGHUP); } #ifdef HAVE_IFADDRS_H /* * Search a interface address list (returned from getifaddrs(3)) for an * address that matches the desired address family on the specified interface. * Returns 0 and fills in *resultp and *rlenp on success. Returns -1 on failure. */ static int check_ifaddrs(const char *ifname, int af, const struct ifaddrs *ifaddrs, struct sockaddr_storage *resultp, socklen_t *rlenp) { struct sockaddr_in6 *sa6; struct sockaddr_in *sa; struct in6_addr *v6addr; const struct ifaddrs *ifa; int allow_local; /* * Prefer addresses that are not loopback or linklocal, but use them * if nothing else matches. */ for (allow_local = 0; allow_local < 2; allow_local++) { for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL || (ifa->ifa_flags & IFF_UP) == 0 || ifa->ifa_addr->sa_family != af || strcmp(ifa->ifa_name, options.bind_interface) != 0) continue; switch (ifa->ifa_addr->sa_family) { case AF_INET: sa = (struct sockaddr_in *)ifa->ifa_addr; if (!allow_local && sa->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) continue; if (*rlenp < sizeof(struct sockaddr_in)) { error_f("v4 addr doesn't fit"); return -1; } *rlenp = sizeof(struct sockaddr_in); memcpy(resultp, sa, *rlenp); return 0; case AF_INET6: sa6 = (struct sockaddr_in6 *)ifa->ifa_addr; v6addr = &sa6->sin6_addr; if (!allow_local && (IN6_IS_ADDR_LINKLOCAL(v6addr) || IN6_IS_ADDR_LOOPBACK(v6addr))) continue; if (*rlenp < sizeof(struct sockaddr_in6)) { error_f("v6 addr doesn't fit"); return -1; } *rlenp = sizeof(struct sockaddr_in6); memcpy(resultp, sa6, *rlenp); return 0; } } } return -1; } #endif /* * Creates a socket for use as the ssh connection. */ static int ssh_create_socket(struct addrinfo *ai) { int sock, r; struct sockaddr_storage bindaddr; socklen_t bindaddrlen = 0; struct addrinfo hints, *res = NULL; #ifdef HAVE_IFADDRS_H struct ifaddrs *ifaddrs = NULL; #endif char ntop[NI_MAXHOST]; sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock == -1) { error("socket: %s", strerror(errno)); return -1; } (void)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; if (options.bind_address != NULL) { memset(&hints, 0, sizeof(hints)); hints.ai_family = ai->ai_family; hints.ai_socktype = ai->ai_socktype; hints.ai_protocol = ai->ai_protocol; hints.ai_flags = AI_PASSIVE; if ((r = getaddrinfo(options.bind_address, NULL, &hints, &res)) != 0) { error("getaddrinfo: %s: %s", options.bind_address, ssh_gai_strerror(r)); goto fail; } if (res == NULL) { error("getaddrinfo: no addrs"); goto fail; } memcpy(&bindaddr, res->ai_addr, res->ai_addrlen); bindaddrlen = res->ai_addrlen; } else if (options.bind_interface != NULL) { #ifdef HAVE_IFADDRS_H if ((r = getifaddrs(&ifaddrs)) != 0) { error("getifaddrs: %s: %s", options.bind_interface, strerror(errno)); goto fail; } bindaddrlen = sizeof(bindaddr); if (check_ifaddrs(options.bind_interface, ai->ai_family, ifaddrs, &bindaddr, &bindaddrlen) != 0) { logit("getifaddrs: %s: no suitable addresses", options.bind_interface); goto fail; } #else error("BindInterface not supported on this platform."); #endif } if ((r = getnameinfo((struct sockaddr *)&bindaddr, bindaddrlen, ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST)) != 0) { error_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_f("bound to %s", ntop); /* success */ goto out; fail: close(sock); sock = -1; out: if (res != NULL) freeaddrinfo(res); #ifdef HAVE_IFADDRS_H if (ifaddrs != NULL) freeifaddrs(ifaddrs); #endif return sock; } /* * Opens a TCP/IP connection to the remote server on the given host. * The address of the remote host will be returned in hostaddr. * If port is 0, the default port will be used. * Connection_attempts specifies the maximum number of tries (one per * second). If proxy_command is non-NULL, it specifies the command (with %h * and %p substituted for host and port, respectively) to use to contact * the daemon. */ static int ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop, struct sockaddr_storage *hostaddr, u_short port, int 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; debug3_f("entering"); memset(ntop, 0, sizeof(ntop)); memset(strport, 0, sizeof(strport)); for (attempt = 0; attempt < connection_attempts; attempt++) { if (attempt > 0) { /* Sleep a moment before retrying. */ sleep(1); debug("Trying again..."); } /* * Loop through addresses for this host, and try each one in * sequence until the connection succeeds. */ for (ai = aitop; ai; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) { errno = EAFNOSUPPORT; continue; } if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { oerrno = errno; error_f("getnameinfo failed"); errno = oerrno; continue; } + if (options.address_family != AF_UNSPEC && + ai->ai_family != options.address_family) { + debug2_f("skipping address [%s]:%s: " + "wrong address family", ntop, strport); + errno = EAFNOSUPPORT; + continue; + } + debug("Connecting to %.200s [%.100s] port %s.", host, ntop, strport); /* Create a socket for connecting. */ sock = ssh_create_socket(ai); if (sock < 0) { /* Any error is already output */ errno = 0; continue; } *timeout_ms = saved_timeout_ms; if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen, timeout_ms) >= 0) { /* Successful connection. */ memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen); break; } else { oerrno = errno; debug("connect to address %s port %s: %s", ntop, strport, strerror(errno)); close(sock); sock = -1; errno = oerrno; } } if (sock != -1) break; /* Successful connection. */ } /* Return failure if we didn't get a successful connection. */ if (sock == -1) { error("ssh: connect to host %s port %s: %s", host, strport, errno == 0 ? "failure" : strerror(errno)); return -1; } debug("Connection established."); /* Set SO_KEEPALIVE if requested. */ if (want_keepalive && setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)) == -1) error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); /* Set the connection. */ if (ssh_packet_set_connection(ssh, sock, sock) == NULL) return -1; /* ssh_packet_set_connection logs error */ return 0; } int ssh_connect(struct ssh *ssh, const char *host, const char *host_arg, struct addrinfo *addrs, struct sockaddr_storage *hostaddr, u_short port, 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, 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_f("dup() in/out failed"); return -1; /* ssh_packet_set_connection logs error */ } if ((ssh_packet_set_connection(ssh, in, out)) == NULL) return -1; /* ssh_packet_set_connection logs error */ return 0; } else if (options.proxy_use_fdpass) { return ssh_proxy_fdpass_connect(ssh, host, host_arg, port, options.proxy_command); } return ssh_proxy_connect(ssh, host, host_arg, port, options.proxy_command); } /* defaults to 'no' */ static int 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, *cp; int ret = -1; if (options.batch_mode) return 0; for (msg = prompt;;msg = fingerprint ? again_fp : again) { cp = p = read_passphrase(msg, RP_ECHO); if (p == NULL) return 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 && strcmp(p, fingerprint) == 0)) ret = 1; free(cp); if (ret != -1) return ret; } } static int sockaddr_is_local(struct sockaddr *hostaddr) { switch (hostaddr->sa_family) { case AF_INET: return (ntohl(((struct sockaddr_in *)hostaddr)-> sin_addr.s_addr) >> 24) == IN_LOOPBACKNET; case AF_INET6: return IN6_IS_ADDR_LOOPBACK( &(((struct sockaddr_in6 *)hostaddr)->sin6_addr)); default: return 0; } } /* * Prepare the hostname and ip address strings that are used to lookup * host keys in known_hosts files. These may have a port number appended. */ void get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr, u_short port, char **hostfile_hostname, char **hostfile_ipaddr) { char ntop[NI_MAXHOST]; socklen_t addrlen; switch (hostaddr == NULL ? -1 : hostaddr->sa_family) { case -1: addrlen = 0; break; case AF_INET: addrlen = sizeof(struct sockaddr_in); break; case AF_INET6: addrlen = sizeof(struct sockaddr_in6); break; default: addrlen = sizeof(struct sockaddr); break; } /* * We don't have the remote ip-address for connections * using a proxy command */ if (hostfile_ipaddr != NULL) { if (options.proxy_command == NULL) { if (getnameinfo(hostaddr, addrlen, ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0) fatal_f("getnameinfo failed"); *hostfile_ipaddr = put_host_port(ntop, port); } else { *hostfile_ipaddr = xstrdup(""); } } /* * Allow the user to record the key under a different name or * differentiate a non-standard port. This is useful for ssh * tunneling over forwarded connections or if you run multiple * sshd's on different ports on the same machine. */ if (hostfile_hostname != NULL) { if (options.host_key_alias != NULL) { *hostfile_hostname = xstrdup(options.host_key_alias); debug("using hostkeyalias: %s", *hostfile_hostname); } else { *hostfile_hostname = put_host_port(hostname, port); } } } /* returns non-zero if path appears in hostfiles, or 0 if not. */ static int path_in_hostfiles(const char *path, char **hostfiles, u_int num_hostfiles) { u_int i; for (i = 0; i < num_hostfiles; i++) { if (strcmp(path, hostfiles[i]) == 0) return 1; } return 0; } struct find_by_key_ctx { const char *host, *ip; const struct sshkey *key; char **names; u_int nnames; }; /* Try to replace home directory prefix (per $HOME) with a ~/ sequence */ static char * try_tilde_unexpand(const char *path) { char *home, *ret = NULL; size_t l; if (*path != '/') return xstrdup(path); if ((home = getenv("HOME")) == NULL || (l = strlen(home)) == 0) return xstrdup(path); if (strncmp(path, home, l) != 0) return xstrdup(path); /* * ensure we have matched on a path boundary: either the $HOME that * we just compared ends with a '/' or the next character of the path * must be a '/'. */ if (home[l - 1] != '/' && path[l] != '/') return xstrdup(path); if (path[l] == '/') l++; xasprintf(&ret, "~/%s", path + l); return ret; } static int hostkeys_find_by_key_cb(struct hostkey_foreach_line *l, void *_ctx) { struct find_by_key_ctx *ctx = (struct find_by_key_ctx *)_ctx; char *path; /* we are looking for keys with names that *do not* match */ if ((l->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 omitted)", 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) != 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. */ #define RDRW 0 #define RDONLY 1 #define ROQUIET 2 static int 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, const char *hostfile_command) { 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, *fail_reason = NULL; 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; int hostkey_trusted = 0; /* Known or explicitly accepted by user */ struct hostkeys *host_hostkeys, *ip_hostkeys; u_int i; /* * Force accepting of the host key for loopback/localhost. The * problem is that if the home directory is NFS-mounted to multiple * machines, localhost will refer to a different machine in each of * them, and the user will get bogus HOST_CHANGED warnings. This * essentially disables host authentication for localhost; however, * this is probably not a real problem. */ if (options.no_host_authentication_for_localhost == 1 && local && options.host_key_alias == NULL) { debug("Forcing accepting of host key for " "loopback/localhost."); options.update_hostkeys = 0; return 0; } /* * Don't ever try to write an invalid name to a known hosts file. * Note: do this before get_hostfile_hostname_ipaddr() to catch * '[' or ']' in the name before they are added. */ if (strcspn(hostname, "@?*#[]|'\'\"\\") != strlen(hostname)) { debug_f("invalid hostname \"%s\"; will not record: %s", hostname, fail_reason); readonly = RDONLY; } /* * 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, clobber_port ? 0 : port, &host, &ip); /* * Turn off check_host_ip if the connection is to localhost, via proxy * command or if we don't have a hostname to compare with */ if (options.check_host_ip && (local || strcmp(hostname, ip) == 0 || options.proxy_command != NULL)) options.check_host_ip = 0; host_hostkeys = init_hostkeys(); for (i = 0; i < num_user_hostfiles; i++) load_hostkeys(host_hostkeys, host, user_hostfiles[i], 0); for (i = 0; i < num_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], 0); for (i = 0; i < num_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: /* Reload these as they may have changed on cert->key downgrade */ want_cert = sshkey_is_cert(host_key); type = sshkey_type(host_key); /* * Check if the host key is present in the user's list of known * hosts or in the systemwide list. */ host_status = check_key_in_hostkeys(host_hostkeys, host_key, &host_found); /* * 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 * address to begin with. */ if (!want_cert && ip_hostkeys != NULL) { ip_status = check_key_in_hostkeys(ip_hostkeys, host_key, &ip_found); if (host_status == HOST_CHANGED && (ip_status != HOST_CHANGED || (ip_found != NULL && !sshkey_equal(ip_found->key, host_found->key)))) host_ip_differ = 1; } else ip_status = host_status; switch (host_status) { case HOST_OK: /* The host is known and the key matches. */ debug("Host '%.200s' is known and matches the %s host %s.", host, type, want_cert ? "certificate" : "key"); debug("Found %s in %s:%lu", want_cert ? "CA key" : "key", host_found->file, host_found->line); if (want_cert) { 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 " "'%.128s' not in list of known hosts.", type, ip); else if (!add_host_to_hostfile(user_hostfiles[0], ip, host_key, options.hash_known_hosts)) logit("Failed to add the %s host key for IP " "address '%.128s' to the list of known " "hosts (%.500s).", type, ip, user_hostfiles[0]); else logit("Warning: Permanently added the %s host " "key for IP address '%.128s' to the list " "of known hosts.", type, ip); } else if (options.visual_host_key) { fp = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_DEFAULT); ra = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_RANDOMART); if (fp == NULL || ra == NULL) fatal_f("sshkey_fingerprint failed"); logit("Host key fingerprint is %s\n%s", fp, ra); free(ra); free(fp); } hostkey_trusted = 1; break; case HOST_NEW: if (options.host_key_alias == NULL && port != 0 && port != SSH_DEFAULT_PORT && !clobber_port) { debug("checking without port identifier"); 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; } } if (readonly || want_cert) goto fail; /* The host is new. */ if (options.strict_host_key_checking == SSH_STRICT_HOSTKEY_YES) { /* * User has requested strict host key checking. We * will not add the host key automatically. The only * alternative left is to abort. */ error("No %s host key is known for %.200s and you " "have requested strict checking.", type, host); goto fail; } else if (options.strict_host_key_checking == SSH_STRICT_HOSTKEY_ASK) { char *msg1 = 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, "", "."); 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_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) { xextendf(&msg1, "\n", "%s host key fingerprint found in DNS.", matching_host_key_dns ? "Matching" : "No matching"); } /* 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])? "); confirmed = confirm(msg1, fp); free(ra); free(fp); free(msg1); free(msg2); if (!confirmed) goto fail; hostkey_trusted = 1; /* user explicitly confirmed */ } /* * If in "new" or "off" strict mode, add the key automatically * to the local known_hosts file. */ if (options.check_host_ip && ip_status == HOST_NEW) { snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); hostp = hostline; if (options.hash_known_hosts) { /* Add hash of host and IP separately */ r = add_host_to_hostfile(user_hostfiles[0], host, host_key, options.hash_known_hosts) && add_host_to_hostfile(user_hostfiles[0], ip, host_key, options.hash_known_hosts); } else { /* Add unhashed "host,ip" */ r = add_host_to_hostfile(user_hostfiles[0], hostline, host_key, options.hash_known_hosts); } } else { r = add_host_to_hostfile(user_hostfiles[0], host, host_key, options.hash_known_hosts); hostp = host; } if (!r) logit("Failed to add the host to the list of known " "hosts (%.500s).", user_hostfiles[0]); else logit("Warning: Permanently added '%.200s' (%s) to the " "list of known hosts.", hostp, type); break; case HOST_REVOKED: error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("@ WARNING: REVOKED HOST KEY DETECTED! @"); error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("The %s host key for %s is marked as revoked.", type, host); error("This could mean that a stolen key is being used to"); error("impersonate this host."); /* * If strict host key checking is in use, the user will have * to edit the key manually and we can only abort. */ if (options.strict_host_key_checking != SSH_STRICT_HOSTKEY_OFF) { error("%s host key for %.200s was revoked and you have " "requested strict checking.", type, host); goto fail; } goto continue_unsafe; case HOST_CHANGED: if (want_cert) { /* * This is only a debug() since it is valid to have * CAs with wildcard DNS matches that don't match * all hosts that one might visit. */ debug("Host certificate authority does not " "match %s in %s:%lu", CA_MARKER, host_found->file, host_found->line); goto fail; } if (readonly == ROQUIET) goto fail; if (options.check_host_ip && host_ip_differ) { char *key_msg; if (ip_status == HOST_NEW) key_msg = "is unknown"; else if (ip_status == HOST_OK) key_msg = "is unchanged"; else key_msg = "has a different value"; error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @"); error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("The %s host key for %s has changed,", type, host); error("and the key for the corresponding IP address %s", ip); error("%s. This could either mean that", key_msg); error("DNS SPOOFING is happening or the IP address for the host"); error("and its host key have changed at the same time."); if (ip_status != HOST_NEW) error("Offending key for IP in %s:%lu", ip_found->file, ip_found->line); } /* The host key has changed. */ warn_changed_key(host_key); if (num_user_hostfiles > 0 || num_system_hostfiles > 0) { error("Add correct host key in %.100s to get rid " "of this message.", num_user_hostfiles > 0 ? user_hostfiles[0] : system_hostfiles[0]); } error("Offending %s key in %s:%lu", sshkey_type(host_found->key), host_found->file, host_found->line); /* * If strict host key checking is in use, the user will have * to edit the key manually and we can only abort. */ if (options.strict_host_key_checking != SSH_STRICT_HOSTKEY_OFF) { error("Host key for %.200s has changed and you have " "requested strict checking.", host); goto fail; } continue_unsafe: /* * If strict host key checking has not been requested, allow * the connection but without MITM-able authentication or * forwarding. */ if (options.password_authentication) { error("Password authentication is disabled to avoid " "man-in-the-middle attacks."); options.password_authentication = 0; cancelled_forwarding = 1; } if (options.kbd_interactive_authentication) { error("Keyboard-interactive authentication is disabled" " to avoid man-in-the-middle attacks."); options.kbd_interactive_authentication = 0; cancelled_forwarding = 1; } if (options.forward_agent) { error("Agent forwarding is disabled to avoid " "man-in-the-middle attacks."); options.forward_agent = 0; cancelled_forwarding = 1; } if (options.forward_x11) { error("X11 forwarding is disabled to avoid " "man-in-the-middle attacks."); options.forward_x11 = 0; cancelled_forwarding = 1; } if (options.num_local_forwards > 0 || options.num_remote_forwards > 0) { error("Port forwarding is disabled to avoid " "man-in-the-middle attacks."); options.num_local_forwards = options.num_remote_forwards = 0; cancelled_forwarding = 1; } if (options.tun_open != SSH_TUNMODE_NO) { error("Tunnel forwarding is disabled to avoid " "man-in-the-middle attacks."); options.tun_open = SSH_TUNMODE_NO; cancelled_forwarding = 1; } if (options.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"); /* * XXX Should permit the user to change to use the new id. * This could be done by converting the host key to an * identifying sentence, tell that the host identifies itself * by that sentence, and ask the user if they wish to * accept the authentication. */ break; case HOST_FOUND: fatal("internal error"); break; } if (options.check_host_ip && host_status != HOST_CHANGED && ip_status == HOST_CHANGED) { snprintf(msg, sizeof(msg), "Warning: the %s host key for '%.200s' " "differs from the key for the IP address '%.128s'" "\nOffending key for IP in %s:%lu", type, host, ip, ip_found->file, ip_found->line); if (host_status == HOST_OK) { len = strlen(msg); snprintf(msg + len, sizeof(msg) - len, "\nMatching host key in %s:%lu", host_found->file, host_found->line); } if (options.strict_host_key_checking == SSH_STRICT_HOSTKEY_ASK) { strlcat(msg, "\nAre you sure you want " "to continue connecting (yes/no)? ", sizeof(msg)); if (!confirm(msg, NULL)) goto fail; } else if (options.strict_host_key_checking != SSH_STRICT_HOSTKEY_OFF) { logit("%s", msg); error("Exiting, you have requested strict checking."); goto fail; } else { logit("%s", msg); } } if (!hostkey_trusted && options.update_hostkeys) { debug_f("hostkey not known or explicitly trusted: " "disabling UpdateHostkeys"); options.update_hostkeys = 0; } free(ip); free(host); if (host_hostkeys != NULL) free_hostkeys(host_hostkeys); if (ip_hostkeys != NULL) free_hostkeys(ip_hostkeys); return 0; fail: if (want_cert && host_status != HOST_REVOKED) { /* * No matching certificate. Downgrade cert to raw key and * search normally. */ debug("No matching CA found. Retry with plain key"); if ((r = sshkey_from_private(host_key, &raw_key)) != 0) fatal_fr(r, "decode key"); if ((r = sshkey_drop_cert(raw_key)) != 0) fatal_r(r, "Couldn't drop certificate"); host_key = raw_key; goto retry; } sshkey_free(raw_key); free(ip); free(host); if (host_hostkeys != NULL) free_hostkeys(host_hostkeys); if (ip_hostkeys != NULL) free_hostkeys(ip_hostkeys); return -1; } /* returns 0 if key verifies or -1 if key does NOT verify */ int verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key, const struct ssh_conn_info *cinfo) { u_int i; int r = -1, flags = 0; char valid[64], *fp = NULL, *cafp = NULL; struct sshkey *plain = NULL; if ((fp = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { error_fr(r, "fingerprint host key"); r = -1; goto out; } if (sshkey_is_cert(host_key)) { if ((cafp = sshkey_fingerprint(host_key->cert->signature_key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { error_fr(r, "fingerprint CA key"); r = -1; goto out; } sshkey_format_cert_validity(host_key->cert, valid, sizeof(valid)); debug("Server host certificate: %s %s, serial %llu " "ID \"%s\" CA %s %s valid %s", sshkey_ssh_name(host_key), fp, (unsigned long long)host_key->cert->serial, host_key->cert->key_id, sshkey_ssh_name(host_key->cert->signature_key), cafp, valid); for (i = 0; i < host_key->cert->nprincipals; i++) { debug2("Server host certificate hostname: %s", host_key->cert->principals[i]); } } else { debug("Server host key: %s %s", sshkey_ssh_name(host_key), fp); } if (sshkey_equal(previous_host_key, host_key)) { debug2_f("server host key %s %s matches cached key", sshkey_type(host_key), fp); r = 0; goto out; } /* Check in RevokedHostKeys file if specified */ if (options.revoked_host_keys != NULL) { r = sshkey_check_revoked(host_key, options.revoked_host_keys); switch (r) { case 0: break; /* not revoked */ case SSH_ERR_KEY_REVOKED: error("Host key %s %s revoked by file %s", sshkey_type(host_key), fp, options.revoked_host_keys); r = -1; goto out; default: error_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; } } if (options.verify_host_key_dns) { /* * XXX certs are not yet supported for DNS, so downgrade * them and try the plain key. */ if ((r = sshkey_from_private(host_key, &plain)) != 0) goto out; if (sshkey_is_cert(plain)) sshkey_drop_cert(plain); if (verify_host_key_dns(host, hostaddr, plain, &flags) == 0) { if (flags & DNS_VERIFY_FOUND) { if (options.verify_host_key_dns == 1 && flags & DNS_VERIFY_MATCH && flags & DNS_VERIFY_SECURE) { r = 0; goto out; } if (flags & DNS_VERIFY_MATCH) { matching_host_key_dns = 1; } else { warn_changed_key(plain); error("Update the SSHFP RR in DNS " "with the new host key to get rid " "of this message."); } } } } r = check_host_key(host, 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); free(fp); free(cafp); if (r == 0 && host_key != NULL) { sshkey_free(previous_host_key); r = sshkey_from_private(host_key, &previous_host_key); } return r; } /* * Starts a dialog with the server, and authenticates the current user on the * server. This does not need any extra privileges. The basic connection * to the server must already have been established before this is called. * If login fails, this function prints an error and never returns. * This function does not require super-user privileges. */ void ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost, 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; /* Convert the user-supplied hostname into all lowercase. */ host = xstrdup(orighost); lowercase(host); /* Exchange protocol version identification strings with the server. */ 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); /* key exchange */ /* authenticate user */ debug("Authenticating to %s:%d as '%s'", host, port, server_user); ssh_kex2(ssh, host, hostaddr, port, cinfo); ssh_userauth2(ssh, local_user, server_user, host, sensitive); free(local_user); free(host); } /* print all known host keys for a given host, but skip keys of given type */ static int show_other_keys(struct hostkeys *hostkeys, struct sshkey *key) { int type[] = { KEY_RSA, KEY_DSA, KEY_ECDSA, KEY_ED25519, KEY_XMSS, -1 }; int i, ret = 0; char *fp, *ra; const struct hostkey_entry *found; for (i = 0; type[i] != -1; i++) { if (type[i] == key->type) continue; if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], -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_f("sshkey_fingerprint fail"); logit("WARNING: %s key found for host %s\n" "in %s:%lu\n" "%s key fingerprint %s.", sshkey_type(found->key), found->host, found->file, found->line, sshkey_type(found->key), fp); if (options.visual_host_key) logit("%s", ra); free(ra); free(fp); ret = 1; } return ret; } static void warn_changed_key(struct sshkey *host_key) { char *fp; fp = sshkey_fingerprint(host_key, options.fingerprint_hash, SSH_FP_DEFAULT); if (fp == NULL) fatal_f("sshkey_fingerprint fail"); error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); error("It is also possible that a host key has just been changed."); error("The fingerprint for the %s key sent by the remote host is\n%s.", sshkey_type(host_key), fp); error("Please contact your system administrator."); free(fp); } /* * Execute a local command */ int ssh_local_cmd(const char *args) { char *shell; pid_t pid; int status; void (*osighand)(int); if (!options.permit_local_command || args == NULL || !*args) return (1); if ((shell = getenv("SHELL")) == NULL || *shell == '\0') shell = _PATH_BSHELL; osighand = ssh_signal(SIGCHLD, SIG_DFL); pid = fork(); if (pid == 0) { 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", shell, args, strerror(errno)); _exit(1); } else if (pid == -1) fatal("fork failed: %.100s", strerror(errno)); while (waitpid(pid, &status, 0) == -1) if (errno != EINTR) fatal("Couldn't wait for child: %s", strerror(errno)); ssh_signal(SIGCHLD, osighand); if (!WIFEXITED(status)) return (1); return (WEXITSTATUS(status)); } void 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; if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { debug3("no authentication agent, not adding key"); return; } if (options.add_keys_to_agent == 2 && !ask_permission("Add key %s (%s) to agent?", authfile, comment)) { debug3("user denied adding this key"); close(auth_sock); return; } if (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, NULL, 0)) == 0) debug("identity added to agent: %s", authfile); else debug("could not add identity to agent: %s (%d)", authfile, r); close(auth_sock); } diff --git a/crypto/openssh/sshconnect.h b/crypto/openssh/sshconnect.h index f518a9a1302f..79d35cc195df 100644 --- a/crypto/openssh/sshconnect.h +++ b/crypto/openssh/sshconnect.h @@ -1,94 +1,96 @@ -/* $OpenBSD: sshconnect.h,v 1.46 2020/12/22 00:15:23 djm Exp $ */ +/* $OpenBSD: sshconnect.h,v 1.47 2023/10/12 02:18:18 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ typedef struct Sensitive Sensitive; struct Sensitive { struct sshkey **keys; 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; + char *jmphost; }; 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 + "u", conn_info->locuser, \ + "j", conn_info->jmphost int ssh_connect(struct ssh *, const char *, const char *, struct addrinfo *, struct sockaddr_storage *, u_short, int, int *, int); void ssh_kill_proxy_command(void); void ssh_login(struct ssh *, Sensitive *, const char *, struct sockaddr *, u_short, struct passwd *, int, const struct ssh_conn_info *); 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, 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(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/crypto/openssh/sshconnect2.c b/crypto/openssh/sshconnect2.c index 6401e304a977..fab1e36bea03 100644 --- a/crypto/openssh/sshconnect2.c +++ b/crypto/openssh/sshconnect2.c @@ -1,2349 +1,2374 @@ -/* $OpenBSD: sshconnect2.c,v 1.367 2023/08/01 08:15:04 dtucker Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.371 2023/12/18 14:45:49 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) #include #endif #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "sshbuf.h" #include "packet.h" #include "compat.h" #include "cipher.h" #include "sshkey.h" #include "kex.h" #include "sshconnect.h" #include "authfile.h" #include "dh.h" #include "authfd.h" #include "log.h" #include "misc.h" #include "readconf.h" #include "match.h" #include "dispatch.h" #include "canohost.h" #include "msg.h" #include "pathnames.h" #include "uidswap.h" #include "hostfile.h" #include "ssherr.h" #include "utf8.h" #include "ssh-sk.h" #include "sk-api.h" #ifdef GSSAPI #include "ssh-gss.h" #endif /* import */ extern char *client_version_string; extern char *server_version_string; extern Options options; /* * SSH2 key exchange */ 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) { int r; if ((r = sshkey_check_rsa_length(hostkey, options.required_rsa_size)) != 0) fatal_r(r, "Bad server host key"); 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 * first_alg(const char *algs) { 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 = NULL; int ktype; u_int i; /* Find all hostkeys for this hostname */ get_hostfile_hostname_ipaddr(host, hostaddr, port, &hostname, NULL); hostkeys = init_hostkeys(); for (i = 0; i < options.num_user_hostfiles; i++) load_hostkeys(hostkeys, hostname, options.user_hostfiles[i], 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); + "ORDER", cinfo, NULL, hostname); } /* * 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; } /* * 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); *first = *last = '\0'; #define ALG_APPEND(to, from) \ do { \ if (*to != '\0') \ strlcat(to, ",", maxlen); \ strlcat(to, from, maxlen); \ } while (0) while ((alg = strsep(&avail, ",")) && *alg != '\0') { if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC) fatal_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); 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_f("prefer hostkeyalgs: %s", first); else debug3_f("no algorithms matched; accept original"); out: free(best); free(first); free(last); free(hostname); free(oavail); free_hostkeys(hostkeys); return ret; } void ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, const struct ssh_conn_info *cinfo) { char *myproposal[PROPOSAL_MAX]; char *s, *all_key, *hkalgs = NULL; int r, use_known_hosts_order = 0; xxx_host = host; xxx_hostaddr = hostaddr; xxx_conn_info = cinfo; if (options.rekey_limit || options.rekey_interval) ssh_packet_set_rekey_limits(ssh, options.rekey_limit, options.rekey_interval); /* * 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_f("kex_names_cat"); if (use_known_hosts_order) hkalgs = order_hostkeyalgs(host, hostaddr, port, cinfo); kex_proposal_populate_entries(ssh, myproposal, s, options.ciphers, options.macs, compression_alg_list(options.compression), hkalgs ? hkalgs : options.hostkeyalgorithms); free(hkalgs); /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) 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; ssh->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_client; ssh->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_client; ssh->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_client; ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif #endif ssh->kex->kex[KEX_C25519_SHA256] = 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 */ free(myproposal[PROPOSAL_KEX_ALGS]); myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(ssh, options.kex_algorithms); if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) fatal_r(r, "kex_prop2buf"); #ifdef DEBUG_KEXDH /* send 1st encrypted/maced/compressed message */ if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || (r = sshpkt_put_cstring(ssh, "markus")) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "send packet"); #endif kex_proposal_free_entries(myproposal); } /* * Authenticate user */ typedef struct cauthctxt Authctxt; typedef struct cauthmethod Authmethod; typedef struct identity Identity; typedef struct idlist Idlist; struct identity { TAILQ_ENTRY(identity) next; int agent_fd; /* >=0 if agent supports key */ struct sshkey *key; /* public/private key */ char *filename; /* comment for agent-only keys */ int tried; int isprivate; /* key points to the private key */ int userprovided; }; TAILQ_HEAD(idlist, identity); struct cauthctxt { const char *server_user; const char *local_user; const char *host; const char *service; struct cauthmethod *method; sig_atomic_t success; char *authlist; #ifdef GSSAPI /* gssapi */ gss_OID_set gss_supported_mechs; u_int mech_tried; #endif /* pubkey */ struct idlist keys; int agent_fd; /* hostbased */ Sensitive *sensitive; char *oktypes, *ktypes; const char *active_ktype; /* kbd-interactive */ int info_req_seen; int attempt_kbdint; /* password */ int attempt_passwd; /* generic */ void *methoddata; }; struct cauthmethod { char *name; /* string to compare against server's list */ int (*userauth)(struct ssh *ssh); void (*cleanup)(struct ssh *ssh); int *enabled; /* flag in option struct that enables method */ int *batch_flag; /* flag in option struct that disables method */ }; static int input_userauth_service_accept(int, u_int32_t, struct ssh *); static int input_userauth_success(int, u_int32_t, struct ssh *); static int input_userauth_failure(int, u_int32_t, struct ssh *); static int input_userauth_banner(int, u_int32_t, struct ssh *); static int input_userauth_error(int, u_int32_t, struct ssh *); static int input_userauth_info_req(int, u_int32_t, struct ssh *); static int input_userauth_pk_ok(int, u_int32_t, struct ssh *); static int input_userauth_passwd_changereq(int, u_int32_t, struct ssh *); static int userauth_none(struct ssh *); static int userauth_pubkey(struct ssh *); static int userauth_passwd(struct ssh *); static int userauth_kbdint(struct ssh *); static int userauth_hostbased(struct ssh *); #ifdef GSSAPI static int userauth_gssapi(struct ssh *); static void userauth_gssapi_cleanup(struct ssh *); static int input_gssapi_response(int type, u_int32_t, struct ssh *); static int input_gssapi_token(int type, u_int32_t, struct ssh *); static int input_gssapi_error(int, u_int32_t, struct ssh *); static int input_gssapi_errtok(int, u_int32_t, struct ssh *); #endif void userauth(struct ssh *, char *); static void pubkey_cleanup(struct ssh *); static int sign_and_send_pubkey(struct ssh *ssh, Identity *); static void pubkey_prepare(struct ssh *, Authctxt *); static void pubkey_reset(Authctxt *); static struct sshkey *load_identity_file(Identity *); static Authmethod *authmethod_get(char *authlist); static Authmethod *authmethod_lookup(const char *name); static char *authmethods_get(void); Authmethod authmethods[] = { #ifdef GSSAPI {"gssapi-with-mic", userauth_gssapi, userauth_gssapi_cleanup, &options.gss_authentication, NULL}, #endif {"hostbased", userauth_hostbased, NULL, &options.hostbased_authentication, NULL}, {"publickey", userauth_pubkey, NULL, &options.pubkey_authentication, NULL}, {"keyboard-interactive", userauth_kbdint, NULL, &options.kbd_interactive_authentication, &options.batch_mode}, {"password", userauth_passwd, NULL, &options.password_authentication, &options.batch_mode}, {"none", userauth_none, NULL, NULL, NULL}, {NULL, NULL, NULL, NULL, NULL} }; void ssh_userauth2(struct ssh *ssh, const char *local_user, const char *server_user, char *host, Sensitive *sensitive) { Authctxt authctxt; int r; if (options.preferred_authentications == NULL) options.preferred_authentications = authmethods_get(); /* setup authentication context */ memset(&authctxt, 0, sizeof(authctxt)); authctxt.server_user = server_user; authctxt.local_user = local_user; authctxt.host = host; authctxt.service = "ssh-connection"; /* service name */ authctxt.success = 0; authctxt.method = authmethod_lookup("none"); authctxt.authlist = NULL; authctxt.methoddata = NULL; authctxt.sensitive = sensitive; authctxt.active_ktype = authctxt.oktypes = authctxt.ktypes = NULL; authctxt.info_req_seen = 0; authctxt.attempt_kbdint = 0; authctxt.attempt_passwd = 0; #if GSSAPI authctxt.gss_supported_mechs = NULL; authctxt.mech_tried = 0; #endif authctxt.agent_fd = -1; - pubkey_prepare(ssh, &authctxt); - if (authctxt.method == NULL) { + if (authctxt.method == NULL) 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_fr(r, "send packet"); ssh->authctxt = &authctxt; ssh_dispatch_init(ssh, &input_userauth_error); ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, kex_input_ext_info); ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept); ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt.success); /* loop until success */ pubkey_cleanup(ssh); +#ifdef GSSAPI + if (authctxt.gss_supported_mechs != NULL) { + u_int ms; + + gss_release_oid_set(&ms, &authctxt.gss_supported_mechs); + authctxt.gss_supported_mechs = NULL; + } +#endif ssh->authctxt = NULL; ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); if (!authctxt.success) fatal("Authentication failed."); if (ssh_packet_connection_is_on_socket(ssh)) { verbose("Authenticated to %s ([%s]:%d) using \"%s\".", host, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), authctxt.method->name); } else { verbose("Authenticated to %s (via proxy) using \"%s\".", host, authctxt.method->name); } } static int input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh) { int r; if (ssh_packet_remaining(ssh) > 0) { char *reply; if ((r = sshpkt_get_cstring(ssh, &reply, NULL)) != 0) goto out; debug2("service_accept: %s", reply); free(reply); } else { debug2("buggy server: service_accept w/o service"); } if ((r = sshpkt_get_end(ssh)) != 0) goto out; debug("SSH2_MSG_SERVICE_ACCEPT received"); /* initial userauth request */ userauth_none(ssh); - ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_error); + /* accept EXT_INFO at any time during userauth */ + ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, ssh->kex->ext_info_s ? + &kex_input_ext_info : &input_userauth_error); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner); r = 0; out: return r; } void userauth(struct ssh *ssh, char *authlist) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; if (authctxt->method != NULL && authctxt->method->cleanup != NULL) authctxt->method->cleanup(ssh); free(authctxt->methoddata); authctxt->methoddata = NULL; if (authlist == NULL) { authlist = authctxt->authlist; } else { free(authctxt->authlist); authctxt->authlist = authlist; } for (;;) { Authmethod *method = authmethod_get(authlist); if (method == NULL) fatal("%s@%s: Permission denied (%s).", authctxt->server_user, authctxt->host, authlist); authctxt->method = method; /* reset the per method handler */ ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_PER_METHOD_MIN, SSH2_MSG_USERAUTH_PER_METHOD_MAX, NULL); /* and try new method */ if (method->userauth(ssh) != 0) { debug2("we sent a %s packet, wait for reply", method->name); break; } else { debug2("we did not send a packet, disable method"); method->enabled = NULL; } } } static int input_userauth_error(int type, u_int32_t seq, struct ssh *ssh) { fatal_f("bad message during authentication: type %d", type); return 0; } static int input_userauth_banner(int type, u_int32_t seq, struct ssh *ssh) { char *msg = NULL; size_t len; int r; debug3_f("entering"); if ((r = sshpkt_get_cstring(ssh, &msg, &len)) != 0 || (r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0) goto out; if (len > 0 && options.log_level >= SYSLOG_LEVEL_INFO) fmprintf(stderr, "%s", msg); r = 0; out: free(msg); return r; } static int input_userauth_success(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; if (authctxt == NULL) fatal_f("no authentication context"); free(authctxt->authlist); authctxt->authlist = NULL; if (authctxt->method != NULL && authctxt->method->cleanup != NULL) authctxt->method->cleanup(ssh); free(authctxt->methoddata); authctxt->methoddata = NULL; authctxt->success = 1; /* break out */ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, dispatch_protocol_error); return 0; } #if 0 static int input_userauth_success_unexpected(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; if (authctxt == NULL) fatal_f("no authentication context"); fatal("Unexpected authentication success during %s.", authctxt->method->name); return 0; } #endif static int input_userauth_failure(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; char *authlist = NULL; u_char partial; if (authctxt == NULL) fatal("input_userauth_failure: no authentication context"); if (sshpkt_get_cstring(ssh, &authlist, NULL) != 0 || sshpkt_get_u8(ssh, &partial) != 0 || sshpkt_get_end(ssh) != 0) goto out; if (partial != 0) { verbose("Authenticated using \"%s\" with partial success.", authctxt->method->name); /* reset state */ pubkey_reset(authctxt); } debug("Authentications that can continue: %s", authlist); userauth(ssh, authlist); authlist = NULL; out: free(authlist); return 0; } /* * Format an identity for logging including filename, key type, fingerprint * and location (agent, etc.). Caller must free. */ static char * format_identity(Identity *id) { char *fp = NULL, *ret = NULL; 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" : "", note, id->agent_fd != -1 ? " agent" : ""); free(fp); return ret; } static int input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; struct sshkey *key = NULL; Identity *id = NULL; int pktype, found = 0, sent = 0; size_t blen; char *pkalg = NULL, *fp = NULL, *ident = NULL; u_char *pkblob = NULL; int r; if (authctxt == NULL) fatal("input_userauth_pk_ok: no authentication context"); if ((r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 || (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto done; if ((pktype = sshkey_type_from_name(pkalg)) == KEY_UNSPEC) { debug_f("server sent unknown pkalg %s", pkalg); goto done; } if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { debug_r(r, "no key from blob. pkalg %s", pkalg); goto done; } if (key->type != pktype) { error("input_userauth_pk_ok: type mismatch " "for decoded key (received %d, expected %d)", key->type, pktype); goto done; } /* * search keys in the reverse order, because last candidate has been * moved to the end of the queue. this also avoids confusion by * duplicate keys */ TAILQ_FOREACH_REVERSE(id, &authctxt->keys, idlist, next) { if (sshkey_equal(key, id->key)) { found = 1; break; } } if (!found || id == NULL) { fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); error_f("server replied with unknown key: %s %s", sshkey_type(key), fp == NULL ? "" : fp); goto done; } ident = format_identity(id); debug("Server accepts key: %s", ident); sent = sign_and_send_pubkey(ssh, id); r = 0; done: sshkey_free(key); free(ident); free(fp); free(pkalg); free(pkblob); /* try another method if we did not send a packet */ if (r == 0 && sent == 0) userauth(ssh, NULL); return r; } #ifdef GSSAPI static int userauth_gssapi(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; Gssctxt *gssctxt = NULL; OM_uint32 min; int r, ok = 0; gss_OID mech = NULL; /* Try one GSSAPI method at a time, rather than sending them all at * once. */ if (authctxt->gss_supported_mechs == NULL) gss_indicate_mechs(&min, &authctxt->gss_supported_mechs); /* Check to see whether the mechanism is usable before we offer it */ while (authctxt->mech_tried < authctxt->gss_supported_mechs->count && !ok) { mech = &authctxt->gss_supported_mechs-> elements[authctxt->mech_tried]; /* My DER encoding requires length<128 */ if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt, mech, authctxt->host)) { ok = 1; /* Mechanism works */ } else { authctxt->mech_tried++; } } if (!ok || mech == NULL) return 0; authctxt->methoddata=(void *)gssctxt; if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_put_u32(ssh, 1)) != 0 || (r = sshpkt_put_u32(ssh, (mech->length) + 2)) != 0 || (r = sshpkt_put_u8(ssh, SSH_GSS_OIDTYPE)) != 0 || (r = sshpkt_put_u8(ssh, mech->length)) != 0 || (r = sshpkt_put(ssh, mech->elements, mech->length)) != 0 || (r = sshpkt_send(ssh)) != 0) 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); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); authctxt->mech_tried++; /* Move along to next candidate */ return 1; } static void userauth_gssapi_cleanup(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; Gssctxt *gssctxt = (Gssctxt *)authctxt->methoddata; ssh_gssapi_delete_ctx(&gssctxt); authctxt->methoddata = NULL; - - free(authctxt->gss_supported_mechs); - authctxt->gss_supported_mechs = NULL; } static OM_uint32 process_gssapi_token(struct ssh *ssh, gss_buffer_t recv_tok) { Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt = authctxt->methoddata; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; gss_buffer_desc gssbuf; OM_uint32 status, ms, flags; int r; status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds, recv_tok, &send_tok, &flags); if (send_tok.length > 0) { u_char type = GSS_ERROR(status) ? SSH2_MSG_USERAUTH_GSSAPI_ERRTOK : SSH2_MSG_USERAUTH_GSSAPI_TOKEN; if ((r = sshpkt_start(ssh, type)) != 0 || (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send %u packet", type); gss_release_buffer(&ms, &send_tok); } if (status == GSS_S_COMPLETE) { /* send either complete or MIC, depending on mechanism */ if (!(flags & GSS_C_INTEG_FLAG)) { if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send completion"); } else { struct sshbuf *b; if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service, "gssapi-with-mic", ssh->kex->session_id); if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) fatal_f("sshbuf_mutable_ptr failed"); gssbuf.length = sshbuf_len(b); status = ssh_gssapi_sign(gssctxt, &gssbuf, &mic); if (!GSS_ERROR(status)) { if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_GSSAPI_MIC)) != 0 || (r = sshpkt_put_string(ssh, mic.value, mic.length)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send MIC"); } sshbuf_free(b); gss_release_buffer(&ms, &mic); } } return status; } static int input_gssapi_response(int type, u_int32_t plen, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; size_t oidlen; u_char *oidv = NULL; int r; if (authctxt == NULL) fatal("input_gssapi_response: no authentication context"); gssctxt = authctxt->methoddata; /* Setup our OID */ if ((r = sshpkt_get_string(ssh, &oidv, &oidlen)) != 0) goto done; if (oidlen <= 2 || oidv[0] != SSH_GSS_OIDTYPE || oidv[1] != oidlen - 2) { debug("Badly encoded mechanism OID received"); userauth(ssh, NULL); goto ok; } if (!ssh_gssapi_check_oid(gssctxt, oidv + 2, oidlen - 2)) fatal("Server returned different OID than expected"); if ((r = sshpkt_get_end(ssh)) != 0) goto done; if (GSS_ERROR(process_gssapi_token(ssh, GSS_C_NO_BUFFER))) { /* Start again with next method on list */ debug("Trying to start again"); userauth(ssh, NULL); goto ok; } ok: r = 0; done: free(oidv); return r; } static int input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; gss_buffer_desc recv_tok; u_char *p = NULL; size_t len; OM_uint32 status; int r; if (authctxt == NULL) fatal("input_gssapi_response: no authentication context"); if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; recv_tok.value = p; recv_tok.length = len; status = process_gssapi_token(ssh, &recv_tok); /* Start again with the next method in the list */ if (GSS_ERROR(status)) { userauth(ssh, NULL); /* ok */ } r = 0; out: free(p); return r; } static int input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; gss_buffer_desc recv_tok; OM_uint32 ms; u_char *p = NULL; size_t len; int r; if (authctxt == NULL) fatal("input_gssapi_response: no authentication context"); gssctxt = authctxt->methoddata; if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || (r = sshpkt_get_end(ssh)) != 0) { free(p); return r; } /* Stick it into GSSAPI and see what it says */ recv_tok.value = p; recv_tok.length = len; (void)ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds, &recv_tok, &send_tok, NULL); free(p); gss_release_buffer(&ms, &send_tok); /* Server will be returning a failed packet after this one */ return 0; } static int input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) { char *msg = NULL; char *lang = NULL; int r; if ((r = sshpkt_get_u32(ssh, NULL)) != 0 || /* maj */ (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* min */ (r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0) goto out; r = sshpkt_get_end(ssh); debug("Server GSSAPI Error:\n%s", msg); out: free(msg); free(lang); return r; } #endif /* GSSAPI */ static int userauth_none(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; int r; /* initial userauth request */ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); return 1; } static int userauth_passwd(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; char *password, *prompt = NULL; const char *host = options.host_key_alias ? options.host_key_alias : authctxt->host; int r; if (authctxt->attempt_passwd++ >= options.number_of_password_prompts) return 0; if (authctxt->attempt_passwd != 1) error("Permission denied, please try again."); xasprintf(&prompt, "%s@%s's password: ", authctxt->server_user, host); password = read_passphrase(prompt, 0); if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_put_u8(ssh, 0)) != 0 || (r = sshpkt_put_cstring(ssh, password)) != 0 || (r = sshpkt_add_padding(ssh, 64)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); free(prompt); if (password != NULL) freezero(password, strlen(password)); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, &input_userauth_passwd_changereq); return 1; } /* * parse PASSWD_CHANGEREQ, prompt user and send SSH2_MSG_USERAUTH_REQUEST */ static int input_userauth_passwd_changereq(int type, u_int32_t seqnr, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; char *info = NULL, *lang = NULL, *password = NULL, *retype = NULL; char prompt[256]; const char *host; int r; debug2("input_userauth_passwd_changereq"); if (authctxt == NULL) fatal("input_userauth_passwd_changereq: " "no authentication context"); host = options.host_key_alias ? options.host_key_alias : authctxt->host; if ((r = sshpkt_get_cstring(ssh, &info, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0) goto out; if (strlen(info) > 0) logit("%s", info); if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_put_u8(ssh, 1)) != 0) /* additional info */ goto out; snprintf(prompt, sizeof(prompt), "Enter %.30s@%.128s's old password: ", authctxt->server_user, host); password = read_passphrase(prompt, 0); if ((r = sshpkt_put_cstring(ssh, password)) != 0) goto out; freezero(password, strlen(password)); password = NULL; while (password == NULL) { snprintf(prompt, sizeof(prompt), "Enter %.30s@%.128s's new password: ", authctxt->server_user, host); password = read_passphrase(prompt, RP_ALLOW_EOF); if (password == NULL) { /* bail out */ r = 0; goto out; } snprintf(prompt, sizeof(prompt), "Retype %.30s@%.128s's new password: ", authctxt->server_user, host); retype = read_passphrase(prompt, 0); if (strcmp(password, retype) != 0) { freezero(password, strlen(password)); logit("Mismatch; try again, EOF to quit."); password = NULL; } freezero(retype, strlen(retype)); } if ((r = sshpkt_put_cstring(ssh, password)) != 0 || (r = sshpkt_add_padding(ssh, 64)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, &input_userauth_passwd_changereq); r = 0; out: if (password) freezero(password, strlen(password)); free(info); free(lang); return r; } /* * Select an algorithm for publickey signatures. * Returns algorithm (caller must free) or NULL if no mutual algorithm found. * * Call with ssh==NULL to ignore server-sig-algs extension list and * only attempt with the key's base signature type. */ static char * key_sig_algorithm(struct ssh *ssh, const struct sshkey *key) { char *allowed, *oallowed, *cp, *tmp, *alg = NULL; const char *server_sig_algs; /* * The signature algorithm will only differ from the key algorithm * for RSA keys/certs and when the server advertises support for * newer (SHA2) algorithms. */ if (ssh == NULL || ssh->kex->server_sig_algs == NULL || (key->type != KEY_RSA && key->type != KEY_RSA_CERT) || (key->type == KEY_RSA_CERT && (ssh->compat & SSH_BUG_SIGTYPE))) { /* Filter base key signature alg against our configuration */ return match_list(sshkey_ssh_name(key), options.pubkey_accepted_algos, NULL); } /* * Workaround OpenSSH 7.4 bug: this version supports RSA/SHA-2 but * fails to advertise it via SSH2_MSG_EXT_INFO. */ server_sig_algs = ssh->kex->server_sig_algs; if (key->type == KEY_RSA && (ssh->compat & SSH_BUG_SIGTYPE74)) server_sig_algs = "rsa-sha2-256,rsa-sha2-512"; /* * For RSA keys/certs, since these might have a different sig 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_accepted_algos); while ((cp = strsep(&allowed, ",")) != NULL) { if (sshkey_type_from_name(cp) != key->type) continue; tmp = match_list(sshkey_sigalg_by_name(cp), server_sig_algs, NULL); if (tmp != NULL) alg = xstrdup(cp); free(tmp); if (alg != NULL) break; } free(oallowed); return alg; } static int identity_sign(struct identity *id, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, u_int compat, const char *alg) { struct sshkey *sign_key = NULL, *prv = NULL; int is_agent = 0, 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) { return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp, data, datalen, alg, compat); } /* * We have already loaded the private key or the private key is * stored in external hardware. */ if (id->key != NULL && (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))) { sign_key = id->key; is_agent = 1; } 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; } retry_pin: /* Prompt for touch for non-agent FIDO keys that request UP */ if (!is_agent && sshkey_is_sk(sign_key) && (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 (!retried && pin == NULL && !is_agent && sshkey_is_sk(sign_key) && r == SSH_ERR_KEY_WRONG_PASSPHRASE) { notify_complete(notifier, NULL); notifier = NULL; xasprintf(&prompt, "Enter PIN for %s key %s: ", sshkey_type(sign_key), id->filename); pin = read_passphrase(prompt, 0); retried = 1; goto retry_pin; } goto out; } /* * 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; } /* 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; } static int id_filename_matches(Identity *id, Identity *private_id) { static const char * const suffixes[] = { ".pub", "-cert.pub", NULL }; size_t len = strlen(id->filename), plen = strlen(private_id->filename); size_t i, slen; if (strcmp(id->filename, private_id->filename) == 0) return 1; for (i = 0; suffixes[i]; i++) { slen = strlen(suffixes[i]); if (len > slen && plen == len - slen && strcmp(id->filename + (len - slen), suffixes[i]) == 0 && memcmp(id->filename, private_id->filename, plen) == 0) return 1; } return 0; } static int sign_and_send_pubkey(struct ssh *ssh, Identity *id) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; struct sshbuf *b = NULL; Identity *private_id, *sign_id = NULL; u_char *signature = NULL; size_t slen = 0, skip = 0; int r, fallback_sigtype, sent = 0; char *alg = NULL, *fp = NULL; const char *loc = "", *method = "publickey"; int hostbound = 0; /* prefer host-bound pubkey signatures if supported by server */ if ((ssh->kex->flags & KEX_HAS_PUBKEY_HOSTBOUND) != 0 && (options.pubkey_authentication & SSH_PUBKEY_AUTH_HBOUND) != 0) { hostbound = 1; method = "publickey-hostbound-v00@openssh.com"; } if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) return 0; debug3_f("using %s with %s %s", method, sshkey_type(id->key), fp); /* * If the key is an certificate, try to find a matching private key * and use it to complete the signature. * If no such private key exists, fall back to trying the certificate * key itself in case it has a private half already loaded. * This will try to set sign_id to the private key that will perform * the signature. */ if (sshkey_is_cert(id->key)) { TAILQ_FOREACH(private_id, &authctxt->keys, next) { if (sshkey_equal_public(id->key, private_id->key) && id->key->type != private_id->key->type) { sign_id = private_id; break; } } /* * Exact key matches are preferred, but also allow * filename matches for non-PKCS#11/agent keys that * didn't load public keys. This supports the case * of keeping just a private key file and public * certificate on disk. */ if (sign_id == NULL && !id->isprivate && id->agent_fd == -1 && (id->key->flags & SSHKEY_FLAG_EXT) == 0) { TAILQ_FOREACH(private_id, &authctxt->keys, next) { if (private_id->key == NULL && id_filename_matches(id, private_id)) { sign_id = private_id; break; } } } if (sign_id != NULL) { debug2_f("using private key \"%s\"%s for " "certificate", sign_id->filename, sign_id->agent_fd != -1 ? " from agent" : ""); } else { debug_f("no separate private key for certificate " "\"%s\"", id->filename); } } /* * If the above didn't select another identity to do the signing * then default to the one we started with. */ if (sign_id == NULL) sign_id = id; /* assemble and sign data */ for (fallback_sigtype = 0; fallback_sigtype <= 1; fallback_sigtype++) { free(alg); slen = 0; signature = NULL; if ((alg = key_sig_algorithm(fallback_sigtype ? NULL : ssh, id->key)) == NULL) { error_f("no mutual signature supported"); goto out; } debug3_f("signing using %s %s", alg, fp); sshbuf_free(b); if ((b = sshbuf_new()) == NULL) 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_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 || (r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 || (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || (r = sshbuf_put_cstring(b, method)) != 0 || (r = sshbuf_put_u8(b, 1)) != 0 || (r = sshbuf_put_cstring(b, alg)) != 0 || (r = sshkey_puts(id->key, b)) != 0) { fatal_fr(r, "assemble signed data"); } if (hostbound) { if (ssh->kex->initial_hostkey == NULL) { fatal_f("internal error: initial hostkey " "not recorded"); } if ((r = sshkey_puts(ssh->kex->initial_hostkey, b)) != 0) fatal_fr(r, "assemble %s hostkey", method); } /* generate signature */ r = identity_sign(sign_id, &signature, &slen, sshbuf_ptr(b), sshbuf_len(b), ssh->compat, alg); if (r == 0) break; else if (r == SSH_ERR_KEY_NOT_FOUND) goto out; /* soft failure */ else if (r == SSH_ERR_SIGN_ALG_UNSUPPORTED && !fallback_sigtype) { if (sign_id->agent_fd != -1) loc = "agent "; else if ((sign_id->key->flags & SSHKEY_FLAG_EXT) != 0) loc = "token "; logit("%skey %s %s returned incorrect signature type", loc, sshkey_type(id->key), fp); continue; } error_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_f("no signature"); /* append signature */ if ((r = sshbuf_put_string(b, signature, slen)) != 0) 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_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_fr(r, "enqueue request"); /* success */ sent = 1; out: free(fp); free(alg); sshbuf_free(b); freezero(signature, slen); return sent; } static int send_pubkey_test(struct ssh *ssh, Identity *id) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; u_char *blob = NULL; char *alg = NULL; size_t bloblen; u_int have_sig = 0; int sent = 0, r; if ((alg = key_sig_algorithm(ssh, id->key)) == NULL) { debug_f("no mutual signature algorithm"); goto out; } if ((r = sshkey_to_blob(id->key, &blob, &bloblen)) != 0) { /* we cannot handle this key */ debug3_f("cannot handle key"); goto out; } /* register callback for USERAUTH_PK_OK message */ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok); if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_put_u8(ssh, have_sig)) != 0 || (r = sshpkt_put_cstring(ssh, alg)) != 0 || (r = sshpkt_put_string(ssh, blob, bloblen)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); sent = 1; out: free(alg); free(blob); return sent; } static struct sshkey * load_identity_file(Identity *id) { struct sshkey *private = NULL; char prompt[300], *passphrase, *comment; int r, quit = 0, i; struct stat st; if (stat(id->filename, &st) == -1) { 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, "Enter passphrase for key '%.100s': ", id->filename); for (i = 0; i <= options.number_of_password_prompts; i++) { if (i == 0) passphrase = ""; else { passphrase = read_passphrase(prompt, 0); if (*passphrase == '\0') { debug2("no passphrase given, try next key"); free(passphrase); break; } } switch ((r = sshkey_load_private_type(KEY_UNSPEC, id->filename, passphrase, &private, &comment))) { case 0: break; case SSH_ERR_KEY_WRONG_PASSPHRASE: if (options.batch_mode) { quit = 1; break; } if (i != 0) debug2("bad passphrase given, try again..."); break; case SSH_ERR_SYSTEM_ERROR: if (errno == ENOENT) { debug2_r(r, "Load key \"%s\"", id->filename); quit = 1; break; } /* FALLTHROUGH */ default: 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 && (r = sshkey_check_rsa_length(private, options.required_rsa_size)) != 0) { debug_fr(r, "Skipping key %s", 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, passphrase); if (i > 0) freezero(passphrase, strlen(passphrase)); free(comment); if (private != NULL || quit) break; } return private; } static int key_type_allowed_by_config(struct sshkey *key) { if (match_pattern_list(sshkey_ssh_name(key), options.pubkey_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_accepted_algos, 0) == 1) return 1; if (match_pattern_list("rsa-sha2-256", 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_accepted_algos, 0) == 1) return 1; if (match_pattern_list("rsa-sha2-256-cert-v01@openssh.com", options.pubkey_accepted_algos, 0) == 1) return 1; break; } return 0; } /* obtain a list of keys from the agent */ static int get_agent_identities(struct ssh *ssh, int *agent_fdp, struct ssh_identitylist **idlistp) { int r, agent_fd; struct ssh_identitylist *idlist; if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) { if (r != SSH_ERR_AGENT_NOT_PRESENT) debug_fr(r, "ssh_get_authentication_socket"); return r; } if ((r = ssh_agent_bind_hostkey(agent_fd, ssh->kex->initial_hostkey, ssh->kex->session_id, ssh->kex->initial_sig, 0)) == 0) debug_f("bound agent to hostkey"); else debug2_fr(r, "ssh_agent_bind_hostkey"); if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) { debug_fr(r, "ssh_fetch_identitylist"); close(agent_fd); return r; } /* success */ *agent_fdp = agent_fd; *idlistp = idlist; debug_f("agent returned %zu keys", idlist->nkeys); return 0; } /* * try keys in the following order: * 1. certificates listed in the config file * 2. other input certificates * 3. agent keys that are found in the config file * 4. other agent keys * 5. keys that are only listed in the config file */ static void pubkey_prepare(struct ssh *ssh, Authctxt *authctxt) { struct identity *id, *id2, *tmp; struct idlist agent, files, *preferred; struct sshkey *key; - int agent_fd = -1, i, r, found; + int disallowed, agent_fd = -1, i, r, found; size_t j; struct ssh_identitylist *idlist; - char *ident; + char *cp, *ident; TAILQ_INIT(&agent); /* keys from the agent */ TAILQ_INIT(&files); /* keys from the config file */ preferred = &authctxt->keys; TAILQ_INIT(preferred); /* preferred order of keys */ /* list of keys stored in the filesystem and PKCS#11 */ for (i = 0; i < options.num_identity_files; i++) { key = options.identity_keys[i]; if (key && key->cert && key->cert->type != SSH2_CERT_TYPE_USER) { 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; id->key = key; id->filename = xstrdup(options.identity_files[i]); id->userprovided = options.identity_file_userprovided[i]; TAILQ_INSERT_TAIL(&files, id, next); } /* list of certificates specified by user */ for (i = 0; i < options.num_certificate_files; i++) { key = options.certificates[i]; if (!sshkey_is_cert(key) || key->cert == NULL || key->cert->type != SSH2_CERT_TYPE_USER) { 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; id->filename = xstrdup(options.certificate_files[i]); id->userprovided = options.certificate_file_userprovided[i]; TAILQ_INSERT_TAIL(preferred, id, next); } /* list of keys supported by the agent */ if ((r = get_agent_identities(ssh, &agent_fd, &idlist)) == 0) { for (j = 0; j < idlist->nkeys; j++) { if ((r = sshkey_check_rsa_length(idlist->keys[j], options.required_rsa_size)) != 0) { debug_fr(r, "ignoring %s agent key", sshkey_ssh_name(idlist->keys[j])); continue; } found = 0; TAILQ_FOREACH(id, &files, next) { /* * agent keys from the config file are * preferred */ if (sshkey_equal(idlist->keys[j], id->key)) { TAILQ_REMOVE(&files, id, next); TAILQ_INSERT_TAIL(preferred, id, next); id->agent_fd = agent_fd; found = 1; break; } } if (!found && !options.identities_only) { id = xcalloc(1, sizeof(*id)); /* XXX "steals" key/comment from idlist */ id->key = idlist->keys[j]; id->filename = idlist->comments[j]; idlist->keys[j] = NULL; idlist->comments[j] = NULL; id->agent_fd = agent_fd; TAILQ_INSERT_TAIL(&agent, id, next); } } ssh_free_identitylist(idlist); /* append remaining agent keys */ TAILQ_CONCAT(preferred, &agent, next); authctxt->agent_fd = agent_fd; } /* Prefer PKCS11 keys that are explicitly listed */ TAILQ_FOREACH_SAFE(id, &files, next, tmp) { if (id->key == NULL || (id->key->flags & SSHKEY_FLAG_EXT) == 0) continue; found = 0; TAILQ_FOREACH(id2, &files, next) { if (id2->key == NULL || (id2->key->flags & SSHKEY_FLAG_EXT) != 0) continue; if (sshkey_equal(id->key, id2->key)) { TAILQ_REMOVE(&files, id, next); TAILQ_INSERT_TAIL(preferred, id, next); found = 1; break; } } /* If IdentitiesOnly set and key not found then don't use it */ if (!found && options.identities_only) { TAILQ_REMOVE(&files, id, next); freezero(id, sizeof(*id)); } } /* append remaining keys from the config file */ 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 - " - "corresponding algo not in PubkeyAcceptedAlgorithms", - sshkey_ssh_name(id->key), id->filename); - TAILQ_REMOVE(preferred, id, next); - sshkey_free(id->key); - free(id->filename); - memset(id, 0, sizeof(*id)); + disallowed = 0; + cp = NULL; + if (id->key == NULL) continue; + if (!key_type_allowed_by_config(id->key)) { + debug("Skipping %s key %s - corresponding algorithm " + "not in PubkeyAcceptedAlgorithms", + sshkey_ssh_name(id->key), id->filename); + disallowed = 1; + } else if (ssh->kex->server_sig_algs != NULL && + (cp = key_sig_algorithm(ssh, id->key)) == NULL) { + debug("Skipping %s key %s - corresponding algorithm " + "not supported by server", + sshkey_ssh_name(id->key), id->filename); + disallowed = 1; } + free(cp); + if (!disallowed) + continue; + /* remove key */ + TAILQ_REMOVE(preferred, id, next); + sshkey_free(id->key); + free(id->filename); + memset(id, 0, sizeof(*id)); } /* List the keys we plan on using */ TAILQ_FOREACH_SAFE(id, preferred, next, id2) { ident = format_identity(id); debug("Will attempt key: %s", ident); free(ident); } debug2_f("done"); } static void pubkey_cleanup(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; Identity *id; if (authctxt->agent_fd != -1) { ssh_close_authentication_socket(authctxt->agent_fd); authctxt->agent_fd = -1; } for (id = TAILQ_FIRST(&authctxt->keys); id; id = TAILQ_FIRST(&authctxt->keys)) { TAILQ_REMOVE(&authctxt->keys, id, next); sshkey_free(id->key); free(id->filename); free(id); } } static void pubkey_reset(Authctxt *authctxt) { Identity *id; TAILQ_FOREACH(id, &authctxt->keys, next) id->tried = 0; } static int userauth_pubkey(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; Identity *id; int sent = 0; char *ident; + static int prepared; + + if (!prepared) { + pubkey_prepare(ssh, authctxt); + prepared = 1; + } while ((id = TAILQ_FIRST(&authctxt->keys))) { if (id->tried++) return (0); /* move key to the end of the queue */ TAILQ_REMOVE(&authctxt->keys, id, next); TAILQ_INSERT_TAIL(&authctxt->keys, id, next); /* * send a test message if we have the public key. for * encrypted keys we cannot do this and have to load the * private key instead */ if (id->key != NULL) { ident = format_identity(id); debug("Offering public key: %s", ident); free(ident); sent = send_pubkey_test(ssh, id); } else { debug("Trying private key: %s", id->filename); id->key = load_identity_file(id); if (id->key != NULL) { if (id->key != NULL) { id->isprivate = 1; sent = sign_and_send_pubkey(ssh, id); } sshkey_free(id->key); id->key = NULL; id->isprivate = 0; } } if (sent) return (sent); } return (0); } /* * Send userauth request message specifying keyboard-interactive method. */ static int userauth_kbdint(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; int r; if (authctxt->attempt_kbdint++ >= options.number_of_password_prompts) return 0; /* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */ if (authctxt->attempt_kbdint > 1 && !authctxt->info_req_seen) { debug3("userauth_kbdint: disable: no info_req_seen"); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, NULL); return 0; } debug2("userauth_kbdint"); if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_put_cstring(ssh, "")) != 0 || /* lang */ (r = sshpkt_put_cstring(ssh, options.kbd_interactive_devices ? options.kbd_interactive_devices : "")) != 0 || (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req); return 1; } /* * parse INFO_REQUEST, prompt user and send INFO_RESPONSE */ static int input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; char *name = NULL, *inst = NULL, *lang = NULL, *prompt = NULL; char *display_prompt = NULL, *response = NULL; u_char echo = 0; u_int num_prompts, i; int r; debug2_f("entering"); if (authctxt == NULL) fatal_f("no authentication context"); authctxt->info_req_seen = 1; if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &inst, NULL)) != 0 || (r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0) goto out; if (strlen(name) > 0) logit("%s", name); if (strlen(inst) > 0) logit("%s", inst); if ((r = sshpkt_get_u32(ssh, &num_prompts)) != 0) goto out; /* * Begin to build info response packet based on prompts requested. * We commit to providing the correct number of responses, so if * further on we run into a problem that prevents this, we have to * be sure and clean this up and send a correct error response. */ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_INFO_RESPONSE)) != 0 || (r = sshpkt_put_u32(ssh, num_prompts)) != 0) goto out; debug2_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; 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); free(display_prompt); display_prompt = response = prompt = NULL; } /* done with parsing incoming message. */ if ((r = sshpkt_get_end(ssh)) != 0 || (r = sshpkt_add_padding(ssh, 64)) != 0) goto out; r = sshpkt_send(ssh); out: if (response) freezero(response, strlen(response)); free(prompt); free(display_prompt); free(name); free(inst); free(lang); return r; } static int ssh_keysign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen) { struct sshbuf *b; struct stat st; pid_t pid; int r, to[2], from[2], status; int sock = ssh_packet_get_connection_in(ssh); u_char rversion = 0, version = 2; void (*osigchld)(int); *sigp = NULL; *lenp = 0; if (stat(_PATH_SSH_KEY_SIGN, &st) == -1) { error_f("not installed: %s", strerror(errno)); return -1; } if (fflush(stdout) != 0) { error_f("fflush: %s", strerror(errno)); return -1; } if (pipe(to) == -1) { error_f("pipe: %s", strerror(errno)); return -1; } if (pipe(from) == -1) { error_f("pipe: %s", strerror(errno)); return -1; } if ((pid = fork()) == -1) { error_f("fork: %s", strerror(errno)); return -1; } osigchld = ssh_signal(SIGCHLD, SIG_DFL); if (pid == 0) { close(from[0]); if (dup2(from[1], STDOUT_FILENO) == -1) fatal_f("dup2: %s", strerror(errno)); close(to[1]); if (dup2(to[0], STDIN_FILENO) == -1) fatal_f("dup2: %s", strerror(errno)); close(from[1]); close(to[0]); if (dup2(sock, STDERR_FILENO + 1) == -1) fatal_f("dup2: %s", strerror(errno)); sock = STDERR_FILENO + 1; if (fcntl(sock, F_SETFD, 0) == -1) /* keep the socket on exec */ debug3_f("fcntl F_SETFD: %s", strerror(errno)); closefrom(sock + 1); 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_f("exec(%s): %s", _PATH_SSH_KEY_SIGN, strerror(errno)); } close(from[1]); close(to[0]); sock = STDERR_FILENO + 1; if ((b = sshbuf_new()) == NULL) 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_fr(r, "buffer error"); if (ssh_msg_send(to[1], version, b) == -1) 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_f("no reply"); goto fail; } errno = 0; while (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) { error_f("waitpid %ld: %s", (long)pid, strerror(errno)); goto fail; } } if (!WIFEXITED(status)) { error_f("exited abnormally"); goto fail; } if (WEXITSTATUS(status) != 0) { error_f("exited with status %d", WEXITSTATUS(status)); goto fail; } if ((r = sshbuf_get_u8(b, &rversion)) != 0) { error_fr(r, "buffer error"); goto fail; } if (rversion != version) { error_f("bad version"); goto fail; } if ((r = sshbuf_get_string(b, sigp, lenp)) != 0) { error_fr(r, "buffer error"); fail: ssh_signal(SIGCHLD, osigchld); sshbuf_free(b); return -1; } ssh_signal(SIGCHLD, osigchld); sshbuf_free(b); return 0; } static int userauth_hostbased(struct ssh *ssh) { Authctxt *authctxt = (Authctxt *)ssh->authctxt; struct sshkey *private = NULL; struct sshbuf *b = NULL; u_char *sig = NULL, *keyblob = NULL; char *fp = NULL, *chost = NULL, *lname = NULL; size_t siglen = 0, keylen = 0; int i, r, success = 0; if (authctxt->ktypes == NULL) { authctxt->oktypes = xstrdup(options.hostbased_accepted_algos); authctxt->ktypes = authctxt->oktypes; } /* * Work through each listed type pattern in HostbasedAcceptedAlgorithms, * trying each hostkey that matches the type in turn. */ for (;;) { if (authctxt->active_ktype == NULL) authctxt->active_ktype = strsep(&authctxt->ktypes, ","); if (authctxt->active_ktype == NULL || *authctxt->active_ktype == '\0') break; debug3_f("trying key type %s", authctxt->active_ktype); /* check for a useful key */ private = NULL; for (i = 0; i < authctxt->sensitive->nkeys; i++) { if (authctxt->sensitive->keys[i] == NULL || authctxt->sensitive->keys[i]->type == KEY_UNSPEC) continue; if (!sshkey_match_keyname_to_sigalgs( sshkey_ssh_name(authctxt->sensitive->keys[i]), authctxt->active_ktype)) continue; /* we take and free the key */ private = authctxt->sensitive->keys[i]; authctxt->sensitive->keys[i] = NULL; break; } /* Found one */ if (private != NULL) break; /* No more keys of this type; advance */ authctxt->active_ktype = NULL; } if (private == NULL) { free(authctxt->oktypes); authctxt->oktypes = authctxt->ktypes = NULL; authctxt->active_ktype = NULL; debug("No more client hostkeys for hostbased authentication."); goto out; } if ((fp = sshkey_fingerprint(private, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { error_f("sshkey_fingerprint failed"); goto out; } debug_f("trying hostkey %s %s using sigalg %s", sshkey_ssh_name(private), fp, authctxt->active_ktype); /* figure out a name for the client host */ lname = get_local_name(ssh_packet_get_connection_in(ssh)); if (lname == NULL) { error_f("cannot get local ipaddr/name"); goto out; } /* XXX sshbuf_put_stringf? */ xasprintf(&chost, "%s.", lname); debug2_f("chost %s", chost); /* construct data */ if ((b = sshbuf_new()) == NULL) { error_f("sshbuf_new failed"); goto out; } if ((r = sshkey_to_blob(private, &keyblob, &keylen)) != 0) { error_fr(r, "sshkey_to_blob"); goto out; } 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, 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_fr(r, "buffer error"); goto out; } #ifdef DEBUG_PK sshbuf_dump(b, stderr); #endif if ((r = ssh_keysign(ssh, private, &sig, &siglen, sshbuf_ptr(b), sshbuf_len(b))) != 0) { error("sign using hostkey %s %s failed", sshkey_ssh_name(private), fp); goto out; } if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || (r = sshpkt_put_cstring(ssh, 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_fr(r, "packet error"); goto out; } success = 1; out: if (sig != NULL) freezero(sig, siglen); free(keyblob); free(lname); free(fp); free(chost); sshkey_free(private); sshbuf_free(b); return success; } /* find auth method */ /* * given auth method name, if configurable options permit this method fill * in auth_ident field and return true, otherwise return false. */ static int authmethod_is_enabled(Authmethod *method) { if (method == NULL) return 0; /* return false if options indicate this method is disabled */ if (method->enabled == NULL || *method->enabled == 0) return 0; /* return false if batch mode is enabled but method needs interactive mode */ if (method->batch_flag != NULL && *method->batch_flag != 0) return 0; return 1; } static Authmethod * authmethod_lookup(const char *name) { Authmethod *method = NULL; if (name != NULL) for (method = authmethods; method->name != NULL; method++) if (strcmp(name, method->name) == 0) return method; debug2("Unrecognized authentication method name: %s", name ? name : "NULL"); return NULL; } /* XXX internal state */ static Authmethod *current = NULL; static char *supported = NULL; static char *preferred = NULL; /* * Given the authentication method list sent by the server, return the * next method we should try. If the server initially sends a nil list, * use a built-in default list. */ static Authmethod * authmethod_get(char *authlist) { char *name = NULL; u_int next; /* Use a suitable default if we're passed a nil list. */ if (authlist == NULL || strlen(authlist) == 0) authlist = options.preferred_authentications; if (supported == NULL || strcmp(authlist, supported) != 0) { debug3("start over, passed a different list %s", authlist); free(supported); supported = xstrdup(authlist); preferred = options.preferred_authentications; debug3("preferred %s", preferred); current = NULL; } else if (current != NULL && authmethod_is_enabled(current)) return current; for (;;) { if ((name = match_list(preferred, supported, &next)) == NULL) { debug("No more authentication methods to try."); current = NULL; return NULL; } preferred += next; debug3("authmethod_lookup %s", name); debug3("remaining preferred: %s", preferred); if ((current = authmethod_lookup(name)) != NULL && authmethod_is_enabled(current)) { debug3("authmethod_is_enabled %s", name); debug("Next authentication method: %s", name); free(name); return current; } free(name); } } static char * authmethods_get(void) { Authmethod *method = NULL; struct sshbuf *b; char *list; int r; if ((b = sshbuf_new()) == NULL) fatal_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_fr(r, "buffer error"); } } if ((list = sshbuf_dup_string(b)) == NULL) fatal_f("sshbuf_dup_string failed"); sshbuf_free(b); return list; } diff --git a/crypto/openssh/sshd.c b/crypto/openssh/sshd.c index cfdd61ec5747..6bb0b6c129bb 100644 --- a/crypto/openssh/sshd.c +++ b/crypto/openssh/sshd.c @@ -1,2564 +1,2566 @@ -/* $OpenBSD: sshd.c,v 1.600 2023/03/08 04:43:12 guenther Exp $ */ +/* $OpenBSD: sshd.c,v 1.601 2023/12/18 14:45:49 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved * This program is the ssh daemon. It listens for connections from clients, * and performs authentication, executes use commands or shell, and forwards * information to/from the application to the user client over an encrypted * connection. This can also handle forwarding of X11, TCP/IP, and * authentication agent connections. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose. Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * SSH2 implementation: * Privilege Separation: * * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 2002 Niels Provos. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #include #include #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_SYS_TIME_H # include #endif #include "openbsd-compat/sys-tree.h" #include "openbsd-compat/sys-queue.h" #include #include #include #include #ifdef HAVE_PATHS_H #include #endif #include #ifdef HAVE_POLL_H #include #endif #include #include #include #include #include #include #include #include #ifdef WITH_OPENSSL #include #include #include #include "openbsd-compat/openssl-compat.h" #endif #ifdef HAVE_SECUREWARE #include #include #endif #ifdef __FreeBSD__ #include #if defined(GSSAPI) && defined(HAVE_GSSAPI_GSSAPI_H) #include #elif defined(GSSAPI) && defined(HAVE_GSSAPI_H) #include #endif #endif #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" #include "sshpty.h" #include "packet.h" #include "log.h" #include "sshbuf.h" #include "misc.h" #include "match.h" #include "servconf.h" #include "uidswap.h" #include "compat.h" #include "cipher.h" #include "digest.h" #include "sshkey.h" #include "kex.h" #include "authfile.h" #include "pathnames.h" #include "atomicio.h" #include "canohost.h" #include "hostfile.h" #include "auth.h" #include "authfd.h" #include "msg.h" #include "dispatch.h" #include "channels.h" #include "session.h" #include "monitor.h" #ifdef GSSAPI #include "ssh-gss.h" #endif #include "monitor_wrap.h" #include "ssh-sandbox.h" #include "auth-options.h" #include "version.h" #include "ssherr.h" #include "sk-api.h" #include "srclimit.h" #include "dh.h" #include "blacklist_client.h" #ifdef LIBWRAP #include #include #endif /* LIBWRAP */ /* Re-exec fds */ #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) #define REEXEC_CONFIG_PASS_FD (STDERR_FILENO + 3) #define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4) extern char *__progname; /* Server configuration options. */ ServerOptions options; /* Name of the server configuration file. */ char *config_file_name = _PATH_SERVER_CONFIG_FILE; /* * Debug mode flag. This can be set on the command line. If debug * mode is enabled, extra debugging output will be sent to the system * log, the daemon will not go to background, and will exit after processing * the first connection. */ int debug_flag = 0; /* * Indicating that the daemon should only test the configuration and keys. * If test_flag > 1 ("-T" flag), then sshd will also dump the effective * configuration, optionally using connection information provided by the * "-C" flag. */ static int test_flag = 0; /* Flag indicating that the daemon is being started from inetd. */ static int inetd_flag = 0; /* Flag indicating that sshd should not detach and become a daemon. */ static int no_daemon_flag = 0; /* debug goes to stderr unless inetd_flag is set */ static int log_stderr = 0; /* Saved arguments to main(). */ static char **saved_argv; static int saved_argc; /* re-exec */ static int rexeced_flag = 0; static int rexec_flag = 1; static int rexec_argc = 0; static char **rexec_argv; /* * The sockets that the server is listening; this is used in the SIGHUP * signal handler. */ #define MAX_LISTEN_SOCKS 16 static int listen_socks[MAX_LISTEN_SOCKS]; static int num_listen_socks = 0; /* Daemon's agent connection */ int auth_sock = -1; static int have_agent = 0; /* * Any really sensitive data in the application is contained in this * structure. The idea is that this structure could be locked into memory so * that the pages do not get written into swap. However, there are some * problems. The private key contains BIGNUMs, and we do not (in principle) * have access to the internals of them, and locking just the structure is * not very useful. Currently, memory locking is not implemented. */ struct { struct sshkey **host_keys; /* all private host keys */ struct sshkey **host_pubkeys; /* all public host keys */ struct sshkey **host_certificates; /* all public host certificates */ int have_ssh2_key; } sensitive_data; /* This is set to true when a signal is received. */ static volatile sig_atomic_t received_sighup = 0; static volatile sig_atomic_t received_sigterm = 0; /* record remote hostname or ip */ u_int utmp_len = HOST_NAME_MAX+1; /* * startup_pipes/flags are used for tracking children of the listening sshd * process early in their lifespans. This tracking is needed for three things: * * 1) Implementing the MaxStartups limit of concurrent unauthenticated * connections. * 2) Avoiding a race condition for SIGHUP processing, where child processes * may have listen_socks open that could collide with main listener process * after it restarts. * 3) Ensuring that rexec'd sshd processes have received their initial state * from the parent listen process before handling SIGHUP. * * Child processes signal that they have completed closure of the listen_socks * and (if applicable) received their rexec state by sending a char over their * sock. Child processes signal that authentication has completed by closing * the sock (or by exiting). */ static int *startup_pipes = NULL; static int *startup_flags = NULL; /* Indicates child closed listener */ static int startup_pipe = -1; /* in child */ /* variables used for privilege separation */ int use_privsep = -1; struct monitor *pmonitor = NULL; int privsep_is_preauth = 1; static int privsep_chroot = 1; /* global connection state and authentication contexts */ Authctxt *the_authctxt = NULL; struct ssh *the_active_state; /* global key/cert auth options. XXX move to permanent ssh->authctxt? */ struct sshauthopt *auth_opts = NULL; /* sshd_config buffer */ struct sshbuf *cfg; /* Included files from the configuration file */ struct include_list includes = TAILQ_HEAD_INITIALIZER(includes); /* message to be displayed after login */ struct sshbuf *loginmsg; /* Unprivileged user */ struct passwd *privsep_pw = NULL; /* Prototypes for various functions defined later in this file. */ void destroy_sensitive_data(void); void demote_sensitive_data(void); static void do_ssh2_kex(struct ssh *); static char *listener_proctitle; /* * Close all listening sockets */ static void close_listen_socks(void) { int i; for (i = 0; i < num_listen_socks; i++) close(listen_socks[i]); num_listen_socks = 0; } static void close_startup_pipes(void) { int i; if (startup_pipes) for (i = 0; i < options.max_startups; i++) if (startup_pipes[i] != -1) close(startup_pipes[i]); } /* * Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP; * the effect is to reread the configuration file (and to regenerate * the server key). */ static void sighup_handler(int sig) { received_sighup = 1; } /* * Called from the main program after receiving SIGHUP. * Restarts the server. */ static void sighup_restart(void) { logit("Received SIGHUP; restarting."); if (options.pid_file != NULL) unlink(options.pid_file); platform_pre_restart(); close_listen_socks(); close_startup_pipes(); 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)); exit(1); } /* * Generic signal handler for terminating signals in the master daemon. */ static void sigterm_handler(int sig) { received_sigterm = sig; } /* * SIGCHLD handler. This is called whenever a child dies. This will then * reap any zombies left by exited children. */ static void main_sigchld_handler(int sig) { int save_errno = errno; pid_t pid; int status; while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || (pid == -1 && errno == EINTR)) ; errno = save_errno; } /* * Signal handler for the alarm after the login grace period has expired. */ static void grace_alarm_handler(int sig) { /* * Try to kill any processes that we have spawned, E.g. authorized * keys command helpers or privsep children. */ if (getpgid(0) == getpid()) { ssh_signal(SIGTERM, SIG_IGN); kill(0, SIGTERM); } BLACKLIST_NOTIFY(the_active_state, BLACKLIST_AUTH_FAIL, "ssh"); /* Log error and exit. */ sigdie("Timeout before authentication for %s port %d", ssh_remote_ipaddr(the_active_state), ssh_remote_port(the_active_state)); } /* Destroy the host and server keys. They will no longer be needed. */ void destroy_sensitive_data(void) { u_int i; for (i = 0; i < options.num_host_key_files; i++) { if (sensitive_data.host_keys[i]) { sshkey_free(sensitive_data.host_keys[i]); sensitive_data.host_keys[i] = NULL; } if (sensitive_data.host_certificates[i]) { sshkey_free(sensitive_data.host_certificates[i]); sensitive_data.host_certificates[i] = NULL; } } } /* Demote private to public keys for network child */ void demote_sensitive_data(void) { struct sshkey *tmp; u_int i; int r; for (i = 0; i < options.num_host_key_files; i++) { if (sensitive_data.host_keys[i]) { if ((r = sshkey_from_private( sensitive_data.host_keys[i], &tmp)) != 0) fatal_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; } /* Certs do not need demotion */ } } static void reseed_prngs(void) { u_int32_t rnd[256]; #ifdef WITH_OPENSSL RAND_poll(); #endif arc4random_stir(); /* noop on recent arc4random() implementations */ arc4random_buf(rnd, sizeof(rnd)); /* let arc4random notice PID change */ #ifdef WITH_OPENSSL RAND_seed(rnd, sizeof(rnd)); /* give libcrypto a chance to notice the PID change */ if ((RAND_bytes((u_char *)rnd, 1)) != 1) fatal("%s: RAND_bytes failed", __func__); #endif explicit_bzero(rnd, sizeof(rnd)); } static void privsep_preauth_child(void) { gid_t gidset[1]; /* Enable challenge-response authentication for privilege separation */ privsep_challenge_enable(); #ifdef GSSAPI /* Cache supported mechanism OIDs for later use */ ssh_gssapi_prepare_supported_oids(); #endif reseed_prngs(); /* Demote the private keys to public keys. */ demote_sensitive_data(); /* Demote the child */ if (privsep_chroot) { /* Change our root directory */ if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1) fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR, strerror(errno)); if (chdir("/") == -1) fatal("chdir(\"/\"): %s", strerror(errno)); /* Drop our privileges */ debug3("privsep user:group %u:%u", (u_int)privsep_pw->pw_uid, (u_int)privsep_pw->pw_gid); gidset[0] = privsep_pw->pw_gid; if (setgroups(1, gidset) == -1) fatal("setgroups: %.100s", strerror(errno)); permanently_set_uid(privsep_pw); } } static int privsep_preauth(struct ssh *ssh) { int status, r; pid_t pid; struct ssh_sandbox *box = NULL; /* Set up unprivileged child process to deal with network data */ pmonitor = monitor_init(); /* Store a pointer to the kex for later rekeying */ pmonitor->m_pkex = &ssh->kex; if (use_privsep == PRIVSEP_ON) box = ssh_sandbox_init(pmonitor); pid = fork(); if (pid == -1) { fatal("fork of unprivileged child failed"); } else if (pid != 0) { debug2("Network child is on pid %ld", (long)pid); pmonitor->m_pid = pid; if (have_agent) { r = ssh_get_authentication_socket(&auth_sock); if (r != 0) { error_r(r, "Could not get agent socket"); have_agent = 0; } } if (box != NULL) ssh_sandbox_parent_preauth(box, pid); monitor_child_preauth(ssh, pmonitor); /* Wait for the child's exit status */ while (waitpid(pid, &status, 0) == -1) { if (errno == EINTR) continue; pmonitor->m_pid = -1; fatal_f("waitpid: %s", strerror(errno)); } privsep_is_preauth = 0; pmonitor->m_pid = -1; if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) fatal_f("preauth child exited with status %d", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) fatal_f("preauth child terminated by signal %d", WTERMSIG(status)); if (box != NULL) ssh_sandbox_parent_finish(box); return 1; } else { /* child */ close(pmonitor->m_sendfd); close(pmonitor->m_log_recvfd); /* Arrange for logging to be sent to the monitor */ set_log_handler(mm_log_handler, pmonitor); privsep_preauth_child(); setproctitle("%s", "[net]"); if (box != NULL) ssh_sandbox_child(box); return 0; } } static void privsep_postauth(struct ssh *ssh, Authctxt *authctxt) { #ifdef DISABLE_FD_PASSING if (1) { #else if (authctxt->pw->pw_uid == 0) { #endif /* File descriptor passing is broken or root login */ use_privsep = 0; goto skip; } /* New socket pair */ monitor_reinit(pmonitor); pmonitor->m_pid = fork(); if (pmonitor->m_pid == -1) fatal("fork of unprivileged child failed"); else if (pmonitor->m_pid != 0) { verbose("User child is on pid %ld", (long)pmonitor->m_pid); sshbuf_reset(loginmsg); monitor_clear_keystate(ssh, pmonitor); monitor_child_postauth(ssh, pmonitor); /* NEVERREACHED */ exit(0); } /* child */ close(pmonitor->m_sendfd); pmonitor->m_sendfd = -1; /* Demote the private keys to public keys. */ demote_sensitive_data(); reseed_prngs(); /* Drop privileges */ do_setusercontext(authctxt->pw); skip: /* It is safe now to apply the key state */ monitor_apply_keystate(ssh, pmonitor); /* * Tell the packet layer that authentication was successful, since * this information is not part of the key state. */ ssh_packet_set_authenticated(ssh); } static void append_hostkey_type(struct sshbuf *b, const char *s) { int r; if (match_pattern_list(s, options.hostkeyalgorithms, 0) != 1) { debug3_f("%s key not permitted by HostkeyAlgorithms", s); return; } if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) > 0 ? "," : "", s)) != 0) fatal_fr(r, "sshbuf_putf"); } static char * list_hostkey_types(void) { struct sshbuf *b; struct sshkey *key; char *ret; u_int i; if ((b = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); for (i = 0; i < options.num_host_key_files; i++) { key = sensitive_data.host_keys[i]; if (key == NULL) key = sensitive_data.host_pubkeys[i]; if (key == NULL) continue; switch (key->type) { case KEY_RSA: /* for RSA we also support SHA2 signatures */ append_hostkey_type(b, "rsa-sha2-512"); append_hostkey_type(b, "rsa-sha2-256"); /* FALLTHROUGH */ case KEY_DSA: case KEY_ECDSA: case KEY_ED25519: case KEY_ECDSA_SK: case KEY_ED25519_SK: case KEY_XMSS: append_hostkey_type(b, sshkey_ssh_name(key)); break; } /* If the private key has a cert peer, then list that too */ key = sensitive_data.host_certificates[i]; if (key == NULL) continue; switch (key->type) { case KEY_RSA_CERT: /* for RSA we also support SHA2 signatures */ append_hostkey_type(b, "rsa-sha2-512-cert-v01@openssh.com"); append_hostkey_type(b, "rsa-sha2-256-cert-v01@openssh.com"); /* FALLTHROUGH */ case KEY_DSA_CERT: case KEY_ECDSA_CERT: case KEY_ED25519_CERT: case KEY_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_f("sshbuf_dup_string failed"); sshbuf_free(b); debug_f("%s", ret); return ret; } static struct sshkey * get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) { u_int i; struct sshkey *key; for (i = 0; i < options.num_host_key_files; i++) { switch (type) { case KEY_RSA_CERT: case KEY_DSA_CERT: case KEY_ECDSA_CERT: case KEY_ED25519_CERT: case KEY_ECDSA_SK_CERT: case KEY_ED25519_SK_CERT: case KEY_XMSS_CERT: key = sensitive_data.host_certificates[i]; break; default: key = sensitive_data.host_keys[i]; if (key == NULL && !need_private) key = sensitive_data.host_pubkeys[i]; break; } if (key == NULL || key->type != type) 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; } struct sshkey * get_hostkey_public_by_type(int type, int nid, struct ssh *ssh) { return get_hostkey_by_type(type, nid, 0, ssh); } struct sshkey * get_hostkey_private_by_type(int type, int nid, struct ssh *ssh) { return get_hostkey_by_type(type, nid, 1, ssh); } struct sshkey * get_hostkey_by_index(int ind) { if (ind < 0 || (u_int)ind >= options.num_host_key_files) return (NULL); return (sensitive_data.host_keys[ind]); } struct sshkey * get_hostkey_public_by_index(int ind, struct ssh *ssh) { if (ind < 0 || (u_int)ind >= options.num_host_key_files) return (NULL); return (sensitive_data.host_pubkeys[ind]); } int get_hostkey_index(struct sshkey *key, int compare, struct ssh *ssh) { u_int i; for (i = 0; i < options.num_host_key_files; i++) { if (sshkey_is_cert(key)) { if (key == sensitive_data.host_certificates[i] || (compare && sensitive_data.host_certificates[i] && sshkey_equal(key, sensitive_data.host_certificates[i]))) return (i); } else { if (key == sensitive_data.host_keys[i] || (compare && sensitive_data.host_keys[i] && sshkey_equal(key, sensitive_data.host_keys[i]))) return (i); if (key == sensitive_data.host_pubkeys[i] || (compare && sensitive_data.host_pubkeys[i] && sshkey_equal(key, sensitive_data.host_pubkeys[i]))) return (i); } } return (-1); } /* Inform the client of all hostkeys */ static void notify_hostkeys(struct ssh *ssh) { struct sshbuf *buf; struct sshkey *key; u_int i, nkeys; int r; char *fp; /* Some clients cannot cope with the hostkeys message, skip those. */ if (ssh->compat & SSH_BUG_HOSTKEYS) return; if ((buf = sshbuf_new()) == NULL) 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 || sshkey_is_cert(key)) continue; fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT); debug3_f("key %d: %s %s", i, sshkey_ssh_name(key), fp); free(fp); if (nkeys == 0) { /* * Start building the request when we find the * first usable key. */ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || (r = sshpkt_put_cstring(ssh, "hostkeys-00@openssh.com")) != 0 || (r = sshpkt_put_u8(ssh, 0)) != 0) /* want reply */ sshpkt_fatal(ssh, r, "%s: start request", __func__); } /* Append the key to the request */ sshbuf_reset(buf); if ((r = sshkey_putb(key, buf)) != 0) fatal_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_f("sent %u hostkeys", nkeys); if (nkeys == 0) fatal_f("no hostkeys"); if ((r = sshpkt_send(ssh)) != 0) sshpkt_fatal(ssh, r, "%s: send", __func__); sshbuf_free(buf); } /* * returns 1 if connection should be dropped, 0 otherwise. * dropping starts at connection #max_startups_begin with a probability * of (max_startups_rate/100). the probability increases linearly until * all connections are dropped for startups > max_startups */ static int should_drop_connection(int startups) { int p, r; if (startups < options.max_startups_begin) return 0; if (startups >= options.max_startups) return 1; if (options.max_startups_rate == 100) return 1; p = 100 - options.max_startups_rate; p *= startups - options.max_startups_begin; p /= options.max_startups - options.max_startups_begin; p += options.max_startups_rate; r = arc4random_uniform(100); debug_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) { if (options.version_addendum != NULL && *options.version_addendum != '\0') fprintf(stderr, "%s %s, %s\n", SSH_RELEASE, options.version_addendum, SSH_OPENSSL_VERSION); else fprintf(stderr, "%s, %s\n", SSH_RELEASE, SSH_OPENSSL_VERSION); fprintf(stderr, "usage: sshd [-46DdeGiqTtV] [-C connection_spec] [-c host_cert_file]\n" " [-E log_file] [-f config_file] [-g login_grace_time]\n" " [-h host_key_file] [-o option] [-p port] [-u len]\n" ); exit(1); } static void send_rexec_state(int fd, struct sshbuf *conf) { struct sshbuf *m = NULL, *inc = NULL; struct include_item *item = NULL; int r; 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 included_files[] { * string selector * string filename * string contents * } */ if ((r = sshbuf_put_stringb(m, conf)) != 0 || (r = sshbuf_put_stringb(m, inc)) != 0) fatal_fr(r, "compose config"); if (ssh_msg_send(fd, 0, m) == -1) error_f("ssh_msg_send failed"); sshbuf_free(m); sshbuf_free(inc); debug3_f("done"); } static void recv_rexec_state(int fd, struct sshbuf *conf) { struct sshbuf *m, *inc; u_char *cp, ver; size_t len; int r; struct include_item *item; debug3_f("entering fd = %d", fd); if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); if (ssh_msg_recv(fd, m) == -1) fatal_f("ssh_msg_recv failed"); if ((r = sshbuf_get_u8(m, &ver)) != 0) fatal_fr(r, "parse version"); if (ver != 0) 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 (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_f("done"); } /* Accept a connection from inetd */ static void server_accept_inetd(int *sock_in, int *sock_out) { if (rexeced_flag) { close(REEXEC_CONFIG_PASS_FD); *sock_in = *sock_out = dup(STDIN_FILENO); } else { *sock_in = dup(STDIN_FILENO); *sock_out = dup(STDOUT_FILENO); } /* * We intentionally do not close the descriptors 0, 1, and 2 * as our code for setting the descriptors won't work if * ttyfd happens to be one of those. */ if (stdfd_devnull(1, 1, !log_stderr) == -1) error_f("stdfd_devnull failed"); debug("inetd sockets after dupping: %d, %d", *sock_in, *sock_out); } /* * Listen for TCP connections */ static void listen_on_addrs(struct listenaddr *la) { int ret, listen_sock; struct addrinfo *ai; char ntop[NI_MAXHOST], strport[NI_MAXSERV]; for (ai = la->addrs; ai; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) continue; if (num_listen_socks >= MAX_LISTEN_SOCKS) fatal("Too many listen sockets. " "Enlarge MAX_LISTEN_SOCKS"); if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { error("getnameinfo failed: %.100s", ssh_gai_strerror(ret)); continue; } /* Create socket for listening. */ listen_sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (listen_sock == -1) { /* kernel may not support ipv6 */ verbose("socket: %.100s", strerror(errno)); continue; } if (set_nonblock(listen_sock) == -1) { close(listen_sock); continue; } if (fcntl(listen_sock, F_SETFD, FD_CLOEXEC) == -1) { verbose("socket: CLOEXEC: %s", strerror(errno)); close(listen_sock); continue; } /* Socket options */ set_reuseaddr(listen_sock); if (la->rdomain != NULL && set_rdomain(listen_sock, la->rdomain) == -1) { close(listen_sock); continue; } /* Only communicate in IPv6 over AF_INET6 sockets. */ if (ai->ai_family == AF_INET6) sock_set_v6only(listen_sock); debug("Bind to port %s on %s.", strport, ntop); /* Bind the socket to the desired port. */ if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) == -1) { error("Bind to port %s on %s failed: %.200s.", strport, ntop, strerror(errno)); close(listen_sock); continue; } listen_socks[num_listen_socks] = listen_sock; num_listen_socks++; /* Start listening on the port. */ if (listen(listen_sock, SSH_LISTEN_BACKLOG) == -1) fatal("listen on [%s]:%s: %.100s", ntop, strport, strerror(errno)); logit("Server listening on %s port %s%s%s.", ntop, strport, la->rdomain == NULL ? "" : " rdomain ", la->rdomain == NULL ? "" : la->rdomain); } } static void server_listen(void) { u_int i; /* 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); free(options.listen_addrs[i].rdomain); memset(&options.listen_addrs[i], 0, sizeof(options.listen_addrs[i])); } free(options.listen_addrs); options.listen_addrs = NULL; options.num_listen_addrs = 0; if (!num_listen_socks) fatal("Cannot bind any address."); } /* * The main TCP accept loop. Note that, for the non-debug case, returns * from this function are in a forked subprocess. */ static void server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) { struct pollfd *pfd = NULL; int i, j, ret, npfd; int ostartups = -1, startups = 0, listening = 0, lameduck = 0; int startup_p[2] = { -1 , -1 }, *startup_pollfd; char c = 0; struct sockaddr_storage from; socklen_t fromlen; pid_t pid; u_char rnd[256]; sigset_t nsigset, osigset; #ifdef LIBWRAP struct request_info req; request_init(&req, RQ_DAEMON, __progname, 0); #endif /* pipes connected to unauthenticated child sshd processes */ startup_pipes = xcalloc(options.max_startups, sizeof(int)); startup_flags = xcalloc(options.max_startups, sizeof(int)); startup_pollfd = xcalloc(options.max_startups, sizeof(int)); for (i = 0; i < options.max_startups; i++) startup_pipes[i] = -1; /* * Prepare signal mask that we use to block signals that might set * received_sigterm or received_sighup, so that we are guaranteed * to immediately wake up the ppoll if a signal is received after * the flag is checked. */ sigemptyset(&nsigset); sigaddset(&nsigset, SIGHUP); sigaddset(&nsigset, SIGCHLD); sigaddset(&nsigset, SIGTERM); sigaddset(&nsigset, SIGQUIT); /* sized for worst-case */ pfd = xcalloc(num_listen_socks + options.max_startups, sizeof(struct pollfd)); /* * Stay listening for connections until the system crashes or * the daemon is killed with a signal. */ for (;;) { sigprocmask(SIG_BLOCK, &nsigset, &osigset); if (received_sigterm) { logit("Received signal %d; terminating.", (int) received_sigterm); close_listen_socks(); if (options.pid_file != NULL) unlink(options.pid_file); exit(received_sigterm == SIGTERM ? 0 : 255); } if (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"); close_listen_socks(); lameduck = 1; } if (listening <= 0) { sigprocmask(SIG_SETMASK, &osigset, NULL); sighup_restart(); } } for (i = 0; i < num_listen_socks; i++) { pfd[i].fd = listen_socks[i]; pfd[i].events = POLLIN; } npfd = num_listen_socks; for (i = 0; i < options.max_startups; i++) { startup_pollfd[i] = -1; if (startup_pipes[i] != -1) { pfd[npfd].fd = startup_pipes[i]; pfd[npfd].events = POLLIN; startup_pollfd[i] = npfd++; } } /* Wait until a connection arrives or a child exits. */ ret = ppoll(pfd, npfd, NULL, &osigset); if (ret == -1 && errno != EINTR) { error("ppoll: %.100s", strerror(errno)); if (errno == EINVAL) cleanup_exit(1); /* can't recover */ } sigprocmask(SIG_SETMASK, &osigset, NULL); if (ret == -1) continue; for (i = 0; i < options.max_startups; i++) { if (startup_pipes[i] == -1 || startup_pollfd[i] == -1 || !(pfd[startup_pollfd[i]].revents & (POLLIN|POLLHUP))) continue; switch (read(startup_pipes[i], &c, sizeof(c))) { case -1: if (errno == EINTR || errno == EAGAIN) continue; if (errno != EPIPE) { 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]) listening--; break; case 1: /* child has finished preliminaries */ if (startup_flags[i]) { listening--; startup_flags[i] = 0; } break; } } for (i = 0; i < num_listen_socks; i++) { if (!(pfd[i].revents & POLLIN)) continue; fromlen = sizeof(from); *newsock = accept(listen_socks[i], (struct sockaddr *)&from, &fromlen); if (*newsock == -1) { if (errno != EINTR && errno != EWOULDBLOCK && errno != ECONNABORTED && errno != EAGAIN) error("accept: %.100s", strerror(errno)); if (errno == EMFILE || errno == ENFILE) usleep(100 * 1000); continue; } #ifdef LIBWRAP /* Check whether logins are denied from this host. */ request_set(&req, RQ_FILE, *newsock, RQ_CLIENT_NAME, "", RQ_CLIENT_ADDR, "", 0); sock_host(&req); if (!hosts_access(&req)) { const struct linger l = { .l_onoff = 1, .l_linger = 0 }; (void )setsockopt(*newsock, SOL_SOCKET, SO_LINGER, &l, sizeof(l)); (void )close(*newsock); /* * Mimic message from libwrap's refuse() as * precisely as we can afford. The authentic * message prints the IP address and the * hostname it resolves to in parentheses. If * the IP address cannot be resolved to a * hostname, the IP address will be repeated * in parentheses. As name resolution in the * main server loop could stall, and logging * resolved names adds little or no value to * incident investigation, this implementation * only repeats the IP address in parentheses. * This should resemble librwap's refuse() * closely enough not to break auditing * software like sshguard or custom scripts. */ syslog(LOG_WARNING, "refused connect from %s (%s)", eval_hostaddr(req.client), eval_hostaddr(req.client)); debug("Connection refused by tcp wrapper"); continue; } #endif /* LIBWRAP */ if (unset_nonblock(*newsock) == -1) { close(*newsock); continue; } if (pipe(startup_p) == -1) { error_f("pipe(startup_p): %s", strerror(errno)); close(*newsock); continue; } if (drop_connection(*newsock, startups, startup_p[0])) { close(*newsock); close(startup_p[0]); close(startup_p[1]); continue; } if (rexec_flag && socketpair(AF_UNIX, SOCK_STREAM, 0, config_s) == -1) { error("reexec socketpair: %s", strerror(errno)); close(*newsock); close(startup_p[0]); close(startup_p[1]); continue; } for (j = 0; j < options.max_startups; j++) if (startup_pipes[j] == -1) { startup_pipes[j] = startup_p[0]; startups++; startup_flags[j] = 1; break; } /* * Got connection. Fork a child to handle it, unless * we are in debugging mode. */ if (debug_flag) { /* * In debugging mode. Close the listening * socket, and start processing the * connection without forking. */ debug("Server will not fork when running in debugging mode."); close_listen_socks(); *sock_in = *newsock; *sock_out = *newsock; close(startup_p[0]); close(startup_p[1]); startup_pipe = -1; pid = getpid(); if (rexec_flag) { send_rexec_state(config_s[0], cfg); close(config_s[0]); } free(pfd); return; } /* * Normal production daemon. Fork, and have * the child process the connection. The * parent continues listening. */ platform_pre_fork(); listening++; if ((pid = fork()) == 0) { /* * Child. Close the listening and * max_startup sockets. Start using * the accepted socket. Reinitialize * logging (since our pid has changed). * We return from this function to handle * the connection. */ platform_post_fork_child(); startup_pipe = startup_p[1]; close_startup_pipes(); close_listen_socks(); *sock_in = *newsock; *sock_out = *newsock; log_init(__progname, options.log_level, options.log_facility, log_stderr); if (rexec_flag) close(config_s[0]); else { /* * Signal parent that the preliminaries * for this child are complete. For the * re-exec case, this happens after the * child has received the rexec state * from the server. */ (void)atomicio(vwrite, startup_pipe, "\0", 1); } free(pfd); return; } /* Parent. Stay in the loop. */ platform_post_fork_parent(pid); if (pid == -1) error("fork: %.100s", strerror(errno)); else debug("Forked child %ld.", (long)pid); close(startup_p[1]); if (rexec_flag) { close(config_s[1]); send_rexec_state(config_s[0], cfg); close(config_s[0]); } close(*newsock); /* * Ensure that our random state differs * from that of the child */ arc4random_stir(); arc4random_buf(rnd, sizeof(rnd)); #ifdef WITH_OPENSSL RAND_seed(rnd, sizeof(rnd)); if ((RAND_bytes((u_char *)rnd, 1)) != 1) fatal("%s: RAND_bytes failed", __func__); #endif explicit_bzero(rnd, sizeof(rnd)); } } } /* * If IP options are supported, make sure there are none (log and * return an error if any are found). Basically we are worried about * source routing; it can be used to pretend you are somebody * (ip-address) you are not. That itself may be "almost acceptable" * under certain circumstances, but rhosts authentication is useless * if source routing is accepted. Notice also that if we just dropped * source routing here, the other side could use IP spoofing to do * rest of the interaction and could still bypass security. So we * exit here if we detect any IP options. */ static void check_ip_options(struct ssh *ssh) { #ifdef IP_OPTIONS int sock_in = ssh_packet_get_connection_in(ssh); struct sockaddr_storage from; u_char opts[200]; socklen_t i, option_size = sizeof(opts), fromlen = sizeof(from); char text[sizeof(opts) * 3 + 1]; memset(&from, 0, sizeof(from)); if (getpeername(sock_in, (struct sockaddr *)&from, &fromlen) == -1) return; if (from.ss_family != AF_INET) return; /* XXX IPv6 options? */ if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts, &option_size) >= 0 && option_size != 0) { text[0] = '\0'; for (i = 0; i < option_size; i++) snprintf(text + i*3, sizeof(text) - i*3, " %2.2x", opts[i]); fatal("Connection from %.100s port %d with IP opts: %.800s", ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), text); } return; #endif /* IP_OPTIONS */ } /* Set the routing domain for this process */ static void set_process_rdomain(struct ssh *ssh, const char *name) { #if defined(HAVE_SYS_SET_PROCESS_RDOMAIN) if (name == NULL) return; /* default */ if (strcmp(name, "%D") == 0) { /* "expands" to routing domain of connection */ if ((name = ssh_packet_rdomain_in(ssh)) == NULL) return; } /* NB. We don't pass 'ssh' to sys_set_process_rdomain() */ return sys_set_process_rdomain(name); #elif defined(__OpenBSD__) int rtable, ortable = getrtable(); const char *errstr; if (name == NULL) return; /* default */ if (strcmp(name, "%D") == 0) { /* "expands" to routing domain of connection */ if ((name = ssh_packet_rdomain_in(ssh)) == NULL) return; } rtable = (int)strtonum(name, 0, 255, &errstr); if (errstr != NULL) /* Shouldn't happen */ fatal("Invalid routing domain \"%s\": %s", name, errstr); if (rtable != ortable && setrtable(rtable) != 0) fatal("Unable to set routing domain %d: %s", rtable, strerror(errno)); debug_f("set routing domain %d (was %d)", rtable, ortable); #else /* defined(__OpenBSD__) */ fatal("Unable to set routing domain: not supported in this platform"); #endif } static void accumulate_host_timing_secret(struct sshbuf *server_cfg, struct sshkey *key) { static struct ssh_digest_ctx *ctx; u_char *hash; size_t len; struct sshbuf *buf; int r; if (ctx == NULL && (ctx = ssh_digest_start(SSH_DIGEST_SHA512)) == NULL) fatal_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_f("ssh_digest_update"); len = ssh_digest_bytes(SSH_DIGEST_SHA512); hash = xmalloc(len); if (ssh_digest_final(ctx, hash, len) != 0) fatal_f("ssh_digest_final"); options.timing_secret = PEEK_U64(hash); freezero(hash, len); ssh_digest_free(ctx); ctx = NULL; return; } if ((buf = sshbuf_new()) == NULL) fatal_f("could not allocate buffer"); if ((r = sshkey_private_serialize(key, buf)) != 0) fatal_fr(r, "encode %s key", sshkey_ssh_name(key)); if (ssh_digest_update(ctx, sshbuf_ptr(buf), sshbuf_len(buf)) != 0) 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; } static void print_config(struct ssh *ssh, struct connection_info *connection_info) { /* * If no connection info was provided by -C then use * use a blank one that will cause no predicate to match. */ if (connection_info == NULL) connection_info = get_connection_info(ssh, 0, 0); connection_info->test = 1; parse_server_match_config(&options, &includes, connection_info); dump_config(&options); exit(0); } /* * Main program for the daemon. */ int main(int ac, char **av) { struct ssh *ssh = NULL; extern char *optarg; extern int optind; int r, opt, on = 1, do_dump_cfg = 0, already_daemon, remote_port; int sock_in = -1, sock_out = -1, newsock = -1; const char *remote_ip, *rdomain; char *fp, *line, *laddr, *logfile = NULL; int config_s[2] = { -1 , -1 }; u_int i, j; u_int64_t ibytes, obytes; mode_t new_umask; struct sshkey *key; struct sshkey *pubkey; int keytype; Authctxt *authctxt; struct connection_info *connection_info = NULL; sigset_t sigmask; #ifdef HAVE_SECUREWARE (void)set_auth_parameters(ac, av); #endif __progname = ssh_get_progname(av[0]); sigemptyset(&sigmask); sigprocmask(SIG_SETMASK, &sigmask, NULL); /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ saved_argc = ac; rexec_argc = ac; saved_argv = xcalloc(ac + 1, sizeof(*saved_argv)); for (i = 0; (int)i < ac; i++) saved_argv[i] = xstrdup(av[i]); saved_argv[i] = NULL; #ifndef HAVE_SETPROCTITLE /* Prepare for later setproctitle emulation */ compat_init_setproctitle(ac, av); av = saved_argv; #endif if (geteuid() == 0 && setgroups(0, NULL) == -1) debug("setgroups(): %.200s", strerror(errno)); /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); /* Initialize configuration options to their default values. */ initialize_server_options(&options); /* Parse command-line arguments. */ while ((opt = getopt(ac, av, "C:E:b:c:f:g:h:k:o:p:u:46DGQRTdeiqrtV")) != -1) { switch (opt) { case '4': options.address_family = AF_INET; break; case '6': options.address_family = AF_INET6; break; case 'f': config_file_name = optarg; break; case 'c': servconf_add_hostcert("[command-line]", 0, &options, optarg); break; case 'd': if (debug_flag == 0) { debug_flag = 1; options.log_level = SYSLOG_LEVEL_DEBUG1; } else if (options.log_level < SYSLOG_LEVEL_DEBUG3) options.log_level++; break; case 'D': no_daemon_flag = 1; break; case 'G': do_dump_cfg = 1; break; case 'E': logfile = optarg; /* FALLTHROUGH */ case 'e': log_stderr = 1; break; case 'i': inetd_flag = 1; break; case 'r': rexec_flag = 0; break; case 'R': rexeced_flag = 1; inetd_flag = 1; break; case 'Q': /* ignored */ break; case 'q': options.log_level = SYSLOG_LEVEL_QUIET; break; case 'b': /* protocol 1, ignored */ break; case 'p': options.ports_from_cmdline = 1; if (options.num_ports >= MAX_PORTS) { fprintf(stderr, "too many ports.\n"); exit(1); } options.ports[options.num_ports++] = a2port(optarg); if (options.ports[options.num_ports-1] <= 0) { fprintf(stderr, "Bad port number.\n"); exit(1); } break; case 'g': if ((options.login_grace_time = convtime(optarg)) == -1) { fprintf(stderr, "Invalid login grace time.\n"); exit(1); } break; case 'k': /* protocol 1, ignored */ break; case 'h': servconf_add_hostkey("[command-line]", 0, &options, optarg, 1); break; case 't': test_flag = 1; break; case 'T': test_flag = 2; break; case 'C': connection_info = get_connection_info(ssh, 0, 0); if (parse_server_match_testspec(connection_info, optarg) == -1) exit(1); break; case 'u': utmp_len = (u_int)strtonum(optarg, 0, HOST_NAME_MAX+1+1, NULL); if (utmp_len > HOST_NAME_MAX+1) { fprintf(stderr, "Invalid utmp length.\n"); exit(1); } break; case 'o': line = xstrdup(optarg); if (process_server_config_line(&options, line, "command-line", 0, NULL, NULL, &includes) != 0) exit(1); free(line); break; case 'V': fprintf(stderr, "%s, %s\n", SSH_RELEASE, SSH_OPENSSL_VERSION); exit(0); default: usage(); break; } } if (rexeced_flag || inetd_flag) rexec_flag = 0; if (!test_flag && !do_dump_cfg && rexec_flag && !path_absolute(av[0])) fatal("sshd re-exec requires execution with an absolute path"); if (rexeced_flag) closefrom(REEXEC_MIN_FREE_FD); else closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); seed_rng(); /* If requested, redirect the logs to the specified logfile. */ if (logfile != NULL) log_redirect_stderr_to(logfile); /* * Force logging to stderr until we have loaded the private host * key (unless started from inetd) */ log_init(__progname, options.log_level == SYSLOG_LEVEL_NOT_SET ? SYSLOG_LEVEL_INFO : options.log_level, options.log_facility == SYSLOG_FACILITY_NOT_SET ? SYSLOG_FACILITY_AUTH : options.log_facility, log_stderr || !inetd_flag || debug_flag); /* * Unset KRB5CCNAME, otherwise the user's session may inherit it from * root's environment */ if (getenv("KRB5CCNAME") != NULL) (void) unsetenv("KRB5CCNAME"); sensitive_data.have_ssh2_key = 0; /* * If we're not doing an extended test do not silently ignore connection * test params. */ if (test_flag < 2 && connection_info != NULL) fatal("Config test connection parameter (-C) provided without " "test mode (-T)"); /* Fetch our configuration */ if ((cfg = sshbuf_new()) == NULL) fatal_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); close(REEXEC_STARTUP_PIPE_FD); /* * Signal parent that this child is at a point where * they can go away if they have a SIGHUP pending. */ (void)atomicio(vwrite, startup_pipe, "\0", 1); } } else if (strcasecmp(config_file_name, "none") != 0) load_server_config(config_file_name, cfg); parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, cfg, &includes, NULL, rexeced_flag); #ifdef WITH_OPENSSL if (options.moduli_file != NULL) dh_set_moduli_file(options.moduli_file); #endif /* Fill in default values for those options not explicitly set. */ fill_default_server_options(&options); /* Check that options are sensible */ if (options.authorized_keys_command_user == NULL && (options.authorized_keys_command != NULL && strcasecmp(options.authorized_keys_command, "none") != 0)) fatal("AuthorizedKeysCommand set without " "AuthorizedKeysCommandUser"); if (options.authorized_principals_command_user == NULL && (options.authorized_principals_command != NULL && strcasecmp(options.authorized_principals_command, "none") != 0)) fatal("AuthorizedPrincipalsCommand set without " "AuthorizedPrincipalsCommandUser"); /* * Check whether there is any path through configured auth methods. * Unfortunately it is not possible to verify this generally before * daemonisation in the presence of Match block, but this catches * and warns for trivial misconfigurations that could break login. */ if (options.num_auth_methods != 0) { for (i = 0; i < options.num_auth_methods; i++) { if (auth2_methods_valid(options.auth_methods[i], 1) == 0) break; } if (i >= options.num_auth_methods) fatal("AuthenticationMethods cannot be satisfied by " "enabled authentication methods"); } /* Check that there are no remaining arguments. */ if (optind < ac) { fprintf(stderr, "Extra argument %s.\n", av[optind]); exit(1); } debug("sshd version %s, %s", SSH_VERSION, SSH_OPENSSL_VERSION); if (do_dump_cfg) print_config(ssh, connection_info); /* Store privilege separation user for later use if required. */ privsep_chroot = use_privsep && (getuid() == 0 || geteuid() == 0); if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { if (privsep_chroot || options.kerberos_authentication) fatal("Privilege separation user %s does not exist", SSH_PRIVSEP_USER); } else { privsep_pw = pwcopy(privsep_pw); freezero(privsep_pw->pw_passwd, strlen(privsep_pw->pw_passwd)); privsep_pw->pw_passwd = xstrdup("*"); } endpwent(); /* load host keys */ sensitive_data.host_keys = xcalloc(options.num_host_key_files, sizeof(struct sshkey *)); sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files, sizeof(struct sshkey *)); if (options.host_key_agent) { if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) setenv(SSH_AUTHSOCKET_ENV_NAME, options.host_key_agent, 1); if ((r = ssh_get_authentication_socket(NULL)) == 0) have_agent = 1; else error_r(r, "Could not connect to agent \"%s\"", options.host_key_agent); } for (i = 0; i < options.num_host_key_files; i++) { int ll = options.host_key_file_userprovided[i] ? SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_DEBUG1; if (options.host_key_files[i] == NULL) continue; if ((r = sshkey_load_private(options.host_key_files[i], "", &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) 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_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_r(r, "Could not demote key: \"%s\"", options.host_key_files[i]); } if (pubkey != NULL && (r = sshkey_check_rsa_length(pubkey, options.required_rsa_size)) != 0) { error_fr(r, "Host key %s", options.host_key_files[i]); sshkey_free(pubkey); sshkey_free(key); continue; } sensitive_data.host_keys[i] = key; sensitive_data.host_pubkeys[i] = pubkey; if (key == NULL && pubkey != NULL && have_agent) { debug("will rely on agent for hostkey %s", options.host_key_files[i]); keytype = pubkey->type; } else if (key != NULL) { keytype = key->type; accumulate_host_timing_secret(cfg, key); } else { do_log2(ll, "Unable to load host key: %s", options.host_key_files[i]); sensitive_data.host_keys[i] = NULL; sensitive_data.host_pubkeys[i] = NULL; continue; } switch (keytype) { case KEY_RSA: case KEY_DSA: case KEY_ECDSA: case KEY_ED25519: case KEY_ECDSA_SK: case KEY_ED25519_SK: case KEY_XMSS: if (have_agent || key != NULL) sensitive_data.have_ssh2_key = 1; break; } if ((fp = sshkey_fingerprint(pubkey, options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal("sshkey_fingerprint failed"); debug("%s host key #%d: %s %s", key ? "private" : "agent", i, sshkey_ssh_name(pubkey), fp); free(fp); } accumulate_host_timing_secret(cfg, NULL); if (!sensitive_data.have_ssh2_key) { logit("sshd: no hostkeys available -- exiting."); exit(1); } /* * Load certificates. They are stored in an array at identical * indices to the public keys that they relate to. */ sensitive_data.host_certificates = xcalloc(options.num_host_key_files, sizeof(struct sshkey *)); for (i = 0; i < options.num_host_key_files; i++) sensitive_data.host_certificates[i] = NULL; for (i = 0; i < options.num_host_cert_files; i++) { if (options.host_cert_files[i] == NULL) continue; if ((r = sshkey_load_public(options.host_cert_files[i], &key, NULL)) != 0) { error_r(r, "Could not load host certificate \"%s\"", options.host_cert_files[i]); continue; } if (!sshkey_is_cert(key)) { error("Certificate file is not a certificate: %s", options.host_cert_files[i]); sshkey_free(key); continue; } /* Find matching private key */ for (j = 0; j < options.num_host_key_files; j++) { if (sshkey_equal_public(key, sensitive_data.host_pubkeys[j])) { sensitive_data.host_certificates[j] = key; break; } } if (j >= options.num_host_key_files) { error("No matching private key for certificate: %s", options.host_cert_files[i]); sshkey_free(key); continue; } sensitive_data.host_certificates[j] = key; debug("host certificate: #%u type %d %s", j, key->type, sshkey_type(key)); } if (privsep_chroot) { struct stat st; if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) || (S_ISDIR(st.st_mode) == 0)) fatal("Missing privilege separation directory: %s", _PATH_PRIVSEP_CHROOT_DIR); #ifdef HAVE_CYGWIN if (check_ntsec(_PATH_PRIVSEP_CHROOT_DIR) && (st.st_uid != getuid () || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0)) #else if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0) #endif fatal("%s must be owned by root and not group or " "world-writable.", _PATH_PRIVSEP_CHROOT_DIR); } if (test_flag > 1) print_config(ssh, connection_info); /* Configuration looks good, so exit if in test mode. */ if (test_flag) exit(0); /* * Clear out any supplemental groups we may have inherited. This * prevents inadvertent creation of files with bad modes (in the * portable version at least, it's certainly possible for PAM * to create a file, and we can't control the code in every * module which might be used). */ if (setgroups(0, NULL) < 0) debug("setgroups() failed: %.200s", strerror(errno)); if (rexec_flag) { if (rexec_argc < 0) fatal("rexec_argc %d < 0", rexec_argc); rexec_argv = xcalloc(rexec_argc + 2, sizeof(char *)); for (i = 0; i < (u_int)rexec_argc; i++) { debug("rexec_argv[%d]='%s'", i, saved_argv[i]); rexec_argv[i] = saved_argv[i]; } rexec_argv[rexec_argc] = "-R"; rexec_argv[rexec_argc + 1] = NULL; } listener_proctitle = prepare_proctitle(ac, av); /* Ensure that umask disallows at least group and world write */ new_umask = umask(0077) | 0022; (void) umask(new_umask); /* Initialize the log (it is reinitialized below in case we forked). */ if (debug_flag && (!inetd_flag || rexeced_flag)) log_stderr = 1; log_init(__progname, options.log_level, options.log_facility, log_stderr); 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 * daemonized (eg re-exec via SIGHUP), disconnect from the controlling * terminal, and fork. The original process exits. */ already_daemon = daemonized(); if (!(debug_flag || inetd_flag || no_daemon_flag || already_daemon)) { if (daemon(0, 0) == -1) fatal("daemon() failed: %.200s", strerror(errno)); disconnect_controlling_tty(); } /* Reinitialize the log (because of the fork above). */ log_init(__progname, options.log_level, options.log_facility, log_stderr); /* Avoid killing the process in high-pressure swapping environments. */ if (!inetd_flag && madvise(NULL, 0, MADV_PROTECT) != 0) debug("madvise(): %.200s", strerror(errno)); /* * Chdir to the root directory so that the current disk can be * unmounted if desired. */ if (chdir("/") == -1) error("chdir(\"/\"): %s", strerror(errno)); /* ignore SIGPIPE */ ssh_signal(SIGPIPE, SIG_IGN); /* Get a connection, either from inetd or a listening TCP socket */ if (inetd_flag) { server_accept_inetd(&sock_in, &sock_out); } else { platform_pre_listen(); server_listen(); 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 * is setup and the listen sockets are bound */ if (options.pid_file != NULL && !debug_flag) { FILE *f = fopen(options.pid_file, "w"); if (f == NULL) { error("Couldn't create pid file \"%s\": %s", options.pid_file, strerror(errno)); } else { fprintf(f, "%ld\n", (long) getpid()); fclose(f); } } /* Accept a connection and return in a forked child */ server_accept_loop(&sock_in, &sock_out, &newsock, config_s); } /* This is the child processing a new connection. */ setproctitle("%s", "[accepted]"); /* * Create a new session and process group since the 4.4BSD * setlogin() affects the entire process group. We don't * want the child to be able to affect the parent. */ if (!debug_flag && !inetd_flag && setsid() == -1) error("setsid: %.100s", strerror(errno)); if (rexec_flag) { debug("rexec start in %d out %d newsock %d pipe %d sock %d", sock_in, sock_out, newsock, startup_pipe, config_s[0]); if (dup2(newsock, STDIN_FILENO) == -1) debug3_f("dup2 stdin: %s", strerror(errno)); if (dup2(STDIN_FILENO, STDOUT_FILENO) == -1) debug3_f("dup2 stdout: %s", strerror(errno)); if (startup_pipe == -1) close(REEXEC_STARTUP_PIPE_FD); else if (startup_pipe != REEXEC_STARTUP_PIPE_FD) { if (dup2(startup_pipe, REEXEC_STARTUP_PIPE_FD) == -1) debug3_f("dup2 startup_p: %s", strerror(errno)); close(startup_pipe); startup_pipe = REEXEC_STARTUP_PIPE_FD; } if (dup2(config_s[1], REEXEC_CONFIG_PASS_FD) == -1) debug3_f("dup2 config_s: %s", strerror(errno)); 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 */ error("rexec of %s failed: %s", rexec_argv[0], strerror(errno)); recv_rexec_state(REEXEC_CONFIG_PASS_FD, NULL); log_init(__progname, options.log_level, options.log_facility, log_stderr); /* Clean up fds */ close(REEXEC_CONFIG_PASS_FD); newsock = sock_out = sock_in = dup(STDIN_FILENO); if (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]); } /* Executed child processes don't need these. */ fcntl(sock_out, F_SETFD, FD_CLOEXEC); fcntl(sock_in, F_SETFD, FD_CLOEXEC); /* 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); #ifdef __FreeBSD__ /* * Initialize the resolver. This may not happen automatically * before privsep chroot(). */ if ((_res.options & RES_INIT) == 0) { debug("res_init()"); res_init(); } #ifdef GSSAPI /* * Force GSS-API to parse its configuration and load any * mechanism plugins. */ { gss_OID_set mechs; OM_uint32 minor_status; gss_indicate_mechs(&minor_status, &mechs); gss_release_oid_set(&minor_status, &mechs); } #endif #endif /* * Register our connection. This turns encryption off because we do * not have a key. */ if ((ssh = ssh_packet_set_connection(NULL, sock_in, sock_out)) == NULL) fatal("Unable to create connection"); the_active_state = ssh; ssh_packet_set_server(ssh); check_ip_options(ssh); /* Prepare the channels layer */ channel_init_channels(ssh); channel_set_af(ssh, options.address_family); process_channel_timeouts(ssh, &options); process_permitopen(ssh, &options); /* Set SO_KEEPALIVE if requested. */ if (options.tcp_keep_alive && ssh_packet_connection_is_on_socket(ssh) && setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) == -1) error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); if ((remote_port = ssh_remote_port(ssh)) < 0) { debug("ssh_remote_port failed"); cleanup_exit(255); } if (options.routing_domain != NULL) set_process_rdomain(ssh, options.routing_domain); /* * The rest of the code depends on the fact that * ssh_remote_ipaddr() caches the remote ip, even if * the socket goes away. */ remote_ip = ssh_remote_ipaddr(ssh); #ifdef HAVE_LOGIN_CAP /* Also caches remote hostname for sandboxed child. */ auth_get_canonical_hostname(ssh, options.use_dns); #endif #ifdef SSH_AUDIT_EVENTS audit_connection_from(remote_ip, remote_port); #endif rdomain = ssh_packet_rdomain_in(ssh); /* Log the connection. */ laddr = get_local_ipaddr(sock_in); verbose("Connection from %s port %d on %s port %d%s%s%s", remote_ip, remote_port, laddr, ssh_local_port(ssh), rdomain == NULL ? "" : " rdomain \"", rdomain == NULL ? "" : rdomain, rdomain == NULL ? "" : "\""); free(laddr); /* * We don't want to listen forever unless the other side * successfully authenticates itself. So we set up an alarm which is * cleared after successful authentication. A limit of zero * indicates no limit. Note that we don't set the alarm in debugging * mode; it is just annoying to have the server exit just when you * are about to discover the bug. */ ssh_signal(SIGALRM, grace_alarm_handler); if (!debug_flag) alarm(options.login_grace_time); 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 */ authctxt = xcalloc(1, sizeof(*authctxt)); ssh->authctxt = authctxt; authctxt->loginmsg = loginmsg; /* XXX global for cleanup, access from other modules */ the_authctxt = authctxt; /* Set default key authentication options */ if ((auth_opts = sshauthopt_new_with_keys_defaults()) == NULL) fatal("allocation failed"); /* prepare buffer to collect messages to display to user after login */ if ((loginmsg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); auth_debug_reset(); BLACKLIST_INIT(); if (use_privsep) { if (privsep_preauth(ssh) == 1) goto authenticated; } else if (have_agent) { if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) { error_r(r, "Unable to get agent socket"); have_agent = 0; } } /* perform the key exchange */ /* authenticate user and start session */ do_ssh2_kex(ssh); do_authentication2(ssh); /* * If we use privilege separation, the unprivileged child transfers * the current keystate and exits */ if (use_privsep) { mm_send_keystate(ssh, pmonitor); ssh_packet_clear_keys(ssh); exit(0); } authenticated: /* * Cancel the alarm we set to limit the time taken for * authentication. */ alarm(0); ssh_signal(SIGALRM, SIG_DFL); authctxt->authenticated = 1; if (startup_pipe != -1) { close(startup_pipe); startup_pipe = -1; } #ifdef SSH_AUDIT_EVENTS audit_event(ssh, SSH_AUTH_SUCCESS); #endif #ifdef GSSAPI if (options.gss_authentication) { temporarily_use_uid(authctxt->pw); ssh_gssapi_storecreds(); restore_uid(); } #endif #ifdef USE_PAM if (options.use_pam) { do_pam_setcred(1); do_pam_session(ssh); } #endif /* * In privilege separation, we fork another child and prepare * file descriptor passing. */ if (use_privsep) { privsep_postauth(ssh, authctxt); /* the monitor process [priv] will not return */ } ssh_packet_set_timeout(ssh, options.client_alive_interval, options.client_alive_count_max); /* Try to send all our hostkeys to the client */ notify_hostkeys(ssh); /* Start session. */ do_authenticated(ssh, authctxt); /* The connection has been terminated. */ ssh_packet_get_bytes(ssh, &ibytes, &obytes); verbose("Transferred: sent %llu, received %llu bytes", (unsigned long long)obytes, (unsigned long long)ibytes); verbose("Closing connection to %.500s port %d", remote_ip, remote_port); #ifdef USE_PAM if (options.use_pam) finish_pam(); #endif /* USE_PAM */ #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(ssh, SSH_CONNECTION_CLOSE)); #endif ssh_packet_close(ssh); if (use_privsep) mm_terminate(); exit(0); } int sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey, struct sshkey *pubkey, u_char **signature, size_t *slenp, const u_char *data, size_t dlen, const char *alg) { int r; if (use_privsep) { if (privkey) { if (mm_sshkey_sign(ssh, privkey, signature, slenp, 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, options.sk_provider, NULL, ssh->compat) < 0) fatal_f("pubkey sign failed"); } } else { if (privkey) { if (sshkey_sign(privkey, signature, slenp, data, dlen, 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_fr(r, "agent sign failed"); } } } return 0; } /* SSH2 key exchange */ static void do_ssh2_kex(struct ssh *ssh) { char *hkalgs = NULL, *myproposal[PROPOSAL_MAX]; const char *compression = NULL; struct kex *kex; int r; if (options.rekey_limit || options.rekey_interval) ssh_packet_set_rekey_limits(ssh, options.rekey_limit, options.rekey_interval); if (options.compression == COMP_NONE) compression = "none"; hkalgs = list_hostkey_types(); kex_proposal_populate_entries(ssh, myproposal, options.kex_algorithms, options.ciphers, options.macs, compression, hkalgs); free(hkalgs); /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) fatal_r(r, "kex_setup"); + kex_set_server_sig_algs(ssh, options.pubkey_accepted_algos); kex = ssh->kex; + #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; # ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif #endif 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; ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &kex->done); #ifdef DEBUG_KEXDH /* send 1st encrypted/maced/compressed message */ if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || (r = sshpkt_put_cstring(ssh, "markus")) != 0 || (r = sshpkt_send(ssh)) != 0 || (r = ssh_packet_write_wait(ssh)) != 0) fatal_fr(r, "send test"); #endif kex_proposal_free_entries(myproposal); debug("KEX done"); } /* server specific fatal cleanup */ void cleanup_exit(int i) { if (the_active_state != NULL && the_authctxt != NULL) { do_cleanup(the_active_state, the_authctxt); if (use_privsep && privsep_is_preauth && pmonitor != NULL && pmonitor->m_pid > 1) { debug("Killing privsep child %d", pmonitor->m_pid); if (kill(pmonitor->m_pid, SIGKILL) != 0 && errno != ESRCH) { error_f("kill(%d): %s", pmonitor->m_pid, strerror(errno)); } } } #ifdef SSH_AUDIT_EVENTS /* done after do_cleanup so it can cancel the PAM auth 'thread' */ if (the_active_state != NULL && (!use_privsep || mm_is_monitor())) audit_event(the_active_state, SSH_CONNECTION_ABANDON); #endif _exit(i); } diff --git a/crypto/openssh/sshd_config b/crypto/openssh/sshd_config index de1b87e17699..46214f141b2b 100644 --- a/crypto/openssh/sshd_config +++ b/crypto/openssh/sshd_config @@ -1,121 +1,121 @@ # $OpenBSD: sshd_config,v 1.104 2021/07/02 05:11:21 dtucker Exp $ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. # This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin # The strategy used for options in the default sshd_config shipped with # OpenSSH is to specify options with their default value where # possible, but leave them commented. Uncommented options override the # default value. # Note that some of FreeBSD's defaults differ from OpenBSD's, and # FreeBSD has a few additional options. #Port 22 #AddressFamily any #ListenAddress 0.0.0.0 #ListenAddress :: #HostKey /etc/ssh/ssh_host_rsa_key #HostKey /etc/ssh/ssh_host_ecdsa_key #HostKey /etc/ssh/ssh_host_ed25519_key # Ciphers and keying #RekeyLimit default none # Logging #SyslogFacility AUTH #LogLevel INFO # Authentication: #LoginGraceTime 2m #PermitRootLogin no #StrictModes yes #MaxAuthTries 6 #MaxSessions 10 #PubkeyAuthentication yes # The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2 # but this is overridden so installations will only check .ssh/authorized_keys AuthorizedKeysFile .ssh/authorized_keys #AuthorizedPrincipalsFile none #AuthorizedKeysCommand none #AuthorizedKeysCommandUser nobody # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts #HostbasedAuthentication no # Change to yes if you don't trust ~/.ssh/known_hosts for # HostbasedAuthentication #IgnoreUserKnownHosts no # Don't read the user's ~/.rhosts and ~/.shosts files #IgnoreRhosts yes # Change to yes to enable built-in password authentication. # Note that passwords may also be accepted via KbdInteractiveAuthentication. #PasswordAuthentication no #PermitEmptyPasswords no # Change to no to disable PAM authentication #KbdInteractiveAuthentication yes # Kerberos options #KerberosAuthentication no #KerberosOrLocalPasswd yes #KerberosTicketCleanup yes #KerberosGetAFSToken no # GSSAPI options #GSSAPIAuthentication no #GSSAPICleanupCredentials yes # Set this to 'no' to disable PAM authentication, account processing, # and session processing. If this is enabled, PAM authentication will # be allowed through the KbdInteractiveAuthentication and # PasswordAuthentication. Depending on your PAM configuration, # PAM authentication via KbdInteractiveAuthentication may bypass # the setting of "PermitRootLogin prohibit-password". # If you just want the PAM account and session checks to run without # PAM authentication, then enable this but set PasswordAuthentication # and KbdInteractiveAuthentication to 'no'. #UsePAM yes #AllowAgentForwarding yes #AllowTcpForwarding yes #GatewayPorts no #X11Forwarding no #X11DisplayOffset 10 #X11UseLocalhost yes #PermitTTY yes #PrintMotd yes #PrintLastLog yes #TCPKeepAlive yes #PermitUserEnvironment no #Compression delayed #ClientAliveInterval 0 #ClientAliveCountMax 3 #UseDNS yes #PidFile /var/run/sshd.pid #MaxStartups 10:30:100 #PermitTunnel no #ChrootDirectory none #UseBlacklist no -#VersionAddendum FreeBSD-20231004 +#VersionAddendum FreeBSD-20240104 # no default banner path #Banner none # override default of no subsystems Subsystem sftp /usr/libexec/sftp-server # Example of overriding settings on a per-user basis #Match User anoncvs # X11Forwarding no # AllowTcpForwarding no # PermitTTY no # ForceCommand cvs server diff --git a/crypto/openssh/sshd_config.5 b/crypto/openssh/sshd_config.5 index e38e3d662dbb..be5ad6fae76b 100644 --- a/crypto/openssh/sshd_config.5 +++ b/crypto/openssh/sshd_config.5 @@ -1,2128 +1,2128 @@ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland .\" All rights reserved .\" .\" As far as I am concerned, the code I have written for this software .\" can be used freely for any purpose. Any derived versions of this .\" software must be clearly marked as such, and if the derived work is .\" incompatible with the protocol description in the RFC file, it must be .\" called by a name other than "ssh" or "Secure Shell". .\" .\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved. .\" Copyright (c) 1999 Aaron Campbell. All rights reserved. .\" Copyright (c) 1999 Theo de Raadt. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" $OpenBSD: sshd_config.5,v 1.350 2023/07/28 05:42:36 jmc Exp $ .Dd $Mdocdate: July 28 2023 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME .Nm sshd_config .Nd OpenSSH daemon configuration file .Sh DESCRIPTION .Xr sshd 8 reads configuration data from .Pa /etc/ssh/sshd_config (or the file specified with .Fl f on the command line). The file contains keyword-argument pairs, one per line. Unless noted otherwise, for each keyword, the first obtained value will be used. Lines starting with .Ql # and empty lines are interpreted as comments. Arguments may optionally be enclosed in double quotes .Pq \&" in order to represent arguments containing spaces. .Pp The possible keywords and their meanings are as follows (note that keywords are case-insensitive and arguments are case-sensitive): .Bl -tag -width Ds .It Cm AcceptEnv Specifies what environment variables sent by the client will be copied into the session's .Xr environ 7 . See .Cm SendEnv and .Cm SetEnv in .Xr ssh_config 5 for how to configure the client. The .Ev TERM environment variable is always accepted whenever the client requests a pseudo-terminal as it is required by the protocol. Variables are specified by name, which may contain the wildcard characters .Ql * and .Ql \&? . Multiple environment variables may be separated by whitespace or spread across multiple .Cm AcceptEnv directives. Be warned that some environment variables could be used to bypass restricted user environments. For this reason, care should be taken in the use of this directive. The default is not to accept any environment variables. .It Cm AddressFamily Specifies which address family should be used by .Xr sshd 8 . Valid arguments are .Cm any (the default), .Cm inet (use IPv4 only), or .Cm inet6 (use IPv6 only). .It Cm AllowAgentForwarding Specifies whether .Xr ssh-agent 1 forwarding is permitted. The default is .Cm yes . Note that disabling agent forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders. .It Cm AllowGroups This keyword can be followed by a list of group name patterns, separated by spaces. If specified, login is allowed only for users whose primary group or supplementary group list matches one of the patterns. Only group names are valid; a numerical group ID is not recognized. By default, login is allowed for all groups. The allow/deny groups directives are processed in the following order: .Cm DenyGroups , .Cm AllowGroups . .Pp See PATTERNS in .Xr ssh_config 5 for more information on patterns. This keyword may appear multiple times in .Nm with each instance appending to the list. .It Cm AllowStreamLocalForwarding Specifies whether StreamLocal (Unix-domain socket) forwarding is permitted. The available options are .Cm yes (the default) or .Cm all to allow StreamLocal forwarding, .Cm no to prevent all StreamLocal forwarding, .Cm local to allow local (from the perspective of .Xr ssh 1 ) forwarding only or .Cm remote to allow remote forwarding only. Note that disabling StreamLocal forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders. .It Cm AllowTcpForwarding Specifies whether TCP forwarding is permitted. The available options are .Cm yes (the default) or .Cm all to allow TCP forwarding, .Cm no to prevent all TCP forwarding, .Cm local to allow local (from the perspective of .Xr ssh 1 ) forwarding only or .Cm remote to allow remote forwarding only. Note that disabling TCP forwarding does not improve security unless users are also denied shell access, as they can always install their own forwarders. .It Cm AllowUsers This keyword can be followed by a list of user name patterns, separated by spaces. If specified, login is allowed only for user names that match one of the patterns. Only user names are valid; a numerical user ID is not recognized. By default, login is allowed for all users. If the pattern takes the form USER@HOST then USER and HOST are separately checked, restricting logins to particular users from particular hosts. HOST criteria may additionally contain addresses to match in CIDR address/masklen format. The allow/deny users directives are processed in the following order: .Cm DenyUsers , .Cm AllowUsers . .Pp See PATTERNS in .Xr ssh_config 5 for more information on patterns. This keyword may appear multiple times in .Nm with each instance appending to the list. .It Cm AuthenticationMethods Specifies the authentication methods that must be successfully completed for a user to be granted access. This option must be followed by one or more lists of comma-separated authentication method names, or by the single string .Cm any to indicate the default behaviour of accepting any single authentication method. If the default is overridden, then successful authentication requires completion of every method in at least one of these lists. .Pp For example, .Qq publickey,password publickey,keyboard-interactive would require the user to complete public key authentication, followed by either password or keyboard interactive authentication. Only methods that are next in one or more lists are offered at each stage, so for this example it would not be possible to attempt password or keyboard-interactive authentication before public key. .Pp For keyboard interactive authentication it is also possible to restrict authentication to a specific device by appending a colon followed by the device identifier .Cm bsdauth or .Cm pam . depending on the server configuration. For example, .Qq keyboard-interactive:bsdauth would restrict keyboard interactive authentication to the .Cm bsdauth device. .Pp If the publickey method is listed more than once, .Xr sshd 8 verifies that keys that have been used successfully are not reused for subsequent authentications. For example, .Qq publickey,publickey requires successful authentication using two different public keys. .Pp Note that each authentication method listed should also be explicitly enabled in the configuration. .Pp The available authentication methods are: .Qq gssapi-with-mic , .Qq hostbased , .Qq keyboard-interactive , .Qq none (used for access to password-less accounts when .Cm PermitEmptyPasswords is enabled), .Qq password and .Qq publickey . .It Cm AuthorizedKeysCommand Specifies a program to be used to look up the user's public keys. The program must be owned by root, not writable by group or others and specified by an absolute path. Arguments to .Cm AuthorizedKeysCommand accept the tokens described in the .Sx TOKENS section. If no arguments are specified then the username of the target user is used. .Pp The program should produce on standard output zero or more lines of authorized_keys output (see .Sx AUTHORIZED_KEYS in .Xr sshd 8 ) . .Cm AuthorizedKeysCommand is tried after the usual .Cm AuthorizedKeysFile files and will not be executed if a matching key is found there. By default, no .Cm AuthorizedKeysCommand is run. .It Cm AuthorizedKeysCommandUser Specifies the user under whose account the .Cm AuthorizedKeysCommand is run. It is recommended to use a dedicated user that has no other role on the host than running authorized keys commands. If .Cm AuthorizedKeysCommand is specified but .Cm AuthorizedKeysCommandUser is not, then .Xr sshd 8 will refuse to start. .It Cm AuthorizedKeysFile Specifies the file that contains the public keys used for user authentication. The format is described in the AUTHORIZED_KEYS FILE FORMAT section of .Xr sshd 8 . Arguments to .Cm AuthorizedKeysFile accept the tokens described in the .Sx TOKENS section. After expansion, .Cm AuthorizedKeysFile is taken to be an absolute path or one relative to the user's home directory. Multiple files may be listed, separated by whitespace. Alternately this option may be set to .Cm none to skip checking for user keys in files. The default is .Qq .ssh/authorized_keys .ssh/authorized_keys2 . .It Cm AuthorizedPrincipalsCommand Specifies a program to be used to generate the list of allowed certificate principals as per .Cm AuthorizedPrincipalsFile . The program must be owned by root, not writable by group or others and specified by an absolute path. Arguments to .Cm AuthorizedPrincipalsCommand accept the tokens described in the .Sx TOKENS section. If no arguments are specified then the username of the target user is used. .Pp The program should produce on standard output zero or more lines of .Cm AuthorizedPrincipalsFile output. If either .Cm AuthorizedPrincipalsCommand or .Cm AuthorizedPrincipalsFile is specified, then certificates offered by the client for authentication must contain a principal that is listed. By default, no .Cm AuthorizedPrincipalsCommand is run. .It Cm AuthorizedPrincipalsCommandUser Specifies the user under whose account the .Cm AuthorizedPrincipalsCommand is run. It is recommended to use a dedicated user that has no other role on the host than running authorized principals commands. If .Cm AuthorizedPrincipalsCommand is specified but .Cm AuthorizedPrincipalsCommandUser is not, then .Xr sshd 8 will refuse to start. .It Cm AuthorizedPrincipalsFile Specifies a file that lists principal names that are accepted for certificate authentication. When using certificates signed by a key listed in .Cm TrustedUserCAKeys , this file lists names, one of which must appear in the certificate for it to be accepted for authentication. Names are listed one per line preceded by key options (as described in .Sx AUTHORIZED_KEYS FILE FORMAT in .Xr sshd 8 ) . Empty lines and comments starting with .Ql # are ignored. .Pp Arguments to .Cm AuthorizedPrincipalsFile accept the tokens described in the .Sx TOKENS section. After expansion, .Cm AuthorizedPrincipalsFile is taken to be an absolute path or one relative to the user's home directory. The default is .Cm none , i.e. not to use a principals file \(en in this case, the username of the user must appear in a certificate's principals list for it to be accepted. .Pp Note that .Cm AuthorizedPrincipalsFile is only used when authentication proceeds using a CA listed in .Cm TrustedUserCAKeys and is not consulted for certification authorities trusted via .Pa ~/.ssh/authorized_keys , though the .Cm principals= key option offers a similar facility (see .Xr sshd 8 for details). .It Cm Banner The contents of the specified file are sent to the remote user before authentication is allowed. If the argument is .Cm none then no banner is displayed. By default, no banner is displayed. .It Cm CASignatureAlgorithms Specifies which algorithms are allowed for signing of certificates by certificate authorities (CAs). The default is: .Bd -literal -offset indent 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 .Ed .Pp If the specified list begins with a .Sq + 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 algorithms (including wildcards) will be removed from the default set instead of replacing them. .Pp Certificates signed using other algorithms will not be accepted for public key or host-based authentication. .It Cm ChannelTimeout Specifies whether and how quickly .Xr sshd 8 should close inactive channels. Timeouts are specified as one or more .Dq type=interval pairs separated by whitespace, where the .Dq type must be a channel type name (as described in the table below), optionally containing wildcard characters. .Pp The timeout value .Dq interval is specified in seconds or may use any of the units documented in the .Sx TIME FORMATS section. For example, .Dq session:*=5m would cause all sessions to terminate after five minutes of inactivity. Specifying a zero value disables the inactivity timeout. .Pp The available channel types include: .Bl -tag -width Ds .It Cm agent-connection Open connections to .Xr ssh-agent 1 . .It Cm direct-tcpip , Cm direct-streamlocal@openssh.com Open TCP or Unix socket (respectively) connections that have been established from a .Xr ssh 1 local forwarding, i.e.\& .Cm LocalForward or .Cm DynamicForward . .It Cm forwarded-tcpip , Cm forwarded-streamlocal@openssh.com Open TCP or Unix socket (respectively) connections that have been established to a .Xr sshd 8 listening on behalf of a .Xr ssh 1 remote forwarding, i.e.\& .Cm RemoteForward . .It Cm session:command Command execution sessions. .It Cm session:shell Interactive shell sessions. .It Cm session:subsystem:... Subsystem sessions, e.g. for .Xr sftp 1 , which could be identified as .Cm session:subsystem:sftp . .It Cm x11-connection Open X11 forwarding sessions. .El .Pp Note that in all the above cases, terminating an inactive session does not guarantee to remove all resources associated with the session, e.g. shell processes or X11 clients relating to the session may continue to execute. .Pp Moreover, terminating an inactive channel or session does not necessarily close the SSH connection, nor does it prevent a client from requesting another channel of the same type. In particular, expiring an inactive forwarding session does not prevent another identical forwarding from being subsequently created. See also .Cm UnusedConnectionTimeout , which may be used in conjunction with this option. .Pp The default is not to expire channels of any type for inactivity. .It Cm ChrootDirectory Specifies the pathname of a directory to .Xr chroot 2 to after authentication. At session startup .Xr sshd 8 checks that all components of the pathname are root-owned directories which are not writable by any other user or group. After the chroot, .Xr sshd 8 changes the working directory to the user's home directory. Arguments to .Cm ChrootDirectory accept the tokens described in the .Sx TOKENS section. .Pp The .Cm ChrootDirectory must contain the necessary files and directories to support the user's session. For an interactive session this requires at least a shell, typically .Xr sh 1 , and basic .Pa /dev nodes such as .Xr null 4 , .Xr zero 4 , .Xr stdin 4 , .Xr stdout 4 , .Xr stderr 4 , and .Xr tty 4 devices. For file transfer sessions using SFTP no additional configuration of the environment is necessary if the in-process sftp-server is used, though sessions which use logging may require .Pa /dev/log inside the chroot directory on some operating systems (see .Xr sftp-server 8 for details). .Pp For safety, it is very important that the directory hierarchy be prevented from modification by other processes on the system (especially those outside the jail). Misconfiguration can lead to unsafe environments which .Xr sshd 8 cannot detect. .Pp The default is .Cm none , indicating not to .Xr chroot 2 . .It Cm Ciphers Specifies the ciphers allowed. Multiple ciphers must be comma-separated. If the specified list begins with a .Sq + character, then the specified ciphers will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - character, then the specified ciphers (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 ciphers will be placed at the head of the default set. .Pp The supported ciphers are: .Pp .Bl -item -compact -offset indent .It 3des-cbc .It aes128-cbc .It aes192-cbc .It aes256-cbc .It aes128-ctr .It aes192-ctr .It aes256-ctr .It aes128-gcm@openssh.com .It aes256-gcm@openssh.com .It chacha20-poly1305@openssh.com .El .Pp The default is: .Bd -literal -offset indent chacha20-poly1305@openssh.com, aes128-ctr,aes192-ctr,aes256-ctr, aes128-gcm@openssh.com,aes256-gcm@openssh.com .Ed .Pp The list of available ciphers may also be obtained using .Qq ssh -Q cipher . .It Cm ClientAliveCountMax Sets the number of client alive messages which may be sent without .Xr sshd 8 receiving any messages back from the client. If this threshold is reached while client alive messages are being sent, sshd will disconnect the client, terminating the session. It is important to note that the use of client alive messages is very different from .Cm TCPKeepAlive . The client alive messages are sent through the encrypted channel and therefore will not be spoofable. The TCP keepalive option enabled by .Cm TCPKeepAlive is spoofable. The client alive mechanism is valuable when the client or server depend on knowing when a connection has become unresponsive. .Pp The default value is 3. If .Cm ClientAliveInterval is set to 15, and .Cm ClientAliveCountMax is left at the default, unresponsive SSH clients will be disconnected after approximately 45 seconds. 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, .Xr sshd 8 will send a message through the encrypted channel to request a response from the client. The default is 0, indicating that these messages will not be sent to the client. .It Cm Compression Specifies whether compression is enabled after the user has authenticated successfully. The argument must be .Cm yes , .Cm delayed (a legacy synonym for .Cm yes ) or .Cm no . The default is .Cm yes . .It Cm DenyGroups This keyword can be followed by a list of group name patterns, separated by spaces. Login is disallowed for users whose primary group or supplementary group list matches one of the patterns. Only group names are valid; a numerical group ID is not recognized. By default, login is allowed for all groups. The allow/deny groups directives are processed in the following order: .Cm DenyGroups , .Cm AllowGroups . .Pp See PATTERNS in .Xr ssh_config 5 for more information on patterns. This keyword may appear multiple times in .Nm with each instance appending to the list. .It Cm DenyUsers This keyword can be followed by a list of user name patterns, separated by spaces. Login is disallowed for user names that match one of the patterns. Only user names are valid; a numerical user ID is not recognized. By default, login is allowed for all users. If the pattern takes the form USER@HOST then USER and HOST are separately checked, restricting logins to particular users from particular hosts. HOST criteria may additionally contain addresses to match in CIDR address/masklen format. The allow/deny users directives are processed in the following order: .Cm DenyUsers , .Cm AllowUsers . .Pp See PATTERNS in .Xr ssh_config 5 for more information on patterns. This keyword may appear multiple times in .Nm with each instance appending to the list. .It Cm DisableForwarding Disables all forwarding features, including X11, .Xr ssh-agent 1 , TCP and StreamLocal. This option overrides all other forwarding-related options and may simplify restricted configurations. .It Cm ExposeAuthInfo Writes a temporary file containing a list of authentication methods and public credentials (e.g. keys) used to authenticate the user. The location of the file is exposed to the user session through the .Ev SSH_USER_AUTH environment variable. The default is .Cm no . .It Cm FingerprintHash Specifies the hash algorithm used when logging key fingerprints. Valid options are: .Cm md5 and .Cm sha256 . The default is .Cm sha256 . .It Cm ForceCommand Forces the execution of the command specified by .Cm ForceCommand , ignoring any command supplied by the client and .Pa ~/.ssh/rc if present. The command is invoked by using the user's login shell with the -c option. This applies to shell, command, or subsystem execution. It is most useful inside a .Cm Match block. The command originally supplied by the client is available in the .Ev SSH_ORIGINAL_COMMAND environment variable. Specifying a command of .Cm internal-sftp will force the use of an in-process SFTP server that requires no support files when used with .Cm ChrootDirectory . The default is .Cm none . .It Cm GatewayPorts Specifies whether remote hosts are allowed to connect to ports forwarded for the client. By default, .Xr sshd 8 binds remote port forwardings to the loopback address. This prevents other remote hosts from connecting to forwarded ports. .Cm GatewayPorts can be used to specify that sshd should allow remote port forwardings to bind to non-loopback addresses, thus allowing other hosts to connect. The argument may be .Cm no to force remote port forwardings to be available to the local host only, .Cm yes to force remote port forwardings to bind to the wildcard address, or .Cm clientspecified to allow the client to select the address to which the forwarding is bound. The default is .Cm no . .It Cm GSSAPIAuthentication Specifies whether user authentication based on GSSAPI is allowed. The default is .Cm no . .It Cm GSSAPICleanupCredentials Specifies whether to automatically destroy the user's credentials cache on logout. The default is .Cm yes . .It Cm GSSAPIStrictAcceptorCheck Determines whether to be strict about the identity of the GSSAPI acceptor a client authenticates against. If set to .Cm yes then the client must authenticate against the host service on the current hostname. If set to .Cm no then the client may authenticate against any service key stored in the machine's default store. This facility is provided to assist with operation on multi homed machines. The default is .Cm yes . .It Cm 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 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-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 .Ed .Pp 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 (host-based authentication). The default is .Cm no . .It Cm HostbasedUsesNameFromPacketOnly Specifies whether or not the server will attempt to perform a reverse name lookup when matching the name in the .Pa ~/.shosts , .Pa ~/.rhosts , and .Pa /etc/hosts.equiv files during .Cm HostbasedAuthentication . A setting of .Cm yes means that .Xr sshd 8 uses the name supplied by the client rather than attempting to resolve the name from the TCP connection itself. The default is .Cm no . .It Cm HostCertificate Specifies a file containing a public host certificate. The certificate's public key must match a private host key already specified by .Cm HostKey . The default behaviour of .Xr sshd 8 is not to load any certificates. .It Cm HostKey Specifies a file containing a private host key used by SSH. The defaults are .Pa /etc/ssh/ssh_host_ecdsa_key , .Pa /etc/ssh/ssh_host_ed25519_key and .Pa /etc/ssh/ssh_host_rsa_key . .Pp Note that .Xr sshd 8 will refuse to use a file if it is group/world-accessible and that the .Cm HostKeyAlgorithms option restricts which of the keys are actually used by .Xr sshd 8 . .Pp It is possible to have multiple host key files. It is also possible to specify public host key files instead. In this case operations on the private key will be delegated to an .Xr ssh-agent 1 . .It Cm HostKeyAgent Identifies the UNIX-domain socket used to communicate with an agent that has access to the private host keys. If the string .Qq SSH_AUTH_SOCK is specified, the location of the socket will be read from the .Ev SSH_AUTH_SOCK environment variable. .It Cm HostKeyAlgorithms Specifies the host key 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, 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-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 .Ed .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q HostKeyAlgorithms . .It Cm IgnoreRhosts Specifies whether to ignore per-user .Pa .rhosts and .Pa .shosts files during .Cm HostbasedAuthentication . The system-wide .Pa /etc/hosts.equiv and .Pa /etc/ssh/shosts.equiv 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 should ignore the user's .Pa ~/.ssh/known_hosts during .Cm HostbasedAuthentication and use only the system-wide known hosts file .Pa /etc/ssh/ssh_known_hosts . The default is .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 .Cm af11 , .Cm af12 , .Cm af13 , .Cm af21 , .Cm af22 , .Cm af23 , .Cm af31 , .Cm af32 , .Cm af33 , .Cm af41 , .Cm af42 , .Cm af43 , .Cm cs0 , .Cm cs1 , .Cm cs2 , .Cm cs3 , .Cm cs4 , .Cm cs5 , .Cm cs6 , .Cm cs7 , .Cm ef , .Cm le , .Cm lowdelay , .Cm throughput , .Cm reliability , a numeric value, or .Cm none to use the operating system default. This option may take one or two arguments, separated by whitespace. If one argument is specified, it is used as the packet class unconditionally. If two values are specified, the first is automatically selected for interactive sessions and the second for non-interactive sessions. The default is .Cm af21 (Low-Latency Data) for interactive sessions and .Cm cs1 (Lower Effort) for non-interactive sessions. .It Cm KbdInteractiveAuthentication Specifies whether to allow keyboard-interactive authentication. All authentication styles from .Xr login.conf 5 are supported. The default is .Cm yes . The argument to this keyword must be .Cm yes or .Cm no . .Cm ChallengeResponseAuthentication is a deprecated alias for this. .It Cm KerberosAuthentication Specifies whether the password provided by the user for .Cm PasswordAuthentication will be validated through the Kerberos KDC. To use this option, the server needs a Kerberos servtab which allows the verification of the KDC's identity. The default is .Cm no . .It Cm KerberosGetAFSToken If AFS is active and the user has a Kerberos 5 TGT, attempt to acquire an AFS token before accessing the user's home directory. The default is .Cm no . .It Cm KerberosOrLocalPasswd If password authentication through Kerberos fails then the password will be validated via any additional local mechanism such as .Pa /etc/passwd . The default is .Cm yes . .It Cm KerberosTicketCleanup Specifies whether to automatically destroy the user's ticket cache file on logout. The default is .Cm yes . .It Cm KexAlgorithms Specifies the available KEX (Key Exchange) algorithms. Multiple algorithms must be comma-separated. Alternately if the specified list begins with a .Sq + 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 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 algorithms will be placed at the head of the default set. The supported algorithms are: .Pp .Bl -item -compact -offset indent .It curve25519-sha256 .It curve25519-sha256@libssh.org .It diffie-hellman-group1-sha1 .It diffie-hellman-group14-sha1 .It diffie-hellman-group14-sha256 .It diffie-hellman-group16-sha512 .It diffie-hellman-group18-sha512 .It diffie-hellman-group-exchange-sha1 .It diffie-hellman-group-exchange-sha256 .It ecdh-sha2-nistp256 .It ecdh-sha2-nistp384 .It ecdh-sha2-nistp521 .It sntrup761x25519-sha512@openssh.com .El .Pp The default is: .Bd -literal -offset indent sntrup761x25519-sha512@openssh.com, 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 .Ed .Pp The list of available key exchange algorithms may also be obtained using .Qq ssh -Q KexAlgorithms . .It Cm ListenAddress Specifies the local addresses .Xr sshd 8 should listen on. The following forms may be used: .Pp .Bl -item -offset indent -compact .It .Cm ListenAddress .Sm off .Ar hostname | address .Sm on .Op Cm rdomain Ar domain .It .Cm ListenAddress .Sm off .Ar hostname : port .Sm on .Op Cm rdomain Ar domain .It .Cm ListenAddress .Sm off .Ar IPv4_address : port .Sm on .Op Cm rdomain Ar domain .It .Cm ListenAddress .Sm off .Oo Ar hostname | address Oc : Ar port .Sm on .Op Cm rdomain Ar domain .El .Pp The optional .Cm rdomain qualifier requests .Xr sshd 8 listen in an explicit routing domain. If .Ar port is not specified, sshd will listen on the address and all .Cm Port options specified. The default is to listen on all local addresses on the current default routing domain. Multiple .Cm ListenAddress options are permitted. For more information on routing domains, see .Xr rdomain 4 . .It Cm LoginGraceTime The server disconnects after this time if the user has not successfully logged in. If the value is 0, there is no time limit. The default is 120 seconds. .It Cm LogLevel Gives the verbosity level that is used when logging messages from .Xr sshd 8 . The possible values are: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO. DEBUG and DEBUG1 are equivalent. DEBUG2 and DEBUG3 each specify higher levels of debugging output. Logging with a DEBUG level violates the privacy of users and is not recommended. .It Cm 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. Multiple algorithms must be comma-separated. If the specified list begins with a .Sq + 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 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 algorithms will be placed at the head of the default set. .Pp The algorithms that contain .Qq -etm calculate the MAC after encryption (encrypt-then-mac). These are considered safer and their use recommended. The supported MACs are: .Pp .Bl -item -compact -offset indent .It hmac-md5 .It hmac-md5-96 .It hmac-sha1 .It hmac-sha1-96 .It hmac-sha2-256 .It hmac-sha2-512 .It umac-64@openssh.com .It umac-128@openssh.com .It hmac-md5-etm@openssh.com .It hmac-md5-96-etm@openssh.com .It hmac-sha1-etm@openssh.com .It hmac-sha1-96-etm@openssh.com .It hmac-sha2-256-etm@openssh.com .It hmac-sha2-512-etm@openssh.com .It umac-64-etm@openssh.com .It umac-128-etm@openssh.com .El .Pp The default is: .Bd -literal -offset indent umac-64-etm@openssh.com,umac-128-etm@openssh.com, hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, hmac-sha1-etm@openssh.com, umac-64@openssh.com,umac-128@openssh.com, hmac-sha2-256,hmac-sha2-512,hmac-sha1 .Ed .Pp The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . .It Cm Match Introduces a conditional block. If all of the criteria on the .Cm Match line are satisfied, the keywords on the following lines override those set in the global section of the config file, until either another .Cm Match line or the end of the file. If a keyword appears in multiple .Cm Match blocks that are satisfied, only the first instance of the keyword is applied. .Pp The arguments to .Cm Match are one or more criteria-pattern pairs or the single token .Cm All which matches all criteria. The available criteria are .Cm User , .Cm Group , .Cm Host , .Cm LocalAddress , .Cm LocalPort , .Cm RDomain , and .Cm Address (with .Cm RDomain representing the .Xr rdomain 4 on which the connection was received). .Pp The match patterns may consist of single entries or comma-separated lists and may use the wildcard and negation operators described in the .Sx PATTERNS section of .Xr ssh_config 5 . .Pp The patterns in an .Cm Address criteria may additionally contain addresses to match in CIDR address/masklen format, such as 192.0.2.0/24 or 2001:db8::/32. Note that the mask length provided must be consistent with the address - it is an error to specify a mask length that is too long for the address or one with bits set in this host portion of the address. For example, 192.0.2.0/33 and 192.0.2.0/8, respectively. .Pp Only a subset of keywords may be used on the lines following a .Cm Match keyword. Available keywords are .Cm AcceptEnv , .Cm AllowAgentForwarding , .Cm AllowGroups , .Cm AllowStreamLocalForwarding , .Cm AllowTcpForwarding , .Cm AllowUsers , .Cm AuthenticationMethods , .Cm AuthorizedKeysCommand , .Cm AuthorizedKeysCommandUser , .Cm AuthorizedKeysFile , .Cm AuthorizedPrincipalsCommand , .Cm AuthorizedPrincipalsCommandUser , .Cm AuthorizedPrincipalsFile , .Cm Banner , .Cm CASignatureAlgorithms , .Cm ChannelTimeout , .Cm ChrootDirectory , .Cm ClientAliveCountMax , .Cm ClientAliveInterval , .Cm DenyGroups , .Cm DenyUsers , .Cm DisableForwarding , .Cm ExposeAuthInfo , .Cm ForceCommand , .Cm GatewayPorts , .Cm GSSAPIAuthentication , .Cm HostbasedAcceptedAlgorithms , .Cm HostbasedAuthentication , .Cm HostbasedUsesNameFromPacketOnly , .Cm IgnoreRhosts , .Cm Include , .Cm IPQoS , .Cm KbdInteractiveAuthentication , .Cm KerberosAuthentication , .Cm LogLevel , .Cm MaxAuthTries , .Cm MaxSessions , .Cm PasswordAuthentication , .Cm PermitEmptyPasswords , .Cm PermitListen , .Cm PermitOpen , .Cm PermitRootLogin , .Cm PermitTTY , .Cm PermitTunnel , .Cm PermitUserRC , .Cm PubkeyAcceptedAlgorithms , .Cm PubkeyAuthentication , .Cm PubkeyAuthOptions , .Cm RekeyLimit , .Cm RevokedKeys , .Cm RDomain , .Cm SetEnv , .Cm StreamLocalBindMask , .Cm StreamLocalBindUnlink , .Cm TrustedUserCAKeys , .Cm UnusedConnectionTimeout , .Cm X11DisplayOffset , .Cm X11Forwarding and .Cm X11UseLocalhost . .It Cm MaxAuthTries Specifies the maximum number of authentication attempts permitted per connection. Once the number of failures reaches half this value, additional failures are logged. The default is 6. .It Cm MaxSessions Specifies the maximum number of open shell, login or subsystem (e.g. sftp) sessions permitted per network connection. Multiple sessions may be established by clients that support connection multiplexing. Setting .Cm MaxSessions to 1 will effectively disable session multiplexing, whereas setting it to 0 will prevent all shell, login and subsystem sessions while still permitting forwarding. The default is 10. .It Cm MaxStartups Specifies the maximum number of concurrent unauthenticated connections to the SSH daemon. Additional connections will be dropped until authentication succeeds or the .Cm LoginGraceTime expires for a connection. The default is 10:30:100. .Pp Alternatively, random early drop can be enabled by specifying the three colon separated values start:rate:full (e.g. "10:30:60"). .Xr sshd 8 will refuse connection attempts with a probability of rate/100 (30%) if there are currently start (10) unauthenticated connections. The probability increases linearly and all connection attempts are refused if the number of unauthenticated connections reaches full (60). .It Cm ModuliFile Specifies the .Xr moduli 5 file that contains the Diffie-Hellman groups used for the .Dq diffie-hellman-group-exchange-sha1 and .Dq diffie-hellman-group-exchange-sha256 key exchange methods. The default is .Pa /etc/moduli . .It Cm PasswordAuthentication Specifies whether password authentication is allowed. Note that passwords may also be accepted via .Cm KbdInteractiveAuthentication . See also .Cm UsePAM . The default is .Cm no . .It Cm PermitEmptyPasswords When password authentication is allowed, it specifies whether the server allows login to accounts with empty password strings. The default is .Cm no . .It Cm PermitListen Specifies the addresses/ports on which a remote TCP port forwarding may listen. The listen specification must be one of the following forms: .Pp .Bl -item -offset indent -compact .It .Cm PermitListen .Sm off .Ar port .Sm on .It .Cm PermitListen .Sm off .Ar host : port .Sm on .El .Pp Multiple permissions may be specified by separating them with whitespace. An argument of .Cm any can be used to remove all restrictions and permit any listen requests. An argument of .Cm none can be used to prohibit all listen requests. The host name may contain wildcards as described in the PATTERNS section in .Xr ssh_config 5 . The wildcard .Sq * can also be used in place of a port number to allow all ports. By default all port forwarding listen requests are permitted. Note that the .Cm GatewayPorts option may further restrict which addresses may be listened on. Note also that .Xr ssh 1 will request a listen host of .Dq localhost if no listen host was specifically requested, and this name is treated differently to explicit localhost addresses of .Dq 127.0.0.1 and .Dq ::1 . .It Cm PermitOpen Specifies the destinations to which TCP port forwarding is permitted. The forwarding specification must be one of the following forms: .Pp .Bl -item -offset indent -compact .It .Cm PermitOpen .Sm off .Ar host : port .Sm on .It .Cm PermitOpen .Sm off .Ar IPv4_addr : port .Sm on .It .Cm PermitOpen .Sm off .Ar \&[ IPv6_addr \&] : port .Sm on .El .Pp Multiple forwards may be specified by separating them with whitespace. An argument of .Cm any can be used to remove all restrictions and permit any forwarding requests. An argument of .Cm none can be used to prohibit all forwarding requests. The wildcard .Sq * can be used for host or port to allow all hosts or ports respectively. 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 .Xr ssh 1 . The argument must be .Cm yes , .Cm prohibit-password , .Cm forced-commands-only , or .Cm no . The default is .Cm no . Note that if .Cm ChallengeResponseAuthentication and .Cm UsePAM are both .Cm yes , this setting may be overridden by the PAM policy. .Pp If this option is set to .Cm prohibit-password (or its deprecated alias, .Cm without-password ) , password and keyboard-interactive authentication are disabled for root. .Pp If this option is set to .Cm forced-commands-only , root login with public key authentication will be allowed, but only if the .Ar command option has been specified (which may be useful for taking remote backups even if root login is normally not allowed). All other authentication methods are disabled for root. .Pp If this option is set to .Cm no , root is not allowed to log in. .It Cm PermitTTY Specifies whether .Xr pty 4 allocation is permitted. The default is .Cm yes . .It Cm PermitTunnel Specifies whether .Xr tun 4 device forwarding is allowed. The argument must be .Cm yes , .Cm point-to-point (layer 3), .Cm ethernet (layer 2), or .Cm no . Specifying .Cm yes permits both .Cm point-to-point and .Cm ethernet . The default is .Cm no . .Pp Independent of this setting, the permissions of the selected .Xr tun 4 device must allow access to the user. .It Cm PermitUserEnvironment Specifies whether .Pa ~/.ssh/environment and .Cm environment= options in .Pa ~/.ssh/authorized_keys are processed by .Xr sshd 8 . Valid options are .Cm yes , .Cm no or a pattern-list specifying which environment variable names to accept (for example .Qq LANG,LC_* ) . The default is .Cm no . Enabling environment processing may enable users to bypass access restrictions in some configurations using mechanisms such as .Ev LD_PRELOAD . .It Cm PermitUserRC Specifies whether any .Pa ~/.ssh/rc file is executed. The default is .Cm yes . .It Cm 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 .Cm none to not write one. The default is .Pa /var/run/sshd.pid . .It Cm Port Specifies the port number that .Xr sshd 8 listens on. The default is 22. Multiple options of this type are permitted. See also .Cm ListenAddress . .It Cm PrintLastLog Specifies whether .Xr sshd 8 should print the date and time of the last user login when a user logs in interactively. The default is .Cm yes . .It Cm PrintMotd Specifies whether .Xr sshd 8 should print .Pa /etc/motd when a user logs in interactively. (On some systems it is also printed by the shell, .Pa /etc/profile , or equivalent.) The default is .Cm yes . .It Cm 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 algorithms will be appended to the default set instead of replacing them. If the specified list begins with a .Sq - 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 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-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 .Ed .Pp 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 or received before the 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 , .Sq M , or .Sq G to indicate Kilobytes, Megabytes, or Gigabytes, respectively. The default is between .Sq 1G and .Sq 4G , depending on the cipher. The optional second value is specified in seconds and may use any of the units documented in the .Sx TIME FORMATS section. The default value for .Cm RekeyLimit is .Cm default none , which means that rekeying is performed after the cipher's default amount of data has been sent or received and no time based rekeying is done. .It Cm RequiredRSASize Specifies the minimum RSA key size (in bits) that .Xr sshd 8 will accept. User and host-based authentication keys smaller than this limit will be refused. The default is .Cm 1024 bits. Note that this limit may only be raised from the default. .It Cm RevokedKeys Specifies revoked public keys file, or .Cm none to not use one. Keys listed in this file will be refused for public key authentication. Note that if this file is not readable, then public key authentication will be refused for all users. Keys may be specified as a text file, listing one public key per line, or as an OpenSSH Key Revocation List (KRL) as generated by .Xr ssh-keygen 1 . For more information on KRLs, see the KEY REVOCATION LISTS section in .Xr ssh-keygen 1 . .It Cm RDomain Specifies an explicit routing domain that is applied after authentication has completed. The user session, as well as any forwarded or listening IP sockets, will be bound to this .Xr rdomain 4 . If the routing domain is set to .Cm \&%D , then the domain in which the incoming connection was received will be applied. .It Cm 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 .Xr sshd 8 as .Dq NAME=VALUE . The environment value may be quoted (e.g. if it contains whitespace characters). Environment variables set by .Cm SetEnv override the default environment and any variables specified by the user via .Cm AcceptEnv or .Cm PermitUserEnvironment . .It Cm StreamLocalBindMask Sets the octal file creation mode mask .Pq umask used when creating a Unix-domain socket file for local or remote port forwarding. This option is only used for port forwarding to a Unix-domain socket file. .Pp The default value is 0177, which creates a Unix-domain socket file that is readable and writable only by the owner. Note that not all operating systems honor the file mode on Unix-domain socket files. .It Cm StreamLocalBindUnlink Specifies whether to remove an existing Unix-domain socket file for local or remote port forwarding before creating a new one. If the socket file already exists and .Cm StreamLocalBindUnlink is not enabled, .Nm sshd will be unable to forward the port to the Unix-domain socket file. This option is only used for port forwarding to a Unix-domain socket file. .Pp The argument must be .Cm yes or .Cm no . The default is .Cm no . .It Cm StrictModes Specifies whether .Xr sshd 8 should check file modes and ownership of the user's files and home directory before accepting login. This is normally desirable because novices sometimes accidentally leave their directory or files world-writable. The default is .Cm yes . Note that this does not apply to .Cm ChrootDirectory , whose permissions and ownership are checked unconditionally. .It Cm Subsystem Configures an external subsystem (e.g. file transfer daemon). Arguments should be a subsystem name and a command (with optional arguments) to execute upon subsystem request. .Pp The command .Cm sftp-server implements the SFTP file transfer subsystem. .Pp Alternately the name .Cm internal-sftp implements an in-process SFTP server. This may simplify configurations using .Cm ChrootDirectory to force a different filesystem root on clients. .Pp By default no subsystems are defined. .It Cm SyslogFacility Gives the facility code that is used when logging messages from .Xr sshd 8 . The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The default is AUTH. .It Cm TCPKeepAlive Specifies whether the system should send TCP keepalive messages to the other side. If they are sent, death of the connection or crash of one of the machines will be properly noticed. However, this means that connections will die if the route is down temporarily, and some people find it annoying. On the other hand, if TCP keepalives are not sent, sessions may hang indefinitely on the server, leaving .Qq ghost users and consuming server resources. .Pp The default is .Cm yes (to send TCP keepalive messages), and the server will notice if the network goes down or the client host crashes. This avoids infinitely hanging sessions. .Pp To disable TCP keepalive messages, the value should be set to .Cm no . .It Cm TrustedUserCAKeys Specifies a file containing public keys of certificate authorities that are trusted to sign user certificates for authentication, or .Cm none to not use one. Keys are listed one per line; empty lines and comments starting with .Ql # are allowed. If a certificate is presented for authentication and has its signing CA key listed in this file, then it may be used for authentication for any user listed in the certificate's principals list. Note that certificates that lack a list of principals will not be permitted for authentication using .Cm TrustedUserCAKeys . For more details on certificates, see the CERTIFICATES section in .Xr ssh-keygen 1 . .It Cm UnusedConnectionTimeout Specifies whether and how quickly .Xr sshd 8 should close client connections with no open channels. Open channels include active shell, command execution or subsystem sessions, connected network, socket, agent or X11 forwardings. Forwarding listeners, such as those from the .Xr ssh 1 .Fl R flag, are not considered as open channels and do not prevent the timeout. The timeout value is specified in seconds or may use any of the units documented in the .Sx TIME FORMATS section. .Pp Note that this timeout starts when the client connection completes user authentication but before the client has an opportunity to open any channels. Caution should be used when using short timeout values, as they may not provide sufficient time for the client to request and open its channels before terminating the connection. .Pp The default .Cm none is to never expire connections for having no open channels. This option may be useful in conjunction with .Cm ChannelTimeout . .It Cm UseBlacklist Specifies whether .Xr sshd 8 attempts to send authentication success and failure messages to the .Xr blacklistd 8 daemon. The default is .Cm no . For forward compatibility with an upcoming .Xr blacklistd rename, the .Cm UseBlocklist alias can be used instead. .It Cm UseDNS Specifies whether .Xr sshd 8 should look up the remote host name, and to check that the resolved host name for the remote IP address maps back to the very same IP address. .Pp If this option is set to .Cm no , then only addresses and not host names may be used in .Pa ~/.ssh/authorized_keys .Cm from and .Nm .Cm Match .Cm Host directives. The default is .Dq yes . .It Cm UsePAM Enables the Pluggable Authentication Module interface. If set to .Cm yes this will enable PAM authentication using .Cm KbdInteractiveAuthentication and .Cm PasswordAuthentication in addition to PAM account and session module processing for all authentication types. .Pp Because PAM keyboard-interactive authentication usually serves an equivalent role to password authentication, you should disable either .Cm PasswordAuthentication or .Cm KbdInteractiveAuthentication . .Pp If .Cm UsePAM is enabled, you will not be able to run .Xr sshd 8 as a non-root user. The default is .Cm yes . .It Cm VersionAddendum Optionally specifies additional text to append to the SSH protocol banner sent by the server upon connection. The default is -.Qq FreeBSD-20231004 . +.Qq FreeBSD-20240104 . The value .Cm none may be used to disable this. .It Cm X11DisplayOffset Specifies the first display number available for .Xr sshd 8 Ns 's X11 forwarding. This prevents sshd from interfering with real X11 servers. The default is 10. .It Cm X11Forwarding Specifies whether X11 forwarding is permitted. The argument must be .Cm yes or .Cm no . The default is .Cm no . .Pp When X11 forwarding is enabled, there may be additional exposure to the server and to client displays if the .Xr sshd 8 proxy display is configured to listen on the wildcard address (see .Cm X11UseLocalhost ) , though this is not the default. Additionally, the authentication spoofing and authentication data verification and substitution occur on the client side. The security risk of using X11 forwarding is that the client's X11 display server may be exposed to attack when the SSH client requests forwarding (see the warnings for .Cm ForwardX11 in .Xr ssh_config 5 ) . A system administrator may have a stance in which they want to protect clients that may expose themselves to attack by unwittingly requesting X11 forwarding, which can warrant a .Cm no setting. .Pp Note that disabling X11 forwarding does not prevent users from forwarding X11 traffic, as users can always install their own forwarders. .It Cm X11UseLocalhost Specifies whether .Xr sshd 8 should bind the X11 forwarding server to the loopback address or to the wildcard address. By default, sshd binds the forwarding server to the loopback address and sets the hostname part of the .Ev DISPLAY environment variable to .Cm localhost . This prevents remote hosts from connecting to the proxy display. However, some older X11 clients may not function with this configuration. .Cm X11UseLocalhost may be set to .Cm no to specify that the forwarding server should be bound to the wildcard address. The argument must be .Cm yes or .Cm no . The default is .Cm yes . .It Cm XAuthLocation Specifies the full pathname of the .Xr xauth 1 program, or .Cm none to not use one. The default is .Pa /usr/local/bin/xauth . .El .Sh TIME FORMATS .Xr sshd 8 command-line arguments and configuration file options that specify time may be expressed using a sequence of the form: .Sm off .Ar time Op Ar qualifier , .Sm on where .Ar time is a positive integer value and .Ar qualifier is one of the following: .Pp .Bl -tag -width Ds -compact -offset indent .It Aq Cm none seconds .It Cm s | Cm S seconds .It Cm m | Cm M minutes .It Cm h | Cm H hours .It Cm d | Cm D days .It Cm w | Cm W weeks .El .Pp Each member of the sequence is added together to calculate the total time value. .Pp Time format examples: .Pp .Bl -tag -width Ds -compact -offset indent .It 600 600 seconds (10 minutes) .It 10m 10 minutes .It 1h30m 1 hour 30 minutes (90 minutes) .El .Sh TOKENS Arguments to some keywords can make use of tokens, which are expanded at runtime: .Pp .Bl -tag -width XXXX -offset indent -compact .It %% A literal .Sq % . .It \&%C Identifies the connection endpoints, containing four space-separated values: client address, client port number, server address, and server port number. .It \&%D The routing domain in which the incoming connection was received. .It %F The fingerprint of the CA key. .It %f The fingerprint of the key or certificate. .It %h The home directory of the user. .It %i The key ID in the certificate. .It %K The base64-encoded CA key. .It %k The base64-encoded key or certificate for authentication. .It %s The serial number of the certificate. .It \&%T The type of the CA key. .It %t The key or certificate type. .It \&%U The numeric user ID of the target user. .It %u The username. .El .Pp .Cm AuthorizedKeysCommand accepts the tokens %%, %C, %D, %f, %h, %k, %t, %U, and %u. .Pp .Cm AuthorizedKeysFile accepts the tokens %%, %h, %U, and %u. .Pp .Cm AuthorizedPrincipalsCommand accepts the tokens %%, %C, %D, %F, %f, %h, %i, %K, %k, %s, %T, %t, %U, and %u. .Pp .Cm AuthorizedPrincipalsFile accepts the tokens %%, %h, %U, and %u. .Pp .Cm ChrootDirectory accepts the tokens %%, %h, %U, and %u. .Pp .Cm RoutingDomain accepts the token %D. .Sh FILES .Bl -tag -width Ds .It Pa /etc/ssh/sshd_config Contains configuration data for .Xr sshd 8 . This file should be writable by root only, but it is recommended (though not necessary) that it be world-readable. .El .Sh SEE ALSO .Xr sftp-server 8 , .Xr sshd 8 .Sh AUTHORS .An -nosplit OpenSSH is a derivative of the original and free ssh 1.2.12 release by .An Tatu Ylonen . .An Aaron Campbell , Bob Beck , Markus Friedl , Niels Provos , .An Theo de Raadt and .An Dug Song removed many bugs, re-added newer features and created OpenSSH. .An Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. .An Niels Provos and .An Markus Friedl contributed support for privilege separation. diff --git a/crypto/openssh/sshkey.c b/crypto/openssh/sshkey.c index 2d3906ad8475..06db9b5da34b 100644 --- a/crypto/openssh/sshkey.c +++ b/crypto/openssh/sshkey.c @@ -1,3670 +1,3706 @@ -/* $OpenBSD: sshkey.c,v 1.138 2023/08/21 04:36:46 djm Exp $ */ +/* $OpenBSD: sshkey.c,v 1.140 2023/10/16 08:40:00 dtucker Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. * Copyright (c) 2010,2011 Damien Miller. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "includes.h" #include #include #ifdef WITH_OPENSSL #include #include #include #endif #include "crypto_api.h" #include #include #include #include #include #include #include #ifdef HAVE_UTIL_H #include #endif /* HAVE_UTIL_H */ #include "ssh2.h" #include "ssherr.h" #include "misc.h" #include "sshbuf.h" #include "cipher.h" #include "digest.h" #define SSHKEY_INTERNAL #include "sshkey.h" #include "match.h" #include "ssh-sk.h" #ifdef WITH_XMSS #include "sshkey-xmss.h" #include "xmss_fast.h" #endif #include "openbsd-compat/openssl-compat.h" /* openssh private key file format */ #define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n" #define MARK_END "-----END OPENSSH PRIVATE KEY-----\n" #define MARK_BEGIN_LEN (sizeof(MARK_BEGIN) - 1) #define MARK_END_LEN (sizeof(MARK_END) - 1) #define KDFNAME "bcrypt" #define AUTH_MAGIC "openssh-key-v1" #define SALT_LEN 16 #define DEFAULT_CIPHERNAME "aes256-ctr" #define DEFAULT_ROUNDS 24 /* Version identification string for SSH v1 identity files. */ #define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n" /* * Constants relating to "shielding" support; protection of keys expected * to remain in memory for long durations */ #define SSHKEY_SHIELD_PREKEY_LEN (16 * 1024) #define SSHKEY_SHIELD_CIPHER "aes256-ctr" /* XXX want AES-EME* */ #define SSHKEY_SHIELD_PREKEY_HASH SSH_DIGEST_SHA512 int sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, enum sshkey_serialize_rep); static int sshkey_from_blob_internal(struct sshbuf *buf, struct sshkey **keyp, int allow_cert); /* Supported key types */ extern const struct sshkey_impl sshkey_ed25519_impl; extern const struct sshkey_impl sshkey_ed25519_cert_impl; extern const struct sshkey_impl sshkey_ed25519_sk_impl; extern const struct sshkey_impl sshkey_ed25519_sk_cert_impl; #ifdef WITH_OPENSSL # ifdef OPENSSL_HAS_ECC # ifdef ENABLE_SK extern const struct sshkey_impl sshkey_ecdsa_sk_impl; extern const struct sshkey_impl sshkey_ecdsa_sk_cert_impl; extern const struct sshkey_impl sshkey_ecdsa_sk_webauthn_impl; # endif /* ENABLE_SK */ extern const struct sshkey_impl sshkey_ecdsa_nistp256_impl; extern const struct sshkey_impl sshkey_ecdsa_nistp256_cert_impl; extern const struct sshkey_impl sshkey_ecdsa_nistp384_impl; extern const struct sshkey_impl sshkey_ecdsa_nistp384_cert_impl; # ifdef OPENSSL_HAS_NISTP521 extern const struct sshkey_impl sshkey_ecdsa_nistp521_impl; extern const struct sshkey_impl sshkey_ecdsa_nistp521_cert_impl; # endif /* OPENSSL_HAS_NISTP521 */ # endif /* OPENSSL_HAS_ECC */ extern const struct sshkey_impl sshkey_rsa_impl; extern const struct sshkey_impl sshkey_rsa_cert_impl; extern const struct sshkey_impl sshkey_rsa_sha256_impl; extern const struct sshkey_impl sshkey_rsa_sha256_cert_impl; extern const struct sshkey_impl sshkey_rsa_sha512_impl; extern const struct sshkey_impl sshkey_rsa_sha512_cert_impl; extern const struct sshkey_impl sshkey_dss_impl; extern const struct sshkey_impl sshkey_dsa_cert_impl; #endif /* WITH_OPENSSL */ #ifdef WITH_XMSS extern const struct sshkey_impl sshkey_xmss_impl; extern const struct sshkey_impl sshkey_xmss_cert_impl; #endif const struct sshkey_impl * const keyimpls[] = { &sshkey_ed25519_impl, &sshkey_ed25519_cert_impl, #ifdef ENABLE_SK &sshkey_ed25519_sk_impl, &sshkey_ed25519_sk_cert_impl, #endif #ifdef WITH_OPENSSL # ifdef OPENSSL_HAS_ECC &sshkey_ecdsa_nistp256_impl, &sshkey_ecdsa_nistp256_cert_impl, &sshkey_ecdsa_nistp384_impl, &sshkey_ecdsa_nistp384_cert_impl, # ifdef OPENSSL_HAS_NISTP521 &sshkey_ecdsa_nistp521_impl, &sshkey_ecdsa_nistp521_cert_impl, # endif /* OPENSSL_HAS_NISTP521 */ # ifdef ENABLE_SK &sshkey_ecdsa_sk_impl, &sshkey_ecdsa_sk_cert_impl, &sshkey_ecdsa_sk_webauthn_impl, # endif /* ENABLE_SK */ # endif /* OPENSSL_HAS_ECC */ &sshkey_dss_impl, &sshkey_dsa_cert_impl, &sshkey_rsa_impl, &sshkey_rsa_cert_impl, &sshkey_rsa_sha256_impl, &sshkey_rsa_sha256_cert_impl, &sshkey_rsa_sha512_impl, &sshkey_rsa_sha512_cert_impl, #endif /* WITH_OPENSSL */ #ifdef WITH_XMSS &sshkey_xmss_impl, &sshkey_xmss_cert_impl, #endif NULL }; static const struct sshkey_impl * sshkey_impl_from_type(int type) { int i; for (i = 0; keyimpls[i] != NULL; i++) { if (keyimpls[i]->type == type) return keyimpls[i]; } return NULL; } static const struct sshkey_impl * sshkey_impl_from_type_nid(int type, int nid) { int i; for (i = 0; keyimpls[i] != NULL; i++) { if (keyimpls[i]->type == type && (keyimpls[i]->nid == 0 || keyimpls[i]->nid == nid)) return keyimpls[i]; } return NULL; } static const struct sshkey_impl * sshkey_impl_from_key(const struct sshkey *k) { if (k == NULL) return NULL; return sshkey_impl_from_type_nid(k->type, k->ecdsa_nid); } const char * sshkey_type(const struct sshkey *k) { const struct sshkey_impl *impl; if ((impl = sshkey_impl_from_key(k)) == NULL) return "unknown"; return impl->shortname; } static const char * sshkey_ssh_name_from_type_nid(int type, int nid) { const struct sshkey_impl *impl; if ((impl = sshkey_impl_from_type_nid(type, nid)) == NULL) return "ssh-unknown"; return impl->name; } int sshkey_type_is_cert(int type) { const struct sshkey_impl *impl; if ((impl = sshkey_impl_from_type(type)) == NULL) return 0; return impl->cert; } const char * sshkey_ssh_name(const struct sshkey *k) { return sshkey_ssh_name_from_type_nid(k->type, k->ecdsa_nid); } const char * sshkey_ssh_name_plain(const struct sshkey *k) { return sshkey_ssh_name_from_type_nid(sshkey_type_plain(k->type), k->ecdsa_nid); } int sshkey_type_from_name(const char *name) { int i; const struct sshkey_impl *impl; for (i = 0; keyimpls[i] != NULL; i++) { impl = keyimpls[i]; /* Only allow shortname matches for plain key types */ if ((impl->name != NULL && strcmp(name, impl->name) == 0) || (!impl->cert && strcasecmp(impl->shortname, name) == 0)) return impl->type; } 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) { int i; for (i = 0; keyimpls[i] != NULL; i++) { if (!key_type_is_ecdsa_variant(keyimpls[i]->type)) continue; if (keyimpls[i]->name != NULL && strcmp(name, keyimpls[i]->name) == 0) return keyimpls[i]->nid; } return -1; } int sshkey_match_keyname_to_sigalgs(const char *keyname, const char *sigalgs) { int ktype; if (sigalgs == NULL || *sigalgs == '\0' || (ktype = sshkey_type_from_name(keyname)) == KEY_UNSPEC) return 0; else if (ktype == KEY_RSA) { return match_pattern_list("ssh-rsa", sigalgs, 0) == 1 || match_pattern_list("rsa-sha2-256", sigalgs, 0) == 1 || match_pattern_list("rsa-sha2-512", sigalgs, 0) == 1; } else if (ktype == KEY_RSA_CERT) { return match_pattern_list("ssh-rsa-cert-v01@openssh.com", sigalgs, 0) == 1 || match_pattern_list("rsa-sha2-256-cert-v01@openssh.com", sigalgs, 0) == 1 || match_pattern_list("rsa-sha2-512-cert-v01@openssh.com", sigalgs, 0) == 1; } else return match_pattern_list(keyname, sigalgs, 0) == 1; } char * sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) { char *tmp, *ret = NULL; size_t i, nlen, rlen = 0; const struct sshkey_impl *impl; for (i = 0; keyimpls[i] != NULL; i++) { impl = keyimpls[i]; if (impl->name == NULL) continue; if (!include_sigonly && impl->sigonly) continue; if ((certs_only && !impl->cert) || (plain_only && impl->cert)) continue; if (ret != NULL) ret[rlen++] = sep; nlen = strlen(impl->name); if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { free(ret); return NULL; } ret = tmp; memcpy(ret + rlen, impl->name, nlen + 1); rlen += nlen; } return ret; } int sshkey_names_valid2(const char *names, int allow_wildcard, int plain_only) { char *s, *cp, *p; const struct sshkey_impl *impl; int i, type; if (names == NULL || strcmp(names, "") == 0) return 0; if ((s = cp = strdup(names)) == NULL) return 0; for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { type = sshkey_type_from_name(p); if (type == KEY_UNSPEC) { if (allow_wildcard) { /* * Try matching key types against the string. * If any has a positive or negative match then * the component is accepted. */ impl = NULL; for (i = 0; keyimpls[i] != NULL; i++) { if (match_pattern_list( keyimpls[i]->name, p, 0) != 0) { impl = keyimpls[i]; break; } } if (impl != NULL) continue; } free(s); return 0; } else if (plain_only && sshkey_type_is_cert(type)) { free(s); return 0; } } free(s); return 1; } u_int sshkey_size(const struct sshkey *k) { const struct sshkey_impl *impl; if ((impl = sshkey_impl_from_key(k)) == NULL) return 0; if (impl->funcs->size != NULL) return impl->funcs->size(k); return impl->keybits; } static int sshkey_type_is_valid_ca(int type) { const struct sshkey_impl *impl; if ((impl = sshkey_impl_from_type(type)) == NULL) return 0; /* All non-certificate types may act as CAs */ return !impl->cert; } int sshkey_is_cert(const struct sshkey *k) { if (k == NULL) return 0; 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) { switch (type) { case KEY_RSA_CERT: return KEY_RSA; case KEY_DSA_CERT: return KEY_DSA; case KEY_ECDSA_CERT: return KEY_ECDSA; case KEY_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: return type; } } /* Return the cert equivalent to a plain key type */ static int sshkey_type_certified(int type) { switch (type) { case KEY_RSA: return KEY_RSA_CERT; case KEY_DSA: return KEY_DSA_CERT; case KEY_ECDSA: return KEY_ECDSA_CERT; case KEY_ECDSA_SK: return KEY_ECDSA_SK_CERT; case KEY_ED25519: return KEY_ED25519_CERT; case KEY_ED25519_SK: return KEY_ED25519_SK_CERT; case KEY_XMSS: return KEY_XMSS_CERT; default: return -1; } } #ifdef WITH_OPENSSL /* XXX: these are really begging for a table-driven approach */ int sshkey_curve_name_to_nid(const char *name) { if (strcmp(name, "nistp256") == 0) return NID_X9_62_prime256v1; else if (strcmp(name, "nistp384") == 0) return NID_secp384r1; # ifdef OPENSSL_HAS_NISTP521 else if (strcmp(name, "nistp521") == 0) return NID_secp521r1; # endif /* OPENSSL_HAS_NISTP521 */ else return -1; } u_int sshkey_curve_nid_to_bits(int nid) { switch (nid) { case NID_X9_62_prime256v1: return 256; case NID_secp384r1: return 384; # ifdef OPENSSL_HAS_NISTP521 case NID_secp521r1: return 521; # endif /* OPENSSL_HAS_NISTP521 */ default: return 0; } } int sshkey_ecdsa_bits_to_nid(int bits) { switch (bits) { case 256: return NID_X9_62_prime256v1; case 384: return NID_secp384r1; # ifdef OPENSSL_HAS_NISTP521 case 521: return NID_secp521r1; # endif /* OPENSSL_HAS_NISTP521 */ default: return -1; } } const char * sshkey_curve_nid_to_name(int nid) { switch (nid) { case NID_X9_62_prime256v1: return "nistp256"; case NID_secp384r1: return "nistp384"; # ifdef OPENSSL_HAS_NISTP521 case NID_secp521r1: return "nistp521"; # endif /* OPENSSL_HAS_NISTP521 */ default: return NULL; } } int sshkey_ec_nid_to_hash_alg(int nid) { int kbits = sshkey_curve_nid_to_bits(nid); if (kbits <= 0) return -1; /* RFC5656 section 6.2.1 */ if (kbits <= 256) return SSH_DIGEST_SHA256; else if (kbits <= 384) return SSH_DIGEST_SHA384; else return SSH_DIGEST_SHA512; } #endif /* WITH_OPENSSL */ static void cert_free(struct sshkey_cert *cert) { u_int i; if (cert == NULL) return; sshbuf_free(cert->certblob); sshbuf_free(cert->critical); sshbuf_free(cert->extensions); free(cert->key_id); for (i = 0; i < cert->nprincipals; i++) free(cert->principals[i]); free(cert->principals); sshkey_free(cert->signature_key); free(cert->signature_type); freezero(cert, sizeof(*cert)); } static struct sshkey_cert * cert_new(void) { struct sshkey_cert *cert; if ((cert = calloc(1, sizeof(*cert))) == NULL) return NULL; if ((cert->certblob = sshbuf_new()) == NULL || (cert->critical = sshbuf_new()) == NULL || (cert->extensions = sshbuf_new()) == NULL) { cert_free(cert); return NULL; } cert->key_id = NULL; cert->principals = NULL; cert->signature_key = NULL; cert->signature_type = NULL; return cert; } struct sshkey * sshkey_new(int type) { struct sshkey *k; const struct sshkey_impl *impl = NULL; if (type != KEY_UNSPEC && (impl = sshkey_impl_from_type(type)) == NULL) return NULL; /* All non-certificate types may act as CAs */ if ((k = calloc(1, sizeof(*k))) == NULL) return NULL; k->type = type; k->ecdsa_nid = -1; if (impl != NULL && impl->funcs->alloc != NULL) { if (impl->funcs->alloc(k) != 0) { free(k); return NULL; } } if (sshkey_is_cert(k)) { if ((k->cert = cert_new()) == NULL) { sshkey_free(k); return NULL; } } return k; } /* Frees common FIDO fields */ void sshkey_sk_cleanup(struct sshkey *k) { free(k->sk_application); sshbuf_free(k->sk_key_handle); sshbuf_free(k->sk_reserved); k->sk_application = NULL; k->sk_key_handle = k->sk_reserved = NULL; } static void sshkey_free_contents(struct sshkey *k) { const struct sshkey_impl *impl; if (k == NULL) return; if ((impl = sshkey_impl_from_type(k->type)) != NULL && impl->funcs->cleanup != NULL) impl->funcs->cleanup(k); if (sshkey_is_cert(k)) cert_free(k->cert); freezero(k->shielded_private, k->shielded_len); freezero(k->shield_prekey, k->shield_prekey_len); } void sshkey_free(struct sshkey *k) { sshkey_free_contents(k); freezero(k, sizeof(*k)); } static int cert_compare(struct sshkey_cert *a, struct sshkey_cert *b) { if (a == NULL && b == NULL) return 1; if (a == NULL || b == NULL) return 0; if (sshbuf_len(a->certblob) != sshbuf_len(b->certblob)) return 0; if (timingsafe_bcmp(sshbuf_ptr(a->certblob), sshbuf_ptr(b->certblob), sshbuf_len(a->certblob)) != 0) return 0; return 1; } /* Compares FIDO-specific pubkey fields only */ int sshkey_sk_fields_equal(const struct sshkey *a, const struct sshkey *b) { if (a->sk_application == NULL || b->sk_application == NULL) return 0; if (strcmp(a->sk_application, b->sk_application) != 0) return 0; return 1; } /* * Compare public portions of key only, allowing comparisons between * certificates and plain keys too. */ int sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) { const struct sshkey_impl *impl; if (a == NULL || b == NULL || sshkey_type_plain(a->type) != sshkey_type_plain(b->type)) return 0; if ((impl = sshkey_impl_from_type(a->type)) == NULL) return 0; return impl->funcs->equal(a, b); } int sshkey_equal(const struct sshkey *a, const struct sshkey *b) { if (a == NULL || b == NULL || a->type != b->type) return 0; if (sshkey_is_cert(a)) { if (!cert_compare(a->cert, b->cert)) return 0; } return sshkey_equal_public(a, b); } /* Serialise common FIDO key parts */ int sshkey_serialize_sk(const struct sshkey *key, struct sshbuf *b) { int r; if ((r = sshbuf_put_cstring(b, key->sk_application)) != 0) return r; return 0; } static int to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, enum sshkey_serialize_rep opts) { int type, ret = SSH_ERR_INTERNAL_ERROR; const char *typename; const struct sshkey_impl *impl; if (key == NULL) return SSH_ERR_INVALID_ARGUMENT; type = force_plain ? sshkey_type_plain(key->type) : key->type; if (sshkey_type_is_cert(type)) { if (key->cert == NULL) return SSH_ERR_EXPECTED_CERT; if (sshbuf_len(key->cert->certblob) == 0) return SSH_ERR_KEY_LACKS_CERTBLOB; /* Use the existing blob */ if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0) return ret; return 0; } if ((impl = sshkey_impl_from_type(type)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid); if ((ret = sshbuf_put_cstring(b, typename)) != 0) return ret; return impl->funcs->serialize_public(key, b, opts); } int sshkey_putb(const struct sshkey *key, struct sshbuf *b) { return to_blob_buf(key, b, 0, SSHKEY_SERIALIZE_DEFAULT); } int sshkey_puts_opts(const struct sshkey *key, struct sshbuf *b, enum sshkey_serialize_rep opts) { struct sshbuf *tmp; int r; if ((tmp = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; r = to_blob_buf(key, tmp, 0, opts); if (r == 0) r = sshbuf_put_stringb(b, tmp); sshbuf_free(tmp); return r; } int sshkey_puts(const struct sshkey *key, struct sshbuf *b) { return sshkey_puts_opts(key, b, SSHKEY_SERIALIZE_DEFAULT); } int sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b) { return to_blob_buf(key, b, 1, SSHKEY_SERIALIZE_DEFAULT); } static int to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain, enum sshkey_serialize_rep opts) { int ret = SSH_ERR_INTERNAL_ERROR; size_t len; struct sshbuf *b = NULL; if (lenp != NULL) *lenp = 0; if (blobp != NULL) *blobp = NULL; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((ret = to_blob_buf(key, b, force_plain, opts)) != 0) goto out; len = sshbuf_len(b); if (lenp != NULL) *lenp = len; if (blobp != NULL) { if ((*blobp = malloc(len)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(*blobp, sshbuf_ptr(b), len); } ret = 0; out: sshbuf_free(b); return ret; } int sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) { return to_blob(key, blobp, lenp, 0, SSHKEY_SERIALIZE_DEFAULT); } int sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp) { return to_blob(key, blobp, lenp, 1, SSHKEY_SERIALIZE_DEFAULT); } int sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg, u_char **retp, size_t *lenp) { u_char *blob = NULL, *ret = NULL; size_t blob_len = 0; int r = SSH_ERR_INTERNAL_ERROR; if (retp != NULL) *retp = NULL; if (lenp != NULL) *lenp = 0; if (ssh_digest_bytes(dgst_alg) == 0) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if ((r = to_blob(k, &blob, &blob_len, 1, SSHKEY_SERIALIZE_DEFAULT)) != 0) goto out; if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = ssh_digest_memory(dgst_alg, blob, blob_len, ret, SSH_DIGEST_MAX_LENGTH)) != 0) goto out; /* success */ if (retp != NULL) { *retp = ret; ret = NULL; } if (lenp != NULL) *lenp = ssh_digest_bytes(dgst_alg); r = 0; out: free(ret); if (blob != NULL) freezero(blob, blob_len); return r; } static char * fingerprint_b64(const char *alg, u_char *dgst_raw, size_t dgst_raw_len) { char *ret; size_t plen = strlen(alg) + 1; size_t rlen = ((dgst_raw_len + 2) / 3) * 4 + plen + 1; if (dgst_raw_len > 65536 || (ret = calloc(1, rlen)) == NULL) return NULL; strlcpy(ret, alg, rlen); strlcat(ret, ":", rlen); if (dgst_raw_len == 0) return ret; if (b64_ntop(dgst_raw, dgst_raw_len, ret + plen, rlen - plen) == -1) { freezero(ret, rlen); return NULL; } /* Trim padding characters from end */ ret[strcspn(ret, "=")] = '\0'; return ret; } static char * fingerprint_hex(const char *alg, u_char *dgst_raw, size_t dgst_raw_len) { char *retval, hex[5]; size_t i, rlen = dgst_raw_len * 3 + strlen(alg) + 2; if (dgst_raw_len > 65536 || (retval = calloc(1, rlen)) == NULL) return NULL; strlcpy(retval, alg, rlen); strlcat(retval, ":", rlen); for (i = 0; i < dgst_raw_len; i++) { snprintf(hex, sizeof(hex), "%s%02x", i > 0 ? ":" : "", dgst_raw[i]); strlcat(retval, hex, rlen); } return retval; } static char * fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len) { char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; u_int i, j = 0, rounds, seed = 1; char *retval; rounds = (dgst_raw_len / 2) + 1; if ((retval = calloc(rounds, 6)) == NULL) return NULL; retval[j++] = 'x'; for (i = 0; i < rounds; i++) { u_int idx0, idx1, idx2, idx3, idx4; if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) { idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) + seed) % 6; idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15; idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) + (seed / 6)) % 6; retval[j++] = vowels[idx0]; retval[j++] = consonants[idx1]; retval[j++] = vowels[idx2]; if ((i + 1) < rounds) { idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15; idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15; retval[j++] = consonants[idx3]; retval[j++] = '-'; retval[j++] = consonants[idx4]; seed = ((seed * 5) + ((((u_int)(dgst_raw[2 * i])) * 7) + ((u_int)(dgst_raw[(2 * i) + 1])))) % 36; } } else { idx0 = seed % 6; idx1 = 16; idx2 = seed / 6; retval[j++] = vowels[idx0]; retval[j++] = consonants[idx1]; retval[j++] = vowels[idx2]; } } retval[j++] = 'x'; retval[j++] = '\0'; return retval; } /* * Draw an ASCII-Art representing the fingerprint so human brain can * profit from its built-in pattern recognition ability. * This technique is called "random art" and can be found in some * scientific publications like this original paper: * * "Hash Visualization: a New Technique to improve Real-World Security", * Perrig A. and Song D., 1999, International Workshop on Cryptographic * Techniques and E-Commerce (CrypTEC '99) * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf * * The subject came up in a talk by Dan Kaminsky, too. * * If you see the picture is different, the key is different. * If the picture looks the same, you still know nothing. * * The algorithm used here is a worm crawling over a discrete plane, * leaving a trace (augmenting the field) everywhere it goes. * Movement is taken from dgst_raw 2bit-wise. Bumping into walls * makes the respective movement vector be ignored for this turn. * Graphs are not unambiguous, because circles in graphs can be * walked in either direction. */ /* * Field sizes for the random art. Have to be odd, so the starting point * can be in the exact middle of the picture, and FLDBASE should be >=8 . * Else pictures would be too dense, and drawing the frame would * fail, too, because the key type would not fit in anymore. */ #define FLDBASE 8 #define FLDSIZE_Y (FLDBASE + 1) #define FLDSIZE_X (FLDBASE * 2 + 1) static char * fingerprint_randomart(const char *alg, u_char *dgst_raw, size_t dgst_raw_len, const struct sshkey *k) { /* * Chars to be used after each other every time the worm * intersects with itself. Matter of taste. */ char *augmentation_string = " .o+=*BOX@%&#/^SE"; char *retval, *p, title[FLDSIZE_X], hash[FLDSIZE_X]; u_char field[FLDSIZE_X][FLDSIZE_Y]; size_t i, tlen, hlen; u_int b; int x, y, r; size_t len = strlen(augmentation_string) - 1; if ((retval = calloc((FLDSIZE_X + 3), (FLDSIZE_Y + 2))) == NULL) return NULL; /* initialize field */ memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char)); x = FLDSIZE_X / 2; y = FLDSIZE_Y / 2; /* process raw key */ for (i = 0; i < dgst_raw_len; i++) { int input; /* each byte conveys four 2-bit move commands */ input = dgst_raw[i]; for (b = 0; b < 4; b++) { /* evaluate 2 bit, rest is shifted later */ x += (input & 0x1) ? 1 : -1; y += (input & 0x2) ? 1 : -1; /* assure we are still in bounds */ x = MAXIMUM(x, 0); y = MAXIMUM(y, 0); x = MINIMUM(x, FLDSIZE_X - 1); y = MINIMUM(y, FLDSIZE_Y - 1); /* augment the field */ if (field[x][y] < len - 2) field[x][y]++; input = input >> 2; } } /* mark starting point and end point*/ field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1; field[x][y] = len; /* assemble title */ r = snprintf(title, sizeof(title), "[%s %u]", sshkey_type(k), sshkey_size(k)); /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */ if (r < 0 || r > (int)sizeof(title)) r = snprintf(title, sizeof(title), "[%s]", sshkey_type(k)); tlen = (r <= 0) ? 0 : strlen(title); /* assemble hash ID. */ r = snprintf(hash, sizeof(hash), "[%s]", alg); hlen = (r <= 0) ? 0 : strlen(hash); /* output upper border */ p = retval; *p++ = '+'; for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++) *p++ = '-'; memcpy(p, title, tlen); p += tlen; for (i += tlen; i < FLDSIZE_X; i++) *p++ = '-'; *p++ = '+'; *p++ = '\n'; /* output content */ for (y = 0; y < FLDSIZE_Y; y++) { *p++ = '|'; for (x = 0; x < FLDSIZE_X; x++) *p++ = augmentation_string[MINIMUM(field[x][y], len)]; *p++ = '|'; *p++ = '\n'; } /* output lower border */ *p++ = '+'; for (i = 0; i < (FLDSIZE_X - hlen) / 2; i++) *p++ = '-'; memcpy(p, hash, hlen); p += hlen; for (i += hlen; i < FLDSIZE_X; i++) *p++ = '-'; *p++ = '+'; return retval; } char * sshkey_fingerprint(const struct sshkey *k, int dgst_alg, enum sshkey_fp_rep dgst_rep) { char *retval = NULL; u_char *dgst_raw; size_t dgst_raw_len; if (sshkey_fingerprint_raw(k, dgst_alg, &dgst_raw, &dgst_raw_len) != 0) return NULL; switch (dgst_rep) { case SSH_FP_DEFAULT: if (dgst_alg == SSH_DIGEST_MD5) { retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg), dgst_raw, dgst_raw_len); } else { retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg), dgst_raw, dgst_raw_len); } break; case SSH_FP_HEX: retval = fingerprint_hex(ssh_digest_alg_name(dgst_alg), dgst_raw, dgst_raw_len); break; case SSH_FP_BASE64: retval = fingerprint_b64(ssh_digest_alg_name(dgst_alg), dgst_raw, dgst_raw_len); break; case SSH_FP_BUBBLEBABBLE: retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len); break; case SSH_FP_RANDOMART: retval = fingerprint_randomart(ssh_digest_alg_name(dgst_alg), dgst_raw, dgst_raw_len, k); break; default: freezero(dgst_raw, dgst_raw_len); return NULL; } freezero(dgst_raw, dgst_raw_len); return retval; } static int peek_type_nid(const char *s, size_t l, int *nid) { const struct sshkey_impl *impl; int i; for (i = 0; keyimpls[i] != NULL; i++) { impl = keyimpls[i]; if (impl->name == NULL || strlen(impl->name) != l) continue; if (memcmp(s, impl->name, l) == 0) { *nid = -1; if (key_type_is_ecdsa_variant(impl->type)) *nid = impl->nid; return impl->type; } } return KEY_UNSPEC; } /* XXX this can now be made const char * */ int sshkey_read(struct sshkey *ret, char **cpp) { struct sshkey *k; char *cp, *blobcopy; size_t space; int r, type, curve_nid = -1; struct sshbuf *blob; if (ret == NULL) return SSH_ERR_INVALID_ARGUMENT; if (ret->type != KEY_UNSPEC && sshkey_impl_from_type(ret->type) == NULL) return SSH_ERR_INVALID_ARGUMENT; /* Decode type */ cp = *cpp; space = strcspn(cp, " \t"); if (space == strlen(cp)) return SSH_ERR_INVALID_FORMAT; if ((type = peek_type_nid(cp, space, &curve_nid)) == KEY_UNSPEC) return SSH_ERR_INVALID_FORMAT; /* skip whitespace */ for (cp += space; *cp == ' ' || *cp == '\t'; cp++) ; if (*cp == '\0') return SSH_ERR_INVALID_FORMAT; if (ret->type != KEY_UNSPEC && ret->type != type) return SSH_ERR_KEY_TYPE_MISMATCH; if ((blob = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; /* find end of keyblob and decode */ space = strcspn(cp, " \t"); if ((blobcopy = strndup(cp, space)) == NULL) { sshbuf_free(blob); return SSH_ERR_ALLOC_FAIL; } if ((r = sshbuf_b64tod(blob, blobcopy)) != 0) { free(blobcopy); sshbuf_free(blob); return r; } free(blobcopy); if ((r = sshkey_fromb(blob, &k)) != 0) { sshbuf_free(blob); return r; } sshbuf_free(blob); /* skip whitespace and leave cp at start of comment */ for (cp += space; *cp == ' ' || *cp == '\t'; cp++) ; /* ensure type of blob matches type at start of line */ if (k->type != type) { sshkey_free(k); return SSH_ERR_KEY_TYPE_MISMATCH; } if (key_type_is_ecdsa_variant(type) && curve_nid != k->ecdsa_nid) { sshkey_free(k); return SSH_ERR_EC_CURVE_MISMATCH; } /* Fill in ret from parsed key */ sshkey_free_contents(ret); *ret = *k; freezero(k, sizeof(*k)); /* success */ *cpp = cp; return 0; } int sshkey_to_base64(const struct sshkey *key, char **b64p) { int r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *b = NULL; char *uu = NULL; if (b64p != NULL) *b64p = NULL; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshkey_putb(key, b)) != 0) goto out; if ((uu = sshbuf_dtob64_string(b, 0)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* Success */ if (b64p != NULL) { *b64p = uu; uu = NULL; } r = 0; out: sshbuf_free(b); free(uu); return r; } int sshkey_format_text(const struct sshkey *key, struct sshbuf *b) { int r = SSH_ERR_INTERNAL_ERROR; char *uu = NULL; if ((r = sshkey_to_base64(key, &uu)) != 0) goto out; if ((r = sshbuf_putf(b, "%s %s", sshkey_ssh_name(key), uu)) != 0) goto out; r = 0; out: free(uu); return r; } int sshkey_write(const struct sshkey *key, FILE *f) { struct sshbuf *b = NULL; int r = SSH_ERR_INTERNAL_ERROR; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshkey_format_text(key, b)) != 0) goto out; if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) { if (feof(f)) errno = EPIPE; r = SSH_ERR_SYSTEM_ERROR; goto out; } /* Success */ r = 0; out: sshbuf_free(b); return r; } const char * sshkey_cert_type(const struct sshkey *k) { switch (k->cert->type) { case SSH2_CERT_TYPE_USER: return "user"; case SSH2_CERT_TYPE_HOST: return "host"; default: return "unknown"; } } int sshkey_check_rsa_length(const struct sshkey *k, int min_size) { #ifdef WITH_OPENSSL const BIGNUM *rsa_n; int nbits; if (k == NULL || k->rsa == NULL || (k->type != KEY_RSA && k->type != KEY_RSA_CERT)) return 0; RSA_get0_key(k->rsa, &rsa_n, NULL, NULL); nbits = BN_num_bits(rsa_n); if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE || (min_size > 0 && nbits < min_size)) return SSH_ERR_KEY_LENGTH; #endif /* WITH_OPENSSL */ return 0; } #ifdef WITH_OPENSSL # ifdef OPENSSL_HAS_ECC int sshkey_ecdsa_key_to_nid(EC_KEY *k) { EC_GROUP *eg; int nids[] = { NID_X9_62_prime256v1, NID_secp384r1, # ifdef OPENSSL_HAS_NISTP521 NID_secp521r1, # endif /* OPENSSL_HAS_NISTP521 */ -1 }; int nid; u_int i; const EC_GROUP *g = EC_KEY_get0_group(k); /* * The group may be stored in a ASN.1 encoded private key in one of two * ways: as a "named group", which is reconstituted by ASN.1 object ID * or explicit group parameters encoded into the key blob. Only the * "named group" case sets the group NID for us, but we can figure * it out for the other case by comparing against all the groups that * are supported. */ if ((nid = EC_GROUP_get_curve_name(g)) > 0) return nid; for (i = 0; nids[i] != -1; i++) { if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) return -1; if (EC_GROUP_cmp(g, eg, NULL) == 0) break; EC_GROUP_free(eg); } if (nids[i] != -1) { /* Use the group with the NID attached */ EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE); if (EC_KEY_set_group(k, eg) != 1) { EC_GROUP_free(eg); return -1; } } return nids[i]; } # endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ int sshkey_generate(int type, u_int bits, struct sshkey **keyp) { struct sshkey *k; int ret = SSH_ERR_INTERNAL_ERROR; const struct sshkey_impl *impl; if (keyp == NULL || sshkey_type_is_cert(type)) return SSH_ERR_INVALID_ARGUMENT; *keyp = NULL; if ((impl = sshkey_impl_from_type(type)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; if (impl->funcs->generate == NULL) return SSH_ERR_FEATURE_UNSUPPORTED; if ((k = sshkey_new(KEY_UNSPEC)) == NULL) return SSH_ERR_ALLOC_FAIL; k->type = type; if ((ret = impl->funcs->generate(k, bits)) != 0) { sshkey_free(k); return ret; } /* success */ *keyp = k; return 0; } int sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key) { u_int i; const struct sshkey_cert *from; struct sshkey_cert *to; int r = SSH_ERR_INTERNAL_ERROR; if (to_key == NULL || (from = from_key->cert) == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((to = cert_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_putb(to->certblob, from->certblob)) != 0 || (r = sshbuf_putb(to->critical, from->critical)) != 0 || (r = sshbuf_putb(to->extensions, from->extensions)) != 0) goto out; to->serial = from->serial; to->type = from->type; if (from->key_id == NULL) to->key_id = NULL; else if ((to->key_id = strdup(from->key_id)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } to->valid_after = from->valid_after; to->valid_before = from->valid_before; if (from->signature_key == NULL) to->signature_key = NULL; else if ((r = sshkey_from_private(from->signature_key, &to->signature_key)) != 0) goto out; if (from->signature_type != NULL && (to->signature_type = strdup(from->signature_type)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if (from->nprincipals > 0) { if ((to->principals = calloc(from->nprincipals, sizeof(*to->principals))) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } for (i = 0; i < from->nprincipals; i++) { to->principals[i] = strdup(from->principals[i]); if (to->principals[i] == NULL) { to->nprincipals = i; r = SSH_ERR_ALLOC_FAIL; goto out; } } } to->nprincipals = from->nprincipals; /* success */ cert_free(to_key->cert); to_key->cert = to; to = NULL; r = 0; out: cert_free(to); return r; } int sshkey_copy_public_sk(const struct sshkey *from, struct sshkey *to) { /* Append security-key application string */ if ((to->sk_application = strdup(from->sk_application)) == NULL) return SSH_ERR_ALLOC_FAIL; return 0; } int sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) { struct sshkey *n = NULL; int r = SSH_ERR_INTERNAL_ERROR; const struct sshkey_impl *impl; *pkp = NULL; if ((impl = sshkey_impl_from_key(k)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; if ((n = sshkey_new(k->type)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = impl->funcs->copy_public(k, n)) != 0) goto out; if (sshkey_is_cert(k) && (r = sshkey_cert_copy(k, n)) != 0) goto out; /* success */ *pkp = n; n = NULL; r = 0; out: sshkey_free(n); return r; } int sshkey_is_shielded(struct sshkey *k) { return k != NULL && k->shielded_private != NULL; } int sshkey_shield_private(struct sshkey *k) { struct sshbuf *prvbuf = NULL; u_char *prekey = NULL, *enc = NULL, keyiv[SSH_DIGEST_MAX_LENGTH]; struct sshcipher_ctx *cctx = NULL; const struct sshcipher *cipher; size_t i, enclen = 0; struct sshkey *kswap = NULL, tmp; int r = SSH_ERR_INTERNAL_ERROR; #ifdef DEBUG_PK fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k)); #endif if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if (cipher_keylen(cipher) + cipher_ivlen(cipher) > ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) { r = SSH_ERR_INTERNAL_ERROR; goto out; } /* Prepare a random pre-key, and from it an ephemeral key */ if ((prekey = malloc(SSHKEY_SHIELD_PREKEY_LEN)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } arc4random_buf(prekey, SSHKEY_SHIELD_PREKEY_LEN); if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH, prekey, SSHKEY_SHIELD_PREKEY_LEN, keyiv, SSH_DIGEST_MAX_LENGTH)) != 0) goto out; #ifdef DEBUG_PK fprintf(stderr, "%s: key+iv\n", __func__); sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH), stderr); #endif if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher), keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 1)) != 0) goto out; /* Serialise and encrypt the private key using the ephemeral key */ if ((prvbuf = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (sshkey_is_shielded(k) && (r = sshkey_unshield_private(k)) != 0) goto out; if ((r = sshkey_private_serialize_opt(k, prvbuf, SSHKEY_SERIALIZE_SHIELD)) != 0) goto out; /* pad to cipher blocksize */ i = 0; while (sshbuf_len(prvbuf) % cipher_blocksize(cipher)) { if ((r = sshbuf_put_u8(prvbuf, ++i & 0xff)) != 0) goto out; } #ifdef DEBUG_PK fprintf(stderr, "%s: serialised\n", __func__); sshbuf_dump(prvbuf, stderr); #endif /* encrypt */ enclen = sshbuf_len(prvbuf); if ((enc = malloc(enclen)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = cipher_crypt(cctx, 0, enc, sshbuf_ptr(prvbuf), sshbuf_len(prvbuf), 0, 0)) != 0) goto out; #ifdef DEBUG_PK fprintf(stderr, "%s: encrypted\n", __func__); sshbuf_dump_data(enc, enclen, stderr); #endif /* Make a scrubbed, public-only copy of our private key argument */ if ((r = sshkey_from_private(k, &kswap)) != 0) goto out; /* Swap the private key out (it will be destroyed below) */ tmp = *kswap; *kswap = *k; *k = tmp; /* Insert the shielded key into our argument */ k->shielded_private = enc; k->shielded_len = enclen; k->shield_prekey = prekey; k->shield_prekey_len = SSHKEY_SHIELD_PREKEY_LEN; enc = prekey = NULL; /* transferred */ enclen = 0; /* preserve key fields that are required for correct operation */ k->sk_flags = kswap->sk_flags; /* success */ r = 0; out: /* XXX behaviour on error - invalidate original private key? */ cipher_free(cctx); explicit_bzero(keyiv, sizeof(keyiv)); explicit_bzero(&tmp, sizeof(tmp)); freezero(enc, enclen); freezero(prekey, SSHKEY_SHIELD_PREKEY_LEN); sshkey_free(kswap); sshbuf_free(prvbuf); return r; } /* Check deterministic padding after private key */ static int private2_check_padding(struct sshbuf *decrypted) { u_char pad; size_t i; int r; i = 0; while (sshbuf_len(decrypted)) { if ((r = sshbuf_get_u8(decrypted, &pad)) != 0) goto out; if (pad != (++i & 0xff)) { r = SSH_ERR_INVALID_FORMAT; goto out; } } /* success */ r = 0; out: explicit_bzero(&pad, sizeof(pad)); explicit_bzero(&i, sizeof(i)); return r; } int sshkey_unshield_private(struct sshkey *k) { struct sshbuf *prvbuf = NULL; u_char *cp, keyiv[SSH_DIGEST_MAX_LENGTH]; struct sshcipher_ctx *cctx = NULL; const struct sshcipher *cipher; struct sshkey *kswap = NULL, tmp; int r = SSH_ERR_INTERNAL_ERROR; #ifdef DEBUG_PK fprintf(stderr, "%s: entering for %s\n", __func__, sshkey_ssh_name(k)); #endif if (!sshkey_is_shielded(k)) return 0; /* nothing to do */ if ((cipher = cipher_by_name(SSHKEY_SHIELD_CIPHER)) == NULL) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if (cipher_keylen(cipher) + cipher_ivlen(cipher) > ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH)) { r = SSH_ERR_INTERNAL_ERROR; goto out; } /* check size of shielded key blob */ if (k->shielded_len < cipher_blocksize(cipher) || (k->shielded_len % cipher_blocksize(cipher)) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* Calculate the ephemeral key from the prekey */ if ((r = ssh_digest_memory(SSHKEY_SHIELD_PREKEY_HASH, k->shield_prekey, k->shield_prekey_len, keyiv, SSH_DIGEST_MAX_LENGTH)) != 0) goto out; if ((r = cipher_init(&cctx, cipher, keyiv, cipher_keylen(cipher), keyiv + cipher_keylen(cipher), cipher_ivlen(cipher), 0)) != 0) goto out; #ifdef DEBUG_PK fprintf(stderr, "%s: key+iv\n", __func__); sshbuf_dump_data(keyiv, ssh_digest_bytes(SSHKEY_SHIELD_PREKEY_HASH), stderr); #endif /* Decrypt and parse the shielded private key using the ephemeral key */ if ((prvbuf = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_reserve(prvbuf, k->shielded_len, &cp)) != 0) goto out; /* decrypt */ #ifdef DEBUG_PK fprintf(stderr, "%s: encrypted\n", __func__); sshbuf_dump_data(k->shielded_private, k->shielded_len, stderr); #endif if ((r = cipher_crypt(cctx, 0, cp, k->shielded_private, k->shielded_len, 0, 0)) != 0) goto out; #ifdef DEBUG_PK fprintf(stderr, "%s: serialised\n", __func__); sshbuf_dump(prvbuf, stderr); #endif /* Parse private key */ if ((r = sshkey_private_deserialize(prvbuf, &kswap)) != 0) goto out; if ((r = private2_check_padding(prvbuf)) != 0) goto out; /* Swap the parsed key back into place */ tmp = *kswap; *kswap = *k; *k = tmp; /* success */ r = 0; out: cipher_free(cctx); explicit_bzero(keyiv, sizeof(keyiv)); explicit_bzero(&tmp, sizeof(tmp)); sshkey_free(kswap); sshbuf_free(prvbuf); return r; } static int cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) { struct sshbuf *principals = NULL, *crit = NULL; struct sshbuf *exts = NULL, *ca = NULL; u_char *sig = NULL; size_t signed_len = 0, slen = 0, kidlen = 0; int ret = SSH_ERR_INTERNAL_ERROR; /* Copy the entire key blob for verification and later serialisation */ if ((ret = sshbuf_putb(key->cert->certblob, certbuf)) != 0) return ret; /* Parse body of certificate up to signature */ if ((ret = sshbuf_get_u64(b, &key->cert->serial)) != 0 || (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 || (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 || (ret = sshbuf_froms(b, &principals)) != 0 || (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 || (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 || (ret = sshbuf_froms(b, &crit)) != 0 || (ret = sshbuf_froms(b, &exts)) != 0 || (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || (ret = sshbuf_froms(b, &ca)) != 0) { /* XXX debug print error for ret */ ret = SSH_ERR_INVALID_FORMAT; goto out; } /* Signature is left in the buffer so we can calculate this length */ signed_len = sshbuf_len(key->cert->certblob) - sshbuf_len(b); if ((ret = sshbuf_get_string(b, &sig, &slen)) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if (key->cert->type != SSH2_CERT_TYPE_USER && key->cert->type != SSH2_CERT_TYPE_HOST) { ret = SSH_ERR_KEY_CERT_UNKNOWN_TYPE; goto out; } /* Parse principals section */ while (sshbuf_len(principals) > 0) { char *principal = NULL; char **oprincipals = NULL; if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) { ret = SSH_ERR_INVALID_FORMAT; goto out; } if ((ret = sshbuf_get_cstring(principals, &principal, NULL)) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } oprincipals = key->cert->principals; key->cert->principals = recallocarray(key->cert->principals, key->cert->nprincipals, key->cert->nprincipals + 1, sizeof(*key->cert->principals)); if (key->cert->principals == NULL) { free(principal); key->cert->principals = oprincipals; ret = SSH_ERR_ALLOC_FAIL; goto out; } key->cert->principals[key->cert->nprincipals++] = principal; } /* * Stash a copies of the critical options and extensions sections * for later use. */ if ((ret = sshbuf_putb(key->cert->critical, crit)) != 0 || (exts != NULL && (ret = sshbuf_putb(key->cert->extensions, exts)) != 0)) goto out; /* * Validate critical options and extensions sections format. */ while (sshbuf_len(crit) != 0) { if ((ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0 || (ret = sshbuf_get_string_direct(crit, NULL, NULL)) != 0) { sshbuf_reset(key->cert->critical); ret = SSH_ERR_INVALID_FORMAT; goto out; } } while (exts != NULL && sshbuf_len(exts) != 0) { if ((ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0 || (ret = sshbuf_get_string_direct(exts, NULL, NULL)) != 0) { sshbuf_reset(key->cert->extensions); ret = SSH_ERR_INVALID_FORMAT; goto out; } } /* Parse CA key and check signature */ if (sshkey_from_blob_internal(ca, &key->cert->signature_key, 0) != 0) { ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; goto out; } if (!sshkey_type_is_valid_ca(key->cert->signature_key->type)) { ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; goto out; } if ((ret = sshkey_verify(key->cert->signature_key, sig, slen, sshbuf_ptr(key->cert->certblob), signed_len, NULL, 0, NULL)) != 0) goto out; if ((ret = sshkey_get_sigtype(sig, slen, &key->cert->signature_type)) != 0) goto out; /* Success */ ret = 0; out: sshbuf_free(ca); sshbuf_free(crit); sshbuf_free(exts); sshbuf_free(principals); free(sig); return ret; } int sshkey_deserialize_sk(struct sshbuf *b, struct sshkey *key) { /* Parse additional security-key application string */ if (sshbuf_get_cstring(b, &key->sk_application, NULL) != 0) return SSH_ERR_INVALID_FORMAT; return 0; } static int sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, int allow_cert) { int type, ret = SSH_ERR_INTERNAL_ERROR; char *ktype = NULL; struct sshkey *key = NULL; struct sshbuf *copy; const struct sshkey_impl *impl; #ifdef DEBUG_PK /* XXX */ sshbuf_dump(b, stderr); #endif if (keyp != NULL) *keyp = NULL; if ((copy = sshbuf_fromb(b)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (sshbuf_get_cstring(b, &ktype, NULL) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } type = sshkey_type_from_name(ktype); if (!allow_cert && sshkey_type_is_cert(type)) { ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; goto out; } if ((impl = sshkey_impl_from_type(type)) == NULL) { ret = SSH_ERR_KEY_TYPE_UNKNOWN; goto out; } if ((key = sshkey_new(type)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (sshkey_type_is_cert(type)) { /* Skip nonce that preceeds all certificates */ if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } } if ((ret = impl->funcs->deserialize_public(ktype, b, key)) != 0) goto out; /* Parse certificate potion */ if (sshkey_is_cert(key) && (ret = cert_parse(b, key, copy)) != 0) goto out; if (key != NULL && sshbuf_len(b) != 0) { ret = SSH_ERR_INVALID_FORMAT; goto out; } ret = 0; if (keyp != NULL) { *keyp = key; key = NULL; } out: sshbuf_free(copy); sshkey_free(key); free(ktype); return ret; } int sshkey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp) { struct sshbuf *b; int r; if ((b = sshbuf_from(blob, blen)) == NULL) return SSH_ERR_ALLOC_FAIL; r = sshkey_from_blob_internal(b, keyp, 1); sshbuf_free(b); return r; } int sshkey_fromb(struct sshbuf *b, struct sshkey **keyp) { return sshkey_from_blob_internal(b, keyp, 1); } int sshkey_froms(struct sshbuf *buf, struct sshkey **keyp) { struct sshbuf *b; int r; if ((r = sshbuf_froms(buf, &b)) != 0) return r; r = sshkey_from_blob_internal(b, keyp, 1); sshbuf_free(b); return r; } int sshkey_get_sigtype(const u_char *sig, size_t siglen, char **sigtypep) { int r; struct sshbuf *b = NULL; char *sigtype = NULL; if (sigtypep != NULL) *sigtypep = NULL; if ((b = sshbuf_from(sig, siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_get_cstring(b, &sigtype, NULL)) != 0) goto out; /* success */ if (sigtypep != NULL) { *sigtypep = sigtype; sigtype = NULL; } r = 0; out: free(sigtype); sshbuf_free(b); return r; } /* * * Checks whether a certificate's signature type is allowed. * Returns 0 (success) if the certificate signature type appears in the * "allowed" pattern-list, or the key is not a certificate to begin with. * Otherwise returns a ssherr.h code. */ int sshkey_check_cert_sigtype(const struct sshkey *key, const char *allowed) { if (key == NULL || allowed == NULL) return SSH_ERR_INVALID_ARGUMENT; if (!sshkey_type_is_cert(key->type)) return 0; if (key->cert == NULL || key->cert->signature_type == NULL) return SSH_ERR_INVALID_ARGUMENT; if (match_pattern_list(key->cert->signature_type, allowed, 0) != 1) return SSH_ERR_SIGN_ALG_UNSUPPORTED; return 0; } /* * Returns the expected signature algorithm for a given public key algorithm. */ const char * sshkey_sigalg_by_name(const char *name) { const struct sshkey_impl *impl; int i; for (i = 0; keyimpls[i] != NULL; i++) { impl = keyimpls[i]; if (strcmp(impl->name, name) != 0) continue; if (impl->sigalg != NULL) return impl->sigalg; if (!impl->cert) return impl->name; return sshkey_ssh_name_from_type_nid( sshkey_type_plain(impl->type), impl->nid); } return NULL; } /* * Verifies that the signature algorithm appearing inside the signature blob * matches that which was requested. */ int sshkey_check_sigtype(const u_char *sig, size_t siglen, const char *requested_alg) { const char *expected_alg; char *sigtype = NULL; int r; if (requested_alg == NULL) return 0; if ((expected_alg = sshkey_sigalg_by_name(requested_alg)) == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0) return r; r = strcmp(expected_alg, sigtype) == 0; free(sigtype); return r ? 0 : SSH_ERR_SIGN_ALG_UNSUPPORTED; } int sshkey_sign(struct sshkey *key, u_char **sigp, size_t *lenp, 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; const struct sshkey_impl *impl; if (sigp != NULL) *sigp = NULL; if (lenp != NULL) *lenp = 0; if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; if ((impl = sshkey_impl_from_key(key)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; if ((r = sshkey_unshield_private(key)) != 0) return r; if (sshkey_is_sk(key)) { r = sshsk_sign(sk_provider, key, sigp, lenp, data, datalen, compat, sk_pin); } else { if (impl->funcs->sign == NULL) r = SSH_ERR_SIGN_ALG_UNSUPPORTED; else { r = impl->funcs->sign(key, sigp, lenp, data, datalen, alg, sk_provider, sk_pin, compat); } } if (was_shielded && (r2 = sshkey_shield_private(key)) != 0) return r2; return r; } /* * ssh_key_verify returns 0 for a correct signature and < 0 on error. * If "alg" specified, then the signature must use that algorithm. */ int sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, const u_char *data, size_t dlen, const char *alg, u_int compat, struct sshkey_sig_details **detailsp) { const struct sshkey_impl *impl; if (detailsp != NULL) *detailsp = NULL; if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; if ((impl = sshkey_impl_from_key(key)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; return impl->funcs->verify(key, sig, siglen, data, dlen, alg, compat, detailsp); } /* Convert a plain key to their _CERT equivalent */ int sshkey_to_certified(struct sshkey *k) { int newtype; if ((newtype = sshkey_type_certified(k->type)) == -1) return SSH_ERR_INVALID_ARGUMENT; if ((k->cert = cert_new()) == NULL) return SSH_ERR_ALLOC_FAIL; k->type = newtype; return 0; } /* Convert a certificate to its raw key equivalent */ int sshkey_drop_cert(struct sshkey *k) { if (!sshkey_type_is_cert(k->type)) return SSH_ERR_KEY_TYPE_UNKNOWN; cert_free(k->cert); k->cert = NULL; k->type = sshkey_type_plain(k->type); return 0; } /* Sign a certified key, (re-)generating the signed certblob. */ int sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, const char *sk_provider, const char *sk_pin, sshkey_certify_signer *signer, void *signer_ctx) { const struct sshkey_impl *impl; struct sshbuf *principals = NULL; u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32]; size_t i, ca_len, sig_len; int ret = SSH_ERR_INTERNAL_ERROR; struct sshbuf *cert = NULL; char *sigtype = NULL; if (k == NULL || k->cert == NULL || k->cert->certblob == NULL || ca == NULL) return SSH_ERR_INVALID_ARGUMENT; if (!sshkey_is_cert(k)) return SSH_ERR_KEY_TYPE_UNKNOWN; if (!sshkey_type_is_valid_ca(ca->type)) return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; if ((impl = sshkey_impl_from_key(k)) == NULL) return SSH_ERR_INTERNAL_ERROR; /* * If no alg specified as argument but a signature_type was set, * then prefer that. If both were specified, then they must match. */ if (alg == NULL) alg = k->cert->signature_type; else if (k->cert->signature_type != NULL && strcmp(alg, k->cert->signature_type) != 0) return SSH_ERR_INVALID_ARGUMENT; /* * If no signing algorithm or signature_type was specified and we're * using a RSA key, then default to a good signature algorithm. */ if (alg == NULL && ca->type == KEY_RSA) alg = "rsa-sha2-512"; if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0) return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY; cert = k->cert->certblob; /* for readability */ sshbuf_reset(cert); if ((ret = sshbuf_put_cstring(cert, sshkey_ssh_name(k))) != 0) goto out; /* -v01 certs put nonce first */ arc4random_buf(&nonce, sizeof(nonce)); if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0) goto out; /* Public key next */ if ((ret = impl->funcs->serialize_public(k, cert, SSHKEY_SERIALIZE_DEFAULT)) != 0) goto out; /* Then remaining cert fields */ if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0 || (ret = sshbuf_put_u32(cert, k->cert->type)) != 0 || (ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0) goto out; if ((principals = sshbuf_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } for (i = 0; i < k->cert->nprincipals; i++) { if ((ret = sshbuf_put_cstring(principals, k->cert->principals[i])) != 0) goto out; } if ((ret = sshbuf_put_stringb(cert, principals)) != 0 || (ret = sshbuf_put_u64(cert, k->cert->valid_after)) != 0 || (ret = sshbuf_put_u64(cert, k->cert->valid_before)) != 0 || (ret = sshbuf_put_stringb(cert, k->cert->critical)) != 0 || (ret = sshbuf_put_stringb(cert, k->cert->extensions)) != 0 || (ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */ (ret = sshbuf_put_string(cert, ca_blob, ca_len)) != 0) goto out; /* Sign the whole mess */ if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert), sshbuf_len(cert), alg, 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) goto out; if (alg != NULL && strcmp(alg, sigtype) != 0) { ret = SSH_ERR_SIGN_ALG_UNSUPPORTED; goto out; } if (k->cert->signature_type == NULL) { k->cert->signature_type = sigtype; sigtype = NULL; } /* Append signature and we are done */ if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0) goto out; ret = 0; out: if (ret != 0) sshbuf_reset(cert); free(sig_blob); free(ca_blob); free(sigtype); sshbuf_free(principals); return ret; } static int default_key_sign(struct sshkey *key, u_char **sigp, size_t *lenp, const u_char *data, size_t datalen, 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, sk_provider, sk_pin, compat); } int 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, sk_provider, sk_pin, default_key_sign, NULL); } int sshkey_cert_check_authority(const struct sshkey *k, int want_host, int require_principal, int wildcard_pattern, uint64_t verify_time, const char *name, const char **reason) { u_int i, principal_matches; 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"; return SSH_ERR_KEY_CERT_INVALID; } } else { if (k->cert->type != SSH2_CERT_TYPE_USER) { *reason = "Certificate invalid: not a user certificate"; return SSH_ERR_KEY_CERT_INVALID; } } if (verify_time < k->cert->valid_after) { *reason = "Certificate invalid: not yet valid"; return SSH_ERR_KEY_CERT_INVALID; } if (verify_time >= k->cert->valid_before) { *reason = "Certificate invalid: expired"; return SSH_ERR_KEY_CERT_INVALID; } if (k->cert->nprincipals == 0) { if (require_principal) { *reason = "Certificate lacks principal list"; return SSH_ERR_KEY_CERT_INVALID; } } else if (name != NULL) { principal_matches = 0; for (i = 0; i < k->cert->nprincipals; i++) { if (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; } } if (!principal_matches) { *reason = "Certificate invalid: name is not a listed " "principal"; return SSH_ERR_KEY_CERT_INVALID; } } return 0; } int sshkey_cert_check_authority_now(const struct sshkey *k, int want_host, int require_principal, int wildcard_pattern, const char *name, const char **reason) { time_t now; if ((now = time(NULL)) < 0) { /* yikes - system clock before epoch! */ *reason = "Certificate invalid: not yet valid"; return SSH_ERR_KEY_CERT_INVALID; } return sshkey_cert_check_authority(k, want_host, require_principal, wildcard_pattern, (uint64_t)now, name, reason); } 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_now(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[128]; *from = *to = '\0'; if (cert->valid_after == 0 && cert->valid_before == 0xffffffffffffffffULL) return strlcpy(s, "forever", l); if (cert->valid_after != 0) format_absolute_time(cert->valid_after, from, sizeof(from)); if (cert->valid_before != 0xffffffffffffffffULL) format_absolute_time(cert->valid_before, to, sizeof(to)); if (cert->valid_after == 0) snprintf(ret, sizeof(ret), "before %s", to); else if (cert->valid_before == 0xffffffffffffffffULL) snprintf(ret, sizeof(ret), "after %s", from); else snprintf(ret, sizeof(ret), "from %s to %s", from, to); return strlcpy(s, ret, l); } /* Common serialization for FIDO private keys */ int sshkey_serialize_private_sk(const struct sshkey *key, struct sshbuf *b) { int r; if ((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) return r; return 0; } int sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, enum sshkey_serialize_rep opts) { int r = SSH_ERR_INTERNAL_ERROR; int was_shielded = sshkey_is_shielded(key); struct sshbuf *b = NULL; const struct sshkey_impl *impl; if ((impl = sshkey_impl_from_key(key)) == NULL) return SSH_ERR_INTERNAL_ERROR; if ((r = sshkey_unshield_private(key)) != 0) return r; if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0) goto out; if (sshkey_is_cert(key)) { 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) goto out; } if ((r = impl->funcs->serialize_private(key, b, opts)) != 0) goto out; /* * success (but we still need to append the output to buf after * possibly re-shielding the private key) */ r = 0; out: if (was_shielded) r = sshkey_shield_private(key); if (r == 0) r = sshbuf_putb(buf, b); sshbuf_free(b); return r; } int sshkey_private_serialize(struct sshkey *key, struct sshbuf *b) { return sshkey_private_serialize_opt(key, b, SSHKEY_SERIALIZE_DEFAULT); } /* Shared deserialization of FIDO private key components */ int sshkey_private_deserialize_sk(struct sshbuf *buf, struct sshkey *k) { int r; if ((k->sk_key_handle = sshbuf_new()) == NULL || (k->sk_reserved = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; 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) return r; return 0; } int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) { const struct sshkey_impl *impl; char *tname = NULL; char *expect_sk_application = NULL; u_char *expect_ed25519_pk = NULL; struct sshkey *k = NULL; int type, r = SSH_ERR_INTERNAL_ERROR; if (kp != NULL) *kp = NULL; if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0) goto out; type = sshkey_type_from_name(tname); 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; /* XXX xmss too or refactor */ } else { if ((k = sshkey_new(type)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } } if ((impl = sshkey_impl_from_type(type)) == NULL) { r = SSH_ERR_INTERNAL_ERROR; goto out; } if ((r = impl->funcs->deserialize_private(tname, buf, k)) != 0) goto out; /* XXX xmss too or refactor */ 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) { *kp = k; k = NULL; } out: free(tname); sshkey_free(k); free(expect_sk_application); free(expect_ed25519_pk); return r; } #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) int sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) { EC_POINT *nq = NULL; BIGNUM *order = NULL, *x = NULL, *y = NULL, *tmp = NULL; int ret = SSH_ERR_KEY_INVALID_EC_VALUE; /* * NB. This assumes OpenSSL has already verified that the public * point lies on the curve. This is done by EC_POINT_oct2point() * implicitly calling EC_POINT_is_on_curve(). If this code is ever * reachable with public points not unmarshalled using * EC_POINT_oct2point then the caller will need to explicitly check. */ /* * We shouldn't ever hit this case because bignum_get_ecpoint() * refuses to load GF2m points. */ if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != NID_X9_62_prime_field) goto out; /* Q != infinity */ if (EC_POINT_is_at_infinity(group, public)) goto out; if ((x = BN_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, NULL) != 1 || EC_POINT_get_affine_coordinates_GFp(group, public, x, y, NULL) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (BN_num_bits(x) <= BN_num_bits(order) / 2 || BN_num_bits(y) <= BN_num_bits(order) / 2) goto out; /* nQ == infinity (n == order of subgroup) */ if ((nq = EC_POINT_new(group)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } if (EC_POINT_mul(group, nq, NULL, public, order, NULL) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (EC_POINT_is_at_infinity(group, nq) != 1) goto out; /* x < order - 1, y < order - 1 */ if (!BN_sub(tmp, order, BN_value_one())) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (BN_cmp(x, tmp) >= 0 || BN_cmp(y, tmp) >= 0) goto out; ret = 0; out: BN_clear_free(x); BN_clear_free(y); BN_clear_free(order); BN_clear_free(tmp); EC_POINT_free(nq); return ret; } int sshkey_ec_validate_private(const EC_KEY *key) { BIGNUM *order = NULL, *tmp = NULL; int ret = SSH_ERR_KEY_INVALID_EC_VALUE; 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, NULL) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (BN_num_bits(EC_KEY_get0_private_key(key)) <= BN_num_bits(order) / 2) goto out; /* private < order - 1 */ if (!BN_sub(tmp, order, BN_value_one())) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) goto out; ret = 0; out: BN_clear_free(order); BN_clear_free(tmp); return ret; } void sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point) { BIGNUM *x = NULL, *y = NULL; if (point == NULL) { fputs("point=(NULL)\n", stderr); 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__); goto out; } if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, NULL) != 1) { fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n", __func__); goto out; } fputs("x=", stderr); BN_print_fp(stderr, x); fputs("\ny=", stderr); BN_print_fp(stderr, y); fputs("\n", stderr); out: BN_clear_free(x); BN_clear_free(y); } void sshkey_dump_ec_key(const EC_KEY *key) { const BIGNUM *exponent; sshkey_dump_ec_point(EC_KEY_get0_group(key), EC_KEY_get0_public_key(key)); fputs("exponent=", stderr); if ((exponent = EC_KEY_get0_private_key(key)) == NULL) fputs("(NULL)", stderr); else BN_print_fp(stderr, EC_KEY_get0_private_key(key)); fputs("\n", stderr); } #endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */ static int sshkey_private_to_blob2(struct sshkey *prv, struct sshbuf *blob, const char *passphrase, const char *comment, const char *ciphername, int rounds) { u_char *cp, *key = NULL, *pubkeyblob = NULL; u_char salt[SALT_LEN]; size_t i, pubkeylen, keylen, ivlen, blocksize, authlen; u_int check; int r = SSH_ERR_INTERNAL_ERROR; struct sshcipher_ctx *ciphercontext = NULL; const struct sshcipher *cipher; const char *kdfname = KDFNAME; struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL; if (rounds <= 0) rounds = DEFAULT_ROUNDS; if (passphrase == NULL || !strlen(passphrase)) { ciphername = "none"; kdfname = "none"; } else if (ciphername == NULL) ciphername = DEFAULT_CIPHERNAME; if ((cipher = cipher_by_name(ciphername)) == NULL) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if ((kdf = sshbuf_new()) == NULL || (encoded = sshbuf_new()) == NULL || (encrypted = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } blocksize = cipher_blocksize(cipher); keylen = cipher_keylen(cipher); ivlen = cipher_ivlen(cipher); authlen = cipher_authlen(cipher); if ((key = calloc(1, keylen + ivlen)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (strcmp(kdfname, "bcrypt") == 0) { arc4random_buf(salt, SALT_LEN); if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } if ((r = sshbuf_put_string(kdf, salt, SALT_LEN)) != 0 || (r = sshbuf_put_u32(kdf, rounds)) != 0) goto out; } else if (strcmp(kdfname, "none") != 0) { /* Unsupported KDF type */ r = SSH_ERR_KEY_UNKNOWN_CIPHER; goto out; } if ((r = cipher_init(&ciphercontext, cipher, key, keylen, key + keylen, ivlen, 1)) != 0) goto out; if ((r = sshbuf_put(encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC))) != 0 || (r = sshbuf_put_cstring(encoded, ciphername)) != 0 || (r = sshbuf_put_cstring(encoded, kdfname)) != 0 || (r = sshbuf_put_stringb(encoded, kdf)) != 0 || (r = sshbuf_put_u32(encoded, 1)) != 0 || /* number of keys */ (r = sshkey_to_blob(prv, &pubkeyblob, &pubkeylen)) != 0 || (r = sshbuf_put_string(encoded, pubkeyblob, pubkeylen)) != 0) goto out; /* set up the buffer that will be encrypted */ /* Random check bytes */ check = arc4random(); if ((r = sshbuf_put_u32(encrypted, check)) != 0 || (r = sshbuf_put_u32(encrypted, check)) != 0) goto out; /* append private key and comment*/ if ((r = sshkey_private_serialize_opt(prv, encrypted, SSHKEY_SERIALIZE_FULL)) != 0 || (r = sshbuf_put_cstring(encrypted, comment)) != 0) goto out; /* padding */ i = 0; while (sshbuf_len(encrypted) % blocksize) { if ((r = sshbuf_put_u8(encrypted, ++i & 0xff)) != 0) goto out; } /* length in destination buffer */ if ((r = sshbuf_put_u32(encoded, sshbuf_len(encrypted))) != 0) goto out; /* encrypt */ if ((r = sshbuf_reserve(encoded, sshbuf_len(encrypted) + authlen, &cp)) != 0) goto out; if ((r = cipher_crypt(ciphercontext, 0, cp, sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0) goto out; sshbuf_reset(blob); /* assemble uuencoded key */ if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0 || (r = sshbuf_dtob64(encoded, blob, 1)) != 0 || (r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(kdf); sshbuf_free(encoded); sshbuf_free(encrypted); cipher_free(ciphercontext); explicit_bzero(salt, sizeof(salt)); if (key != NULL) freezero(key, keylen + ivlen); if (pubkeyblob != NULL) freezero(pubkeyblob, pubkeylen); return r; } static int private2_uudecode(struct sshbuf *blob, struct sshbuf **decodedp) { const u_char *cp; size_t encoded_len; int r; u_char last; struct sshbuf *encoded = NULL, *decoded = NULL; if (blob == NULL || decodedp == NULL) return SSH_ERR_INVALID_ARGUMENT; *decodedp = NULL; if ((encoded = sshbuf_new()) == NULL || (decoded = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } /* check preamble */ cp = sshbuf_ptr(blob); encoded_len = sshbuf_len(blob); if (encoded_len < (MARK_BEGIN_LEN + MARK_END_LEN) || memcmp(cp, MARK_BEGIN, MARK_BEGIN_LEN) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } cp += MARK_BEGIN_LEN; encoded_len -= MARK_BEGIN_LEN; /* Look for end marker, removing whitespace as we go */ while (encoded_len > 0) { if (*cp != '\n' && *cp != '\r') { if ((r = sshbuf_put_u8(encoded, *cp)) != 0) goto out; } last = *cp; encoded_len--; cp++; if (last == '\n') { if (encoded_len >= MARK_END_LEN && memcmp(cp, MARK_END, MARK_END_LEN) == 0) { /* \0 terminate */ if ((r = sshbuf_put_u8(encoded, 0)) != 0) goto out; break; } } } if (encoded_len == 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* decode base64 */ if ((r = sshbuf_b64tod(decoded, (char *)sshbuf_ptr(encoded))) != 0) goto out; /* check magic */ if (sshbuf_len(decoded) < sizeof(AUTH_MAGIC) || memcmp(sshbuf_ptr(decoded), AUTH_MAGIC, sizeof(AUTH_MAGIC))) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* 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) 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; if ((cipher = cipher_by_name(ciphername)) == NULL) { r = SSH_ERR_KEY_UNKNOWN_CIPHER; goto out; } if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) { r = SSH_ERR_KEY_UNKNOWN_CIPHER; goto out; } if (strcmp(kdfname, "none") == 0 && strcmp(ciphername, "none") != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } if ((passphrase == NULL || strlen(passphrase) == 0) && strcmp(kdfname, "none") != 0) { /* passphrase required */ r = SSH_ERR_KEY_WRONG_PASSPHRASE; goto out; } /* check size of encrypted key blob */ blocksize = cipher_blocksize(cipher); if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* setup key */ keylen = cipher_keylen(cipher); ivlen = cipher_ivlen(cipher); authlen = cipher_authlen(cipher); if ((key = calloc(1, keylen + ivlen)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (strcmp(kdfname, "bcrypt") == 0) { if ((r = sshbuf_get_string(kdf, &salt, &slen)) != 0 || (r = sshbuf_get_u32(kdf, &rounds)) != 0) goto out; if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen, key, keylen + ivlen, rounds) < 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } } /* check that an appropriate amount of auth data is present */ if (sshbuf_len(decoded) < authlen || sshbuf_len(decoded) - authlen < encrypted_len) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* decrypt private portion of key */ if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 || (r = cipher_init(&ciphercontext, cipher, key, keylen, key + keylen, ivlen, 0)) != 0) goto out; if ((r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(decoded), encrypted_len, 0, authlen)) != 0) { /* an integrity error here indicates an incorrect passphrase */ if (r == SSH_ERR_MAC_INVALID) r = SSH_ERR_KEY_WRONG_PASSPHRASE; goto out; } if ((r = sshbuf_consume(decoded, encrypted_len + authlen)) != 0) goto out; /* there should be no trailing data */ if (sshbuf_len(decoded) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } /* check check bytes */ if ((r = sshbuf_get_u32(decrypted, &check1)) != 0 || (r = sshbuf_get_u32(decrypted, &check2)) != 0) goto out; if (check1 != check2) { r = SSH_ERR_KEY_WRONG_PASSPHRASE; goto out; } /* 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; } 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; if (keyp != NULL) { *keyp = k; k = NULL; } if (commentp != NULL) { *commentp = comment; comment = NULL; } out: free(comment); sshbuf_free(decoded); 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 */ static int sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf, int format, const char *_passphrase, const char *comment) { int was_shielded = sshkey_is_shielded(key); int success, r; int blen, len = strlen(_passphrase); u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL; const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL; char *bptr; BIO *bio = NULL; struct sshbuf *blob; EVP_PKEY *pkey = NULL; if (len > 0 && len <= 4) return SSH_ERR_PASSPHRASE_TOO_SHORT; if ((blob = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; if ((bio = BIO_new(BIO_s_mem())) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if (format == SSHKEY_PRIVATE_PKCS8 && (pkey = EVP_PKEY_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshkey_unshield_private(key)) != 0) goto out; switch (key->type) { case KEY_DSA: if (format == SSHKEY_PRIVATE_PEM) { success = PEM_write_bio_DSAPrivateKey(bio, key->dsa, cipher, passphrase, len, NULL, NULL); } else { success = EVP_PKEY_set1_DSA(pkey, key->dsa); } break; #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: if (format == SSHKEY_PRIVATE_PEM) { success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa, cipher, passphrase, len, NULL, NULL); } else { success = EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa); } break; #endif case KEY_RSA: if (format == SSHKEY_PRIVATE_PEM) { success = PEM_write_bio_RSAPrivateKey(bio, key->rsa, cipher, passphrase, len, NULL, NULL); } else { success = EVP_PKEY_set1_RSA(pkey, key->rsa); } break; default: success = 0; break; } if (success == 0) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if (format == SSHKEY_PRIVATE_PKCS8) { if ((success = PEM_write_bio_PrivateKey(bio, pkey, cipher, passphrase, len, NULL, NULL)) == 0) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } } if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) { r = SSH_ERR_INTERNAL_ERROR; goto out; } if ((r = sshbuf_put(blob, bptr, blen)) != 0) goto out; r = 0; out: if (was_shielded) r = sshkey_shield_private(key); if (r == 0) r = sshbuf_putb(buf, blob); EVP_PKEY_free(pkey); sshbuf_free(blob); BIO_free(bio); return r; } #endif /* WITH_OPENSSL */ /* Serialise "key" to buffer "blob" */ int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, const char *passphrase, const char *comment, int format, const char *openssh_format_cipher, int openssh_format_rounds) { switch (key->type) { #ifdef WITH_OPENSSL case KEY_DSA: case KEY_ECDSA: case KEY_RSA: 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: return SSH_ERR_KEY_TYPE_UNKNOWN; } #ifdef WITH_OPENSSL switch (format) { case SSHKEY_PRIVATE_OPENSSH: return sshkey_private_to_blob2(key, blob, passphrase, comment, openssh_format_cipher, openssh_format_rounds); case SSHKEY_PRIVATE_PEM: case SSHKEY_PRIVATE_PKCS8: return sshkey_private_to_blob_pem_pkcs8(key, blob, format, passphrase, comment); default: return SSH_ERR_INVALID_ARGUMENT; } #endif /* WITH_OPENSSL */ } #ifdef WITH_OPENSSL static int translate_libcrypto_error(unsigned long pem_err) { int pem_reason = ERR_GET_REASON(pem_err); switch (ERR_GET_LIB(pem_err)) { case ERR_LIB_PEM: switch (pem_reason) { case PEM_R_BAD_PASSWORD_READ: #ifdef PEM_R_PROBLEMS_GETTING_PASSWORD case PEM_R_PROBLEMS_GETTING_PASSWORD: #endif #ifdef PEM_R_BAD_DECRYPT case PEM_R_BAD_DECRYPT: #endif return SSH_ERR_KEY_WRONG_PASSPHRASE; default: return SSH_ERR_INVALID_FORMAT; } case ERR_LIB_EVP: switch (pem_reason) { #ifdef EVP_R_BAD_DECRYPT case EVP_R_BAD_DECRYPT: return SSH_ERR_KEY_WRONG_PASSPHRASE; #endif #ifdef EVP_R_BN_DECODE_ERROR case EVP_R_BN_DECODE_ERROR: #endif case EVP_R_DECODE_ERROR: #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR case EVP_R_PRIVATE_KEY_DECODE_ERROR: #endif return SSH_ERR_INVALID_FORMAT; default: return SSH_ERR_LIBCRYPTO_ERROR; } case ERR_LIB_ASN1: return SSH_ERR_INVALID_FORMAT; } return SSH_ERR_LIBCRYPTO_ERROR; } static void clear_libcrypto_errors(void) { while (ERR_get_error() != 0) ; } /* * Translate OpenSSL error codes to determine whether * passphrase is required/incorrect. */ static int convert_libcrypto_error(void) { /* * Some password errors are reported at the beginning * of the error queue. */ if (translate_libcrypto_error(ERR_peek_error()) == SSH_ERR_KEY_WRONG_PASSPHRASE) return SSH_ERR_KEY_WRONG_PASSPHRASE; return translate_libcrypto_error(ERR_peek_last_error()); } static int pem_passphrase_cb(char *buf, int size, int rwflag, void *u) { char *p = (char *)u; size_t len; if (p == NULL || (len = strlen(p)) == 0) return -1; if (size < 0 || len > (size_t)size) return -1; memcpy(buf, p, len); return (int)len; } static int sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, const char *passphrase, struct sshkey **keyp) { EVP_PKEY *pk = NULL; struct sshkey *prv = NULL; BIO *bio = NULL; int r; if (keyp != NULL) *keyp = NULL; if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX) return SSH_ERR_ALLOC_FAIL; if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) != (int)sshbuf_len(blob)) { r = SSH_ERR_ALLOC_FAIL; goto out; } clear_libcrypto_errors(); if ((pk = PEM_read_bio_PrivateKey(bio, NULL, pem_passphrase_cb, (char *)passphrase)) == NULL) { /* * libcrypto may return various ASN.1 errors when attempting * to parse a key with an incorrect passphrase. * Treat all format errors as "incorrect passphrase" if a * passphrase was supplied. */ if (passphrase != NULL && *passphrase != '\0') r = SSH_ERR_KEY_WRONG_PASSPHRASE; else r = convert_libcrypto_error(); goto out; } if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA && (type == KEY_UNSPEC || type == KEY_RSA)) { if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } prv->rsa = EVP_PKEY_get1_RSA(pk); prv->type = KEY_RSA; #ifdef DEBUG_PK RSA_print_fp(stderr, prv->rsa, 8); #endif if (RSA_blinding_on(prv->rsa, NULL) != 1) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } if ((r = sshkey_check_rsa_length(prv, 0)) != 0) goto out; } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA && (type == KEY_UNSPEC || type == KEY_DSA)) { if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } prv->dsa = EVP_PKEY_get1_DSA(pk); prv->type = KEY_DSA; #ifdef DEBUG_PK DSA_print_fp(stderr, prv->dsa, 8); #endif #ifdef OPENSSL_HAS_ECC } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_EC && (type == KEY_UNSPEC || type == KEY_ECDSA)) { if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk); prv->type = KEY_ECDSA; prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa); if (prv->ecdsa_nid == -1 || sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL || sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa), EC_KEY_get0_public_key(prv->ecdsa)) != 0 || sshkey_ec_validate_private(prv->ecdsa) != 0) { r = SSH_ERR_INVALID_FORMAT; goto out; } # ifdef DEBUG_PK if (prv != NULL && prv->ecdsa != NULL) sshkey_dump_ec_key(prv->ecdsa); # endif #endif /* OPENSSL_HAS_ECC */ +#ifdef OPENSSL_HAS_ED25519 + } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_ED25519 && + (type == KEY_UNSPEC || type == KEY_ED25519)) { + size_t len; + + if ((prv = sshkey_new(KEY_UNSPEC)) == NULL || + (prv->ed25519_sk = calloc(1, ED25519_SK_SZ)) == NULL || + (prv->ed25519_pk = calloc(1, ED25519_PK_SZ)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + prv->type = KEY_ED25519; + len = ED25519_PK_SZ; + if (!EVP_PKEY_get_raw_public_key(pk, prv->ed25519_pk, &len)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if (len != ED25519_PK_SZ) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + len = ED25519_SK_SZ - ED25519_PK_SZ; + if (!EVP_PKEY_get_raw_private_key(pk, prv->ed25519_sk, &len)) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + if (len != ED25519_SK_SZ - ED25519_PK_SZ) { + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + /* Append the public key to our private key */ + memcpy(prv->ed25519_sk + (ED25519_SK_SZ - ED25519_PK_SZ), + prv->ed25519_pk, ED25519_PK_SZ); +# ifdef DEBUG_PK + sshbuf_dump_data(prv->ed25519_sk, ED25519_SK_SZ, stderr); +# endif +#endif /* OPENSSL_HAS_ED25519 */ } else { r = SSH_ERR_INVALID_FORMAT; goto out; } r = 0; if (keyp != NULL) { *keyp = prv; prv = NULL; } out: BIO_free(bio); EVP_PKEY_free(pk); sshkey_free(prv); return r; } #endif /* WITH_OPENSSL */ int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, const char *passphrase, struct sshkey **keyp, char **commentp) { int r = SSH_ERR_INTERNAL_ERROR; if (keyp != NULL) *keyp = NULL; if (commentp != NULL) *commentp = NULL; switch (type) { - case KEY_ED25519: case KEY_XMSS: /* No fallback for new-format-only keys */ return sshkey_parse_private2(blob, type, passphrase, keyp, commentp); default: r = sshkey_parse_private2(blob, type, passphrase, keyp, commentp); /* 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, passphrase, keyp); #else return SSH_ERR_INVALID_FORMAT; #endif /* WITH_OPENSSL */ } } int sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase, struct sshkey **keyp, char **commentp) { if (keyp != NULL) *keyp = NULL; if (commentp != NULL) *commentp = NULL; return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC, passphrase, keyp, commentp); } 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 * maxsign times. */ int sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b, u_int32_t maxsign, int printerror) { int r, rupdate; if (maxsign == 0 || sshkey_type_plain(k->type) != KEY_XMSS) return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT); if ((r = sshkey_xmss_get_state(k, 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, printerror)) != 0) { if (r == 0) r = rupdate; } return r; } u_int32_t sshkey_signatures_left(const struct sshkey *k) { if (sshkey_type_plain(k->type) == KEY_XMSS) return sshkey_xmss_signatures_left(k); return 0; } int sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign) { if (sshkey_type_plain(k->type) != KEY_XMSS) return SSH_ERR_INVALID_ARGUMENT; return sshkey_xmss_enable_maxsign(k, maxsign); } int sshkey_set_filename(struct sshkey *k, const char *filename) { if (k == NULL) return SSH_ERR_INVALID_ARGUMENT; if (sshkey_type_plain(k->type) != KEY_XMSS) return 0; if (filename == NULL) return SSH_ERR_INVALID_ARGUMENT; if ((k->xmss_filename = strdup(filename)) == NULL) return SSH_ERR_ALLOC_FAIL; return 0; } #else int sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b, u_int32_t maxsign, int printerror) { return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT); } u_int32_t sshkey_signatures_left(const struct sshkey *k) { return 0; } int sshkey_enable_maxsign(struct sshkey *k, u_int32_t maxsign) { return SSH_ERR_INVALID_ARGUMENT; } int sshkey_set_filename(struct sshkey *k, const char *filename) { if (k == NULL) return SSH_ERR_INVALID_ARGUMENT; return 0; } #endif /* WITH_XMSS */ diff --git a/crypto/openssh/sshsig.c b/crypto/openssh/sshsig.c index d219db90e9a3..d50d65fe203c 100644 --- a/crypto/openssh/sshsig.c +++ b/crypto/openssh/sshsig.c @@ -1,1158 +1,1157 @@ -/* $OpenBSD: sshsig.c,v 1.33 2023/09/06 23:18:15 djm Exp $ */ +/* $OpenBSD: sshsig.c,v 1.34 2023/12/08 09:18:39 markus 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 "authfd.h" #include "authfile.h" #include "log.h" #include "misc.h" #include "sshbuf.h" #include "sshsig.h" #include "ssherr.h" #include "sshkey.h" #include "match.h" #include "digest.h" #define SIG_VERSION 0x01 #define MAGIC_PREAMBLE "SSHSIG" #define MAGIC_PREAMBLE_LEN (sizeof(MAGIC_PREAMBLE) - 1) #define BEGIN_SIGNATURE "-----BEGIN SSH SIGNATURE-----" #define END_SIGNATURE "-----END SSH SIGNATURE-----" #define RSA_SIGN_ALG "rsa-sha2-512" /* XXX maybe make configurable */ #define RSA_SIGN_ALLOWED "rsa-sha2-512,rsa-sha2-256" #define HASHALG_DEFAULT "sha512" /* XXX maybe make configurable */ #define HASHALG_ALLOWED "sha256,sha512" int sshsig_armor(const struct sshbuf *blob, struct sshbuf **out) { struct sshbuf *buf = NULL; int r = SSH_ERR_INTERNAL_ERROR; *out = NULL; if ((buf = sshbuf_new()) == NULL) { error_f("sshbuf_new failed"); r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_putf(buf, "%s\n", BEGIN_SIGNATURE)) != 0) { error_fr(r, "sshbuf_putf"); goto out; } if ((r = sshbuf_dtob64(blob, buf, 1)) != 0) { 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_fr(r, "sshbuf_put"); goto out; } /* success */ *out = buf; buf = NULL; /* transferred */ r = 0; out: sshbuf_free(buf); return r; } int sshsig_dearmor(struct sshbuf *sig, struct sshbuf **out) { int r; size_t eoffset = 0; struct sshbuf *buf = NULL; struct sshbuf *sbuf = NULL; char *b64 = NULL; if ((sbuf = sshbuf_fromb(sig)) == NULL) { error_f("sshbuf_fromb failed"); return SSH_ERR_ALLOC_FAIL; } /* Expect and consume preamble + lf/crlf */ if ((r = sshbuf_cmp(sbuf, 0, BEGIN_SIGNATURE, sizeof(BEGIN_SIGNATURE)-1)) != 0) { error("Couldn't parse signature: missing header"); goto done; } if ((r = sshbuf_consume(sbuf, sizeof(BEGIN_SIGNATURE)-1)) != 0) { error_fr(r, "consume"); goto done; } if ((r = sshbuf_cmp(sbuf, 0, "\r\n", 2)) == 0) eoffset = 2; else if ((r = sshbuf_cmp(sbuf, 0, "\n", 1)) == 0) eoffset = 1; else { r = SSH_ERR_INVALID_FORMAT; error_f("no header eol"); goto done; } if ((r = sshbuf_consume(sbuf, eoffset)) != 0) { error_fr(r, "consume eol"); goto done; } /* Find and consume lf + suffix (any prior cr would be ignored) */ if ((r = sshbuf_find(sbuf, 0, "\n" END_SIGNATURE, sizeof(END_SIGNATURE), &eoffset)) != 0) { error("Couldn't parse signature: missing footer"); goto done; } if ((r = sshbuf_consume_end(sbuf, sshbuf_len(sbuf)-eoffset)) != 0) { error_fr(r, "consume"); goto done; } if ((b64 = sshbuf_dup_string(sbuf)) == NULL) { error_f("sshbuf_dup_string failed"); r = SSH_ERR_ALLOC_FAIL; goto done; } if ((buf = sshbuf_new()) == NULL) { error_f("sshbuf_new() failed"); r = SSH_ERR_ALLOC_FAIL; goto done; } if ((r = sshbuf_b64tod(buf, b64)) != 0) { error_fr(r, "decode base64"); goto done; } /* success */ *out = buf; r = 0; buf = NULL; /* transferred */ done: sshbuf_free(buf); sshbuf_free(sbuf); free(b64); return r; } static int sshsig_wrap_sign(struct sshkey *key, const char *hashalg, 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; u_char *sig = NULL; struct sshbuf *blob = NULL; struct sshbuf *tosign = NULL; const char *sign_alg = NULL; if ((tosign = sshbuf_new()) == NULL || (blob = sshbuf_new()) == NULL) { error_f("sshbuf_new failed"); r = SSH_ERR_ALLOC_FAIL; goto done; } if ((r = sshbuf_put(tosign, MAGIC_PREAMBLE, MAGIC_PREAMBLE_LEN)) != 0 || (r = sshbuf_put_cstring(tosign, sig_namespace)) != 0 || (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_fr(r, "assemble message to sign"); goto done; } /* If using RSA keys then default to a good signature algorithm */ if (sshkey_type_plain(key->type) == KEY_RSA) sign_alg = RSA_SIGN_ALG; if (signer != NULL) { if ((r = signer(key, &sig, &slen, sshbuf_ptr(tosign), sshbuf_len(tosign), 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, sk_provider, sk_pin, 0)) != 0) { error_r(r, "Couldn't sign message"); goto done; } } if ((r = sshbuf_put(blob, MAGIC_PREAMBLE, MAGIC_PREAMBLE_LEN)) != 0 || (r = sshbuf_put_u32(blob, SIG_VERSION)) != 0 || (r = sshkey_puts(key, blob)) != 0 || (r = sshbuf_put_cstring(blob, sig_namespace)) != 0 || (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_fr(r, "assemble signature object"); goto done; } if (out != NULL) { *out = blob; blob = NULL; } r = 0; done: free(sig); sshbuf_free(blob); sshbuf_free(tosign); return r; } /* Check preamble and version. */ static int sshsig_parse_preamble(struct sshbuf *buf) { int r = SSH_ERR_INTERNAL_ERROR; uint32_t sversion; if ((r = sshbuf_cmp(buf, 0, MAGIC_PREAMBLE, MAGIC_PREAMBLE_LEN)) != 0 || (r = sshbuf_consume(buf, (sizeof(MAGIC_PREAMBLE)-1))) != 0 || (r = sshbuf_get_u32(buf, &sversion)) != 0) { error("Couldn't verify signature: invalid format"); return r; } if (sversion > SIG_VERSION) { error("Signature version %lu is larger than supported " "version %u", (unsigned long)sversion, SIG_VERSION); return SSH_ERR_INVALID_FORMAT; } return 0; } static int sshsig_check_hashalg(const char *hashalg) { if (hashalg == NULL || match_pattern_list(hashalg, HASHALG_ALLOWED, 0) == 1) return 0; error_f("unsupported hash algorithm \"%.100s\"", hashalg); return SSH_ERR_SIGN_ALG_UNSUPPORTED; } static int sshsig_peek_hashalg(struct sshbuf *signature, char **hashalgp) { struct sshbuf *buf = NULL; char *hashalg = NULL; int r = SSH_ERR_INTERNAL_ERROR; if (hashalgp != NULL) *hashalgp = NULL; if ((buf = sshbuf_fromb(signature)) == NULL) return SSH_ERR_ALLOC_FAIL; if ((r = sshsig_parse_preamble(buf)) != 0) goto done; if ((r = sshbuf_get_string_direct(buf, NULL, NULL)) != 0 || (r = sshbuf_get_string_direct(buf, NULL, NULL)) != 0 || (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_fr(r, "parse signature object"); goto done; } /* success */ r = 0; *hashalgp = hashalg; hashalg = NULL; done: free(hashalg); sshbuf_free(buf); return r; } 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_sig_details **sig_details) { int r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *buf = NULL, *toverify = NULL; struct sshkey *key = NULL; const u_char *sig; char *got_namespace = NULL, *sigtype = NULL, *sig_hashalg = NULL; size_t siglen; 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_f("sshbuf_new failed"); r = SSH_ERR_ALLOC_FAIL; goto done; } if ((r = sshbuf_put(toverify, MAGIC_PREAMBLE, MAGIC_PREAMBLE_LEN)) != 0 || (r = sshbuf_put_cstring(toverify, expect_namespace)) != 0 || (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_fr(r, "assemble message to verify"); goto done; } if ((r = sshsig_parse_preamble(signature)) != 0) goto done; if ((r = sshkey_froms(signature, &key)) != 0 || (r = sshbuf_get_cstring(signature, &got_namespace, NULL)) != 0 || (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_fr(r, "parse signature object"); goto done; } if (sshbuf_len(signature) != 0) { error("Signature contains trailing data"); r = SSH_ERR_INVALID_FORMAT; goto done; } if (strcmp(expect_namespace, got_namespace) != 0) { error("Couldn't verify signature: namespace does not match"); 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_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_r(r, "Couldn't verify signature: unable to get " "signature type"); goto done; } if (match_pattern_list(sigtype, RSA_SIGN_ALLOWED, 0) != 1) { error("Couldn't verify signature: unsupported RSA " "signature algorithm %s", sigtype); r = SSH_ERR_SIGN_ALG_UNSUPPORTED; goto done; } } if ((r = sshkey_verify(key, sig, siglen, sshbuf_ptr(toverify), sshbuf_len(toverify), NULL, 0, sig_details)) != 0) { error_r(r, "Signature verification failed"); goto done; } /* success */ r = 0; if (sign_keyp != NULL) { *sign_keyp = key; key = NULL; /* transferred */ } done: free(got_namespace); free(sigtype); free(sig_hashalg); sshbuf_free(buf); sshbuf_free(toverify); sshkey_free(key); return r; } static int hash_buffer(const struct sshbuf *m, const char *hashalg, struct sshbuf **bp) { char *hex, hash[SSH_DIGEST_MAX_LENGTH]; int alg, r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *b = NULL; *bp = NULL; memset(hash, 0, sizeof(hash)); if ((r = sshsig_check_hashalg(hashalg)) != 0) return r; if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) { 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_fr(r, "ssh_digest_buffer"); return r; } if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) { debug3_f("final hash: %s", hex); freezero(hex, strlen(hex)); } if ((b = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) { error_fr(r, "sshbuf_put"); goto out; } *bp = b; b = NULL; /* transferred */ /* success */ r = 0; out: sshbuf_free(b); explicit_bzero(hash, sizeof(hash)); 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) { struct sshbuf *b = NULL; int r = SSH_ERR_INTERNAL_ERROR; if (hashalg == NULL) hashalg = HASHALG_DEFAULT; if (out != NULL) *out = NULL; if ((r = hash_buffer(message, hashalg, &b)) != 0) { error_fr(r, "hash buffer"); goto out; } if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, sk_pin, b, sig_namespace, out, signer, signer_ctx)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(b); return r; } int sshsig_verifyb(struct sshbuf *signature, const struct sshbuf *message, 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_f("signature made with hash \"%s\"", hashalg); if ((r = hash_buffer(message, hashalg, &b)) != 0) { error_fr(r, "hash buffer"); goto out; } if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace, sign_keyp, sig_details)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(b); free(hashalg); return r; } static int hash_file(int fd, const char *hashalg, struct sshbuf **bp) { char *hex, rbuf[8192], hash[SSH_DIGEST_MAX_LENGTH]; ssize_t n, total = 0; struct ssh_digest_ctx *ctx = NULL; int alg, oerrno, r = SSH_ERR_INTERNAL_ERROR; struct sshbuf *b = NULL; *bp = NULL; memset(hash, 0, sizeof(hash)); if ((r = sshsig_check_hashalg(hashalg)) != 0) return r; if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) { error_f("can't look up hash algorithm %s", hashalg); return SSH_ERR_INTERNAL_ERROR; } if ((ctx = ssh_digest_start(alg)) == NULL) { error_f("ssh_digest_start failed"); return SSH_ERR_INTERNAL_ERROR; } for (;;) { if ((n = read(fd, rbuf, sizeof(rbuf))) == -1) { if (errno == EINTR || errno == EAGAIN) continue; oerrno = errno; error_f("read: %s", strerror(errno)); errno = oerrno; r = SSH_ERR_SYSTEM_ERROR; goto out; } else if (n == 0) { debug2_f("hashed %zu bytes", total); break; /* EOF */ } total += (size_t)n; if ((r = ssh_digest_update(ctx, rbuf, (size_t)n)) != 0) { error_fr(r, "ssh_digest_update"); goto out; } } if ((r = ssh_digest_final(ctx, hash, sizeof(hash))) != 0) { error_fr(r, "ssh_digest_final"); goto out; } if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) { debug3_f("final hash: %s", hex); freezero(hex, strlen(hex)); } if ((b = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) { error_fr(r, "sshbuf_put"); goto out; } *bp = b; b = NULL; /* transferred */ /* success */ r = 0; out: oerrno = errno; sshbuf_free(b); ssh_digest_free(ctx); explicit_bzero(hash, sizeof(hash)); errno = oerrno; 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) { struct sshbuf *b = NULL; int r = SSH_ERR_INTERNAL_ERROR; if (hashalg == NULL) hashalg = HASHALG_DEFAULT; if (out != NULL) *out = NULL; if ((r = hash_file(fd, hashalg, &b)) != 0) { error_fr(r, "hash_file"); return r; } if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, sk_pin, b, sig_namespace, out, signer, signer_ctx)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(b); return r; } int sshsig_verify_fd(struct sshbuf *signature, int fd, 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_f("signature made with hash \"%s\"", hashalg); if ((r = hash_file(fd, hashalg, &b)) != 0) { error_fr(r, "hash_file"); goto out; } if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace, sign_keyp, sig_details)) != 0) goto out; /* success */ r = 0; out: sshbuf_free(b); free(hashalg); return r; } struct sshsigopt { int ca; char *namespaces; uint64_t valid_after, valid_before; }; struct sshsigopt * sshsigopt_parse(const char *opts, const char *path, u_long linenum, const char **errstrp) { struct sshsigopt *ret; int r; char *opt; const char *errstr = NULL; if ((ret = calloc(1, sizeof(*ret))) == NULL) return NULL; if (opts == NULL || *opts == '\0') return ret; /* Empty options yields empty options :) */ while (*opts && *opts != ' ' && *opts != '\t') { /* flag options */ if ((r = opt_flag("cert-authority", 0, &opts)) != -1) { ret->ca = 1; } else if (opt_match(&opts, "namespaces")) { if (ret->namespaces != NULL) { errstr = "multiple \"namespaces\" clauses"; goto fail; } ret->namespaces = opt_dequote(&opts, &errstr); if (ret->namespaces == NULL) goto fail; } else if (opt_match(&opts, "valid-after")) { if (ret->valid_after != 0) { errstr = "multiple \"valid-after\" clauses"; goto fail; } if ((opt = opt_dequote(&opts, &errstr)) == NULL) goto fail; if (parse_absolute_time(opt, &ret->valid_after) != 0 || ret->valid_after == 0) { free(opt); errstr = "invalid \"valid-after\" time"; goto fail; } free(opt); } else if (opt_match(&opts, "valid-before")) { if (ret->valid_before != 0) { errstr = "multiple \"valid-before\" clauses"; goto fail; } if ((opt = opt_dequote(&opts, &errstr)) == NULL) goto fail; if (parse_absolute_time(opt, &ret->valid_before) != 0 || ret->valid_before == 0) { free(opt); errstr = "invalid \"valid-before\" time"; goto fail; } free(opt); } /* * Skip the comma, and move to the next option * (or break out if there are no more). */ if (*opts == '\0' || *opts == ' ' || *opts == '\t') break; /* End of options. */ /* Anything other than a comma is an unknown option */ if (*opts != ',') { errstr = "unknown key option"; goto fail; } opts++; if (*opts == '\0') { errstr = "unexpected end-of-options"; goto fail; } } /* final consistency check */ if (ret->valid_after != 0 && ret->valid_before != 0 && ret->valid_before <= ret->valid_after) { errstr = "\"valid-before\" time is before \"valid-after\""; goto fail; } /* success */ return ret; fail: if (errstrp != NULL) *errstrp = errstr; sshsigopt_free(ret); return NULL; } void sshsigopt_free(struct sshsigopt *opts) { if (opts == NULL) return; free(opts->namespaces); free(opts); } static int 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) { 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 (principalsp != NULL) *principalsp = NULL; if (sigoptsp != NULL) *sigoptsp = NULL; if (keyp != NULL) *keyp = NULL; cp = line; cp = cp + strspn(cp, " \t"); /* skip leading whitespace */ if (*cp == '#' || *cp == '\0') return SSH_ERR_KEY_NOT_FOUND; /* blank or all-comment line */ /* format: identity[,identity...] [option[,option...]] key */ if ((tmp = strdelimw(&cp)) == NULL || 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); r = SSH_ERR_INVALID_FORMAT; goto out; } if (cp == NULL || *cp == '\0') { error("%s:%lu: missing key", path, linenum); r = SSH_ERR_INVALID_FORMAT; goto out; } *cp++ = '\0'; skip_space(&cp); 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 cert_filter_principals(const char *path, u_long linenum, char **principalsp, const struct sshkey *cert, uint64_t verify_time) { char *cp, *oprincipals, *principals; const char *reason; struct sshbuf *nprincipals; int r = SSH_ERR_INTERNAL_ERROR, success = 0; u_int i; oprincipals = principals = *principalsp; *principalsp = NULL; if ((nprincipals = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } while ((cp = strsep(&principals, ",")) != NULL && *cp != '\0') { /* Check certificate validity */ if ((r = sshkey_cert_check_authority(cert, 0, 1, 0, verify_time, NULL, &reason)) != 0) { debug("%s:%lu: principal \"%s\" not authorized: %s", path, linenum, cp, reason); continue; } /* Return all matching principal names from the cert */ for (i = 0; i < cert->cert->nprincipals; i++) { if (match_pattern(cert->cert->principals[i], cp)) { if ((r = sshbuf_putf(nprincipals, "%s%s", sshbuf_len(nprincipals) != 0 ? "," : "", cert->cert->principals[i])) != 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 check_allowed_keys_line(const char *path, u_long linenum, char *line, const struct sshkey *sign_key, const char *principal, const char *sig_namespace, uint64_t verify_time, char **principalsp) { struct sshkey *found_key = NULL; char *principals = NULL; int r, success = 0; const char *reason = NULL; struct sshsigopt *sigopts = NULL; char tvalid[64], tverify[64]; if (principalsp != NULL) *principalsp = NULL; /* Parse the line */ if ((r = parse_principals_key_and_options(path, linenum, line, principal, &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); } else if (sigopts->ca && sshkey_is_cert(sign_key) && sshkey_equal_public(sign_key->cert->signature_key, found_key)) { if (principal) { /* Match certificate CA key with specified principal */ if ((r = sshkey_cert_check_authority(sign_key, 0, 1, 0, verify_time, principal, &reason)) != 0) { error("%s:%lu: certificate not authorized: %s", path, linenum, reason); goto done; } debug("%s:%lu: matched certificate CA key", path, linenum); } else { /* No principal specified - find all matching ones */ if ((r = cert_filter_principals(path, linenum, &principals, sign_key, verify_time)) != 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); } } else { /* Didn't match key */ goto done; } /* Check whether options preclude the use of this key */ if (sigopts->namespaces != NULL && sig_namespace != NULL && match_pattern_list(sig_namespace, sigopts->namespaces, 0) != 1) { error("%s:%lu: key is not permitted for use in signature " "namespace \"%s\"", path, linenum, sig_namespace); goto done; } /* check key time validity */ format_absolute_time((uint64_t)verify_time, tverify, sizeof(tverify)); if (sigopts->valid_after != 0 && (uint64_t)verify_time < sigopts->valid_after) { format_absolute_time(sigopts->valid_after, tvalid, sizeof(tvalid)); error("%s:%lu: key is not yet valid: " "verify time %s < valid-after %s", path, linenum, tverify, tvalid); goto done; } if (sigopts->valid_before != 0 && (uint64_t)verify_time > sigopts->valid_before) { format_absolute_time(sigopts->valid_before, tvalid, sizeof(tvalid)); error("%s:%lu: key has expired: " "verify time %s > valid-before %s", path, linenum, tverify, tvalid); goto done; } success = 1; done: if (success && principalsp != NULL) { *principalsp = principals; principals = NULL; /* transferred */ } free(principals); sshkey_free(found_key); sshsigopt_free(sigopts); return success ? 0 : SSH_ERR_KEY_NOT_FOUND; } int sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key, const char *principal, const char *sig_namespace, uint64_t verify_time) { FILE *f = NULL; char *line = NULL; size_t linesize = 0; u_long linenum = 0; int r = SSH_ERR_KEY_NOT_FOUND, oerrno; /* Check key and principal against file */ 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 = check_allowed_keys_line(path, linenum, line, sign_key, principal, sig_namespace, verify_time, NULL); 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; } /* Either we hit an error parsing or we simply didn't find the key */ fclose(f); free(line); return r; } int sshsig_find_principals(const char *path, const struct sshkey *sign_key, uint64_t verify_time, char **principals) { FILE *f = NULL; char *line = NULL; size_t linesize = 0; u_long linenum = 0; int r = SSH_ERR_KEY_NOT_FOUND, 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 = check_allowed_keys_line(path, linenum, line, sign_key, NULL, NULL, verify_time, 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; } int sshsig_match_principals(const char *path, const char *principal, char ***principalsp, size_t *nprincipalsp) { FILE *f = NULL; char *found, *line = NULL, **principals = NULL, **tmp; size_t i, nprincipals = 0, linesize = 0; u_long linenum = 0; int oerrno = 0, r, ret = 0; if (principalsp != NULL) *principalsp = NULL; if (nprincipalsp != NULL) *nprincipalsp = 0; /* Check key and principal against file */ 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++; /* Parse the line */ if ((r = parse_principals_key_and_options(path, linenum, line, principal, &found, NULL, NULL)) != 0) { if (r == SSH_ERR_KEY_NOT_FOUND) continue; ret = r; oerrno = errno; break; /* unexpected error */ } if ((tmp = recallocarray(principals, nprincipals, nprincipals + 1, sizeof(*principals))) == NULL) { ret = SSH_ERR_ALLOC_FAIL; free(found); break; } principals = tmp; principals[nprincipals++] = found; /* transferred */ free(line); line = NULL; linesize = 0; } fclose(f); if (ret == 0) { if (nprincipals == 0) ret = SSH_ERR_KEY_NOT_FOUND; + if (nprincipalsp != 0) + *nprincipalsp = nprincipals; if (principalsp != NULL) { *principalsp = principals; principals = NULL; /* transferred */ - } - if (nprincipalsp != 0) { - *nprincipalsp = nprincipals; nprincipals = 0; } } for (i = 0; i < nprincipals; i++) free(principals[i]); free(principals); errno = oerrno; return ret; } 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/crypto/openssh/version.h b/crypto/openssh/version.h index ba3690668818..6b7067e19f8b 100644 --- a/crypto/openssh/version.h +++ b/crypto/openssh/version.h @@ -1,8 +1,8 @@ -/* $OpenBSD: version.h,v 1.99 2023/10/04 04:04:09 djm Exp $ */ +/* $OpenBSD: version.h,v 1.100 2023/12/18 14:48:44 djm Exp $ */ -#define SSH_VERSION "OpenSSH_9.5" +#define SSH_VERSION "OpenSSH_9.6" #define SSH_PORTABLE "p1" #define SSH_RELEASE SSH_VERSION SSH_PORTABLE -#define SSH_VERSION_FREEBSD "FreeBSD-20231004" +#define SSH_VERSION_FREEBSD "FreeBSD-20240104" diff --git a/secure/usr.bin/ssh-agent/Makefile b/secure/usr.bin/ssh-agent/Makefile index 9d0f23db7dae..83813452e69a 100644 --- a/secure/usr.bin/ssh-agent/Makefile +++ b/secure/usr.bin/ssh-agent/Makefile @@ -1,25 +1,25 @@ .include .include "${SRCTOP}/secure/ssh.mk" PROG= ssh-agent -SRCS= ssh-agent.c +SRCS= ssh-agent.c ssh-pkcs11-client.c PACKAGE= ssh LIBADD= ssh .if ${MK_LDNS} != "no" CFLAGS+= -DHAVE_LDNS=1 #DPADD+= ${LIBLDNS} #LDADD+= -lldns .endif .if defined(LOCALBASE) CFLAGS+= -DDEFAULT_PKCS11_WHITELIST='"/usr/lib*/*,${LOCALBASE}/lib*/*"' .endif LIBADD+= crypto .include .PATH: ${SSHDIR}