diff --git a/.depend b/.depend index 152905fb7b78..93e4d864eb52 100644 --- a/.depend +++ b/.depend @@ -79,6 +79,7 @@ loginrec.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-comp 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-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 digest.h log.h ssherr.h misc.h pathnames.h ssh.h xmalloc.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 srclimit.h @@ -113,8 +114,8 @@ servconf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-comp 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 version.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 +session.o: kex.h mac.h crypto_api.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h authfd.h pathnames.h log.h misc.h servconf.h sshlogin.h serverloop.h canohost.h session.h monitor_wrap.h sftp.h atomicio.h sftp-client.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/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 @@ -128,24 +129,22 @@ sntrup761.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-com 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 ./openbsd-compat/sys-tree.h addr.h canohost.h log.h ssherr.h misc.h srclimit.h xmalloc.h servconf.h openbsd-compat/sys-queue.h match.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-keygen.o: 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 atomicio.h krl.h digest.h utf8.h authfd.h sshsig.h ssh-sk.h sk-api.h cipher.h cipher-chachapoly.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-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 pathnames.h xmalloc.h sshbuf.h log.h ssherr.h misc.h sshkey.h authfd.h atomicio.h ssh-pkcs11.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 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-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-pkcs11.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 dh.h misc.h version.h myproposal.h sshbuf.h openbsd-compat/openssl-compat.h @@ -163,11 +162,10 @@ sshd-auth.o: chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h sshkey.h ke sshd-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 ./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 sshd-session.o: chacha.h 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 auth-options.h version.h sk-api.h srclimit.h dh.h sshd-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-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 -sshd.o: audit.h loginrec.h authfd.h msg.h version.h sk-api.h addr.h srclimit.h atomicio.h +sshd.o: audit.h loginrec.h authfd.h msg.h version.h sk-api.h addr.h srclimit.h atomicio.h monitor_wrap.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 sshpty.h log.h ssherr.h sshbuf.h misc.h servconf.h compat.h digest.h sshkey.h authfile.h pathnames.h canohost.h hostfile.h auth.h auth-pam.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 +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 ssh-pkcs11.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 @@ -178,8 +176,3 @@ umac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.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/.github/README.md b/.github/README.md new file mode 100644 index 000000000000..4af94282ec87 --- /dev/null +++ b/.github/README.md @@ -0,0 +1,266 @@ +# `.github/` — AI-Assisted Development for OpenSSH-Portable (Windows Fork) + +This folder contains everything needed to work on the PowerShell team's +Windows fork of OpenSSH-Portable with AI assistance in VS Code (GitHub +Copilot Chat / agent mode). It bundles together **agents**, **prompts**, +**instructions**, **skills**, and a set of PowerShell **tools** exposed as +an **MCP server** so that complex workflows (especially upstream merges) +can be driven mostly by an AI agent with a human reviewer in the loop. + +If you are new here, read the [Overview](#overview) first, set up the +[MCP server](#mcp-server-setup-vscodemcpjson), then jump to +[Merging from upstream](#merging-from-upstream) for the most common +workflow. + +--- + +## Overview + +### What lives in `.github/` + +| Folder | Purpose | +|---|---| +| [`agents/`](./agents/) | Custom Copilot **agent modes** — pre-configured personas with curated tool access for specific workflows. | +| [`prompts/`](./prompts/) | Reusable **prompt templates** that kick off a workflow with the right inputs and context. | +| [`instructions/`](./instructions/) | **Instructions** auto-loaded into agent context (via `applyTo` globs) describing repo conventions, build process, merge strategy, testing, etc. | +| [`skills/`](./skills/) | Self-contained **skill packages** the agent can invoke for narrow, repeatable tasks (e.g. bumping a vcpkg port). | +| [`tools/`](./tools/) | PowerShell scripts exposed through the MCP server as callable tools (build, test, git, merge orchestration, vcpkg). | +| [`workflows/`](./workflows/) | GitHub Actions workflows (CI). Not AI-related. | + +### How the pieces fit together + +``` +┌────────────────────────────────────────────────────────────────┐ +│ VS Code + GitHub Copilot (chat / agent mode) │ +│ │ +│ ├─ loads instructions/*.md (auto, by applyTo) │ +│ ├─ can switch into an agent from agents/*.agent.md │ +│ ├─ can be launched via a prompt from prompts/*.prompt.md │ +│ ├─ can invoke skills from skills/*/SKILL.md │ +│ └─ can call MCP tools ──────────────────┐ │ +└───────────────────────────────────────────┼────────────────────┘ + ▼ + ┌─────────────────────────────┐ + │ MCP server (openssh-server)│ + │ defined in .vscode/mcp.json│ + │ runs PowerShell from │ + │ .github/tools/*.ps1 │ + └─────────────────────────────┘ +``` + +--- + +## Repository setup + +Follow [instructions/setup.instructions.md](./instructions/setup.instructions.md) +end-to-end. It covers cloning the fork, configuring the `upstream` and +`upstream-pwsh` remotes, prerequisites (Visual Studio + Windows SDK), and +cloning + bootstrapping vcpkg via +[Install-VcpkgDependencies.ps1](./tools/Install-VcpkgDependencies.ps1). +For the vendored dependency model itself, see +[instructions/vcpkg.instructions.md](./instructions/vcpkg.instructions.md). +Once setup is complete, do a baseline build per +[instructions/build.instructions.md](./instructions/build.instructions.md). + +--- + +## MCP server setup (`.vscode/mcp.json`) + +The PowerShell scripts in [`tools/`](./tools/) are exposed to Copilot via +a small MCP (Model Context Protocol) server so the agent can call them as +first-class tools (`mcp_openssh-server_Start_OpenSSHBuild`, +`mcp_openssh-server_Invoke_Git`, etc.). + +### 1. Install the MCP host module + +The server is hosted by the `MCPServerPS` PowerShell module, which wraps +each `.ps1` in `-ScriptRoot` as an MCP tool. See the linked package page +for installation details: https://github.com/daxian-dbw/MCPServerPS/pkgs/nuget/MCPServerPS + +### 2. Configure VS Code + +Create `.vscode/mcp.json` at the repo root (already present in this repo +— adjust the path if your clone lives elsewhere): + +```json +{ + "servers": { + "openssh-server": { + "type": "stdio", + "command": "pwsh", + "args": [ + "-noprofile", + "-c", + "MCPServerPS\\Start-MyMCP -ScriptRoot C:\\repos\\openssh-portable\\.github\\tools" + ] + } + }, + "inputs": [] +} +``` + +> **Path note:** Update `C:\repos\openssh-portable\.github\tools` to the +> absolute path of `.github/tools` in your clone. + +### 3. Start the server in VS Code + +- Open the **MCP: List Servers** command (Command Palette). +- Start `openssh-server`. You should see the tools become available to + Copilot Chat (their names are prefixed with + `mcp_openssh-server_`, e.g. `mcp_openssh-server_Invoke_Git`). +- In agent mode, the agent will discover and call them automatically. + +### 4. Available MCP tools + +All tools are PowerShell scripts under [`tools/`](./tools/). They are +documented in detail inside their respective instruction files; here's a +quick map: + +| Tool (MCP name) | Script | What it does | +|---|---|---| +| `mcp_openssh-server_Test_MergePrerequisites` | [Test-MergePrerequisites.ps1](./tools/Test-MergePrerequisites.ps1) | Verify environment + remotes are ready for a merge. | +| `mcp_openssh-server_Get_CommitGroups` | [Get-CommitGroups.ps1](./tools/Get-CommitGroups.ps1) | Group upstream commits into mergeable batches by CI presence/success. | +| `mcp_openssh-server_Get_RemainingCommitCount` | [Get-RemainingCommitCount.ps1](./tools/Get-RemainingCommitCount.ps1) | Count commits remaining between a start ref and the end tag/HEAD (merge progress). | +| `mcp_openssh-server_Invoke_Git` | [Invoke-Git.ps1](./tools/Invoke-Git.ps1) | Structured wrapper around git operations (Status, Merge, Diff, Checkout, …). | +| `mcp_openssh-server_Get_ConflictContext` | [Get-ConflictContext.ps1](./tools/Get-ConflictContext.ps1) | Three-way diff context for high-complexity merge conflicts. | +| `mcp_openssh-server_Test_MergeConflictMarkers` | [Test-MergeConflictMarkers.ps1](./tools/Test-MergeConflictMarkers.ps1) | Scan the working tree for leftover conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`) and unmerged paths. | +| `mcp_openssh-server_Sync_VersionResource` | [Sync-VersionResource.ps1](./tools/Sync-VersionResource.ps1) | Sync `contrib/win32/openssh/version.rc` numbers to `version.h` after a version bump. | +| `mcp_openssh-server_Start_OpenSSHBuild` | [Start-OpenSSHBuild.ps1](./tools/Start-OpenSSHBuild.ps1) | Build the Win32-OpenSSH solution. Defaults to the host architecture. | +| `mcp_openssh-server_Test_OpenSSHBuild` | [Test-OpenSSHBuild.ps1](./tools/Test-OpenSSHBuild.ps1) | Parse the most recent build log for errors and warnings. | +| `mcp_openssh-server_Test_OpenSSHFunctionality` | [Test-OpenSSHFunctionality.ps1](./tools/Test-OpenSSHFunctionality.ps1) | End-to-end smoke test (install service, connect, cleanup). | +| `mcp_openssh-server_Invoke_OpenSSHTests` | [Invoke-OpenSSHTests.ps1](./tools/Invoke-OpenSSHTests.ps1) | Full CI suite (unit + bash + Pester E2E). | +| `mcp_openssh-server_Install_VcpkgDependencies` | [Install-VcpkgDependencies.ps1](./tools/Install-VcpkgDependencies.ps1) | Bootstrap vcpkg and install vendored deps. Also runnable directly from a terminal for first-time setup. | +| `mcp_openssh-server_Update_VcpkgPort` | [Update-VcpkgPort.ps1](./tools/Update-VcpkgPort.ps1) | Bump a vendored vcpkg port. Orchestrated by the `update-vcpkg-port` skill. | + +--- + +## Instructions, agents, prompts, and skills + +### Instructions ([`instructions/`](./instructions/)) + +Markdown files with YAML frontmatter that the agent loads automatically +based on `applyTo` globs. They encode the conventions and workflows of +this repo so you don't need to repeat them in every prompt. + +General: +- [getting-started.instructions.md](./instructions/getting-started.instructions.md) — index of all instruction files +- [repository-overview.instructions.md](./instructions/repository-overview.instructions.md) — repo layout + Windows compatibility layer +- [setup.instructions.md](./instructions/setup.instructions.md) — clone, remotes, prerequisites, vcpkg +- [build.instructions.md](./instructions/build.instructions.md) — building on Windows + warning policy +- [testing.instructions.md](./instructions/testing.instructions.md) — functional + full CI testing +- [vcpkg.instructions.md](./instructions/vcpkg.instructions.md) — vendored dependency reference +- [agent-communication.instructions.md](./instructions/agent-communication.instructions.md) — how the agent should talk to you + +Merge-specific (under [`instructions/merge/`](./instructions/merge/)): +- [merge-process-overview.instructions.md](./instructions/merge/merge-process-overview.instructions.md) — the two-phase workflow end-to-end +- [merge-details.instructions.md](./instructions/merge/merge-details.instructions.md) — conflict resolution patterns + decision trees +- [research.instructions.md](./instructions/merge/research.instructions.md) — what to read before merging (release notes, prior PRs) +- [agent-communication-merge.instructions.md](./instructions/merge/agent-communication-merge.instructions.md) — communication templates for batches + +### Agents ([`agents/`](./agents/)) + +Custom Copilot agent modes with curated tool sets and a system prompt +tuned to a workflow. + +- [merge-upstream.agent.md](./agents/merge-upstream.agent.md) — drives + the upstream merge workflow end-to-end (analysis → batch merges → + build → test → PR prep). Switch to it from the Copilot Chat agent + picker. +- [conflict-review.agent.md](./agents/conflict-review.agent.md) — + review-only subagent the merge agent delegates to after resolving a + batch's conflicts. Audits resolutions for leftover markers, prefer- + upstream bias, balanced Windows guards, silently auto-merged changes + needing Windows follow-up, and version sync; returns APPROVE or + CHANGES-REQUIRED. + +### Prompts ([`prompts/`](./prompts/)) + +Reusable prompt templates with documented inputs. + +- [merge.prompt.md](./prompts/merge.prompt.md) — kicks off a merge with + the right context. Provide a start ref (and optionally end ref, + remotes, validation scenario), and the agent handles the rest. + +### Skills ([`skills/`](./skills/)) + +Self-contained workflow skills the agent reads on demand. + +- [update-vcpkg-port](./skills/update-vcpkg-port/SKILL.md) — bump a + vendored vcpkg dependency (LibreSSL, libfido2, libcbor, zlib) with + all the side effects (overlay portfile SHA512, LibreSSL resource + patch) handled correctly. +- [resolve-merge-conflict](./skills/resolve-merge-conflict/SKILL.md) — + conflict-resolution procedure for upstream merges (prefer-upstream + + adapt for Windows, strategy preference order, silent auto-merge + hunting, regress-test and version-resource sync) plus how to summarize + the resolutions for the pull request. +- [merge-retrospective](./skills/merge-retrospective/SKILL.md) — run + after a merge PR lands to capture new conflict-resolution patterns and + feed lessons back into the instructions, skills, agents, and tools. + +--- + +## Merging from upstream + +Merging from `openssh/openssh-portable` is the headline workflow this +folder is built around. It uses a **two-phase approach** (all incremental +merges, conflict resolution, build fixes, and validation happen on a +scratch branch; then a real merge branch is created from the same +starting commit, a single `git merge` of the upstream target is +performed, and any conflicts are resolved by copying the resolved files +from the scratch branch). This preserves upstream commit history +exactly. The full workflow lives in +[instructions/merge/merge-process-overview.instructions.md](./instructions/merge/merge-process-overview.instructions.md); +conflict-resolution patterns are in +[merge-details.instructions.md](./instructions/merge/merge-details.instructions.md); +background reading is in +[research.instructions.md](./instructions/merge/research.instructions.md). + +### Driving the merge with AI (recommended) + +1. Make sure the [MCP server is running](#mcp-server-setup-vscodemcpjson). +2. In Copilot Chat, switch to the **`merge-upstream`** agent + ([agents/merge-upstream.agent.md](./agents/merge-upstream.agent.md)). +3. Invoke the merge prompt + ([prompts/merge.prompt.md](./prompts/merge.prompt.md)) with at minimum + a start ref — see that file for the full input list and examples. +4. Approve each batch summary the agent presents; at the end, push the + real branch and open the PR. + +### Driving the merge manually + +Follow +[merge-process-overview.instructions.md](./instructions/merge/merge-process-overview.instructions.md) +step by step. + +### Validation + +Default validation is end-to-end via +`mcp_openssh-server_Test_OpenSSHFunctionality`. The full CI suite is +documented in +[instructions/testing.instructions.md](./instructions/testing.instructions.md). + +--- + +## Other AI-assisted workflows + +### Bumping a vendored vcpkg dependency + +Use the [`update-vcpkg-port`](./skills/update-vcpkg-port/SKILL.md) skill. +Ask Copilot something like *"Bump LibreSSL to 4.1.1 using the +update-vcpkg-port skill."* The skill orchestrates +[Update-VcpkgPort.ps1](./tools/Update-VcpkgPort.ps1) (manifest, overlay +portfile SHA512, LibreSSL resource patch), validates via +[Install-VcpkgDependencies.ps1](./tools/Install-VcpkgDependencies.ps1), +then builds to confirm. + +### Building / testing / debugging + +Even outside a merge, the MCP tools are useful day-to-day. See +[build.instructions.md](./instructions/build.instructions.md) and +[testing.instructions.md](./instructions/testing.instructions.md) for +the full parameter reference of `Start-OpenSSHBuild`, +`Test-OpenSSHBuild`, `Test-OpenSSHFunctionality`, and +`Invoke-OpenSSHTests`. + + diff --git a/.github/agents/conflict-review.agent.md b/.github/agents/conflict-review.agent.md new file mode 100644 index 000000000000..50fc9c3f906b --- /dev/null +++ b/.github/agents/conflict-review.agent.md @@ -0,0 +1,127 @@ +--- +name: conflict-review +description: Reviews the merge agent's conflict-resolution decisions for a batch and flags incorrect, risky, or incomplete Windows handling before the batch is accepted. +tools: + ['read', 'search', 'execute', 'openssh-server/*', 'todo'] +--- +# Conflict Resolution Review Agent + +## Agent Purpose + +This is a **review-only** subagent. The `merge-upstream` agent delegates to it +after resolving the conflicts for a batch (and before completing the merge / +moving to the next batch). Its job is to independently audit the conflict +resolutions and Windows-compatibility decisions and return a verdict, so a +second set of eyes catches mistakes the resolver may have missed. + +It does **not** edit code. It reads the resolved files, the upstream diffs, and +the surrounding context, then reports findings. The `merge-upstream` agent +decides what to act on. + +## When It Is Invoked + +- By `merge-upstream` after the conflicts for a batch have been resolved and + staged, on the **scratch branch**, before `MergeContinue` (or immediately + after, before the batch summary). +- Whenever the resolver is unsure about a specific file and wants a targeted + second opinion. + +## Inputs the Caller Should Provide + +1. The batch's upstream commit range (start..end SHAs). +2. The list of files that had conflicts and how each was resolved (a one-line + strategy per file: took-upstream / combined-with-ifdef / excluded-with-ifndef + / manual-rewrite). +3. Any files that were **auto-merged** but then hand-edited on the scratch + branch (these are easy to miss — see the review checklist). + +If the caller does not provide these, reconstruct them from git: +- `Invoke-Git Operation="Diff" Range=".." NameOnly=true` for the + set of upstream-touched files. +- `git log --merges` / `git show ` for what was merged. +- `Test-MergeConflictMarkers` (`mcp_openssh-server_Test_MergeConflictMarkers`) + to confirm no unresolved markers remain. + +## Review Checklist + +For **each** resolved file, verify: + +1. **No leftover markers.** Run `Test-MergeConflictMarkers`. Any `<<<<<<<`, + `=======`, `>>>>>>>`, or `|||||||` remaining is an automatic FAIL. + +2. **Upstream intent preserved.** Compare the resolved region against the + upstream *after* version (use `Get-ConflictContext` + `mcp_openssh-server_Get_ConflictContext` for high-complexity files). The + resolution should keep upstream's behavioral change unless there is a + documented Windows reason not to. + +3. **Prefer-upstream bias respected.** The fork's policy is to **take upstream + changes and wrap Windows differences in `#ifdef WINDOWS`**, not to keep the + old fork behavior just because it was there. Flag any resolution that + silently retains the fork's prior logic where upstream moved on. (Classic + example: upstream relocating pre-auth/KEX work between `sshd-session` and + `sshd-auth` — the correct resolution follows upstream's placement and adds + Windows adjustments, rather than forcing the work back into the old file for + Windows.) + +4. **Windows guards are correct and balanced.** Every `#ifdef WINDOWS` / + `#ifndef WINDOWS` has a matching `#endif`; the non-Windows branch still + contains upstream's code verbatim; guards don't accidentally exclude code + needed on Windows. + +5. **No upstream code deleted.** Upstream additions should be preserved (guarded + if necessary), never removed — removal creates recurring future conflicts. + +6. **Auto-merged-but-impactful changes.** Look beyond conflicted files. Scan the + batch for upstream changes that merged cleanly (no conflict) but still need + Windows follow-up that git could not know about, e.g.: + - `ssh-agent.c` / agent protocol changes not mirrored in the separate + Windows agent under `contrib/win32/win32compat/ssh-agent/`. + - New feature flags / `#define`s that must be added to + `contrib/win32/openssh/config.h.vs`. + - New source files added to `Makefile.in` that are missing from the relevant + `.vcxproj` / the solution. + - New syscalls / POSIX APIs (fork, signal, pipe, socket options) with no + `w32_*` equivalent in `win32compat`. + +7. **Regress tests.** For any touched `regress/*.sh` that already contains + `if [ "$os" == "windows" ]` blocks, confirm new upstream test cases got the + same Windows adaptation (e.g. `diff --strip-trailing-cr`). + +8. **version.h / version.rc.** If `version.h` was part of the batch, confirm the + Windows fields were preserved and `version.rc` was synced + (`mcp_openssh-server_Sync_VersionResource`). + +## Output Format + +Return a concise structured verdict: + +```markdown +## Conflict Review — Batch .. + +**Verdict:** APPROVE / APPROVE WITH NITS / CHANGES REQUIRED + +### Blocking issues (CHANGES REQUIRED) +- + +### Non-blocking nits +- + +### Auto-merged changes needing Windows follow-up +- (win32compat / config.h.vs / vcxproj / …) + +### Verified clean +- No leftover conflict markers (Test-MergeConflictMarkers: PASS) +- +``` + +Be specific and cite file:line. Only raise **blocking** issues for genuine +correctness/compat problems (leftover markers, dropped upstream behavior, broken +guards, missing Windows follow-up that will break the build or runtime). Do not +block on style. If everything is clean, say so plainly and APPROVE. + +## Reference Material + +- [merge-details.instructions.md](../instructions/merge/merge-details.instructions.md) — conflict-resolution patterns (prefer-upstream, `#ifdef WINDOWS`, regress adaptation, silent auto-merge follow-up). +- [resolve-merge-conflict skill](../skills/resolve-merge-conflict/SKILL.md) — the checklist the resolver is expected to follow. +- [repository-overview.instructions.md](../instructions/repository-overview.instructions.md) — win32compat layer and the separate Windows ssh-agent. diff --git a/.github/agents/merge-upstream.agent.md b/.github/agents/merge-upstream.agent.md new file mode 100644 index 000000000000..e3979ea0dad1 --- /dev/null +++ b/.github/agents/merge-upstream.agent.md @@ -0,0 +1,669 @@ +--- +name: merge-upstream +description: Assist with merging upstream OpenSSH commits into the PowerShell fork. +tools: + ['vscode', 'execute', 'read', 'edit', 'search', 'web', 'agent', 'openssh-server/*', 'todo'] +--- +# OpenSSH Upstream Merge Agent + +## Agent Purpose +This agent assists with merging upstream OpenSSH commits into the PowerShell fork (PowerShell/openssh-portable). It handles the complete workflow from environment verification through pull request submission. + +**Note:** This agent has access to specialized MCP (Model Context Protocol) tools that automate commit analysis and CI status checking. When available, use the MCP tools instead of running scripts manually. + +## Agent Capabilities + +### Core Functions +- **Environment verification and setup** +- **Commit group analysis** using Get-CommitGroups MCP tool +- **Two-phase merge**: (1) incremental work on a scratch branch (batched merges, conflict resolution, build fixes, validation); (2) create the real merge branch from the same starting point, perform a single merge of the final upstream target, and resolve any conflicts by copying the already-resolved files from the scratch branch. +- **Windows-specific build system updates** +- **Compilation and testing** +- **Documentation and PR preparation** + +### Key Tools Available + +1. **Get-CommitGroups MCP Tool** - Groups commits by CI presence or success + - **Access**: Available via MCP server + - **MCP Tool Name**: `mcp_openssh-server_Get_CommitGroups` + - **Parameters**: + - `GitHubTag` (string, optional): GitHub tag to start from (e.g., "V_10_0_P2") + - `StartCommit` (string, optional): Commit SHA to start from + - `EndCommit` (string, optional): Commit SHA to end at (default: HEAD - most recent upstream commit) + - `FirstChunkOnly` (boolean, optional): Stop after finding first chunk + - `GroupByCIPresence` (boolean, optional): Group by CI presence instead of CI success + - **Required Usage**: Always pass `-FirstChunkOnly`. The value of `-GroupByCIPresence` is determined by the user-supplied **CI grouping mode** (see Phase 0): + - `presence` → `GroupByCIPresence=true` (batches end at any commit with CI runs) + - `success` → `GroupByCIPresence=false` (batches end only at commits with successful CI) + - **If the user has not specified a mode, ask before invoking the tool.** Do not assume a default. + - **Usage**: Use the MCP tool function directly - it handles all GitHub API calls + - **If tool unavailable**: ERROR - This tool is required for the merge workflow + +2. **Start-OpenSSHBuild MCP Tool** - Build automation + - **MCP Tool Name**: `mcp_openssh-server_Start_OpenSSHBuild` + - **Parameters**: + - `Configuration` (string, optional): Build configuration - "Debug" or "Release" (default: "Release") + - `Architecture` (string, optional): Target architecture - "x64", "x86", "ARM", "ARM64". **Defaults to the host machine's architecture** (auto-detected). If you pass an architecture that does not match the host, the tool throws unless `-AllowArchMismatch` is also passed. Do NOT hard-code `x64`. + - `AllowArchMismatch` (switch, optional): Permit building for a non-host architecture (e.g. cross-compiling x64 on an ARM64 host). + - `Clean` (boolean, optional): Perform clean build (default: false) + - **If tool unavailable**: ERROR - This tool is required for the merge workflow + +3. **Test-OpenSSHFunctionality MCP Tool** - Functional testing + - **MCP Tool Name**: `mcp_openssh-server_Test_OpenSSHFunctionality` + - **Parameters**: + - `Configuration` (string, optional): Build configuration - "Debug" or "Release" (default: "Release") + - `Architecture` (string, optional): Target architecture. **Defaults to the host architecture**; mismatches are blocked unless `-AllowArchMismatch` is passed. Use the same architecture you built with. + - `SkipFirewall` (boolean, optional): Skip firewall configuration (default: false) + - `NoCleanup` (boolean, optional): Skip cleanup for debugging (default: false) + - **If tool unavailable**: ERROR - This tool is required for the merge workflow + +4. **Get-ConflictContext MCP Tool** - Three-way conflict context for high-complexity conflicts + - **MCP Tool Name**: `mcp_openssh-server_Get_ConflictContext` + - **When to use**: ONLY when `assess_conflict_complexity()` returns `HIGH_COMPLEXITY` + - **Parameters**: + - `FilePath` (string, required): Path to the conflicted file relative to the repository root + - `CommitHash` (string, required): The upstream commit SHA being cherry-picked that caused the conflict + - `ContextLines` (integer, optional): Lines of context above/below each hunk match (default: 40) + - `MaxTotalLines` (integer, optional): Maximum total lines across all three versions and all hunks (default: 150 — ~50 per version). Increase if broader context is needed. + - **What it returns**: For each hunk in the upstream diff — excerpts from three versions: + - `UpstreamBefore`: The file as it existed in upstream *before* this commit + - `UpstreamAfter`: The file in upstream *after* this commit + - `OurFork`: The corresponding region in our fork (located by content-anchor matching, not line numbers) + - **Budget**: `max(10, floor(MaxTotalLines / 3 / hunkCount))` lines per version per hunk; a warning is added to `Message` if the 10-line minimum floor is applied + - **If tool unavailable**: Fall back to reading the conflicted file directly and using `Invoke_Git Operation="Show"` and `Operation="Diff"` to gather context manually + +5. **Git** - Version control operations + - Merge: `Invoke-Git Operation="Merge" CommitHash=""` (uses `--no-ff`) + - MergeContinue / MergeAbort for conflict flow + - Checkout from another branch: `git checkout -- ` (used to copy resolved files from scratch → merge branch) + - Cherry-pick operations remain available for other use cases + - Status: `git status` + - Remotes: `origin`, `upstream-pwsh`, `upstream` + - **Do NOT enable `rerere.enabled`.** The two-phase merge workflow does not rely on rerere; resolutions are copied wholesale from the scratch branch in Phase 6. If `rerere.enabled` is set in the local repo, disable it (`git config --local rerere.enabled false; git config --local rerere.autoupdate false`) so cached resolutions cannot silently influence batch merges. + +6. **vcpkg dependency management** - Vendored library installation and updates + - **Install tool**: `.\.github\tools\Install-VcpkgDependencies.ps1` (also exposed via MCP as `mcp_openssh-server_Install_VcpkgDependencies` when registered). + - When to use: build fails because `contrib/win32/openssh/vcpkg_installed/-custom/` is missing (e.g., on a fresh clone or after `vcpkg.json` changes). + - First-time setup: run with `-Bootstrap`. Multi-arch parity with CI: `-Architecture x64,x86,ARM,ARM64`. + - Default `-Architecture` matches `Start-OpenSSHBuild` (the host architecture). Install the triplet(s) for the architecture(s) you will build. + - **Update skill**: [.github/skills/update-vcpkg-port/SKILL.md](../skills/update-vcpkg-port/SKILL.md). + - When to use: an upstream merge bumps a vendored dependency (libressl, libfido2, libcbor, zlib), or upstream OpenSSH starts requiring a newer minimum. + - The skill orchestrates `Update-VcpkgPort.ps1`, walks the patch-rejection decision tree, validates with the install tool and a build, and produces a commit message. + - **Reference**: [vcpkg.instructions.md](../instructions/vcpkg.instructions.md) for layout, custom triplets, and overlay-port rationale. + +7. **Get-RemainingCommitCount MCP Tool** - Merge progress tracking + - **MCP Tool Name**: `mcp_openssh-server_Get_RemainingCommitCount` + - **Parameters**: `StartRef` (required) — ref to count from; `EndRef` (optional, default `HEAD`) — end tag/commit. + - **When to use**: at the start of each batch (and when reporting progress) to tell the user how many upstream commits remain between the current position and the end tag/HEAD. + +8. **Test-MergeConflictMarkers MCP Tool** - Leftover conflict-marker guard + - **MCP Tool Name**: `mcp_openssh-server_Test_MergeConflictMarkers` + - **Parameters**: `IncludeAll` (switch) to also scan `.github/instructions|agents|prompts|skills` (excluded by default because those docs contain illustrative markers); `FailOnDivider` (switch) to also flag bare `=======`. + - **When to use**: after resolving each batch's conflicts and **before** committing/continuing the merge — verifies no `<<<<<<<`/`=======`/`>>>>>>>` markers or unmerged paths remain. Run again on the real branch after copying files from scratch. + +9. **Sync-VersionResource MCP Tool** - version.rc ↔ version.h sync + - **MCP Tool Name**: `mcp_openssh-server_Sync_VersionResource` + - **Parameters**: `DryRun` (switch) to preview. + - **When to use**: whenever the merge changes `version.h` (nearly every merge). After resolving `version.h`, run this to rewrite `contrib/win32/openssh/version.rc` numbers to match. See [Pattern 7 in merge-details](../instructions/merge/merge-details.instructions.md). + +### Conflict-resolution subagent and skills + +- **conflict-review agent** ([conflict-review.agent.md](./conflict-review.agent.md)) — after resolving a batch's conflicts (and running `Test-MergeConflictMarkers`), **delegate the resolved diff to this review-only subagent** for a second pass before continuing the merge. It audits for leftover markers, prefer-upstream bias, balanced Windows guards, silently auto-merged changes needing Windows follow-up, regress-test adaptation, and version sync, then returns APPROVE or CHANGES-REQUIRED. Address CHANGES-REQUIRED items before proceeding. +- **resolve-merge-conflict skill** ([resolve-merge-conflict/SKILL.md](../skills/resolve-merge-conflict/SKILL.md)) — read when resolving conflicts; encodes the prefer-upstream-and-adapt procedure, strategy preference order, silent auto-merge hunting, regress/version sync, and how to summarize resolutions for the PR. +- **merge-retrospective skill** ([merge-retrospective/SKILL.md](../skills/merge-retrospective/SKILL.md)) — run after the merge PR lands to feed new conflict-resolution patterns back into the instructions/skills/agents/tools. + +## Workflow Phases + +### Phase 0: Research and Planning +**Objective:** Understand the merge scope, requirements, and context + +**Steps:** +1. **Confirm user inputs** required for the workflow: + - **Start ref** (tag or commit) — REQUIRED. + - **End ref** (commit) — OPTIONAL (defaults to HEAD). + - **CI grouping mode** — REQUIRED. Ask the user to choose: + - `presence` (recommended): batches end at any commit with CI runs (passing or failing). Smaller batches, more frequent checkpoints. + - `success`: batches end only at commits with successful CI. Larger batches, fewer checkpoints. + - Record the choice; it will be passed as `GroupByCIPresence` to every `Get-CommitGroups` call in Phases 2 and 5. + - If any required input is missing, ask the user before proceeding. + +2. **Read all merge instructions** from `.github/instructions/merge/` folder: + - `merge-process-overview.instructions.md` - Primary merge workflow and process overview + - `research.instructions.md` - Research methodology and analysis requirements + - `merge-details.instructions.md` - Detailed conflict resolution strategies and patterns + +2. **Analyze upstream changes:** + - Review release notes for target version + - Identify breaking changes and new features + - Note security fixes and critical updates + - Assess Windows-specific impact + +3. **Review historical context:** + - Examine previous merge PRs for patterns + - Identify recurring conflict areas + - Note Windows-specific workarounds from past merges + - Document lessons learned from previous merges + +**Success Criteria:** +- All merge instructions read and understood +- Upstream changes analyzed and documented +- Ready to proceed with environment setup + +### Phase 1: Pre-Merge Setup +**Objective:** Verify environment and establish baseline + +**Steps:** +1. **Run prerequisite verification via MCP tool:** + - **MCP Tool Name**: `mcp_openssh-server_Test_MergePrerequisites` + - **Parameters**: + - `TargetVersion` (string, required): Upstream version/tag to start from (e.g., "V_10_0_P2") + - `EndCommit` (string, optional): Commit SHA to end at (default: HEAD - most recent upstream commit) + - `SkipBaselineBuild` (boolean, optional): Skip baseline build check (default: false) + + This single tool verifies: + - Git, PowerShell, Visual Studio are available + - Repository remotes are configured (origin, upstream, upstream-pwsh) + - Target version/tag exists in upstream + - Working directory is clean (no uncommitted changes) + - Baseline build passes from current branch + - First commit batch is identified + +2. **Proceed only if tool reports success:** + - Tool must return `Success: true` + - Tool must display "ALL PREREQUISITES MET" + - If tool fails, fix reported issues before continuing + +3. **Establish baseline warning count:** + - **MCP Tool Name**: `mcp_openssh-server_Test_OpenSSHBuild` + - **Parameters**: `Configuration="Release"` (Architecture defaults to the host; pass it explicitly only when it matches the host) + - Parse and document the current warning count and categories + - This baseline will be used to detect new warnings introduced during merge + - Store baseline for comparison after each build + +4. **Create the scratch branch only:** + ```pwsh + # Create the scratch branch — ALL work (merging, conflict resolution, + # build fixes, validation) happens here. The real merge branch will be + # created in Phase 6, after all batches are complete. + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="CreateBranch", Branch="scratch-merge-v-" + ``` + + **Important:** Record the exact starting commit (the tip of the branch you started from). Phase 6 needs it to create the real merge branch from the same point. + +**Success Criteria:** +- Prerequisite tool reports all checks passed +- Baseline warning count established and documented +- Scratch branch created from the chosen starting point +- Starting commit recorded for later use in Phase 6 +- Currently on the scratch branch +- Ready to begin Phase 2 (scratch-branch incremental merge) + +### Phase 2: Scratch Branch — Incremental Merge +**Objective:** Merge commits in batches on the scratch branch, resolving conflicts directly. All conflict resolutions, build fixes, and validation work live on the scratch branch — nothing is recorded for later replay. + +**Steps:** +1. **Get first commit batch** using Get-CommitGroups MCP tool: + - **MCP Tool Name**: `mcp_openssh-server_Get_CommitGroups` + - **Parameters** (set `GroupByCIPresence` from the user's Phase 0 CI grouping mode — `true` for `presence`, `false` for `success`): + - For first batch: `GitHubTag="V_10_0_P2"`, `EndCommit=""`, `FirstChunkOnly=true`, `GroupByCIPresence=` + - For subsequent batches: `StartCommit=""`, `EndCommit=""`, `FirstChunkOnly=true`, `GroupByCIPresence=` + - **Note**: If `EndCommit` is not specified, the tool will merge up to the most recent upstream commit (HEAD) + + **The tool returns structured data:** + ```json + { + "ChunkNumber": 1, + "StartCommit": "609fe2c", + "EndCommit": "6fb728d", + "StartCommitFull": "609fe2cae2459d721ac11d23cd27b8a94397ef3c", + "EndCommitFull": "6fb728df50c1afd338cb0223a84ce24579577eff", + "CommitCount": 12, + "StartMessage": "upstream: rework the text for -3 to make it clearer", + "EndMessage": "Run all tests on Cygwin again." + } + ``` + +2. **Display batch information** for verification. + +3. **Merge the batch endpoint:** + ```pwsh + # Merge all commits up to the batch endpoint + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Merge", CommitHash=$result.EndCommitFull + ``` + This brings in all commits from the previous merge point through `EndCommitFull` in a single merge. The `--no-ff` flag ensures a merge commit is always created. + +4. **If conflicts occur, resolve each one directly:** + - Read the [resolve-merge-conflict skill](../skills/resolve-merge-conflict/SKILL.md) and follow it. + - For each conflicted file reported in the merge result's `ConflictedFiles`: + a. Resolve the conflict in place following the **prefer-upstream-and-adapt** principle and Windows preservation patterns (see [merge-details.instructions.md](../instructions/merge/merge-details.instructions.md)). + b. Stage the resolved file: `Invoke-Git Operation="Add" Path=""` + - The resolved files on the scratch branch are the source of truth that will be copied to the real merge branch in Phase 6. No resolution log or rerere recording is needed. + +5. **Verify no conflict markers remain, then complete the merge:** + ```pwsh + # MCP Tool: mcp_openssh-server_Test_MergeConflictMarkers + # (must report no markers and no unmerged paths before continuing) + + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="MergeContinue" + ``` + +6. **Hunt for silently auto-merged changes needing Windows work:** + Even when there were no conflicts, upstream changes can merge cleanly yet + require Windows follow-up (ssh-agent, `config.h.vs`, `.vcxproj`, new POSIX + calls). Diff the batch range (`NameOnly=true`) and check those areas — see + [Pattern 6 in merge-details](../instructions/merge/merge-details.instructions.md). + If `version.h` changed, run `mcp_openssh-server_Sync_VersionResource` to update + `version.rc`. + +7. **Delegate the resolved batch to the conflict-review subagent:** + Hand the batch's resolved diff to the [conflict-review agent](./conflict-review.agent.md) + for a review-only second pass. Address any CHANGES-REQUIRED items it returns + before proceeding to the build. + +**Conflict Resolution Patterns:** +- **Prefer upstream:** Take the upstream change and adapt for Windows; do not keep old fork behavior just to minimize diff. +- **Windows-specific code:** Preserve with `#ifdef WINDOWS` +- **Removed/Unix-only features:** Exclude with `#ifndef WINDOWS` (wrap, never delete upstream code) +- **Build system changes:** Update `.vcxproj` / `.sln` files (use `\r\n` line endings) +- **Configuration:** Add new defines to `contrib/win32/openssh/config.h.vs` + +### Phase 3: Build and Validation +**Objective:** Build successfully and validate if CI was successful + +**Build/validation gating rule:** Build and validation are only required for batches whose merged commit range touches at least one C source or header file (`*.c` or `*.h`, including under `contrib/win32/**`). For batches that only modify non-compiled files (e.g., `*.md`, `*.0`/`*.5` man pages, `regress/*.sh`, `.github/**`, `Makefile.in` text-only changes that do not affect VS projects), skip the build and validation steps and proceed directly to Phase 4 (Summary and Approval), noting in the summary that build was skipped because no compiled sources changed. + +**Detecting code impact:** Before Step 1, list the files changed by the batch: +```pwsh +# MCP Tool: mcp_openssh-server_Invoke_Git +# Operation="Diff", Range="..", NameOnly=true +``` +If any returned path matches `*.c` or `*.h`, perform the build/validation steps below. Otherwise, record "no compiled sources changed" and skip to Phase 4. + +**Steps (when code impact detected):** +1. **Build the merged code:** + - **MCP Tool Name**: `mcp_openssh-server_Start_OpenSSHBuild` + - **Parameters**: `Configuration="Release"` (Architecture defaults to the host machine's architecture — do not hard-code `x64`) + +2. **If build fails, fix compilation errors:** + - Document all compilation errors from build output + - Fix source code issues (add Windows compatibility defines, update function signatures, add platform guards) + - Update Visual Studio project files (add/remove source files, create projects for new binaries) + - Rebuild until successful + - Commit build fixes with detailed description + +3. **Run the functionality smoke test (mandatory after every successful build):** + - **MCP Tool Name**: `mcp_openssh-server_Test_OpenSSHFunctionality` + - **Parameters**: (use defaults — Release, host architecture) + + This test installs service, creates test user, validates SSH connectivity. + If tests fail, fix issues and commit fixes. + **Do not proceed** to next batch until the smoke test passes. + +4. **Full CI suite is NOT run per-batch by default.** + Run `mcp_openssh-server_Invoke_OpenSSHTests` with `TestSuite="All"` ONLY when: + - The user explicitly requests it for a batch, OR + - Before transitioning to the real merge branch (Phase 6), OR + - Before creating the PR. + + When a full-suite run is requested and any sub-suite fails, re-run only the failing + suite (`TestSuite="Unit"`, `TestSuite="Bash"`, or `TestSuite="E2E"`). For a single + failing bash case, use `TestSuite="Bash"` with `BashTestFilePath=""`. + +**Common Build Fixes:** +- Missing source files in .vcxproj files +- Removed files still referenced in projects +- Missing function implementations (add to win32compat) + +**Success Criteria:** +- Clean build with no errors +- All expected binaries generated +- `Test-OpenSSHFunctionality` smoke test passes +- Full CI suite (if explicitly requested) passes + +### Phase 4: Summary and Approval +**Objective:** Summarize changes and get approval before proceeding + +**MANDATORY:** Before proceeding to the next commit batch, provide summary and wait for user approval. + +**Steps:** +1. **Generate batch summary:** + ```markdown + ## Batch Completion Summary + + **Batch:** [StartCommit]..[EndCommit] ( commits) + **End Commit CI Status:** + + ### Changes in this Batch: + - + - + - + + ### Conflicts Resolved: + - : + - : + + ### Build Status: + - Build: ✅ Success / ❌ Failed + - Build fixes applied: + + ### Validation Status: + - Smoke test (`Test-OpenSSHFunctionality`): ✅ Passed / ⏭️ Skipped (no build) / ❌ Failed + - Full CI suite: ⏭️ Not run (default) / ✅ Passed / ❌ Failed + - Test fixes applied: + + ### Next Steps: + - Next batch will start from commit: + - Estimated remaining batches: + + **Ready to proceed to next batch?** + ``` + +2. **Wait for user response:** + - User responds "yes" / "continue" / "proceed" → Continue to Phase 5 + - User responds "no" / "stop" / "wait" → Pause and await further instructions + - User provides feedback → Address concerns and re-summarize + +**Success Criteria:** +- Summary provided with all required information +- User approval received to proceed + +### Phase 5: Scratch Branch Iteration +**Objective:** Process remaining commit batches on the scratch branch until all upstream commits are merged. + +**Steps:** +1. **Return to Phase 2** with `-StartCommit` set to previous batch's end commit and `-EndCommit` set to target end commit +2. **Repeat Phases 2-4** for each batch: + - Get next batch with Get-CommitGroups (passing both StartCommit and EndCommit) + - Merge batch endpoint (`Invoke-Git Merge`) + - Resolve conflicts directly (no resolution log) + - Build (only if the batch touches `*.c` or `*.h` — see Phase 3 gating rule) + - Validate (only if build was performed and the batch ends with successful CI) + - Summarize and get approval +3. **Continue** until the target end commit is reached (or HEAD if no end commit was specified) +4. **Sync the scratch branch with its base branch (re-fetched):** + PRs may have merged into the base branch (e.g. `latestw_all`) since work + started. Bring the scratch branch up to date so the real branch (created from + the refreshed base in Phase 6) matches: + ```pwsh + # Re-fetch the base branch + # MCP Tool: mcp_openssh-server_Invoke_Git → Operation="Fetch", Remote="" + # Merge the refreshed base tip into the scratch branch and resolve any conflicts + # MCP Tool: mcp_openssh-server_Invoke_Git → Operation="Merge", CommitHash="/" + ``` + Re-run `Test-MergeConflictMarkers`, rebuild, and re-run the smoke test if this + sync touched compiled sources. Record the refreshed base tip for Phase 6. +5. **Final scratch-branch validation:** + - **MCP Tool Name**: `mcp_openssh-server_Test_OpenSSHFunctionality` + - **Parameters**: (use defaults — Release, host architecture) + +**Success Criteria:** +- All commit batches processed on scratch branch +- Build remains stable after each batch +- All successful CI checkpoints validated +- Scratch branch contains the fully merged, conflict-resolved, building, and tested state +- Ready to proceed to real-branch single merge + +### Phase 6: Real Branch — Single Merge with Copy-from-Scratch Resolution +**Objective:** Produce clean history on the real merge branch with a single merge commit preserving all upstream SHAs. Conflict resolutions are copied wholesale from the scratch branch — no rerere replay, no resolution log. + +**Steps:** +1. **Create the real merge branch** from the refreshed base tip (recorded in Phase 5's base-sync step), so the single merge below yields a tree matching the scratch branch: + ```pwsh + # Re-fetch the base branch if you have not just done so, then check out its tip + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Checkout", Target="/" # e.g. upstream-pwsh/latestw_all + + # Then create the real merge branch from there + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="CreateBranch", Branch="merge-v-" + # Example: Branch="merge-v10.0P2-20260109" + ``` + > If the base branch has NOT advanced since Phase 1, this is equivalent to the original starting commit. If it HAS advanced (PRs merged in the meantime), creating from the refreshed base tip is required — the scratch branch was synced to it in Phase 5, so both branches share the same base. + +2. **Perform a single merge** of the final upstream target: + ```pwsh + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Merge", CommitHash="" + ``` + This creates one merge commit covering all upstream commits in the range. + +3. **Resolve conflicts by copying from the scratch branch — and account for silently auto-merged files:** + + > ⚠️ **Do not copy only the conflicted files.** Git auto-merges files that had + > no textual conflict, but some of those were hand-edited on the scratch branch + > (build fixes, `config.h.vs`, `.vcxproj`, `win32compat`, `version.rc`, + > regress-test adaptations). Copying only `ConflictedFiles` silently drops those + > edits. Use the whole-tree copy below (recommended), or reconcile with a diff. + + **Recommended — whole-tree copy** (guarantees the real branch tree matches scratch): + ```pwsh + # After `git merge` reports conflicts (do NOT abort): + git checkout scratch-merge-v- -- . + # MCP Tool: mcp_openssh-server_Invoke_Git → Operation="Add", Path="." + ``` + + **Alternative — per-file copy + reconciling diff** (if you want a smaller, explicit change set): + ```pwsh + # Copy each conflicted file: + git checkout scratch-merge-v- -- + ``` + Then find files that differ between the real branch and scratch (i.e. auto-merged + files that were edited on scratch) and copy those too: + ```pwsh + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Diff", Range="scratch-merge-v-", NameOnly=true + ``` + Copy every path this reports, then stage. + +4. **Verify the tree matches scratch and no markers remain:** + ```pwsh + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Diff", Range="scratch-merge-v-", NameOnly=true + # (should be empty after the whole-tree copy) + + # MCP Tool: mcp_openssh-server_Test_MergeConflictMarkers + ``` + +5. **Complete the merge:** + ```pwsh + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="MergeContinue" + ``` + +6. **Apply build fixes** as separate commits after the merge commit (only if you used the per-file copy in step 3 and did not bring over the build-fix changes): + - Cherry-pick or re-apply the build-fix commits made on the scratch branch. + - **CRITICAL: Restore paths.targets before committing:** + ```pwsh + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Checkout", Target=".\contrib\win32\openssh\paths.targets" + ``` + +7. **Build and validate on the real branch:** + - Build: `mcp_openssh-server_Start_OpenSSHBuild` (Release, host architecture) + - Check warnings: `mcp_openssh-server_Test_OpenSSHBuild` + - Validate: `mcp_openssh-server_Test_OpenSSHFunctionality` + +8. **Clean up scratch branch:** + ```pwsh + # The scratch branch is no longer needed once the real branch is verified + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Checkout", Target="merge-v-" + # Then delete scratch: git branch -D scratch-merge-v- + ``` + +**Success Criteria:** +- Real branch has exactly one merge commit (plus any replayed build-fix commits) +- All upstream commits appear in the DAG with original SHAs +- `git log --first-parent` shows a clean merge history +- Real branch's tree matches the scratch branch's tip (modulo intentional differences) +- Build succeeds and functionality tests pass +- Scratch branch deleted + +### Phase 7: Documentation and PR +**Objective:** Document changes and submit for review + +**Steps:** +1. Review all merge commits for clarity +2. Document major conflict resolutions — use the PR-summary guidance in the [resolve-merge-conflict skill](../skills/resolve-merge-conflict/SKILL.md) to structure the description +3. Note any Windows-specific changes +4. Normalize merged upstream `.github/workflows/*.yml` triggers to dispatch-only for this fork (keep `workflow_dispatch`, disable `push`/`pull_request`/`schedule`) +5. Push branch: `git push origin merge-v-` +6. Create PR with comprehensive description +7. Add labels and request reviewers + +**PR Description Template:** +```markdown +## Merge OpenSSH + +This PR merges upstream OpenSSH commits from through . + +### Commit Groups +- Batch 1: to ( commits) +- Batch 2: to ( commits) +... + +### Major Changes +- [List significant upstream changes] + +### Windows-Specific Resolutions +- [List Windows compatibility fixes] +- [List build system updates] + +### Testing +- [x] Builds successfully (host architecture) +- [x] Service starts and runs +- [x] SSH connections work +- [x] Basic operations verified + +### Known Issues +- [List any known limitations or issues] +``` + +**Success Criteria:** +- PR created with complete description +- All CI checks passing +- Reviewers assigned + +### Phase 8: Post-Merge Retrospective (after the PR lands) +**Objective:** Capture new conflict-resolution patterns and improve the tooling. + +Once the merge PR is **merged**, run the [merge-retrospective skill](../skills/merge-retrospective/SKILL.md). +It reviews the conflicts and Windows follow-ups from this merge and feeds any new +or recurring patterns back into the merge instructions, skills, the conflict-review +agent's checklist, and the tools — so the next merge is smoother. This step is +run separately from the merge itself and can be triggered by the user after merge. + +## Decision Points + +### When to Use Commit Groups +- **High complexity merge:** >100 commits, significant changes +- **Medium complexity merge:** 50-100 commits, moderate changes +- **Low complexity merge:** <50 commits, minor changes → single merge OK + +### Conflict Resolution Strategy +**Always preserve:** +- Windows-specific functionality in `#ifdef WINDOWS` blocks +- Security fixes from upstream +- Build system integrity + +**Accept upstream for:** +- Removed deprecated features (e.g., DSA) +- Algorithm updates +- API modernization + +**Combine when:** +- Both sides add different functionality +- Windows needs additional compatibility code +- Upstream changes affect Windows-specific code + +## Key Files to Monitor + +### Frequently Modified +- `config.h` / `config.h.vs` - Configuration defines +- `*.vcxproj` - Visual Studio project files +- `contrib/win32/win32compat/*` - Windows compatibility layer + +### Conflict Hotspots +- Authentication code (`auth*.c`) +- Platform-specific code (`platform*.c`) + +## Recovery Procedures + +### Abort Merge +```bash +git merge --abort +git clean -fd +git reset --hard +``` + +### Abort Cherry-Pick (if used outside merge workflow) +```bash +git cherry-pick --abort +git clean -fd +git reset --hard +``` + +### Restart Scratch Branch +```bash +# Delete the scratch branch and recreate from the original starting commit +git branch -D scratch-merge-v- +git checkout +git checkout -b scratch-merge-v- +``` + +### Restart from Checkpoint +```bash +git checkout scratch-merge-v- +git log --oneline -5 # Verify last successful state +# Continue from there (or recreate scratch branch from the starting commit) +``` + +### Build Failure Recovery +1. Check build log: `contrib\win32\openssh\OpenSSHRelease.log` (e.g. `OpenSSHReleasearm64.log` on an ARM64 host) +2. Search for "error C" or "error LNK" +3. Fix errors in order (compilation before linking) +4. Commit fixes separately for clarity + +## Best Practices + +### Commit Organization +- One logical fix per commit +- Clear commit messages explaining Windows-specific changes +- Reference upstream commit SHAs when applicable + +### Testing Between Batches +- Build after each batch that touches `*.c` or `*.h` files (skip for documentation-only / regress-script-only batches) +- Quick smoke test (service start, simple connection) +- Full test only after all batches complete + +### Documentation +- Comment complex conflict resolutions in code +- Note Windows-specific workarounds +- Link to upstream issues/PRs when relevant + +## Success Metrics +- ✅ All commits from target range merged +- ✅ Clean build with no warnings +- ✅ All tests passing +- ✅ SSH service functional +- ✅ PR approved and merged +- ✅ No regressions reported in first 48 hours + +## Reference Links + +### Repository Links +- [Upstream OpenSSH](https://github.com/openssh/openssh-portable) +- [PowerShell Fork](https://github.com/PowerShell/openssh-portable) + +### Instruction Documents (Phase 0 Required Reading) +- [Merge Process Overview](../instructions/merge/merge-process-overview.instructions.md) +- [Research Instructions](../instructions/merge/research.instructions.md) +- [Merge Details Instructions](../instructions/merge/merge-details.instructions.md) + +### Additional Instructions +- [Build Instructions](../instructions/build.instructions.md) +- [Setup Instructions](../instructions/setup.instructions.md) +- [Testing Instructions](../instructions/testing.instructions.md) diff --git a/.github/ci-status.md b/.github/ci-status.md index 68275715dfb1..5b1f77f2369c 100644 --- a/.github/ci-status.md +++ b/.github/ci-status.md @@ -1,19 +1,17 @@ master : -[![C/C++ CI](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml?query=branch:master) +[![C/C++ CI](../../../actions/workflows/c-cpp.yml/badge.svg)](../../../actions/workflows/c-cpp.yml?query=branch:master) +[![VM CI](../../../actions/workflows/vm.yml/badge.svg)](../../../actions/workflows/vm.yml?query=branch:master) [![C/C++ CI self-hosted](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml/badge.svg)](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml?query=branch:master) [![Upstream self-hosted](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/upstream.yml/badge.svg)](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/upstream.yml?query=branch:master) -[![CIFuzz](https://github.com/openssh/openssh-portable/actions/workflows/cifuzz.yml/badge.svg)](https://github.com/openssh/openssh-portable/actions/workflows/cifuzz.yml) -[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/openssh.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:openssh) +[![CIFuzz](../../../actions/workflows/cifuzz.yml/badge.svg)](../../../actions/workflows/cifuzz.yml) +[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/openssh.svg)](https://issues.oss-fuzz.com/issues?q="Project:+openssh"+is:open) [![Coverity Status](https://scan.coverity.com/projects/21341/badge.svg)](https://scan.coverity.com/projects/openssh-portable) +
+ +10.0 : +[![C/C++ CI](../../../actions/workflows/c-cpp.yml/badge.svg?branch=V_10_0)](../../../actions/workflows/c-cpp.yml?query=branch:V_10_0) +[![C/C++ CI self-hosted](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml/badge.svg?branch=V_10_0)](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml?query=branch:V_10_0) 9.9 : -[![C/C++ CI](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml/badge.svg?branch=V_9_9)](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml?query=branch:V_9_9) +[![C/C++ CI](../../../actions/workflows/c-cpp.yml/badge.svg?branch=V_9_9)](../../../actions/workflows/c-cpp.yml?query=branch:V_9_9) [![C/C++ CI self-hosted](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml/badge.svg?branch=V_9_9)](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml?query=branch:V_9_9) - -9.8 : -[![C/C++ CI](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml/badge.svg?branch=V_9_8)](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml?query=branch:V_9_8) -[![C/C++ CI self-hosted](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml/badge.svg?branch=V_9_8)](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml?query=branch:V_9_8) - -9.7 : -[![C/C++ CI](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml/badge.svg?branch=V_9_7)](https://github.com/openssh/openssh-portable/actions/workflows/c-cpp.yml?query=branch:V_9_7) -[![C/C++ CI self-hosted](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml/badge.svg?branch=V_9_7)](https://github.com/openssh/openssh-portable-selfhosted/actions/workflows/selfhosted.yml?query=branch:V_9_7) diff --git a/.github/configs b/.github/configs index 2526e3ef4812..230258f93f24 100755 --- a/.github/configs +++ b/.github/configs @@ -13,6 +13,10 @@ if [ "$config" = "" ]; then config="default" fi +if [ ! -z "${LTESTS}" ]; then + OVERRIDE_LTESTS="${LTESTS}" +fi + unset CC CFLAGS CPPFLAGS LDFLAGS LTESTS SUDO TEST_TARGET="tests compat-tests" @@ -144,6 +148,8 @@ case "$config" in TCMALLOC_STACKTRACE_METHOD=generic_fp TEST_SSH_SSHD_ENV="TCMALLOC_STACKTRACE_METHOD=generic_fp" export TCMALLOC_STACKTRACE_METHOD TEST_SSH_SSHD_ENV + + SKIP_LTESTS="agent-restrict" ;; krb5|heimdal) CONFIGFLAGS="--with-kerberos5" @@ -277,7 +283,7 @@ case "${TARGET_HOST}" in # Native linker is not great with PIC so OpenSSL is built w/out. CONFIGFLAGS="${CONFIGFLAGS} --disable-security-key" ;; - fbsd14-ppc64) + fbsd14-ppc64|nbsd-arm64be) # Disable security key tests for bigendian interop test. CONFIGFLAGS="${CONFIGFLAGS} --disable-security-key" ;; @@ -392,5 +398,10 @@ if [ -x "$(which plink 2>/dev/null)" ]; then export REGRESS_INTEROP_PUTTY fi +if [ ! -z "${OVERRIDE_LTESTS}" ]; then + echo >&2 "Overriding LTESTS, was '${LTESTS}', now '${OVERRIDE_LTESTS}'" + LTESTS="${OVERRIDE_LTESTS}" +fi + export CC CFLAGS CPPFLAGS LDFLAGS LTESTS SUDO export TEST_TARGET TEST_SSH_UNSAFE_PERMISSIONS TEST_SSH_FAIL_FATAL diff --git a/.github/install_libcrypto.sh b/.github/install_libcrypto.sh new file mode 100755 index 000000000000..d1aa23450679 --- /dev/null +++ b/.github/install_libcrypto.sh @@ -0,0 +1,75 @@ +#!/bin/sh +# +# Install specified libcrypto. +# -a : install version for ABI compatibility test. +# -n : dry run, don't actually build and install. +# +# Usage: $0 [-a] [-n] openssl-$branch/tag destdir [config options] + +set -e + +bincompat_test="" +dryrun="" +while [ "$1" = "-a" ] || [ "$1" = "-n" ]; do + if [ "$1" = "-a" ]; then + abi_compat_test=y + elif [ "$1" = "-n" ]; then + dryrun="echo dryrun:" + fi + shift +done + +ver="$1" +destdir="$2" +opts="$3" + +if [ -z "${ver}" ] || [ -z "${destdir}" ]; then + echo tag/branch and destdir required + exit 1 +fi + +set -x + +if [ ! -d ${HOME}/openssl ]; then + cd ${HOME} + git clone https://github.com/openssl/openssl.git + cd ${HOME}/openssl + git fetch --all +fi +cd ${HOME}/openssl + +if [ "${abi_compat_test}" = "y" ]; then + echo selecting ABI test release/branch for ${ver} + case "${ver}" in + openssl-3.6) + ver=openssl-3.0.0 + echo "selecting older release ${ver}" + ;; + openssl-3.[012345]) + major=$(echo ${ver} | cut -f1 -d.) + minor=$(echo ${ver} | cut -f2 -d.) + ver="${major}.$((${minor} + 1))" + echo selecting next release branch ${ver} + ;; + openssl-3.*.*) + major=$(echo ${ver} | cut -f1 -d.) + minor=$(echo ${ver} | cut -f2 -d.) + patch=$(echo ${ver} | cut -f3 -d.) + ver="${major}.${minor}.$((${patch} + 1))" + echo checking for release tag ${ver} + if git tag | grep -q "^${ver}\$"; then + echo selected next patch release ${ver} + else + ver="${major}.${minor}" + echo not found, selecting release branch ${ver} + fi + ;; + esac +fi + +git checkout ${ver} +make clean >/dev/null 2>&1 || true +${dryrun} ./config no-threads shared ${opts} --prefix=${destdir} \ + -Wl,-rpath,${destdir}/lib64 +${dryrun} make -j4 +${dryrun} sudo make install_sw diff --git a/.github/install_putty.sh b/.github/install_putty.sh new file mode 100755 index 000000000000..6d6d0ad49f41 --- /dev/null +++ b/.github/install_putty.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +ver="$1" + +echo +echo -------------------------------------- +echo Installing PuTTY version ${ver} +echo -------------------------------------- + +cd /tmp + +case "${ver}" in +snapshot) + tarball=putty.tar.gz + url=https://tartarus.org/~simon/putty-snapshots/${tarball} + ;; +*) + tarball=putty-${ver}.tar.gz + url=https://the.earth.li/~sgtatham/putty/${ver}/${tarball} + ;; +esac + +if [ ! -f ${tarball} ]; then + wget -q ${url} +fi + +mkdir -p /tmp/puttybuild +cd /tmp/puttybuild + +tar xfz /tmp/${tarball} && cd putty-* +if [ -f CMakeLists.txt ]; then + cmake . && cmake --build . -j4 && sudo cmake --build . --target install +else + ./configure && make -j4 && sudo make install +fi +sudo rm -rf /tmp/puttybuild +/usr/local/bin/plink -V diff --git a/.github/instructions/agent-communication.instructions.md b/.github/instructions/agent-communication.instructions.md new file mode 100644 index 000000000000..eb5242163023 --- /dev/null +++ b/.github/instructions/agent-communication.instructions.md @@ -0,0 +1,139 @@ +--- +applyTo: "**/*" +--- + +# AI Agent Communication Guidelines + +## Overview +This document establishes how AI agents should communicate with users throughout their interactions. These guidelines apply to **all agent operations** in this workspace. For merge-specific communication templates, see [agent-communication-merge.instructions.md](./merge/agent-communication-merge.instructions.md). + +## Core Principle: Tool Output vs Agent Communication + +### Distinction + +**1. MCP Tool Execution (Write-Host is acceptable):** +- When MCP tools execute PowerShell scripts, those scripts may use `Write-Host` for output +- This is normal and expected behavior for the tool itself +- The agent receives this output and can parse it +- Example: `Test-OpenSSHFunctionality.ps1` uses `Write-Host` to display test progress + +**2. Agent-to-User Communication (Use chat messages ONLY):** +- AI agents **MUST** communicate with users through chat messages, not `Write-Host` +- **DO NOT** invoke `Write-Host` or other console output commands from the agent +- Instead, present information conversationally in your responses +- Parse tool output and summarize it in chat messages + +## Communication Standards + +### ❌ INCORRECT: Agent Using Write-Host +```pwsh +Write-Host "Starting merge process..." +Write-Host "Build succeeded!" -ForegroundColor Green +Write-Host "Found 3 conflicts in auth.c" +``` + +### ✅ CORRECT: Agent Using Chat Messages +``` +Starting the merge process. I'll cherry-pick the commits in this batch and then build. + +The build succeeded! All 14 executables were created successfully. + +Found 3 conflicts in auth.c. Analyzing the conflict types to determine the resolution strategy. +``` + +## Pseudocode Implementation Guidance + +When you see pseudocode functions in instruction files like: +- `update_progress()` +- `generate_test_report()` +- `log()` +- `append_to_progress_log()` + +These represent **conceptual operations**. Implement them by: +1. Generating the information/report internally +2. Communicating the results to the user via chat messages +3. **NOT** by executing `Write-Host` or similar PowerShell output commands + +### Example: Pseudocode to Implementation + +**Pseudocode:** +```pseudocode +FUNCTION update_progress(phase, status, details): + log(f"Phase {phase}: {status}") + IF status == "FAILURE": + generate_failure_report(details) +``` + +**Correct Agent Implementation:** +``` +[Agent analyzes the phase and status] +[Agent sends chat message]: "Phase 1: Conflict Resolution - Completed successfully. Resolved 5 conflicts across 3 files." +``` + +**Incorrect Agent Implementation:** +```pwsh +Write-Host "Phase 1: Conflict Resolution - Completed successfully" +``` + +## Best Practices + +### 1. Be Conversational +- Write naturally, as if speaking to a colleague +- Avoid overly formal or robotic language +- Use active voice + +### 2. Provide Context +- Explain what you're doing and why +- Help users understand the current state +- Highlight important information + +### 3. Use Structured Formatting When Helpful +- Use markdown formatting for clarity +- Use bullet points for lists +- Use code blocks for commands or file paths +- Use file links when referencing specific files + +### 4. Progressive Disclosure +- Start with high-level summaries +- Provide details when relevant +- Don't overwhelm with unnecessary information + +### 5. Clear Status Indicators +Use clear language for status: +- ✅ "succeeded", "completed successfully", "passed" +- ❌ "failed", "encountered errors", "did not pass" +- ⚠️ "warning", "requires attention", "partial success" + +## Examples + +### Good: Progress Update +``` +Analyzing the upstream changes between the last merge commit and V_10_0_P2. Found 127 commits with 8 security fixes and 3 build system changes that will require Visual Studio project updates. +``` + +### Good: Error Report +``` +The build failed with 4 compilation errors: +- auth.c: Missing include for Windows compatibility header +- sshd.c: Undefined reference to fork() - needs Windows equivalent +- config.h.vs: Missing preprocessor definition for HAVE_SETRESUID + +I'll add the Windows compatibility fixes now. +``` + +### Good: Success Report +``` +Testing completed successfully! The SSH service installed, started, and accepted connections. The test command executed correctly with expected output. +``` + +## Merge-Specific Guidelines + +For detailed merge workflow communication templates, including exact formats for tool output summaries and commit batch summaries, see: +- [Merge-Specific Agent Communication Guidelines](./merge/agent-communication-merge.instructions.md) + +## Summary + +- **Tools can use Write-Host** - MCP tools and PowerShell scripts may output to console +- **Agents use chat only** - All agent communication must be via chat messages +- **Parse, don't echo** - Parse tool output and present summaries conversationally +- **Be clear and helpful** - Provide context, use formatting, and communicate status clearly diff --git a/.github/instructions/build.instructions.md b/.github/instructions/build.instructions.md new file mode 100644 index 000000000000..0019676af3b0 --- /dev/null +++ b/.github/instructions/build.instructions.md @@ -0,0 +1,378 @@ +--- +applyTo: "**/*" +--- + +# Build Instructions for AI Agents + +## Overview +This document provides comprehensive build instructions for OpenSSH-Portable on Windows, specifically tailored for AI agents performing upstream merges. + +## Prerequisites Verification + +### Check Required Tools +```pwsh +# Verify PowerShell version +$PSVersionTable.PSVersion + +# Verify Visual Studio installation +Get-ChildItem "C:\Program Files*\Microsoft Visual Studio\*\*\MSBuild\Current\Bin\msbuild.exe" + +# Verify Windows SDK +Get-ChildItem "C:\Program Files*\Windows Kits\10\bin" -Directory + +# Verify Git +git --version +``` + +### vcpkg Dependencies +The build links against vendored libraries (`libressl`, `libfido2`, `libcbor`, +`zlib`) installed via vcpkg. The build will **fail** if +`contrib/win32/openssh/vcpkg_installed/-custom/` is missing. + +To install (or refresh) dependencies: +```pwsh +.\.github\tools\Install-VcpkgDependencies.ps1 -Bootstrap +``` + +See [setup.instructions.md](./setup.instructions.md) Step 6 for first-time +setup and [vcpkg.instructions.md](./vcpkg.instructions.md) for the full +reference (overlay ports, custom triplets, version-bump workflow). + +## Build Process + +### Using MCP Build Tools (Recommended) + +The repository includes MCP tools that automate the build and error analysis process. + +#### Build +Use the Start-OpenSSHBuild MCP tool: +- **MCP Tool Name**: `mcp_openssh-server_Start_OpenSSHBuild` +- **Parameters**: + - `Configuration` (optional): "Debug" or "Release" (default: "Release") + - `Architecture` (optional): "x64", "x86", "ARM", "ARM64" (default: "x64") + - `Clean` (optional): Perform clean build (default: false) + +**Examples:** +- Incremental build: `Configuration="Release"`, `Architecture="x64"` +- Clean build: `Configuration="Release"`, `Architecture="x64"`, `Clean=true` + +#### Test Existing Build (on failure only) +Use the Test-OpenSSHBuild MCP tool when a build fails: +- **MCP Tool Name**: `mcp_openssh-server_Test_OpenSSHBuild` +- **Parameters**: `Configuration="Release"`, `Architecture="x64"` + +## Compiler Warning Policy + +### Overview +All new compiler warnings introduced during the merge process must be reported to users and require approval before proceeding. This ensures code quality is maintained and potential issues are not overlooked. + +### Baseline Establishment +1. **Before starting the merge**, establish a baseline warning count: + - Run Test-OpenSSHBuild on the current branch (before any merge commits) + - Document the total warning count and warning categories + - Store this as the baseline for comparison + +2. **After each build during merge**, compare warnings against baseline: + - Run Test-OpenSSHBuild after every successful build (not just failures) + - Compare current warning count to baseline + - Identify any new warnings introduced + +### Warning Categorization +Attempt to categorize warnings to help users make informed decisions: + +**Common Warning Categories:** +- **Deprecated APIs**: Use of functions/APIs marked as deprecated +- **Type Conversions**: Implicit type conversions that may lose data +- **Unused Variables/Functions**: Declared but unused code elements +- **Potential Bugs**: Logic issues that may cause runtime problems +- **Security-Related**: Potential security vulnerabilities (buffer overruns, etc.) +- **Platform-Specific**: Windows-specific compatibility warnings + +**Note:** Categorization helps users make decisions, but **all new warnings require user approval regardless of predicted severity**. + +### User Approval Requirement +**Critical Rule**: No threshold - every new warning requires user input. + +1. **When new warnings are detected:** + - Report warning count delta (baseline vs current) + - List each new warning with: + - File and line number + - Warning code and message + - Attempted category classification + - Request user decision: fix warnings or proceed as-is + +2. **User must explicitly approve:** + - Fixing warnings before continuing + - Proceeding with warnings (acknowledging they will remain) + - Do NOT automatically proceed if new warnings appear + +3. **Update baseline if user approves proceeding:** + - If user approves proceeding with new warnings, update baseline + - This prevents re-reporting the same warnings in subsequent batches + +## Compilation Error Resolution + +### Common Error Categories + +#### 1. Missing Preprocessor Definitions +**Symptoms:** +``` +error C2065: 'SOME_DEFINE': undeclared identifier +``` + +**Resolution:** +```pwsh +# Edit config.h.vs file +notepad .\contrib\win32\openssh\config.h.vs + +# Add missing definitions (example) +#define SOME_DEFINE 1 +``` + +#### 2. Missing Windows Equivalents +**Symptoms:** +``` +error C3861: 'fork': identifier not found +error C3861: 'signal': identifier not found +``` + +**Resolution Pattern:** +```c +// In source file, add Windows compatibility +#ifdef WINDOWS + // Use Windows equivalent or win32compat function + HANDLE process = CreateProcess(...); +#else + // Original Unix code + pid_t pid = fork(); +#endif +``` + +#### 3. Build System Inconsistencies +**Symptoms:** +``` +error MSB3073: The command exited with code 1 +fatal error C1083: Cannot open source file: 'newfile.c' +``` + +**AI Agent Resolution Process:** +1. **Check Makefile changes:** + ```pwsh + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Diff", Range="upstream-pwsh/latestw_all..upstream/", Path="Makefile.in" + ``` + +2. **Identify new/removed source files:** + ```bash + # Look for patterns like: + # ssh_SOURCES = ssh.c readconf.c clientloop.c sshtty.c \ + # sshconnect.c sshconnect2.c mux.c newfile.c + ``` + +3. **Update Visual Studio projects:** + ```xml + + + ``` + + **Important:** Visual Studio project files (`.vcxproj`) use Windows-style line endings (`\r\n`). When programmatically adding lines to these files, ensure you use `\r\n` instead of just `\n` to maintain consistency with the existing file format. This prevents Git from showing the entire file as changed. + +4. **Update solution if new binaries added:** + ``` + # Check for new programs in Makefile: + # bin_PROGRAMS = ssh sshd ssh-add ssh-keygen ssh-keyscan ssh-copy-id scp sftp sftp-server ssh-pkcs11-helper ssh-sk-helper ssh-agent new-binary + ``` + +### Step-by-Step Error Resolution + +#### AI Agent Workflow: +1. **Run the build** + - Use: **Start-OpenSSHBuild** — `mcp_openssh-server_Start_OpenSSHBuild` with `Configuration` and `Architecture`. +2. **If build succeeded**, skip log parsing and proceed. +3. **If build failed**, **parse errors** using **Test-OpenSSHBuild** — `mcp_openssh-server_Test_OpenSSHBuild`. +4. **Categorize error types** (preprocessor, Windows compatibility, build system). +5. **Apply appropriate resolution strategy** (see error categories above) and **rebuild** with Start-OpenSSHBuild. +6. **CRITICAL: Before committing, restore paths.targets**: + ```pwsh + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Checkout", Target=".\contrib\win32\openssh\paths.targets" + ``` +7. **Commit fixes with detailed message** (only actual code changes, not paths.targets). + +#### Reading Build Logs and Errors (on failure only) +Use the **Test-OpenSSHBuild** MCP tool to read build logs and parse errors **only when the build fails**: +- **MCP Tool Name**: `mcp_openssh-server_Test_OpenSSHBuild` +- **Parameters**: `Configuration="Release"`, `Architecture="x64"` + +**Why use this tool:** +- Automatically locates and parses the build log file +- Provides structured error output with file paths, codes, and messages +- Groups errors and warnings for easier analysis +- Works reliably in MCP context where direct file reading may not be available + +**DO NOT** attempt to read log files directly with `Get-Content` or similar commands. +**DO NOT** try to locate log files manually. + +### Build Tools Invocation Policy + +- Use `Start-OpenSSHBuild.ps1` to run the build for each chunk/batch. +- **ALWAYS invoke `Test-OpenSSHBuild.ps1` after every build** (success or failure): + - On build failure: Parse errors and warnings to fix issues + - On build success: Parse warnings to compare against baseline +- Compare warning count against established baseline +- If new warnings detected, report to user and request approval before proceeding +- Do NOT skip `Test-OpenSSHBuild.ps1` even when build succeeds - warning checks are mandatory. + +#### Alternative: Direct MSBuild (Terminal Only) +Only use this when running directly in a terminal (not via MCP): +```pwsh +& "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MSBuild.exe" .\contrib\win32\openssh\Win32-OpenSSH.sln /p:Configuration=Release /p:Platform=x64 /v:detailed +``` + +### Important Note: paths.targets File Modification + +**The build process automatically modifies `.\contrib\win32\openssh\paths.targets`** to update SDK version paths based on the currently installed Windows SDK. This is normal and expected behavior. + +**Before committing any changes:** +```pwsh +# Check if paths.targets was modified by the build: +# MCP Tool: mcp_openssh-server_Invoke_Git +# Operation="Status" +# Check if paths.targets appears in result.ModifiedFiles + +# If it shows as modified, restore it to a clean state: +# MCP Tool: mcp_openssh-server_Invoke_Git +# Operation="Checkout", Target=".\contrib\win32\openssh\paths.targets" +``` + +**Why this happens:** +- MSBuild automatically updates SDK paths to match your local environment +- These changes are environment-specific and should not be committed +- The file will be modified on every build + +**AI Agent Workflow (CRITICAL):** +1. **ALWAYS restore paths.targets before committing**: + ```pwsh + # This MUST be done before every commit + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Checkout", Target=".\contrib\win32\openssh\paths.targets" + ``` +2. Only commit actual code changes, not build-generated path updates +3. Verify with Invoke-Git `Operation="Status"` that paths.targets is not in `ModifiedFiles` before committing + +## Project File Management + +### Understanding the Project Structure +``` +contrib\win32\openssh\ +├── Win32-OpenSSH.sln # Main solution file +├── libssh.vcxproj # Core SSH library +├── ssh.vcxproj # SSH client +├── sshd.vcxproj # SSH server listener handling +├── sshd-auth.vcxproj # SSH server authentication handling +├── sshd-session.vcxproj # SSH server session handling +├── ssh-add.vcxproj # Key agent utility +├── ssh-agent.vcxproj # Authentication agent +├── ssh-keygen.vcxproj # Key generation utility +├── ssh-keyscan.vcxproj # Key scanning utility +└── ssh-pkcs11-helper.vcxproj # SSH PKCS11 helper +└── ssh-shell-host.vcxproj # SSH shell host +└── ssh-sk-helper.vcxproj # SSH SK helper +├── scp.vcxproj # Secure copy +├── sftp.vcxproj # Secure file transfer client +└── sftp-server.vcxproj # Secure file transfer server +``` + +### Adding New Projects (AI Agent Process) +1. **Identify new binary in Makefile:** + ```bash + grep "bin_PROGRAMS\|sbin_PROGRAMS" Makefile.in + ``` + +2. **Check Windows applicability:** + ```bash + # Skip Unix-only binaries like ssh-keysign + # Include utilities that work on Windows + ``` + +3. **Create new project file:** + ```pwsh + # Copy existing similar project + Copy-Item ssh.vcxproj ssh-newutil.vcxproj + ``` + +4. **Update project references:** + ```xml + + + ssh-newutil + ssh-newutil + + ``` + +5. **Add to solution:** + ``` + # Edit Win32-OpenSSH.sln to include new project + ``` + +**Important Note on Line Endings:** +Both `.vcxproj` and `.sln` files use Windows-style line endings (`\r\n`). When programmatically modifying these files: +- Use `\r\n` instead of `\n` when inserting new lines +- Maintain consistent line endings to avoid Git showing spurious changes +- Example in PowerShell: `$newLine = "`r`n"` +- Example in Python: `new_line = "\r\n"` + +## Validation and Testing + +### Build Verification Using MCP Tools +```pwsh +Use the Start-OpenSSHBuild MCP tool (recommended): +- **MCP Tool Name**: `mcp_openssh-server_Start_OpenSSHBuild` +- **Parameters**: `Configuration="Release"`, `Architecture="x64"` + +If the build fails, parse errors with: +- **MCP Tool Name**: `mcp_openssh-server_Test_OpenSSHBuild` +- **Parameters**: `Configuration="Release"`, `Architecture="x64"` +**Expected Output (on failure):** +- Build failure status +- Parsed errors and warnings +- Build log location +``` +**Expected Artifacts (14 executables):** +- ssh.exe, sshd.exe, sshd-auth.exe, sshd-session.exe +- ssh-agent.exe, ssh-add.exe, ssh-keygen.exe, ssh-keyscan.exe +- scp.exe, sftp.exe, sftp-server.exe +- ssh-pkcs11-helper.exe, ssh-shellhost.exe, ssh-sk-helper.exe + +### Quick Functionality Test +```pwsh +# Verify version reporting +& ".\contrib\win32\openssh\x64\Release\ssh.exe" -V +``` + +## Troubleshooting Guide + +### Build Helper Module Issues +```pwsh +# Force reload module +Remove-Module OpenSSHBuildHelper -Force -ErrorAction SilentlyContinue +Import-Module .\contrib\win32\openssh\OpenSSHBuildHelper.psm1 -Force +``` + +### Path and Environment Issues +```pwsh +# Verify Visual Studio environment +& "${env:ProgramFiles}\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" + +# Check MSBuild path +where.exe msbuild +``` + +### Permission Issues +```pwsh +# Ensure running as Administrator if needed +if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) +{ + Write-Warning "Build may require Administrator privileges" +} +``` diff --git a/.github/instructions/getting-started.instructions.md b/.github/instructions/getting-started.instructions.md new file mode 100644 index 000000000000..d4f064517e42 --- /dev/null +++ b/.github/instructions/getting-started.instructions.md @@ -0,0 +1,28 @@ +### 🔧 General Repository Instructions +These instructions apply to any task involving the OpenSSH-Portable repository: + +- **[repository-overview.instructions.md](./repository-overview.instructions.md)** - Repository structure and Windows compatibility layer overview +- **[setup.instructions.md](./setup.instructions.md)** - Repository setup and environment configuration +- **[build.instructions.md](./build.instructions.md)** - Compilation procedures and error resolution +- **[testing.instructions.md](./testing.instructions.md)** - Validation and testing procedures + +### 🔀 Upstream Merge Task Instructions +These instructions are specific to performing upstream merges from openssh/openssh-portable: + +- **[merge/merge-process-overview.instructions.md](./merge/merge-process-overview.instructions.md)** - Primary merge workflow and process overview +- **[merge/merge-details.instructions.md](./merge/merge-details.instructions.md)** - Detailed conflict resolution strategies and patterns +- **[merge/research.instructions.md](./merge/research.instructions.md)** - Intelligence gathering and analysis procedures + +## Quick Start Guide + +### For Human Developers +1. Read [merge/merge-process-overview.instructions.md](./merge/merge-process-overview.instructions.md) for complete merge workflow overview +2. Follow phase-by-phase process +3. Reference general repository instructions ([setup](./setup.instructions.md), [build](./build.instructions.md), [testing](./testing.instructions.md)) as needed + +### For AI Agents +1. **Start here:** [merge/merge-process-overview.instructions.md](./merge/merge-process-overview.instructions.md) +2. **Understand the repository:** Review general instructions for setup, build, and testing procedures +3. **Follow systematic approach:** Check off each merge item before proceeding +4. **Use automation:** Leverage provided scripts in `tools/` directory +5. **Escalate if needed:** Document blockers and seek human guidance when complexity exceeds capabilities diff --git a/.github/instructions/merge/agent-communication-merge.instructions.md b/.github/instructions/merge/agent-communication-merge.instructions.md new file mode 100644 index 000000000000..73d16da7213e --- /dev/null +++ b/.github/instructions/merge/agent-communication-merge.instructions.md @@ -0,0 +1,421 @@ +--- +applyTo: ".github/instructions/merge/**" +--- + +# Merge-Specific Agent Communication Guidelines + +## Overview +This document provides specific communication templates and guidelines for AI agents performing upstream merge operations. These guidelines **supplement** the high-level agent communication principles defined in [agent-communication.instructions.md](../agent-communication.instructions.md). + +**Key Points:** +- The high-level communication guidelines apply to ALL merge interactions +- This document adds merge-specific templates and formats +- Tool output templates are **MUST use** (exact format required) +- Batch summary templates are **SHOULD include** (flexible adaptation allowed) + +## MCP Tool Output Templates + +These templates define the **exact format** agents MUST use when communicating tool results to users. + +### 1. Start-OpenSSHBuild Tool Output + +**MUST use this format when reporting build results.** + +#### Success Scenario: +``` +Build completed successfully. All 14 executables were created: +- ssh.exe, sshd.exe, sshd-auth.exe, sshd-session.exe +- ssh-agent.exe, ssh-add.exe, ssh-keygen.exe, ssh-keyscan.exe +- scp.exe, sftp.exe, sftp-server.exe +- ssh-pkcs11-helper.exe, ssh-shellhost.exe, ssh-sk-helper.exe + +Configuration: Release | Architecture: x64 +``` + +#### Failure Scenario: +``` +Build failed with compilation errors. Analyzing the build log to identify issues. + +[After running Test-OpenSSHBuild] +Found X compilation errors: +- [file.c]: [brief error description] +- [file.c]: [brief error description] + +I'll resolve these errors now. +``` + +#### Success with New Warnings Scenario: +**MUST use this format when build succeeds but new warnings are detected.** + +``` +Build completed successfully. All 14 executables were created. + +However, new compiler warnings have been introduced: + +Baseline: X warnings → Current: Y warnings (ΔZ new warnings) + +New Warnings Detected: + +**Deprecated APIs (2):** +- [auth.c] (Line 145): C4996 - 'strcpy': This function may be unsafe. Consider using strcpy_s instead. +- [sshd.c] (Line 302): C4996 - 'GetVersion': was declared deprecated + +**Type Conversions (1):** +- [channels.c] (Line 89): C4244 - Conversion from 'size_t' to 'int', possible loss of data + +**Analysis:** +These warnings appear to be introduced by upstream changes. The deprecated API warnings may require Windows-specific alternatives, and the type conversion should be reviewed for potential data loss. + +How would you like to proceed? +1. Fix these warnings before continuing +2. Proceed with warnings (will update baseline) + +Please advise. +``` + +### 2. Test-OpenSSHBuild Tool Output + +**MUST use this format when reporting build error analysis.** + +#### When Build Failed: +``` +Build error analysis complete: + +Compilation Errors (X): +- [filename.c] (Line Y): [Error code] - [Brief description] +- [filename.c] (Line Y): [Error code] - [Brief description] + +Warnings (X): +- [filename.c] (Line Y): [Warning description] + +Error Categories: +- Missing preprocessor definitions: X +- Windows compatibility issues: X +- Build system inconsistencies: X +``` + +#### When Build Succeeded with No New Warnings: +``` +Build analysis complete: + +Compilation Errors: 0 +Warnings: X (no change from baseline) + +No new warnings introduced. Build is clean. +``` + +#### When Build Succeeded with New Warnings: +``` +Build analysis complete: + +Compilation Errors: 0 + +Warnings Comparison: +- Baseline: X warnings +- Current: Y warnings +- New warnings: Z + +New Warnings by Category: + +**Deprecated APIs (2):** +- [auth.c] (Line 145): C4996 - 'strcpy': This function may be unsafe +- [sshd.c] (Line 302): C4996 - 'GetVersion': was declared deprecated + +**Type Conversions (1):** +- [channels.c] (Line 89): C4244 - Conversion from 'size_t' to 'int' + +**Potential Bugs (0)** +**Security-Related (0)** +**Platform-Specific (0)** + +These new warnings require user approval before proceeding. +``` + +**Note:** ALWAYS invoke Test-OpenSSHBuild after every build to check for warnings, not just on failure. + +### 3. Test-OpenSSHFunctionality Tool Output + +**MUST use this format when reporting functionality test results.** + +#### Success Scenario: +``` +Functionality testing completed successfully! + +Test Results: +✅ Administrator privileges verified +✅ Test user created: [username] +✅ SSH service installed successfully +✅ SSH service started successfully +✅ Firewall rule configured +✅ SSH connection test passed +✅ Command execution verified: "echo hello world" returned expected output + +All test resources cleaned up. +``` + +#### Failure Scenario: +``` +Functionality testing failed. + +Test Progress: +✅ Administrator privileges verified +✅ Test user created: [username] +❌ SSH service installation failed + +Error: [Error message from tool] + +The test environment has been cleaned up. I'll investigate the service installation issue. +``` + +#### Partial Success Scenario: +``` +Functionality testing completed with warnings. + +Test Results: +✅ Administrator privileges verified +✅ Test user created: [username] +✅ SSH service installed successfully +✅ SSH service started successfully +⚠️ Firewall rule configuration skipped (SkipFirewall=true) +✅ SSH connection test passed +✅ Command execution verified + +Note: Firewall was not configured as requested. Ensure firewall rules exist if testing remote connections. +``` + +## Commit Batch Summary Template + +**SHOULD include these elements** when summarizing a commit batch. Adapt the format and detail level based on context. + +### Template Structure: + +``` +Processing batch [N] ([X] commits from [start_hash] to [end_hash]) + +Key Changes: +- [Category 1]: [Brief description] +- [Category 2]: [Brief description] +- [Category 3]: [Brief description] + +Files Modified: [X] files +Conflicts: [X] conflicts ([resolved/pending]) + +[Additional context if needed] +``` + +### Example - Simple Batch: +``` +Processing batch 1 (8 commits from a1b2c3d to e4f5a6b) + +Key Changes: +- Security fixes: Updated bounds checking in buffer handling +- Bug fixes: Corrected memory leak in session cleanup +- Documentation: Updated protocol specification comments + +Files Modified: 12 files +Conflicts: 2 conflicts (resolved) +``` + +### Example - Complex Batch: +``` +Processing batch 3 (15 commits from 7h8i9j0 to k1l2m3n) + +Key Changes: +- Build system: Added new source files for MLKEM support +- Authentication: Enhanced certificate validation logic +- Process management: Modified daemon initialization (requires Windows adaptation) +- Configuration: Added 3 new preprocessor definitions + +Files Modified: 28 files +Conflicts: 7 conflicts (5 resolved, 2 require manual review) + +Note: The daemon initialization changes use fork() which needs Windows CreateProcess() equivalent. +``` + +### Example - Minimal Batch: +``` +Processing batch 5 (3 commits from x7y8z9 to a0b1c2) + +Key Changes: +- Minor documentation updates +- Code formatting corrections + +Files Modified: 4 files +Conflicts: None +``` + +## Progress Update Templates + +**SHOULD include these elements** when communicating progress at different workflow phases. Adapt wording to context. + +### Pre-Merge Analysis Phase: +``` +Analyzing upstream changes from [last_merge_tag] to [target_version]... + +Found [X] commits to merge: +- [X] security fixes (HIGH PRIORITY) +- [X] bug fixes +- [X] feature additions +- [X] build system changes + +Grouping commits into batches for incremental merging. +``` + +### Conflict Resolution Phase: +``` +Resolving [X] conflicts in [filename]: + +- Conflict 1: [Brief description] → [Resolution strategy] +- Conflict 2: [Brief description] → [Resolution strategy] + +[X] conflicts resolved, [Y] remaining. +``` + +### Build Fixes Phase: +``` +Applying build fixes for iteration [N]: + +- Added Windows compatibility header to [file.c] +- Updated config.h.vs with [X] new definitions +- Added [source_file.c] to [project.vcxproj] + +Rebuilding... +``` + +### Testing Phase: +``` +Running functionality tests to validate the merge... + +[Use Test-OpenSSHFunctionality template from above] +``` + +### Cleanup Phase: +``` +Finalizing the merge: + +✅ Restored paths.targets to clean state +✅ Verified [X] commits applied successfully +✅ All builds passing +✅ Functionality tests passing + +Ready to commit and push. +``` + +### Scratch-to-Real Branch Transition: +``` +Scratch branch phase complete! + +Summary: +- Processed [N] batches on scratch branch +- Resolved [X] total conflicts across [Y] files +- All [N] batches built successfully + +Switching to the real merge branch for the single final merge. +Conflicts on the real branch will be resolved by copying the already-resolved +files from the scratch branch (`git checkout scratch-branch -- `). +``` + +### Real Branch Resolution Report: +``` +Single merge completed on real branch. Conflict resolution results: + +- Files copied from scratch branch: [X] +- Files needing additional review: [Y] + - [file1]: [brief reason] + +[If all resolved]: All conflicts resolved by copy-from-scratch. Applying build fixes as separate commits. +``` + +## Special Scenarios + +### When Seeking User Approval: +``` +Batch [N] is ready for review: + +Summary: +- [X] commits merged successfully +- Build: ✅ Passed +- Tests: ✅ Passed +- Conflicts: [X] resolved + +Changes include: [brief list] + +May I proceed with the next batch? +``` + +### When Requesting Manual Intervention: +``` +I've encountered a complex conflict that requires manual review: + +File: [filename] +Issue: [Description of the conflict complexity] +Context: [Why automated resolution isn't appropriate] + +Recommendation: [Suggested approach] + +Please advise on how to proceed. +``` + +### When Reporting Critical Issues: +``` +⚠️ CRITICAL: [Issue type detected] + +Details: +- [Specific problem] +- [Impact assessment] +- [Affected components] + +This requires immediate attention before proceeding with the merge. +``` + +## Integration with Pseudocode + +When implementing pseudocode patterns from merge-details.instructions.md, use these communication approaches: + +### update_progress() → Chat Message +```pseudocode +# Pseudocode: +update_progress("Build Fixes", "IN_PROGRESS", "Applied 3 fixes") + +# Agent Implementation (via chat): +"Applying build fixes (iteration 2): Added 3 Windows compatibility changes. Rebuilding now..." +``` + +### generate_test_report() → Structured Chat Message +```pseudocode +# Pseudocode: +report = generate_test_report(test_results) + +# Agent Implementation (via chat): +[Use Test-OpenSSHFunctionality template from above] +``` + +### log() → Contextual Chat Message +```pseudocode +# Pseudocode: +log(f"Skipping {binary} - Unix only") + +# Agent Implementation (via chat): +"Skipping ssh-keysign.exe - Unix-only binary not applicable to Windows build." +``` + +## Best Practices for Merge Communication + +1. **Always include commit hashes** when referencing specific commits (first 7 characters) +2. **Use file links** when referencing specific files: [filename](path/to/filename) +3. **Categorize changes** by type (security, bug fix, feature, build system, etc.) +4. **Highlight Windows-specific considerations** that required special handling +5. **Provide commit counts** to show progress and scope +6. **Be specific about conflict types** and resolution strategies used +7. **Report before and after** major operations (build, test, etc.) +8. **Update after each batch** to maintain transparency +9. **Use consistent terminology** aligned with the instruction files +10. **Mark critical items** with appropriate indicators (⚠️, ✅, ❌) + +## Summary + +- **Tool templates are REQUIRED** - Use exact formats for MCP tool output summaries +- **Batch templates are RECOMMENDED** - Include suggested elements but adapt to context +- **Supplement high-level guidelines** - All general communication principles still apply +- **Maintain transparency** - Keep users informed throughout the merge process +- **Be consistent** - Use standard terminology and formatting patterns diff --git a/.github/instructions/merge/merge-details.instructions.md b/.github/instructions/merge/merge-details.instructions.md new file mode 100644 index 000000000000..22835106ed2e --- /dev/null +++ b/.github/instructions/merge/merge-details.instructions.md @@ -0,0 +1,818 @@ +--- +applyTo: "**/*" +--- + +# Merge Instructions for AI Agents + +## Overview +This AI-specific documentation provides comprehensive instructions and algorithmic frameworks that AI agents can use to systematically approach the OpenSSH merge process with minimal human intervention while maintaining high quality and consistency. It combines conflict resolution strategies with automated decision-making processes. + +**Key Approach: Two-Phase Merge with Scratch Branch** +Instead of cherry-picking commits (which rewrites history), this framework implements a two-phase approach: + +1. **Scratch branch** — All work happens here: incremental `git merge` at batch boundaries (grouped by CI presence or success), conflict resolution, build fixes, and a `Test-OpenSSHFunctionality` smoke test after each built batch. The full CI suite (`Invoke-OpenSSHTests`) is only run when the user explicitly requests it. +2. **Real merge branch** — Created from the same starting commit as the scratch branch, after all scratch-branch work is complete. A single `git merge` of the final upstream target is performed; any conflicts are resolved by copying the already-resolved files from the scratch branch (`git checkout scratch-branch -- `). This produces one merge commit with all upstream SHAs intact and a tree matching the validated scratch-branch state. + +No `git rerere`, no resolution log, and no Save/Replay tooling is needed. + +Benefits: +- Preserves upstream commit history exactly (original SHAs, authors, timestamps) +- Conflicts on the real branch are resolved in seconds via file copy from the validated scratch branch +- Builds after each batch on scratch branch (mandatory when the batch touches `*.c` or `*.h` files) for early error detection +- Runs the `Test-OpenSSHFunctionality` smoke test after each built batch (mandatory when build ran), independent of upstream CI status. The full CI suite is only run when the user explicitly requests it. +- Requires user approval before proceeding to next batch +- Allows for incremental progress and easier rollback +- Reduces complexity of conflict resolution + +## Decision Framework for AI Agents + +### Pre-Merge Analysis Algorithm +```pseudocode +FUNCTION analyze_upstream_changes(target_version): + // Step 1: Find last merged commit and determine range + last_upstream_commit = find_last_upstream_commit_in_fork() + commit_range = get_commit_range(last_upstream_commit, target_version) + + // Step 2: Fetch and analyze release notes + release_notes = fetch_release_notes(target_version) + risk_factors = [] + + FOR EACH change IN release_notes: + IF change.contains(["signal", "fork", "pipe", "process", "daemon", "service"]): + risk_factors.append({type: "PROCESS_MANAGEMENT", change: change}) + IF change.contains(["auth", "pam", "kerberos", "gssapi"]): + risk_factors.append({type: "AUTHENTICATION", change: change}) + IF change.contains(["build", "makefile", "configure", "autotools"]): + risk_factors.append({type: "BUILD_SYSTEM", change: change}) + IF change.contains(["security", "cve", "vulnerability"]): + risk_factors.append({type: "SECURITY", change: change, priority: "HIGH"}) +``` + +### Conflict Resolution Decision Tree +```pseudocode +FUNCTION resolve_conflict(file_path, conflict_content): + conflict_type = analyze_conflict_type(conflict_content) + + SWITCH conflict_type: + CASE "SECURITY_FIX": + // Always accept upstream security fixes + RETURN accept_upstream(conflict_content) + + CASE "BUILD_SYSTEM_CHANGE": + // Need to update Visual Studio projects + upstream_changes = extract_upstream_changes(conflict_content) + RETURN combine_with_windows_build_system(upstream_changes) + + CASE "PROCESS_MANAGEMENT": + // Unix fork/exec vs Windows CreateProcess + IF contains_fork_or_exec(conflict_content): + RETURN wrap_with_platform_ifdef(conflict_content) + ELSE: + RETURN analyze_compatibility(conflict_content) + + CASE "AUTHENTICATION": + // PAM/Kerberos vs Windows auth + RETURN preserve_windows_auth_with_upstream_features(conflict_content) + + CASE "CONFIGURATION": + // config.h vs config.h.vs changes + new_defines = extract_new_defines(conflict_content) + RETURN update_config_h_vs(new_defines) + + DEFAULT: + // Use historical pattern matching + similar_resolutions = find_similar_conflicts(file_path, conflict_content) + RETURN apply_similar_resolution_pattern(similar_resolutions[0]) +``` + +## Information Sources and Analysis + +### Primary References +- [Upstream release notes](https://www.openssh.com/releasenotes.html) - Pay special attention when merging new versions +- [Previous merge PRs](./research.instructions.md) - Review conflict resolution patterns +- Commit history and messages - Use Invoke-Git `Operation="Log"`, `Range="..upstream/"` to understand changes +- Local repository file comparison - Use 3-way diff tools + +### Analysis Commands +```pwsh +# View commit details for understanding changes: +# MCP Tool: mcp_openssh-server_Invoke_Git +# Operation="Show", CommitHash="" + +# Compare files between branches: +# MCP Tool: mcp_openssh-server_Invoke_Git +# Operation="Diff", Range="HEAD..upstream/", Path="" +``` + +## Conflict Resolution Strategies + +### Guiding Principle: Prefer Upstream, Adapt for Windows + +Before choosing a strategy below, apply this bias: **take the upstream change and +add Windows adjustments around it — do not keep the fork's old behavior just +because it was there.** Upstream owns the protocol/logic direction; the fork's +job is to make that direction work on Windows (preferably via the `win32compat` +layer, and via `#ifdef WINDOWS` only where unavoidable). + +The common mistake is **dragging upstream's relocated logic back to where the +fork used to have it** to minimize diff. Do not do this. Follow upstream's new +structure and add the Windows handling in the new location. + +> **Real example (OpenSSH 10.3 split-sshd):** upstream moved pre-auth / KEX and +> banner-exchange work between `sshd-session` and `sshd-auth`. The correct +> resolution follows upstream and performs the Windows-specific handling in +> `sshd-auth` where upstream placed it — **not** forcing that work to remain in +> `sshd-session` for Windows. Keeping it in the old location to reduce change +> caused state/message-ordering bugs (banner/KEX/post-auth failures). See +> [Pattern 4](#pattern-4-openssh-103-split-sshd-state-ordering-windows). + +Only deviate from "prefer upstream" when the upstream code genuinely does not +apply to Windows (then use `#ifndef WINDOWS`, wrapping — never deleting). + +### 1. Taking Upstream Changes +**When to use:** Security fixes, bug fixes, feature improvements that don't conflict with Windows functionality. + +```c +// Example: Accept upstream security patch +<<<<<<< HEAD +// Windows-specific code +======= +// New upstream security fix +>>>>>>> upstream/V_X_Y_PZ +``` +**Resolution:** Take the upstream change completely. + +### 2. Combining Changes with Preprocessor Directives +**When to use:** Upstream changes that conflict with Windows-specific functionality but both are needed. + +```c +// Example: Combining platform-specific implementations +#ifdef WINDOWS + // Windows-specific implementation + return windows_specific_function(); +#else + // Upstream Unix implementation + return unix_specific_function(); +#endif /* WINDOWS */ +``` + +### 3. Excluding Changes with #ifndef WINDOWS +**When to use:** Upstream changes are not applicable to Windows or would break Windows functionality. + +```c +// Example: Excluding Unix-only functionality +#ifndef WINDOWS + // Unix-only code that doesn't apply to Windows + setup_unix_specific_feature(); +#endif /* !WINDOWS */ +``` + +## Automated Conflict Resolution Patterns + +### Pattern 1: Platform-Specific Code Wrapping +```c +// Input conflict: +<<<<<<< HEAD +void windows_specific_function() { + // Windows implementation +} +======= +void unix_specific_function() { + // New upstream Unix implementation +} +>>>>>>> upstream/version + +// AI Resolution: +#ifdef WINDOWS +void windows_specific_function() { + // Windows implementation +} +#else +void unix_specific_function() { + // New upstream Unix implementation +} +#endif /* WINDOWS */ +``` + +### Pattern 2: Configuration File Updates +```pseudocode +FUNCTION update_config_h_vs(upstream_config_changes): + config_vs_path = "./contrib/win32/openssh/config.h.vs" + current_config = read_file(config_vs_path) + + FOR EACH define IN upstream_config_changes: + IF define.is_windows_compatible(): + IF define NOT IN current_config: + add_define_to_config_vs(define, determine_windows_value(define)) + ELSE: + // Add comment explaining why it's not included + add_comment_to_config_vs(f"// {define.name} - Unix only, not applicable to Windows") + + write_file(config_vs_path, current_config) +``` + +### Pattern 3: Build System Synchronization +```pseudocode +FUNCTION sync_build_system(): + makefile_changes = get_makefile_changes() + + FOR EACH binary IN makefile_changes.new_binaries: + IF binary.is_windows_applicable(): + create_visual_studio_project(binary) + add_to_solution_file(binary) + ELSE: + log(f"Skipping {binary} - Unix only") + + FOR EACH binary IN makefile_changes.removed_binaries: + remove_visual_studio_project(binary) + remove_from_solution_file(binary) + + FOR EACH source_file IN makefile_changes.new_source_files: + target_project = determine_target_project(source_file) + add_source_to_project(target_project, source_file) + +// CRITICAL: When modifying .vcxproj or .sln files programmatically, +// ALWAYS use Windows line endings (\r\n) instead of Unix (\n). +// This prevents Git from showing the entire file as modified. +FUNCTION add_source_to_project(project_file, source_file): + // Example: Use \r\n for line endings + new_line = f" \r\n" + insert_into_project_file(project_file, new_line) +``` + +### Pattern 4: OpenSSH 10.3 Split-sshd State Ordering (Windows) + +When upstream changes split pre-auth work between `sshd-session` and `sshd-auth`, preserve the state/message ordering exactly. + +- `sshd-session` (listener/monitor side) should not perform banner exchange that upstream moved to `sshd-auth`. +- For Windows `FORK_NOT_SUPPORTED` post-auth child (`sshd-session -z`), monitor message order matters: + - Receive identification-exchange state first. + - Then receive authenticated user context. + +If this ordering is wrong, common symptoms are: +- pre-auth failures such as banner parsing or signature mismatches +- post-auth `Invalid user` with empty username +- monitor keystate errors like `incomplete message` + +### Pattern 5: Upstream Changes to Regress Tests With Existing Windows Adaptations + +Many bash regression tests under `regress/*.sh` have already been adapted for +Windows in this fork using `if [ "$os" == "windows" ]; then ... else ... fi` +blocks. The most common adaptation wraps `diff` so it tolerates the CRLF line +endings that Windows binaries (e.g. `sshd -T`) emit: + +```sh +if [ "$os" == "windows" ]; then + # Ignore the CR (carriage return) during diff + diff --strip-trailing-cr $OBJ/expected $OBJ/actual || fail "..." +else + diff $OBJ/expected $OBJ/actual || fail "..." +fi +``` + +**The risk:** When upstream adds a *new* test case (or modifies an existing +one) inside a file that already contains these Windows blocks, the new code is +merged verbatim from upstream and arrives with a plain `diff` (or other +Unix-only assumption). Git does not flag a conflict because the surrounding +Windows blocks are untouched, so the regression only surfaces later as a +Windows-specific test failure (the plain `diff` reports trailing-`\r` +mismatches). + +**Required check during merge:** For every `regress/*.sh` file touched by an +upstream batch, determine whether the file *already* contains +`if [ "$os" == "windows" ]` blocks. If it does, inspect each upstream addition +or modification in that file and apply the same Windows adaptation to the new +code: + +```pseudocode +FUNCTION check_regress_test_windows_adaptations(changed_files): + FOR EACH file IN changed_files WHERE file MATCHES "regress/*.sh": + IF file CONTAINS 'if [ "$os" == "windows" ]': + // File is already Windows-aware + FOR EACH upstream_added_or_modified_block IN file: + IF block USES diff AND NOT wrapped_in_windows_conditional(block): + wrap_with_windows_conditional(block) // use diff --strip-trailing-cr + IF block USES other Unix-only assumption (paths, perms, signals): + apply_matching_windows_adaptation(block) +``` + +Real example: the OpenSSH 10.3 merge brought in a new "MaxStartups idempotence" +case in `regress/cfgparse.sh`. The surrounding `listenaddress` tests already had +`diff --strip-trailing-cr` Windows blocks, but the new case used a plain `diff` +and failed on Windows until it was wrapped in the same conditional. + +**When a bash regression test fails, check whether it is a *newly added* upstream +test first.** A failure in a test that upstream added or substantially changed in +this merge is a strong signal that the test needs Windows adaptation before it is +expected to pass — not that the merge broke existing behavior. Triage: + +```pseudocode +FUNCTION triage_failing_bash_test(test_file, batch_range): + // Was this test (or the failing case) introduced/changed by the upstream batch? + added_or_changed = git_diff(batch_range, test_file).touches_failing_case() + IF added_or_changed: + // Likely needs Windows adaptation, not a real regression. + // Apply Pattern 5 adaptations: diff --strip-trailing-cr, path/perm/signal fixes, + // or skip the case on Windows if the feature is Unix-only. + adapt_for_windows(test_file) + ELSE: + // Pre-existing test now failing => investigate as a genuine regression from the merge. + investigate_regression(test_file) +``` + +Run a single failing bash test in isolation with +`mcp_openssh-server_Invoke_OpenSSHTests` (`TestSuite="Bash"`, +`BashTestFilePath=""`) while iterating on the adaptation. + +### Pattern 6: Upstream Changes That Merge Cleanly but Need Windows Follow-up + +Git only flags **textual** conflicts. Many upstream changes merge cleanly yet +still require Windows work that git cannot know about. These are the most +dangerous because nothing stops the merge — the gap surfaces later as a build +break or runtime bug. **After every batch, diff the range and actively hunt for +these**, even when there were zero conflicts: + +```pwsh +# MCP Tool: mcp_openssh-server_Invoke_Git +# Operation="Diff", Range="..", NameOnly=true +``` + +Classes to check: + +- **ssh-agent:** the Windows ssh-agent is a **separate implementation** under + `contrib/win32/win32compat/ssh-agent/`. Upstream changes to `ssh-agent.c` or + the agent protocol merge into the upstream file but are **not** reflected in + the Windows agent. Port relevant logic by hand, or record an explicit TODO for + Windows-team review. (See [repository-overview.instructions.md](../repository-overview.instructions.md).) +- **config.h.vs:** new feature `#define`s that autoconf would set in `config.h` + must be added to `contrib/win32/openssh/config.h.vs` for Windows to get them. +- **Build system:** new source files added to `Makefile.in` must be added to the + correct `.vcxproj` (and the solution) using `\r\n` line endings; removed files + must be dropped. +- **New POSIX usage:** newly introduced `fork`/`exec`/`signal`/`pipe`/socket + options need a `w32_*` equivalent in `win32compat` or a guard. + +The `conflict-review` agent's checklist covers this class explicitly — delegate a +batch to it for a second pass if unsure. + +### Pattern 7: version.h Resolution and version.rc Sync (Windows) + +`version.h` conflicts most upstream merges because upstream bumps the OpenBSD +version tag and `SSH_PORTABLE`. Resolution rule: + +- **Keep** the Windows-only fields the fork owns: `SSH_WINDOWS_VERSION` + (`OpenSSH_for_Windows_.`) and `SSH_WINDOWS_BANNER`. +- **Take upstream** for the OpenBSD `$OpenBSD$` version comment and the value of + `SSH_PORTABLE` (`"pN"`), then update `SSH_WINDOWS_VERSION`'s `.` + to match the new upstream release. + +Then sync the Windows resource file so built binaries report the right version: + +```pwsh +# MCP Tool: mcp_openssh-server_Sync_VersionResource +# (add -DryRun to preview) +``` + +The tool reads `version.h` and rewrites `contrib/win32/openssh/version.rc`: +`FILEVERSION`/`PRODUCTVERSION` become `,,0,0` and the +`FileVersion` string `..0.0`; the patch (`pN`) is reflected in the +`ProductVersion` **text** only (`OpenSSH_.pN for Windows`); the +descriptive text (`OpenSSH for Windows`) is preserved. The numeric third field +stays `0` by fork convention. + +## Common Conflict Patterns + +### File System Operations +- **Fork/exec calls** → Use Windows process creation APIs +- **Signal handling** → Use Windows event mechanisms +- **File permissions** → Adapt to Windows ACL model + +### Privsep and Monitor State Transitions (Windows) +- For split `sshd-session` / `sshd-auth` flows, keep sender/receiver message ordering identical across monitor channels. +- Do not add ad-hoc state shuttling unless both sender and receiver are updated in lockstep. +- When debugging, verify the first protocol failure point (banner exchange vs KEX vs post-auth keystate) before changing multiple stages at once. + +### Build System Changes +- **Makefile additions** → Update Visual Studio project files (use `\r\n` line endings) +- **New dependencies** → Check Windows compatibility +- **Compiler flags** → Translate to MSVC equivalents +- **Project file edits** → Maintain Windows line endings (`\r\n`) to avoid Git diffs + +### Configuration Changes +- **New config options** → Add to `./contrib/win32/openssh/config.h.vs` +- **Feature detection** → Verify Windows support +- **Default values** → Adjust for Windows environment + +### Regress Test Changes (`regress/*.sh`) +- **File already has `if [ "$os" == "windows" ]` blocks** → Check every upstream + addition/modification in that file and apply the same Windows adaptation + (e.g. `diff --strip-trailing-cr`). Git will not flag a conflict because the + existing Windows blocks are untouched. See [Pattern 5](#pattern-5-upstream-changes-to-regress-tests-with-existing-windows-adaptations). +- **New `diff` comparisons** → Wrap with `diff --strip-trailing-cr` on Windows + to tolerate CRLF output from Windows binaries. +- **A bash test fails after the merge** → First check whether it is a *newly + added* or newly changed upstream test in this batch. If so, it likely needs + Windows adaptation (Pattern 5) before it is expected to pass — treat it as an + adaptation task, not a regression. Only if the failing test pre-existed the + merge should you investigate it as a genuine regression. + +### Silent (Clean-Merged) Changes Needing Windows Work +- After every batch, `Diff` the range (`NameOnly=true`) even when there were no + conflicts, and check ssh-agent (`win32compat/ssh-agent/`), `config.h.vs`, + `.vcxproj`/solution, and new POSIX calls. See + [Pattern 6](#pattern-6-upstream-changes-that-merge-cleanly-but-need-windows-follow-up). + +### version.h / version.rc +- Keep Windows fields in `version.h`; take upstream's portable version; then run + `mcp_openssh-server_Sync_VersionResource`. See + [Pattern 7](#pattern-7-versionh-resolution-and-versionrc-sync-windows). + +## Resolution Workflow + +### For Each Conflict: +1. **Analyze the change** + ```pwsh + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Show", CommitHash="upstream/", Path="" + ``` + +2. **Check previous resolutions** + - Search previous merge PRs for similar conflicts + - Look for patterns in Windows-specific handling + +3. **Choose resolution strategy** + - Upstream change: Complete replacement + - Combined: Add preprocessor directives + - Excluded: Use `#ifndef WINDOWS` + +4. **Test the resolution** + - Ensure code compiles + - Verify simple ssh connection to local host works + - Check that upstream functionality is preserved where applicable + +5. **Document the decision** + - Add comments explaining the Windows-specific handling + - Note in commit message why this approach was chosen + +## Build Validation Automation + +### Iterative Build and Fix Process +```pseudocode +FUNCTION automated_build_fix(): + MAX_ITERATIONS = 10 + iteration = 0 + + WHILE iteration < MAX_ITERATIONS: + // Always start with Start-OpenSSHBuild.ps1 + build_result = start_openssh_build(Configuration="Release", Architecture="x64") + + // ALWAYS invoke Test-OpenSSHBuild.ps1 to check warnings (success or failure) + test_result = test_openssh_build(Configuration="Release", Architecture="x64", LogFile=build_result.log) + + IF build_result.success: + // Check for new warnings against baseline + new_warnings = compare_warnings_to_baseline(test_result.warnings, baseline_warnings) + IF new_warnings.count > 0: + categorized_warnings = categorize_warnings(new_warnings) + request_user_approval(categorized_warnings) + // Wait for user decision: fix warnings or proceed + RETURN SUCCESS + + // Build failed - parse errors + errors = test_result.errors + fixes_applied = [] + + FOR EACH error IN errors: + fix = determine_fix_strategy(error) + IF fix: + apply_fix(fix) + fixes_applied.append(fix) + + IF fixes_applied.empty(): + RETURN MANUAL_INTERVENTION_REQUIRED + + commit_build_fixes(fixes_applied, f"Build fixes iteration {iteration + 1}") + iteration += 1 + + RETURN MAX_ITERATIONS_EXCEEDED + +FUNCTION determine_fix_strategy(error): + SWITCH error.type: + CASE "MISSING_INCLUDE": + RETURN add_windows_include(error.missing_header) + CASE "UNDEFINED_FUNCTION": + RETURN add_windows_equivalent(error.function_name) + CASE "MISSING_DEFINE": + RETURN add_to_config_h_vs(error.define_name) + CASE "MISSING_SOURCE_FILE": + RETURN add_source_to_project(error.file_name) + DEFAULT: + RETURN null +``` + +### Build Tools Invocation Policy + +- Use `Start-OpenSSHBuild.ps1` to run the build for each chunk/batch. +- **ALWAYS invoke `Test-OpenSSHBuild.ps1` after every build** (success or failure): + - On build failure: Parse errors and warnings to fix issues + - On build success: Parse warnings to compare against baseline +- Compare warning count against established baseline +- If new warnings detected, report to user with categorization and request approval before proceeding +- Do NOT skip `Test-OpenSSHBuild.ps1` even when build succeeds - warning checks are mandatory. +- On the scratch branch, commit build fixes after each batch merge commit. +- On the real branch, apply the same build fixes as separate commits after the single merge commit. + +### Batch Test Invocation Policy (Scratch Branch) + +- After each batch merge is completed and builds cleanly, run the functionality smoke test: + - **MCP Tool Name**: `mcp_openssh-server_Test_OpenSSHFunctionality` + - **Parameters**: `Configuration="Release"`, `Architecture="x64"` +- This is mandatory for every batch **that was built** (i.e., the batch touched `*.c` or `*.h` files), regardless of whether the upstream endpoint commit had successful CI. +- For batches that only modify documentation, regress scripts, or other non-compiled files, skip both build and smoke-test invocation. +- **Full CI suite (`Invoke-OpenSSHTests` with `TestSuite="All"`) is NOT run per-batch by default.** Only invoke it when the user explicitly requests it for a batch, before transitioning to the real merge branch, or before opening the PR. +- If the smoke test fails, fix and re-run before proceeding to the next batch. +- When a full-suite run is requested and any sub-suite fails, re-run only the failing suite while fixing (`TestSuite="Unit"`, `TestSuite="Bash"`, `TestSuite="E2E"`). For bash triage, run a single failing test with `BashTestFilePath`. + +## Testing Automation Framework + +### Automated Test Execution +```pseudocode +FUNCTION execute_test_suite(): + test_results = {} + + // Phase 1: Build verification + test_results["build"] = verify_build_artifacts() + IF NOT test_results["build"].success: + RETURN test_results + + // Phase 2: Service setup + test_results["service_setup"] = setup_ssh_service() + IF NOT test_results["service_setup"].success: + RETURN test_results + + // Phase 3: Basic connectivity + test_results["connectivity"] = test_basic_ssh_connection() + + // Cleanup + cleanup_test_environment() + + RETURN test_results + +FUNCTION generate_test_report(test_results): + report = "# Automated Test Results\n\n" + + FOR EACH category, result IN test_results: + status = result.success ? "✅ PASS" : "❌ FAIL" + report += f"## {category}: {status}\n" + + IF NOT result.success: + report += f"Error: {result.error}\n" + report += f"Suggested Fix: {result.suggested_fix}\n" + + RETURN report +``` + +## Error Recovery Strategies + +### Automatic Rollback Points +```pseudocode +FUNCTION create_checkpoint(phase_name): + current_commit = get_current_commit_hash() + checkpoints[phase_name] = current_commit + tag_commit(f"checkpoint-{phase_name}", current_commit) + +FUNCTION rollback_to_checkpoint(phase_name): + IF phase_name IN checkpoints: + reset_to_commit(checkpoints[phase_name]) + RETURN SUCCESS + ELSE: + RETURN CHECKPOINT_NOT_FOUND + +// Usage in main workflow +create_checkpoint("pre-merge") +execute_merge() + +IF merge_conflicts_too_complex(): + rollback_to_checkpoint("pre-merge") + request_manual_intervention() +``` + +### Conflict Complexity Assessment +```pseudocode +FUNCTION assess_conflict_complexity(conflicts): + complexity_score = 0 + + FOR EACH conflict IN conflicts: + // File-based scoring + IF conflict.file.ends_with(".c", ".h"): + complexity_score += 2 + IF conflict.file.contains("auth", "pam", "kerberos"): + complexity_score += 5 + IF conflict.file == "config.h": + complexity_score += 3 + + // Content-based scoring + lines_in_conflict = conflict.content.split('\n').length + complexity_score += lines_in_conflict * 0.1 + + // Pattern-based scoring + IF conflict.content.contains("fork", "exec", "signal"): + complexity_score += 10 + IF conflict.content.contains("WIN32", "WINDOWS", "#ifdef"): + complexity_score -= 2 // Already has platform guards + + IF complexity_score > 50: + RETURN "HIGH_COMPLEXITY" + ELIF complexity_score > 20: + RETURN "MEDIUM_COMPLEXITY" + ELSE: + RETURN "LOW_COMPLEXITY" +``` + +### Using Get-ConflictContext for High-Complexity Conflicts + +When `assess_conflict_complexity()` returns `HIGH_COMPLEXITY`, invoke the `Get-ConflictContext` MCP tool **before** attempting to edit the file. It provides three-way context anchored to the actual changed regions, accounting for the fact that our fork's line numbers differ from upstream. + +```pseudocode +FUNCTION resolve_conflict(file_path, conflict_content, merge_batch_commit): + complexity = assess_conflict_complexity([{file: file_path, content: conflict_content}]) + + IF complexity == "HIGH_COMPLEXITY": + // Fetch three-way context before editing + // MCP Tool: mcp_openssh-server_Get_ConflictContext + // FilePath=file_path, CommitHash=merge_batch_commit + // + // If the default MaxTotalLines=150 is insufficient (e.g., many hunks or + // a large function), re-invoke with a higher value such as MaxTotalLines=300. + context = get_conflict_context(file_path, merge_batch_commit) + + FOR EACH hunk IN context.Hunks: + // Use all three excerpts to understand: + // hunk.UpstreamBefore — what the upstream code looked like before the commit + // hunk.UpstreamAfter — what the upstream commit changed it to + // hunk.OurFork — what our fork has in the corresponding region + // (Note field explains how the region was located) + determine_resolution_strategy(hunk) + + // Check Message for budget warnings and increase MaxTotalLines if needed + IF context.Message contains "minimum floor": + re_invoke_with_larger_budget(file_path, merge_batch_commit) + + resolved = apply_resolution_strategy(file_path, conflict_content) + + // The resolved file on the scratch branch is the source of truth. + // It will be copied directly to the real merge branch in the Real Branch Phase + // via `git checkout scratch-branch -- `. No resolution log is recorded. + + RETURN resolved +``` + +**Key behaviours of the tool:** +- **Binary files**: Returns `IsBinary=true` and no excerpts — resolve manually. +- **Unavailable versions**: A version returns `Lines=null` with a `Note` explaining why (e.g. file newly added by this commit). +- **Fork region location**: Uses sliding-window content matching against the diff's unchanged context lines. Falls back to the function name from the `@@` hunk header if the anchor score is too low. The `Note` field on each `OurFork` excerpt describes which strategy was used. +- **Budget warning**: If `MaxTotalLines` is too small to give each hunk 10 lines per version, a warning appears in `Message` — increase `MaxTotalLines` and re-invoke. + +## Anti-Patterns to Avoid + +### ❌ Don't Remove Upstream Code +```c +// WRONG: This will cause future merge conflicts +// Completely removing upstream additions +``` + +### ❌ Don't Modify Upstream Logic Without Guards +```c +// WRONG: Modifying upstream code without preprocessor protection +upstream_function_with_windows_modifications(); +``` + +### ✅ Do Use Preprocessor Guards +```c +// CORRECT: Preserve upstream code with conditional compilation +#ifdef WINDOWS + windows_alternative(); +#else + upstream_function(); +#endif +``` + +## Progress Tracking and Reporting + +### Automated Progress Updates +```pseudocode +FUNCTION update_progress(phase, status, details): + progress_entry = { + timestamp: current_timestamp(), + phase: phase, + status: status, // SUCCESS, FAILURE, IN_PROGRESS + details: details, + commit_hash: get_current_commit_hash() + } + + append_to_progress_log(progress_entry) + + IF status == "FAILURE": + generate_failure_report(phase, details) + suggest_recovery_actions(phase, details) + +FUNCTION generate_merge_summary(): + summary = { + total_conflicts: count_resolved_conflicts(), + build_iterations: count_build_fix_iterations(), + test_results: get_final_test_results(), + time_elapsed: calculate_total_time(), + commits_created: count_commits_since_start(), + complexity_rating: assess_overall_complexity() + } + + RETURN format_summary_report(summary) +``` + +## Integration with Development Workflow + +### Pull Request Preparation +```pseudocode +FUNCTION prepare_pull_request(): + // Generate comprehensive commit history + commit_history = get_commits_since_branch_creation() + + // Create PR description + pr_description = f""" +# Merge OpenSSH {target_version} to Windows Fork + +## Summary +{generate_merge_summary()} + +## Conflict Resolutions +{generate_conflict_resolution_summary()} + +## Testing Results +{generate_test_report(final_test_results)} + +## Files Modified +{list_modified_files()} + +## Breaking Changes +{identify_breaking_changes()} +""" + + RETURN { + title: f"Merge upstream OpenSSH {target_version}", + description: pr_description, + labels: ["upstream-merge", determine_complexity_label()], + assignees: get_default_reviewers() + } + +FUNCTION normalize_fork_workflow_triggers(): + workflow_files = list_files(".github/workflows/*.yml") + + FOR EACH wf IN workflow_files: + // Policy for PowerShell Windows fork: dispatch-only upstream workflows + ensure_trigger_enabled(wf, "workflow_dispatch") + disable_trigger(wf, "push") + disable_trigger(wf, "pull_request") + disable_trigger(wf, "schedule") + + RETURN "workflow triggers normalized for fork policy" +``` + +### Workflow Trigger Policy (Windows Fork) +- Upstream workflow files merged into this fork should default to manual invocation only. +- Keep `workflow_dispatch` active. +- Disable automatic triggers (`push`, `pull_request`, `schedule`) unless the Windows fork explicitly depends on them. +- During final merge review, verify `.github/workflows/*.yml` trigger blocks are policy-compliant. + +## Commit Message Template + +Desired commit object (header, blank line, body): +``` +Resolve merge conflicts for + +Major conflict resolutions: +- : Combined upstream with Windows using #ifdef +- : Excluded upstream with #ifndef WINDOWS due to +- : Accepted upstream completely + +Reasoning: +``` + +Invoke via terminal — the MCPServerPS wrapper around `Invoke-Git` mangles embedded newlines in `Message`, so use repeated `-m` flags (git inserts the blank-line separators between them automatically): +```pwsh +git commit -m "Resolve merge conflicts for " ` + -m "Major conflict resolutions:`n- : Combined upstream with Windows using #ifdef`n- : Excluded upstream with #ifndef WINDOWS due to `n- : Accepted upstream completely" ` + -m "Reasoning: " +``` + +## Troubleshooting + +### If Unsure About a Conflict: +1. Check if the upstream change addresses a CVE or security issue (prioritize) +2. Look for similar code patterns elsewhere in the Windows codebase +3. Consult the OpenSSH-portable issue tracker for context +4. When in doubt, use conditional compilation to preserve both approaches + +### Testing Your Resolution: +- Build the project after each major conflict resolution +- Run ssh connection to local host to ensure basic functionality +- Check that removed functionality wasn't critical to Windows operation \ No newline at end of file diff --git a/.github/instructions/merge/merge-process-overview.instructions.md b/.github/instructions/merge/merge-process-overview.instructions.md new file mode 100644 index 000000000000..c7d8cc7138aa --- /dev/null +++ b/.github/instructions/merge/merge-process-overview.instructions.md @@ -0,0 +1,462 @@ +--- +applyTo: "**/*" +--- + +# OpenSSH-Portable: Merge From Upstream Instructions + +## Overview +This documentation provides comprehensive instructions for merging OpenBSD's OpenSSH-Portable changes into the PowerShell team's Windows-compatible fork. It is designed to be used by both human developers and AI agents to complete a full merge process that results in a ready-to-merge Pull Request. + +## Prerequisites +Ensure the following tools are installed and configured before proceeding: +- **Git** +- **PowerShell** +- **Visual Studio** with: + - Latest C/C++ development tools + - Latest Windows 10/11 SDK + +## Process Overview +The merge process uses a **two-phase approach** to preserve upstream commit history while keeping conflict resolution manageable: + +1. **Scratch branch** — All work happens here: incremental `git merge` at batch boundaries, conflict resolution, build fixes, and a `Test-OpenSSHFunctionality` smoke test after each built batch. The full CI suite (`Invoke-OpenSSHTests`) is only run when the user explicitly requests it (e.g., before the real branch / PR). +2. **Real merge branch** — Created from the same starting commit as the scratch branch, after all scratch-branch work is complete. A single `git merge` of the final upstream target is performed; any conflicts are resolved by copying the already-resolved files from the scratch branch (`git checkout scratch-branch -- `). This produces one merge commit with all upstream SHAs intact and a tree that matches the validated scratch-branch state. + +No `git rerere` recording, no resolution log, and no Save/Replay tooling is required. + +The process consists of several interconnected phases: + +1. **[Setup Phase](#setup-phase)** - Repository configuration and preparation +2. **[Research Phase](#research-phase)** - Understanding changes and conflicts +3. **[Scratch Branch Phase](#scratch-branch-phase)** - Incremental merging, conflict resolution, build fixes, validation +4. **[Real Branch Phase](#real-branch-phase)** - Single merge with conflict resolution by copy from scratch branch +5. **[Build Phase](#build-phase)** - Resolving compilation issues +6. **[Testing Phase](#testing-phase)** - Validating functionality +7. **[Submission Phase](#submission-phase)** - Creating the Pull Request + +## Setup Phase + +**📖 Detailed Instructions:** [Setup Instructions](../setup.instructions.md) + +**Quick Overview:** +1. Clone your fork of the openssh-portable repository +2. Configure upstream remotes (PowerShell team fork + original OpenSSH) +3. Fetch latest changes + +## Research Phase + +**📖 Detailed Instructions:** [Research Instructions](./research.instructions.md) + +**Key Resources:** +- **Upstream Release Notes:** [OpenSSH Release Notes](https://www.openssh.com/releasenotes.html) +- **Previous Merge PRs:** such as https://github.com/PowerShell/openssh-portable/pull/737 + +## Merge Phase + +### Initial Preparation +1. **Verify prerequisites and baseline** + Use the Test-MergePrerequisites MCP tool: + ```pwsh + # Run prerequisite check via MCP tool + # MCP Tool Name: mcp_openssh-server_Test_MergePrerequisites + # Parameters: TargetVersion (required), SkipBaselineBuild (optional) + + # Example invocation (replace with target like "V_10_0_P2"): + # The MCP tool will verify: + # - Git, PowerShell, Visual Studio installed + # - Repository remotes configured (origin, upstream, upstream-pwsh) + # - Target version exists in upstream + # - Working directory is clean + + # Proceed only if tool reports "ALL PREREQUISITES MET" + ``` + +2. **Configure git:** + ```pwsh + # Set non-interactive editor so MergeContinue does not block. + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Config", Key="core.editor", Value="true" + ``` + + **Disable `git rerere` for this merge.** The two-phase workflow does not + use rerere — resolutions are copied wholesale from the scratch branch in + the Real Branch Phase. Cached rerere resolutions from prior sessions can + silently auto-apply (possibly incomplete) resolutions during batch merges, + making conflict decisions opaque. Disable it explicitly: + ```pwsh + git config --local rerere.enabled false + git config --local rerere.autoupdate false + ``` + +3. **Create the scratch branch only (record the starting commit):** + ```pwsh + # Note the current HEAD — this is the starting commit. The real merge + # branch will be created from this same commit in the Real Branch Phase. + # Use a terminal command here: the MCPServerPS wrapper rejects string + # parameter values that start with "-" (e.g. Invoke-Git Log Range="-1" + # yields MCP error -32603, even though Invoke-Git.ps1 itself accepts it). + git log -1 --oneline + + # Create the scratch branch (all work happens here) + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="CreateBranch", Branch="scratch-merge-v-" + ``` + +### Scratch Branch Phase +4. **Identify merge range and group commits:** + Use the Get-CommitGroups MCP tool with `-FirstChunkOnly` and a user-selected CI grouping mode. + + **CI grouping mode (user input required):** + Before invoking the tool, confirm with the user which mode to use: + - `presence` (recommended) → `GroupByCIPresence=true`: batches end at any commit with CI runs (passing or failing). Smaller batches, more frequent build/test checkpoints. + - `success` → `GroupByCIPresence=false`: batches end only at commits with successful CI. Larger batches, fewer checkpoints. + + Do not assume a default — ask the user if not provided. Use the same value for every `Get-CommitGroups` call in the merge. + + **MCP Tool Name**: `mcp_openssh-server_Get_CommitGroups` + + **Parameters**: + - `GitHubTag` (string, optional): Start from last merged tag (e.g., "V_10_0_P2") + - `StartCommit` (string, optional): Start from specific commit SHA + - `EndCommit` (string, optional): End at specific commit SHA (default: HEAD - most recent upstream commit) + - `FirstChunkOnly` (boolean): Set to `true` + - `GroupByCIPresence` (boolean): Set per the user-selected CI grouping mode above + + **Example for first batch**: + - Find the last upstream tag in the fork + - Call tool with `GitHubTag=`, `EndCommit=`, `FirstChunkOnly=true`, `GroupByCIPresence=` + - Omit `EndCommit` to merge all commits up to HEAD (most recent upstream commit) + - With `GroupByCIPresence=true`, this gets commits ending with any commit that has CI runs; with `false`, only commits with successful CI + + **Example output:** + ```json + { + "ChunkNumber": 1, + "StartCommit": "609fe2c", + "EndCommit": "6fb728d", + "StartCommitFull": "609fe2cae2459d721ac11d23cd27b8a94397ef3c", + "EndCommitFull": "6fb728df50c1afd338cb0223a84ce24579577eff", + "CommitCount": 57, + "StartMessage": "upstream: rework the text for -3 to make it clearer what default", + "EndMessage": "Run all tests on Cygwin again." + } + ``` + + Display batch details for verification, then proceed with merging. + + **After completing steps below, get next batch**: + - Call tool with `StartCommit=`, `EndCommit=`, `FirstChunkOnly=true`, `GroupByCIPresence=` (use the same mode chosen for the first batch) + - Continue this process until the target end commit is reached (or HEAD if no end commit specified) + +5. **Execute batch merge on scratch branch:** + + Merge the batch's end commit to bring in all commits in the range at once: + + ```pwsh + # Merge all commits up to the batch endpoint + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Merge", CommitHash=$result.EndCommitFull + ``` + + This uses `--no-ff` to always create a merge commit checkpoint. + +7. **Resolve merge conflicts directly:** + **📖 Detailed Instructions** ([Merge Details](./merge-details.instructions.md)): + + - Resolve conflicts in place for all conflicted files + - Follow established Windows compatibility patterns + - Reference previous merge PRs for similar conflicts + - The resolved files on the scratch branch are the source of truth that will be copied to the real merge branch in the Real Branch Phase. No resolution log or rerere recording is needed. + +8. **Complete the merge after resolution:** + ```pwsh + # Stage all resolved files using Invoke-Git MCP tool: + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Add", Path="." + + # Continue merge using Invoke-Git MCP tool: + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="MergeContinue" + ``` + +9. **Build after completing the batch (only if the batch touched compiled sources):** + **Gating rule:** Build and validation steps (this step and step 10) are only required for batches whose commit range touches at least one C source or header file (`*.c` or `*.h`). For batches that only modify non-compiled files (e.g., `*.md`, man pages, `regress/*.sh`, `.github/**`, documentation), skip steps 9 and 10 and proceed to step 11; note in the batch summary that build/validation were skipped because no compiled sources changed. + + Detect code impact with: + ```pwsh + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Diff", Range="..", NameOnly=true + ``` + If any returned path matches `*.c` or `*.h`, perform the build below. Otherwise, skip to step 11. + + Use the Start-OpenSSHBuild MCP tool: + - **MCP Tool Name**: `mcp_openssh-server_Start_OpenSSHBuild` + - **Parameters**: `Configuration="Release"`, `Architecture="x64"` + + **ALWAYS check warnings after build (success or failure):** + - **Use Test-OpenSSHBuild MCP tool to parse errors and warnings**: + - **MCP Tool Name**: `mcp_openssh-server_Test_OpenSSHBuild` + - **Parameters**: `Configuration="Release"`, `Architecture="x64"` + - **DO NOT** try to read log files directly with `Get-Content` or locate them manually + + If build failed: + - Fix issues based on parsed error output + - Rebuild and verify + + If build succeeded: + - Compare warnings against baseline established in Phase 1 + - If new warnings detected: + - Categorize warnings (deprecated APIs, type conversions, potential bugs, etc.) + - Report to user with warning details and categories + - Request user decision: fix warnings or proceed + - Wait for user approval before continuing + - If user approves proceeding, update baseline to include new warnings + + **CRITICAL: Before committing, restore paths.targets**: + ```pwsh + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Checkout", Target=".\contrib\win32\openssh\paths.targets" + ``` + Commit any build fixes separately with descriptive messages (only actual code changes) + +10. **Run the functionality smoke test after every batch that was built (mandatory when build ran):** + If step 9 was skipped (no `*.c`/`*.h` changes in the batch), skip this step as well. + Otherwise, run the cheap end-to-end SSH smoke test: + - **MCP Tool Name**: `mcp_openssh-server_Test_OpenSSHFunctionality` + - **Parameters**: `Configuration="Release"`, `Architecture="x64"` + + If the smoke test fails, fix issues before proceeding to the next batch. + + **Full CI suite (`Invoke-OpenSSHTests` with `TestSuite="All"`) is NOT run per-batch by default.** Run it only when: + - The user explicitly requests it for a given batch, or + - Before transitioning to the real merge branch (Phase 6), or + - Before creating the PR. + + When you do run it and any suite fails, re-run only the failing suite to iterate faster (`TestSuite="Unit"`, `TestSuite="Bash"`, or `TestSuite="E2E"`). For a single failing bash case, use `TestSuite="Bash"` and `BashTestFilePath=""`. + +11. **Provide summary and get approval:** + - Summarize batch changes, conflicts resolved, build status, and smoke-test status (and full CI suite status if it was run) + - Wait for user approval before proceeding to next batch + - Document next steps (starting commit for next batch) + - After all batches complete on the scratch branch, proceed to the scratch base-sync step below + +**Before the Real Branch Phase — sync the scratch branch with its base branch (re-fetched):** + +Merge work can take long enough that other PRs land on the base branch (e.g. +`latestw_all`) while it is in progress. Because the real merge branch's tree is +taken wholesale from the scratch branch, the scratch branch must be current with +the base branch **before** it becomes the source of truth. Do this once, after +all batches are merged and validated on the scratch branch: + +```pwsh +# 1. Re-fetch the base branch the scratch/merge was started from (its upstream tracking branch) +git fetch # e.g. origin or upstream-pwsh + +# 2. Merge the refreshed base into the scratch branch (still checked out) +# MCP Tool: mcp_openssh-server_Invoke_Git +# Operation="Merge", CommitHash="/" # e.g. origin/latestw_all +``` + +- Resolve any conflicts from this merge the same way as batch conflicts. +- After it completes cleanly, verify no markers remain + (`mcp_openssh-server_Test_MergeConflictMarkers`) and re-run the build + + `Test-OpenSSHFunctionality` smoke test so the scratch tip is known-good. +- In the Real Branch Phase, create the real branch from **this same re-fetched + base branch tip** (not the stale original starting commit), so the real + branch already contains the newly landed base commits and its post-merge tree + can match the synced scratch tip. + +### Real Branch Phase +12. **Create the real merge branch from the re-fetched base branch tip** (see the scratch base-sync step above; this is the updated base, e.g. `origin/latestw_all`, which coincides with the original starting commit only if no PRs landed since): + ```pwsh + # Check out the re-fetched base branch tip (updated base) + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Checkout", Target="/" # e.g. origin/latestw_all + + # Create the real merge branch from there + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="CreateBranch", Branch="merge-v-" + ``` + +13. **Perform a single merge** of the final upstream target: + ```pwsh + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Merge", CommitHash="" + ``` + This creates one merge commit covering all upstream commits in the range. + +14. **Resolve conflicts by copying the resolved files from the scratch branch:** + For each conflicted file, replace it with the already-resolved version from the scratch branch and stage it: + ```pwsh + # In a terminal (no dedicated MCP wrapper needed): + git checkout scratch-merge-v- -- + + # Then stage: + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Add", Path="" + ``` + + > **⚠️ Copying only the conflicted files is not sufficient.** Many fixes on + > the scratch branch were made to files that **auto-merged without conflict** + > — build fixes, `config.h.vs` defines, `.vcxproj` edits, `win32compat` + > shims, regress-test adaptations, `version.rc`. Those files do **not** + > appear in `ConflictedFiles` on the real branch, so a per-file copy of only + > the conflicted set silently drops them. You **must** reconcile the full + > tree against the scratch tip. + + **Recommended (whole-tree copy)** — guarantees the real branch's tree exactly + matches the validated scratch tip in one shot: + ```pwsh + # After the merge reports conflicts (do NOT abort): + git checkout scratch-merge-v- -- . + git add -A + ``` + + **If you instead copied files individually, run a reconciling diff** and copy + over anything that still differs from the scratch tip: + ```pwsh + # List every path where the real branch differs from the scratch tip. + # This surfaces the auto-merged-but-edited files a conflict-only copy missed. + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Diff", Range="scratch-merge-v-", NameOnly=true + # + # For each unexpected path, copy it from scratch and stage it: + # git checkout scratch-merge-v- -- + ``` + The only differences that should remain after reconciling are the build-fix + commits you intend to replay separately in step 15. Before completing the + merge, run `mcp_openssh-server_Test_MergeConflictMarkers` to confirm no + markers survived the copy. + +15. **Complete the merge and apply build fixes:** + ```pwsh + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="MergeContinue" + ``` + If you used the per-file copy in step 14, replay the build-fix commits made on the scratch branch (cherry-pick or re-apply) as separate commits after the merge commit. If you used the whole-tree copy, the build fixes are already included in the merge commit's tree. + +16. **Final build and validation** on the real branch. + +--- + +## Build Phase + +**📖 Detailed Instructions:** [Build Instructions](../build.instructions.md) + +7. **Initial build attempt:** + Use the Start-OpenSSHBuild MCP tool: + - **MCP Tool Name**: `mcp_openssh-server_Start_OpenSSHBuild` + - **Parameters**: `Configuration="Release"`, `Architecture="x64"` + +8. **Resolve compilation errors (iterative process):** + + **Common Areas to Check:** + - **config.h.vs updates:** New preprocessor definitions + - **Function signatures:** Windows equivalents for Unix functions + - **Build system changes:** Makefile vs Visual Studio projects + - **New dependencies:** Windows compatibility verification + +9. **Update Visual Studio projects:** + - Check Makefile for added/removed binaries + - Create/update .vcxproj files as needed + - Update Win32-OpenSSH.sln solution file + - Ensure Windows-applicable binaries only + +10. **Commit build fixes:** + ```pwsh + # Use a terminal command: the MCPServerPS wrapper mangles embedded + # newlines in Invoke-Git's Message parameter, so the conventional + # header + body commit format must be expressed as repeated -m flags. + git commit -m "Fix compilation errors for " ` + -m "Changes:" ` + -m "- Updated config.h.vs with " ` + -m "- Added Windows equivalent for " ` + -m "- Updated project files for " + ``` + +--- + +## Testing Phase + +**📖 Detailed Instructions:** [Testing Instructions](../testing.instructions.md) + +11. **Basic functionality test:** + ```pwsh + # Set up SSH service (see testing.instructions.md) + ssh.exe @localhost + ``` + +12. **Troubleshoot connection issues:** + - Enable verbose logging + - Check service configuration + - Use debugger if necessary + - Verify certificate/key handling + +13. **Commit any test fixes:** + ```pwsh + # Use a terminal command (multi-line Messages break the MCP wrapper): + git commit -m "Fix runtime issues for " ` + -m "Issues resolved:" ` + -m "- " + ``` + +--- + +## Submission Phase + +### Creating the Pull Request +14. **Push to fork:** + ```pwsh + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Push", Remote="origin", Branch="merge-v-" + ``` + +15. **Create Pull Request:** + - Target: `PowerShell/openssh-portable:` (typically the branch you started from, e.g., latestw_all) + - Title: `Merge upstream OpenSSH ` + - Include comprehensive description of changes and resolutions + +16. **Normalize upstream workflow triggers for Windows fork:** + - Ensure merged upstream workflow files under `.github/workflows/*.yml` are dispatch-only in this fork. + - Keep `workflow_dispatch` enabled and disable automatic triggers (`push`, `pull_request`, `schedule`) unless explicitly required for this fork. + - Preserve trigger blocks as commented context where practical so future re-syncs are straightforward. + +17. **Address CI/test failures:** + - Monitor automated tests + - Fix any Windows-specific test failures + - Ensure all checks pass + +18. **Request review:** + - Tag appropriate PowerShell team reviewers + - Provide context for complex conflict resolutions + +--- + +## Success Criteria + +**The merge is complete when:** +- [ ] All merge conflicts resolved with documented reasoning +- [ ] Solution builds successfully on Windows +- [ ] Basic SSH connection test passes +- [ ] All CI tests pass +- [ ] Upstream workflow triggers normalized to dispatch-only for this fork +- [ ] PR approved and ready for merge + +--- + +## AI Agent Resources + +AI agents should utilize these additional resources: + +- **[Reference Analysis](./research.instructions.md)** - Intelligence gathering protocols +- **[Merge Details](./merge-details.instructions.md)** - Comprehensive merge process, conflict resolution, and automation algorithms +- **[Testing Instructions](../testing.instructions.md)** - Detailed validation procedures + +**For AI Agents:** +1. **Start with this overview** - Follow the phases and track progress commit-by-commit +2. **Follow decision trees** - Refer to AI agent instructions for algorithmic guidance +3. **Document everything** - Maintain detailed commit messages and resolution rationale +4. **Use automated testing** - Leverage provided test scripts for validation +5. **Escalate when needed** - If complexity exceeds capabilities, document and request human intervention + +**Success Criteria Check:** +The merge process is successful when an AI agent can complete all phases independently and produce a Pull Request that meets all quality standards without human intervention. diff --git a/.github/instructions/merge/research.instructions.md b/.github/instructions/merge/research.instructions.md new file mode 100644 index 000000000000..3259ac577037 --- /dev/null +++ b/.github/instructions/merge/research.instructions.md @@ -0,0 +1,109 @@ +--- +applyTo: "**/*" +--- + +# References for AI Agents + +## AI Agent Instructions +This file provides reference materials and links that AI agents should review before and during the merge process. Each section contains specific guidance on what to look for and how to use the information. + +## Upstream Release Notes +**URL:** https://www.openssh.com/releasenotes.html + +**AI Agent Task:** +1. Navigate to the release notes page +2. Focus ONLY on the latest release section (at the top of the page) +3. Look for these specific types of changes that require Windows compatibility work: + - Signal handling modifications + - File handling changes + - Inter-process communication (IPC) updates + - New system calls or POSIX-specific functionality + - Changes to build system or dependencies + - Security fixes that might affect Windows implementations + +**Example Analysis:** +``` +If release notes mention "Added support for new signal handling in sshd", +the AI should flag this as requiring Windows event mechanism adaptation. +``` + +## Previous Merge Pull Requests + +**AI Agent Task:** Review these PRs in order of recency for conflict resolution patterns: + +1. **Most Recent:** https://github.com/PowerShell/openssh-portable/pull/737 +2. https://github.com/PowerShell/openssh-portable/pull/703 +3. https://github.com/PowerShell/openssh-portable/pull/684 +4. https://github.com/PowerShell/openssh-portable/pull/657 +5. https://github.com/PowerShell/openssh-portable/pull/626 +6. https://github.com/PowerShell/openssh-portable/pull/577 +7. https://github.com/PowerShell/openssh-portable/pull/504 +8. https://github.com/PowerShell/openssh-portable/pull/351 + +**What to Extract from Each PR:** +1. **Commit Messages:** Look for commits added AFTER the initial merge commit +2. **File Patterns:** Note which files commonly have conflicts +3. **Resolution Strategies:** Document how specific types of conflicts were resolved +4. **Build Fixes:** Note compilation issues and their solutions +5. **Test Failures:** Understand common CI/test failures and fixes + +**Key Contributors to Follow:** +- Regular PowerShell/OpenSSH-Portable contributors +- Their commit patterns and resolution strategies +- Comments and review feedback + +## Upstream Repository Analysis + +**Commands for AI Agent (use Invoke-Git MCP tool):** +```pwsh +# Get commit history for target version: +# MCP Tool: mcp_openssh-server_Invoke_Git +# Operation="Log", Range="..upstream/" + +# Analyze specific commits: +# MCP Tool: mcp_openssh-server_Invoke_Git +# Operation="Show", CommitHash="" + +# Compare branches: +# MCP Tool: mcp_openssh-server_Invoke_Git +# Operation="Diff", Range="HEAD..upstream/" +``` + +## Windows-Specific Knowledge Base + +### Common Conflict Areas +1. **Process Management:** fork() vs CreateProcess() +2. **Signal Handling:** Unix signals vs Windows events +3. **File Permissions:** POSIX permissions vs Windows ACLs +4. **Path Handling:** Unix paths vs Windows paths +5. **Build System:** Makefile vs Visual Studio projects + +### Resolution Pattern Library +```c +// Pattern 1: Platform-specific implementation +#ifdef WINDOWS + // Windows implementation +#else + // Unix implementation +#endif + +// Pattern 2: Exclude Unix-only features +#ifndef WINDOWS + // Unix-only code +#endif + +// Pattern 3: Windows compatibility layer +#ifdef WINDOWS + #include "win32compat.h" +#endif +``` + +## Decision Matrix for AI Agents + +| Conflict Type | Resolution Strategy | Example | +|---------------|-------------------|---------| +| Security Fix | Accept upstream completely | CVE patches | +| Build System | Update VS project files | New source files | +| System Calls | Add Windows equivalent | fork() → CreateProcess() | +| Configuration | Update config.h.vs | New preprocessor defines | +| Test Code | Platform-specific guards | Unix-only tests | diff --git a/.github/instructions/repository-overview.instructions.md b/.github/instructions/repository-overview.instructions.md new file mode 100644 index 000000000000..3fe4c9d6c2b8 --- /dev/null +++ b/.github/instructions/repository-overview.instructions.md @@ -0,0 +1,136 @@ +--- +applyTo: "**/*" +--- + +# Repository Structure and Windows Compatibility Layer + +## Overview + +This repository is a **downstream fork** of [openssh/openssh-portable](https://github.com/openssh/openssh-portable) maintained by the PowerShell team to provide Windows compatibility for OpenSSH. + +## Repository Organization + +### Upstream Code (Base Directory) +The root of the repository contains the upstream OpenSSH code: +- Core SSH implementation files (`.c`, `.h`) +- Unix/POSIX-focused codebase +- Maintained to stay close to upstream for easier merging + +### Windows Compatibility Layer + +#### Primary Windows Code Locations + +**1. `.\contrib\win32\openssh\`** +- Visual Studio project files (`.vcxproj`, `.sln`) +- Windows-specific build configuration +- Project organization for Windows builds + +**2. `.\contrib\win32\win32compat\`** +- Windows compatibility implementation layer +- Provides Windows equivalents for POSIX functions +- Contains platform abstraction code + +#### Compatibility Strategy + +The Windows port follows a **separation of concerns** approach to minimize divergence from upstream: + +1. **Preferred: Compatibility Layer** + - Windows-specific implementations prefixed with `w32_` + - Example: `w32_mkdir()`, `w32_stat()`, `w32_open()` + - Macro redefinition in headers to redirect POSIX calls + - Located in `contrib\win32\win32compat\` + +2. **When Necessary: Conditional Compilation** + - Use `#ifdef WINDOWS` blocks in upstream files + - Keep Windows-specific code minimal and well-documented + - Only when compatibility layer approach is insufficient + +**Example Pattern:** +```c +// In win32compat header (e.g., sys/stat.h) +int w32_mkdir(const char *pathname, unsigned short mode); +#undef mkdir // Clear any existing definition +#define mkdir w32_mkdir // Redirect to Windows implementation + +// In upstream code - no changes needed +mkdir(path, 0700); // Automatically uses w32_mkdir on Windows +``` + +## Special Case: SSH-Agent + +### Important: Separate Windows Implementation + +The **ssh-agent** is a special case that **does not follow** the standard compatibility layer pattern: + +- **Windows ssh-agent location**: `.\contrib\win32\win32compat\ssh-agent\` +- Built from **completely separate code** from the upstream ssh-agent +- Uses Windows-native APIs and service architecture + +### Implications for Upstream Merges + +When merging changes to `ssh-agent.c` or related agent files from upstream: + +1. **Simple changes** (bug fixes, small improvements): + - Manually port functionality to `contrib\win32\win32compat\ssh-agent\` + - Adapt logic to Windows implementation + +2. **Complex changes** (architectural changes, new features): + - Document as TODO in merge commit + - Flag for Windows team review + - May require significant redesign work + +3. **New files** (additional agent-related source files): + - **Not all new upstream files need to be ported** to the Windows ssh-agent + - Evaluate whether the functionality is relevant to the Windows implementation + - If not applicable, document the decision and skip porting + +4. **Do NOT**: + - Directly apply upstream ssh-agent patches to Windows version + - Assume one-to-one code correspondence + - Merge without understanding Windows implementation differences + +### Other Binaries + +All other OpenSSH binaries (ssh, sshd, scp, sftp, etc.) follow the standard compatibility layer approach and can be merged more directly from upstream with appropriate Windows compatibility adjustments. + +## Best Practices for Merging + +### 1. Minimize Direct Modifications +- Prefer extending compatibility layer over adding `#ifdef WINDOWS` blocks +- Keep upstream code as clean as possible + +### 2. Document Windows-Specific Changes +- Clear comments explaining why Windows needs different approach +- Reference related compatibility layer functions + +### 3. Test on Windows +- Always build and test on Windows after merging +- Use provided automation tools in `.github\tools\` +- Verify both functionality and build process + +### 4. Upstream Alignment +- Track which upstream commits have been merged +- Maintain clear merge history +- Document any deviations from upstream behavior + +## Key Files to Know + +### Build System +- `contrib\win32\openssh\Win32-OpenSSH.sln` - Main Visual Studio solution +- `contrib\win32\openssh\*.vcxproj` - Individual project files +- `contrib\win32\openssh\OpenSSHBuildHelper.psm1` - Build helper module + +### Compatibility Headers +- `contrib\win32\win32compat\inc\sys\*` - POSIX header replacements +- `contrib\win32\win32compat\inc\*.h` - Windows compatibility declarations +- `contrib\win32\win32compat\inc\crtheaders.h` - CRT header mappings + +### Compatibility Implementation +- `contrib\win32\win32compat\*.c` - Windows function implementations +- `contrib\win32\win32compat\ssh-agent\*` - Separate Windows ssh-agent + +## Getting Help + +- **Build issues**: See [build.instructions.md](./build.instructions.md) +- **Merge conflicts**: See [merge/merge-details.instructions.md](./merge/merge-details.instructions.md) +- **Testing**: See [testing.instructions.md](./testing.instructions.md) diff --git a/.github/instructions/setup.instructions.md b/.github/instructions/setup.instructions.md new file mode 100644 index 000000000000..2ab9405b0131 --- /dev/null +++ b/.github/instructions/setup.instructions.md @@ -0,0 +1,115 @@ +--- +applyTo: "**/*" +--- + +# Repository Setup Instructions for AI Agents + +## Initial Repository Setup + +### Step 1: Clone Your Fork +```pwsh +# Replace 'your-username' with actual GitHub username +git clone https://github.com/your-username/openssh-portable.git +cd openssh-portable +``` + +### Step 2: Add Upstream Repositories +```pwsh +# Add PowerShell team's fork as upstream-pwsh +git remote add upstream-pwsh https://github.com/PowerShell/openssh-portable.git + +# Add original OpenSSH repository as upstream +git remote add upstream https://github.com/openssh/openssh-portable.git +``` + +### Step 3: Verify Remote Configuration +```pwsh +git remote -v +# Expected output: +# origin https://github.com/your-username/openssh-portable.git (fetch) +# origin https://github.com/your-username/openssh-portable.git (push) +# upstream https://github.com/openssh/openssh-portable.git (fetch) +# upstream https://github.com/openssh/openssh-portable.git (push) +# upstream-pwsh https://github.com/PowerShell/openssh-portable.git (fetch) +# upstream-pwsh https://github.com/PowerShell/openssh-portable.git (push) +``` + +### Step 4: Initial Fetch +Use the Invoke-Git MCP tool to fetch from all remotes: +- **MCP Tool**: `mcp_openssh-server_Invoke_Git` +- **Operation**: `Fetch`, **Remote**: `all` + +## Branch Strategy + +### Understanding the Branch Structure +- **upstream-pwsh/latestw_all**: Main Windows-compatible branch +- **upstream/master**: Latest upstream OpenSSH development +- **upstream/V_X_Y_PZ**: Tagged releases (merge targets) + +### Verification Commands +```pwsh +# List all branches +git branch -r + +# Check current branch +git branch +``` + +### Step 5: Clone vcpkg Repository +```pwsh +# In the same parent directory as openssh-portable (sibling of the repo) +git clone https://github.com/Microsoft/vcpkg.git +``` + +The build expects the vcpkg clone at `..\vcpkg` relative to the repo root. +The `Install-VcpkgDependencies.ps1` tool (Step 6) will also honor +`$env:VCPKG_ROOT` if set. + +### Step 6: Bootstrap vcpkg and Install Dependencies + +The Win32-OpenSSH build links against vendored libraries (`libressl`, +`libfido2`, `libcbor`, `zlib`) installed via vcpkg's manifest mode using +custom triplets and overlay ports under +[contrib/win32/openssh/](../../contrib/win32/openssh/). +[OpenSSHBuildHelper.psm1](../../contrib/win32/openssh/OpenSSHBuildHelper.psm1) +copies `libcrypto.dll` from `vcpkg_installed/-custom/` at build time, +so this step **must complete before `Start-OpenSSHBuild`**. + +**Recommended (use the tool):** +```pwsh +# From the repo root +.\.github\tools\Install-VcpkgDependencies.ps1 -Bootstrap +``` + +The tool auto-discovers `..\vcpkg` (or `$env:VCPKG_ROOT`), bootstraps it if +needed, runs the LibreSSL version cross-check, and invokes `vcpkg install` +with the correct overlay ports and triplet. See +[vcpkg.instructions.md](./vcpkg.instructions.md) for full reference. + +**Manual equivalent (for reference):** +```pwsh +cd ..\vcpkg +.\bootstrap-vcpkg.bat +cd ..\openssh-portable\contrib\win32\openssh +..\..\..\..\vcpkg\vcpkg.exe install ` + --triplet x64-custom ` + --overlay-triplets=.\vcpkg_triplets ` + --overlay-ports=.\vcpkg_overlay_ports +``` + +## AI Agent Checklist + +Before proceeding to merge: +- [ ] Repository cloned successfully +- [ ] All three remotes configured (origin, upstream, upstream-pwsh) +- [ ] Can fetch from all remotes without errors +- [ ] Can see upstream target version/branch +- [ ] Working directory is clean (use Invoke-Git `Operation="Status"` — `ModifiedFiles` and `ConflictedFiles` should both be empty) +- [ ] vcpkg dependencies installed: `contrib/win32/openssh/vcpkg_installed/x64-custom/` exists and contains `bin/libcrypto.dll` + +## Troubleshooting + +### Common Issues +1. **Authentication errors**: Ensure GitHub credentials are configured +2. **Network issues**: Check proxy settings if behind corporate firewall +3. **Branch not found**: Verify branch/tag names are correct diff --git a/.github/instructions/testing.instructions.md b/.github/instructions/testing.instructions.md new file mode 100644 index 000000000000..1c951d8c0f9b --- /dev/null +++ b/.github/instructions/testing.instructions.md @@ -0,0 +1,368 @@ +--- +applyTo: "**/*" +--- + +# Testing Instructions for AI Agents + +## Overview +This document provides comprehensive testing procedures for validating OpenSSH-Portable merges on Windows. Testing should be performed after successful compilation to ensure functionality is preserved. + +## Automated Testing with MCP Tools (Recommended) + +### Using Test-OpenSSHFunctionality Tool + +The repository includes an MCP tool that automates end-to-end functional testing of OpenSSH on Windows. + +Use the Test-OpenSSHFunctionality MCP tool: +- **MCP Tool Name**: `mcp_openssh-server_Test_OpenSSHFunctionality` +- **Parameters**: + - `Configuration` (optional): "Debug" or "Release" (default: "Release") + - `Architecture` (optional): "x64", "x86", "ARM", "ARM64" (default: "x64") + - `SkipFirewall` (optional): Skip firewall configuration (default: false) + - `NoCleanup` (optional): Skip cleanup for debugging (default: false) + +**Examples:** +- Run with defaults: (no parameters needed) +- Test with specific configuration: `Configuration="Debug"`, `Architecture="x64"` +- Skip firewall configuration: `SkipFirewall=true` + +**What the tool does:** +1. Verifies Administrator privileges +2. Creates a temporary test user with random password +3. Installs and starts the SSH service +4. Configures Windows Firewall (unless -SkipFirewall is used) +5. Tests SSH connection with password authentication +6. Executes "echo hello world" command via SSH +7. Cleans up all resources (user, service, firewall rule) + +**Expected output on success:** +``` +=== OpenSSH Functionality Test === +[1/6] Checking Administrator privileges... +✓ Running with Administrator privileges +[2/6] Creating temporary test user... +✓ Created test user: openssh_test_1234 +[3/6] Installing SSH service... +✓ SSH service installed successfully +[4/6] Starting SSH service... +✓ SSH service started successfully +[5/6] Configuring Windows Firewall... +✓ Firewall rule created +[6/6] Testing SSH connection... +✓ SSH connection successful + Command output: hello world + +=== Cleanup === +✓ SSH service uninstalled +✓ Firewall rule removed +✓ Test user removed + +=== Test Summary === +Status: PASSED +``` + +**The tool returns a structured result object with:** +- `Success`: Boolean indicating overall test success +- `ServiceInstalled`: Whether service installation succeeded +- `ServiceStarted`: Whether service started successfully +- `ConnectionSuccessful`: Whether SSH connection test passed +- `CommandOutput`: Output from the test command +- `TestUser`: Name of the temporary test user created +- `Errors`: Array of any errors encountered +- `Message`: Summary message + +## Primary Testing Approach + +**Use the automated Test-OpenSSHFunctionality MCP tool for all testing.** + +The MCP tool performs comprehensive end-to-end testing including: +- Administrator privilege verification +- Temporary test user creation +- SSH service installation and startup +- Windows Firewall configuration +- SSH connection testing with password authentication +- Command execution verification +- Complete cleanup of all test resources + +**MCP Tool Name**: `mcp_openssh-server_Test_OpenSSHFunctionality` + +**Parameters**: +- `Configuration` (optional): "Debug" or "Release" (default: "Release") +- `Architecture` (optional): "x64", "x86", "ARM", "ARM64" (default: "x64") +- `SkipFirewall` (optional): Skip firewall configuration (default: false) +- `NoCleanup` (optional): Skip cleanup for debugging (default: false) + +**When to use**: +- After successful build to validate functionality +- During merge process at CI checkpoints +- Before creating pull requests +- When debugging SSH connectivity issues + +## Full CI Test Suite + +For thorough validation (e.g., before submitting a PR or after a significant merge), run the complete CI test suite: unit tests, bash regression tests, and Pester E2E tests. + +Reference: https://github.com/PowerShell/Win32-OpenSSH/wiki/Run-OpenSSH-Pester-Tests + +### Using the Invoke-OpenSSHTests MCP Tool (Recommended) + +Use the Invoke-OpenSSHTests MCP tool: +- **MCP Tool Name**: `mcp_openssh-server_Invoke_OpenSSHTests` +- **Parameters**: + - `Configuration` (optional): "Debug" or "Release" (default: "Release") + - `Architecture` (optional): "x64", "x86", "ARM", "ARM64" (default: "x64") + - `TestSuite` (optional): "All", "Unit", "Bash", "E2E" — one or more values (default: "All") + - `BashTestFilePath` (optional): Absolute path to a single `.sh` test file for targeted bash testing (e.g., `C:\repos\openssh-portable\regress\banner.sh`) + - `BashShellPath` (optional): Path to `sh.exe` — auto-detected from common Cygwin locations if omitted + - `NoCleanup` (optional): Skip `Clear-OpenSSHTestEnvironment` after the run (default: false) + - `SkipSetup` (optional): Skip `Set-OpenSSHTestEnvironment` when environment is already configured (default: false) + +**The tool returns a structured result with:** +- `Success`: Overall pass/fail +- `UnitTestsPassed`, `BashTestsPassed`, `E2ETestsPassed`: Per-suite results (`$true`/`$false`/`$null` if not run) +- `UnitTestOutput`, `BashTestOutput`, `E2ETestOutput`: Captured output for each suite +- `Errors`: Array of failure messages +- `Warnings`: Known gotchas and environment notes +- `Message`: Summary + +**Examples:** +- Run full suite: (no parameters needed) +- Run only E2E tests: `TestSuite="E2E"` +- Run a single bash test: `TestSuite="Bash"`, `BashTestFilePath="C:\repos\openssh-portable\regress\banner.sh"` + +### Manually Running the Full CI Suite + +Binaries are expected at `C:\repos\openssh-portable\bin\{Architecture}\{Configuration}`. + +```pwsh +# 1. Import the test helper module +Import-Module C:\repos\openssh-portable\contrib\win32\openssh\OpenSSHTestHelper.psm1 -Force + +# 2. Configure the test environment (installs test accounts, sshd test service, etc.) +# This modifies known_hosts and ssh_config; run Clear-OpenSSHTestEnvironment to undo. +Set-OpenSSHTestEnvironment -OpenSSHBinPath "C:\repos\openssh-portable\bin\x64\Release" -Confirm:$false + +# 3. Run unit tests (unittest-*.exe binaries in the bin folder) +Invoke-OpenSSHUnitTest + +# 4. Run bash regression tests (requires Cygwin sh.exe) +Invoke-OpenSSHBashTests + +# 5. Run Pester E2E tests +Invoke-OpenSSHE2ETest + +# 6. Clean up test accounts, service, and ssh config changes +Clear-OpenSSHTestEnvironment +``` + +### Running a Single Bash Test + +Use `bash_tests_iterator.ps1` to run one bash test file in isolation: + +```pwsh +.\contrib\win32\openssh\bash_tests_iterator.ps1 ` + -OpenSSHBinPath "C:\repos\openssh-portable\bin\x64\Release" ` + -BashTestsPath "C:\repos\openssh-portable\regress" ` + -ShellPath "C:\cygwin64\bin\sh.exe" ` + -TestFilePath "C:\repos\openssh-portable\regress\banner.sh" +``` + +### Known CI Test Gotchas + +**`cfginclude.sh` — wrong PowerShell executable:** +The test calls `powershell.exe` directly. When running under `pwsh.exe`, the test will fail unless the file is edited to replace `powershell.exe` with `pwsh.exe`. +See: https://github.com/PowerShell/PowerShell/issues/18530#issuecomment-1325691850 + +**WSMan / Port Forwarding tests — disabled on some VMs:** +The WSMan and port-forwarding Pester tests may fail on VMs where these Windows features are disabled by default. Options: +- Enable the features: turn on "Windows Remote Management" and ensure port-forward firewall rules are allowed. +- Skip the affected test files (e.g., `PortForwarding.Tests.ps1`) when running `Invoke-OpenSSHE2ETest` for routine validation. + +**Pester version requirement:** +The E2E tests require **Pester version < 5**. The helper module will attempt to install Pester 3.4.6 via chocolatey if a compatible version is not found. + +**Cygwin required for bash tests:** +`Invoke-OpenSSHBashTests` auto-detects `sh.exe` at `%SystemDrive%\cygwin64\bin\sh.exe`, `%SystemDrive%\cygwin\bin\sh.exe`, or `%SystemDrive%\tools\cygwin\bin\sh.exe`. If none is found it installs Cygwin via chocolatey. Provide `-BashShellPath` to the MCP tool to override. + +## Manual Testing Procedures (For Troubleshooting Only) + +If the automated MCP tool fails and you need to troubleshoot specific issues manually, follow these procedures: + +### Prerequisites Check +```pwsh +# Verify Windows version compatibility +Get-ComputerInfo | Select-Object WindowsProductName, WindowsVersion + +# Check if running as Administrator - REQUIRED for service installation +if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) +{ + Write-Error "Administrative privileges are REQUIRED for service installation and testing." + Write-Host "Please restart PowerShell or VS Code as Administrator and try again." -ForegroundColor Yellow + Write-Host "To elevate: Right-click PowerShell/VS Code -> 'Run as Administrator'" -ForegroundColor Yellow + exit 1 +} + +Write-Host "✓ Running with Administrator privileges" -ForegroundColor Green + +# Verify build artifacts exist +$buildPath = ".\contrib\win32\openssh\x64\Release" +if (-not (Test-Path "$buildPath\sshd.exe") -or -not (Test-Path "$buildPath\ssh.exe")) { + Write-Error "Build artifacts not found. Please build the project first." + exit 1 +} + +Write-Host "✓ Build artifacts verified" -ForegroundColor Green +``` + +### Test Environment Setup + +### Service Installation and Configuration + +#### Step 1: Install SSH Service +```pwsh +# Navigate to build directory +cd .\contrib\win32\openssh\x64\Release + +# Install SSH server service with PowerShell script +.\install-sshd.ps1 + +# Verify service installation +Get-Service sshd -ErrorAction SilentlyContinue | Select-Object Name, Status, StartType +``` + +#### Step 2: Configure SSH Service +```pwsh +# Start SSH service +Start-Service sshd + +# Verify service is running +Get-Service sshd | Select-Object Name, Status +``` + +#### Step 3: Configure Windows Firewall (if needed) +```pwsh +# Allow SSH through Windows Firewall +New-NetFirewallRule -DisplayName "SSH Server (sshd)" -Direction Inbound -Port 22 -Protocol TCP -Action Allow -ErrorAction SilentlyContinue +``` + +## Basic Functionality Tests + +### Test 1: SSH Client Connection +```pwsh +# Test local connection (most basic test) +$username = $env:USERNAME +$hostname = "localhost" + +Write-Host "Testing SSH connection: ssh $username@$hostname" + +# Basic connection test +.\ssh.exe $username@$hostname "echo 'SSH connection successful'" +``` + +**Expected Output:** +``` +SSH connection successful +``` + +## Error Diagnosis and Troubleshooting + +### Run SSH Server in Debug Mode +```pwsh +# Enable SSH daemon debug logging +Stop-Service sshd +.\sshd.exe -ddd + +# In another terminal, test connection with verbose client logging +.\ssh.exe -vvv $username@$hostname +``` + +### Common Issues and Solutions + +#### Issue 1: Service Won't Start +**Symptoms:** +- Service fails to start +- Event log shows service errors + +**Diagnosis:** +```pwsh +# Check event logs +Get-WinEvent -LogName System | Where-Object {$_.ProviderName -eq "Service Control Manager" -and $_.Id -eq 7034} | Select-Object -First 5 + +# Check sshd configuration +.\sshd.exe -T +``` + +**Common Solutions:** +- Verify configuration file syntax + +#### Issue 2: Connection Timeouts +**Symptoms:** +- SSH client hangs +- Connection timeout errors + +**Diagnosis:** +```pwsh +# Check network connectivity +Test-NetConnection -ComputerName localhost -Port 22 + +# Check Windows Firewall rules +Get-NetFirewallRule | Where-Object {$_.DisplayName -like "*SSH*"} +``` + +## Success Criteria + +**Testing is successful when:** +- [ ] All expected executables are present after build (verified by Test-OpenSSHBuild MCP tool) +- [ ] SSH service installs and starts without errors +- [ ] SSH validation succeeds via password authentication +- [ ] Test command executes successfully via SSH connection +- [ ] All resources cleaned up properly after testing + + +## AI Agent Guidelines + +1. **Use automated testing tools** whenever possible - use the Test-OpenSSHFunctionality MCP tool over manual procedures +2. **Run tests incrementally** during the merge process, not just at the end +3. **Document any test failures** and their resolutions in commit messages +4. **Pay special attention to Windows-specific functionality** that might be affected by upstream changes +5. **Always verify cleanup** - ensure test users, services, and firewall rules are removed +6. **Report any new functionality** that needs additional testing procedures + +### Recommended Testing Workflow for AI Agents + +1. **After successful build**, run the automated functionality test: + - **MCP Tool Name**: `mcp_openssh-server_Test_OpenSSHFunctionality` + - **Parameters**: (use defaults) + +2. **If test passes**, the merge is validated for basic SSH functionality + +3. **If test fails**, use manual procedures and debug mode to diagnose issues + +4. **For full CI validation** (e.g., before creating a PR), run the complete test suite: + - **MCP Tool Name**: `mcp_openssh-server_Invoke_OpenSSHTests` + - **Parameters**: (use defaults to run all suites) + - If a specific suite fails, re-run it in isolation using `TestSuite="Unit"`, `TestSuite="Bash"`, or `TestSuite="E2E"` + - For a single failing bash test: `TestSuite="Bash"`, `BashTestFilePath=""` + +5. **Document results** in commit message or merge documentation + +## Manual Test Environment Cleanup + +If you ran manual tests instead of using the automated tool: + +```pwsh +# Clean up test environment +Stop-Service sshd -ErrorAction SilentlyContinue +cd .\contrib\win32\openssh\x64\Release +.\uninstall-sshd.ps1 + +# Remove firewall rule +Remove-NetFirewallRule -DisplayName "SSH Server (sshd)" -ErrorAction SilentlyContinue + +# Remove any test users manually created +Remove-LocalUser -Name "test_username" -ErrorAction SilentlyContinue + +Write-Host "Test environment cleaned up" +``` + +**Note:** The automated Test-OpenSSHFunctionality.ps1 tool handles all cleanup automatically, even on failure. diff --git a/.github/instructions/vcpkg.instructions.md b/.github/instructions/vcpkg.instructions.md new file mode 100644 index 000000000000..1c8a916c40f6 --- /dev/null +++ b/.github/instructions/vcpkg.instructions.md @@ -0,0 +1,120 @@ +# vcpkg Dependency Management + +This document is the canonical reference for the vcpkg setup used by the +Win32-OpenSSH build. It covers the on-disk layout, why custom triplets and +overlay ports exist, and how to use the automation tools and skills. + +## When to Read This + +- First-time setup of a build environment (see also [setup.instructions.md](./setup.instructions.md)). +- Diagnosing build failures that mention missing `libcrypto.dll`, + `libcrypto-*.lib`, `fido.lib`, `cbor.lib`, or `zlib.lib`. +- Bumping a vendored dependency to a new upstream version. +- Updating the `add-version-file.patch` for LibreSSL. + +## Layout + +All vcpkg-related files live under +[contrib/win32/openssh/](../../contrib/win32/openssh/): + +| Path | Purpose | +|---|---| +| `vcpkg.json` | Manifest. Declares `dependencies` (`zlib`, `libressl`, `libfido2`, `libcbor`), pins versions in `overrides`, and pins the registry baseline in `builtin-baseline`. | +| `vcpkg_overlay_ports/libressl/` | Custom port for LibreSSL. Replaces upstream `openssl`. Contains `portfile.cmake`, `vcpkg.json`, six patches, and the `vcpkg-cmake-wrapper.cmake.in` template. | +| `vcpkg_overlay_ports/libfido2/` | Custom port for libfido2 with two patches that fix CMake and DLL output naming on Windows. | +| `vcpkg_triplets/{x64,x86,arm,arm64}-custom.cmake` | Custom triplets with the linkage and CRT settings the build expects. | +| `vcpkg_installed/` | **Generated**. Output of `vcpkg install`. Gitignored. Consumed by [OpenSSHBuildHelper.psm1](../../contrib/win32/openssh/OpenSSHBuildHelper.psm1) (it copies `libcrypto.dll` from `vcpkg_installed/-custom/-custom/bin/`). | + +The vcpkg clone itself is **not** vendored. It is expected at `..\vcpkg` +relative to the repository root, or at `$env:VCPKG_ROOT`. + +## Why Custom Triplets and Overlay Ports + +- **LibreSSL replaces OpenSSL.** Upstream vcpkg ships an `openssl` port; we + override with `libressl` plus a CMake wrapper so consuming targets that + call `find_package(OpenSSL)` resolve to LibreSSL. +- **ARM64 / aarch64 patches.** Upstream LibreSSL has open issues on + `aarch64-windows`; the overlay port carries `aarch64-windows.diff`. +- **Resource-file metadata.** `add-version-file.patch` and + `add-resource-header-file.patch` embed version metadata in the LibreSSL + DLLs so they pass Microsoft signing/compliance checks. +- **libfido2 output naming.** `modify_output_name.patch` makes the produced + DLL match what the OpenSSH build expects to link against. +- **Custom triplets** pin CRT linkage and disable features that break the + Win32 build. + +## Tools and Skills + +### Install dependencies (tool) + +`.\.github\tools\Install-VcpkgDependencies.ps1` + +- Bootstraps vcpkg if needed and runs `vcpkg install` against the manifest + with the correct overlay ports and triplet. +- Default architecture matches `Start-OpenSSHBuild.ps1` (`x64`). Pass an + array to install multiple triplets in one run: + ```pwsh + .\.github\tools\Install-VcpkgDependencies.ps1 -Architecture x64,x86,ARM,ARM64 + ``` +- Validates the LibreSSL `vcpkg.json` ↔ `add-version-file.patch` + `FileVersion` cross-check before installing. +- Returns a structured hashtable (`Success`, `VcpkgRoot`, `TripletsInstalled`, + `InstalledPath`, `Errors`). + +Also exposed via MCP as `mcp_openssh-server_Install_VcpkgDependencies`. + +### Update a vendored port (tool) + +`.\.github\tools\Update-VcpkgPort.ps1 -Port -Version ` + +- Bumps the matching entry in `vcpkg.json` `overrides[]`. +- For overlay ports (`libressl`, `libfido2`): + - Updates `vcpkg_overlay_ports//vcpkg.json` `version`. + - Downloads the new source archive, computes its SHA512, and rewrites + `portfile.cmake`. + - Re-applies each patch via `git apply --3way` in a scratch worktree. + **Stops on rejected hunks** — patches must be regenerated by hand. +- For `libressl`, also flags whether `add-version-file.patch` needs its + embedded `FileVersion` updated to keep the install-time cross-check + passing. +- Use `-DryRun` to preview changes. + +### Update workflow (skill) + +For non-trivial bumps (especially LibreSSL), invoke the +`update-vcpkg-port` skill at [.github/skills/update-vcpkg-port/SKILL.md](../skills/update-vcpkg-port/SKILL.md). +The skill orchestrates `Update-VcpkgPort.ps1`, walks the patch-rejection +decision tree, validates via `Install-VcpkgDependencies.ps1` and +`Start-OpenSSHBuild`, and produces a commit message. + +## LibreSSL Resource-File Cross-Check + +The `vcpkg.json` `overrides` entry for `libressl` and the `FileVersion` +embedded in `vcpkg_overlay_ports/libressl/add-version-file.patch` must +agree on `..`. CI enforces this in +[.azdo/templates/install-vcpkg-dependencies.yml](../../.azdo/templates/install-vcpkg-dependencies.yml); +the install tool enforces it locally. If they drift, both will fail with: + +> LibreSSL version mismatch: vcpkg.json has X.Y.Z, patch file has A.B.C.D + +Resolve by editing `add-version-file.patch` so the `FileVersion` field is +`...0`. + +## Troubleshooting + +| Symptom | Likely cause | Fix | +|---|---|---| +| Build fails: `libcrypto.dll` not found | Dependencies not installed for current triplet | Run `Install-VcpkgDependencies.ps1` | +| `vcpkg.exe not found` | `..\vcpkg` missing or not bootstrapped | Run install tool with `-Bootstrap`, or `git clone https://github.com/Microsoft/vcpkg.git ..\vcpkg && ..\vcpkg\bootstrap-vcpkg.bat` | +| `LibreSSL version mismatch` | `vcpkg.json` and `add-version-file.patch` disagree | Update the patch's `FileVersion` field to match the manifest | +| Patch hunks rejected after a port bump | Upstream source moved | Use the `update-vcpkg-port` skill; regenerate the patch from a fresh extract | +| `vcpkg install` succeeds but build still can't find libs | Wrong triplet installed (e.g. installed `x64-custom` but built `x86`) | Re-run install tool with matching `-Architecture` | + +## CI Reference + +The local install path mirrors what CI does. See: +- [.azdo/templates/install-vcpkg-dependencies.yml](../../.azdo/templates/install-vcpkg-dependencies.yml) — install + cross-check recipe. +- [.azdo/templates/build-win32-openssh-job.yml](../../.azdo/templates/build-win32-openssh-job.yml) — same bootstrap pattern, then build. + +If the local tool and the AzDO template ever drift, the AzDO template is +the source of truth. diff --git a/.github/prompts/merge.prompt.md b/.github/prompts/merge.prompt.md new file mode 100644 index 000000000000..da4fd0d9b5cd --- /dev/null +++ b/.github/prompts/merge.prompt.md @@ -0,0 +1,41 @@ +# Merge Upstream Prompt + +Assist with merging the commits from upstream into this branch starting from the provided GitHub tag or commit. + +Provide the following when you invoke this prompt: +- Start ref (tag or commit) — REQUIRED (e.g., `upstream/V_9_8_P1` or a commit SHA) +- End ref (commit) — OPTIONAL (default: HEAD - most recent upstream commit) +- CI grouping mode — REQUIRED (`presence` or `success`): controls how `Get-CommitGroups` determines batch boundaries. + - `presence`: Batches end at any commit that has CI runs (passing or failing). Smaller batches, faster iteration, recommended for most merges. + - `success`: Batches end only at commits with successful CI. Larger batches, fewer checkpoints, useful when upstream CI is mostly green and you want to minimize batch count. +- Upstream remote — optional (default: `upstream`) +- Windows fork remote — optional (default: `upstream-pwsh`) +- Target branch — optional (default: current branch) + +Operating guidance: +- Use and follow merge-upstream.agent.md. Treat it as the primary operating guide. +- Rely on the provided for repository overview, setup, build, merge strategy, and testing. Do not re-fetch or re-search them; assume they are already attached in context. +- Use the two-phase merge workflow: (1) do ALL work on a scratch branch — incremental `git merge` at batch boundaries, conflict resolution, build fixes, and validation; (2) create the real merge branch from the same starting commit as the scratch branch, perform a single `git merge` of the final upstream target, and resolve any conflicts by copying the already-resolved files from the scratch branch (`git checkout scratch-branch -- `). No `git rerere`, no Save/Replay merge resolution tooling is needed. +- Build using the MCP tools: `mcp_openssh-server_Start_OpenSSHBuild` (Release; **architecture defaults to the host machine** — do not force `x64`, and pass `-AllowArchMismatch` only to intentionally cross-build). If the build fails, analyze with `mcp_openssh-server_Test_OpenSSHBuild`. +- For validation, use `mcp_openssh-server_Test_OpenSSHFunctionality`. +- Track remaining work with `mcp_openssh-server_Get_RemainingCommitCount` (commits from the current position to the end ref/HEAD). +- After resolving each batch's conflicts, run `mcp_openssh-server_Test_MergeConflictMarkers` (no leftover markers), hunt for silently auto-merged changes needing Windows work, run `mcp_openssh-server_Sync_VersionResource` if `version.h` changed, then delegate the resolved diff to the `conflict-review` agent before continuing. +- Read the `resolve-merge-conflict` skill for conflict-resolution procedure and PR-summary structure; after the PR lands, run the `merge-retrospective` skill. +- Apply Windows compatibility strategies as documented (**prefer upstream changes and adapt for Windows** — win32compat layer first, guard with `#ifdef WINDOWS` only when necessary; do not drag upstream's relocated logic back to its old location; update VS projects for build system changes). +- Summarize a plan, request approval between batches, and clearly list conflict resolutions and rationale. + +Expected outputs per batch: +- Planned commit range and rationale for the batch boundary +- Conflict resolutions (what, why, how), especially Windows-specific handling +- Build result summary and, on failure, parsed errors with applied fixes +- Next-step proposal and explicit ask to proceed + +Quick start examples: +- "Merge from tag `upstream/V_9_8_P1` into my current branch." +- "Merge from tag `upstream/V_9_8_P1` to commit `a1b2c3d` into my current branch." +- "Merge starting at commit `3a1b2c3`, upstream remote `upstream`, target current branch." +- "Merge from tag `upstream/V_10_0_P2` to `upstream/V_10_3_P1`." + +If the Start ref is not provided, ask for it before proceeding. +If the End ref is not provided, merging will continue to HEAD (most recent upstream commit). +If the CI grouping mode is not provided, ask the user to choose between `presence` (default recommendation) and `success` before invoking `Get-CommitGroups`. diff --git a/.github/run_test.sh b/.github/run_test.sh index 74ab2423c0d8..aac9ce57942e 100755 --- a/.github/run_test.sh +++ b/.github/run_test.sh @@ -21,18 +21,6 @@ if [ ! -z "$SUDO" ] && [ ! -z "$TEST_SSH_HOSTBASED_AUTH" ]; then done fi -output_failed_logs() { - for i in regress/failed*.log; do - if [ -f "$i" ]; then - echo ------------------------------------------------------------------------- - echo LOGFILE $i - cat $i - echo ------------------------------------------------------------------------- - fi - done -} -trap output_failed_logs 0 - env="" if [ ! -z "${SUDO}" ]; then env="${env} SUDO=${SUDO}" @@ -47,6 +35,17 @@ if [ ! -z "${env}" ]; then env="env${env}" fi +if [ "$1" = "putty-versions" ]; then + for ver in 0.71 0.72 0.73 0.74 0.75 0.76 0.77 0.78 0.79 0.80 \ + 0.81 0.82 0.83 snapshot; do + .github/install_putty.sh "${ver}" + ${env} make ${TEST_TARGET} \ + SKIP_LTESTS="${SKIP_LTESTS}" LTESTS="${LTESTS}" + done + + exit 0 +fi + if [ -z "${LTESTS}" ]; then ${env} make ${TEST_TARGET} SKIP_LTESTS="${SKIP_LTESTS}" else diff --git a/.github/setup_ci.sh b/.github/setup_ci.sh index f6c4a5c84fb5..c90969627022 100755 --- a/.github/setup_ci.sh +++ b/.github/setup_ci.sh @@ -1,8 +1,17 @@ #!/bin/sh +config="$1" +target="$2" + PACKAGES="" - . .github/configs $@ +echo Running as: +id + +echo Environment: +set + + . .github/configs ${config} host=`./config.guess` echo "config.guess: $host" @@ -10,9 +19,17 @@ case "$host" in *cygwin) PACKAGER=setup echo Setting CYGWIN system environment variable. - setx CYGWIN "binmode" + setx CYGWIN "winsymlinks:native" echo Removing extended ACLs so umask works as expected. + set -x setfacl -b . regress + icacls regress /c /t /q /Inheritance:d + icacls regress /c /t /q /Grant ${USERNAME}:F + icacls regress /c /t /q /Remove:g "Authenticated Users" \ + BUILTIN\\Administrators BUILTIN Everyone System Users + takeown /F regress + icacls regress + set +x PACKAGES="$PACKAGES,autoconf,automake,cygwin-devel,gcc-core" PACKAGES="$PACKAGES,make,openssl,libssl-devel,zlib-devel" ;; @@ -24,7 +41,7 @@ case "$host" in PACKAGER=apt esac -TARGETS=$@ +TARGETS=${config} INSTALL_FIDO_PPA="no" export DEBIAN_FRONTEND=noninteractive @@ -147,7 +164,7 @@ for TARGET in $TARGETS; do PACKAGES="${PACKAGES} cmake ninja-build" ;; putty-*) - INSTALL_PUTTY=$(echo "${TARGET}" | cut -f2 -d-) + INSTALL_PUTTY=0.83 PACKAGES="${PACKAGES} cmake" ;; valgrind*) @@ -184,7 +201,8 @@ while [ ! -z "$PACKAGES" ] && [ "$tries" -gt "0" ]; do fi ;; setup) - if /cygdrive/c/setup.exe -q -P `echo "$PACKAGES" | tr ' ' ,`; then + setup="/cygdrive/$(echo "${CYGWIN_SETUP}" | tr -d : | tr '\' '/')" + if "${setup}" -q -P `echo "$PACKAGES" | tr ' ' ,`; then PACKAGES="" fi ;; @@ -207,13 +225,8 @@ if [ "${INSTALL_HARDENED_MALLOC}" = "yes" ]; then fi if [ ! -z "${INSTALL_OPENSSL}" ]; then - (cd ${HOME} && - git clone https://github.com/openssl/openssl.git && - cd ${HOME}/openssl && - git checkout ${INSTALL_OPENSSL} && - ./config no-threads shared ${SSLCONFOPTS} \ - --prefix=/opt/openssl && - make && sudo make install_sw) + .github/install_libcrypto.sh \ + "${INSTALL_OPENSSL}" /opt/openssl "${SSLCONFOPTS}" fi if [ ! -z "${INSTALL_LIBRESSL}" ]; then @@ -240,7 +253,7 @@ if [ ! -z "${INSTALL_BORINGSSL}" ]; then cd ${HOME}/boringssl && mkdir build && cd build && cmake -GNinja -DCMAKE_POSITION_INDEPENDENT_CODE=ON .. && ninja && mkdir -p /opt/boringssl/lib && - cp ${HOME}/boringssl/build/crypto/libcrypto.a /opt/boringssl/lib && + cp ${HOME}/boringssl/build/libcrypto.a /opt/boringssl/lib && cp -r ${HOME}/boringssl/include /opt/boringssl) fi @@ -260,23 +273,23 @@ if [ ! -z "${INSTALL_ZLIB}" ]; then fi if [ ! -z "${INSTALL_PUTTY}" ]; then - ver="${INSTALL_PUTTY}" - case "${INSTALL_PUTTY}" in - snapshot) - tarball=putty.tar.gz - (cd /tmp && wget https://tartarus.org/~simon/putty-snapshots/${tarball}) - ;; - *) - tarball=putty-${ver}.tar.gz - (cd /tmp && wget https://the.earth.li/~sgtatham/putty/${ver}/${tarball}) + .github/install_putty.sh "${INSTALL_PUTTY}" +fi + +# If we're running on an ephemeral VM, set a random password and set +# up to run the password auth test. +if [ ! -z "${EPHEMERAL_VM}" ]; then + + # This is the github "target" as specified in the yml file. + # In particular, ubuntu-latest sets the password field to the locked + # value, so unless we reset it here most of the tests will fail. + case "${target}" in + ubuntu-*) + echo ${target} target: setting random password. + openssl rand -base64 9 >regress/password + pw=$(tr -d '\n' ..` and + `git show `. +- Build/test-fix commits made after the merge commit (these reveal what the + batch merges missed). +- PR review threads: what reviewers flagged, especially anything Windows- + specific or anything the agent got wrong. +- Any deferred TODOs recorded during the merge (e.g. un-ported ssh-agent + changes). + +### 2. Extract patterns + +Sort findings into buckets: + +- **New conflict-resolution pattern** — a file/area resolved in a non-obvious + way that will recur (e.g. a new split-daemon state-ordering rule, a new + `#ifdef WINDOWS` idiom, a new `win32compat` shim pattern). +- **Silent auto-merge follow-up** — an upstream change that merged cleanly but + needed manual Windows work (config.h.vs define, .vcxproj source add, ssh-agent + port, new `w32_*` shim). Note how it was detected so detection can be + documented/automated. +- **Regress-test adaptation** — a new upstream test that needed Windows tweaks + (e.g. `diff --strip-trailing-cr`). +- **Build/environment gotcha** — anything about SDK, arch, vcpkg, paths.targets, + warnings baseline. +- **Tooling gap** — a manual step that a tool/agent/skill could have caught or + automated. + +### 3. Update the tooling + +For each pattern, make the smallest change that will help next time: + +| Finding type | Where to update | +|---|---| +| New conflict pattern / Windows idiom | [merge-details.instructions.md](../../instructions/merge/merge-details.instructions.md) (add a numbered Pattern) and, if it's a resolver decision, the [resolve-merge-conflict skill](../resolve-merge-conflict/SKILL.md) | +| New silent-follow-up class | resolve-merge-conflict skill checklist + [conflict-review agent](../../agents/conflict-review.agent.md) checklist | +| Regress-test adaptation nuance | merge-details.instructions.md (Pattern 5 family) | +| Build/env gotcha | [build.instructions.md](../../instructions/build.instructions.md) or [testing.instructions.md](../../instructions/testing.instructions.md) | +| Recurring manual step | propose/extend a tool under [.github/tools/](../../tools/); register it in [.github/README.md](../../README.md) | +| Workflow/phase change | [merge-upstream agent](../../agents/merge-upstream.agent.md) and [merge-process-overview.instructions.md](../../instructions/merge/merge-process-overview.instructions.md) | + +Keep edits concrete: cite the real file/area from this merge as the example, the +way existing patterns in merge-details do (e.g. "Real example: the OpenSSH 10.3 +merge…"). Add the specific upstream version so the example is traceable. + +### 4. Record what was NOT changed + +If a finding was a one-off (not expected to recur), note it in the PR/retro +summary but do **not** bloat the instructions with it. The goal is durable, +recurring patterns. + +### 5. Produce a retro summary + +```markdown +## Merge Retrospective — OpenSSH (PR #) + +### New/updated patterns +- → documented in + +### Tooling changes +- updated/created: + +### Deferred / follow-up +- (owner: ) + +### One-offs (not documented) +- +``` + +## Guardrails + +- Only edit `.github/` tooling docs and scripts here — do **not** touch product + source in a retrospective. +- Validate any tool you add/modify runs (parse-check + a smoke invocation) + before finishing, following the conventions of the existing tools. +- Cross-link new assets in [.github/README.md](../../README.md). + +## Related Assets + +- [merge-upstream agent](../../agents/merge-upstream.agent.md) +- [conflict-review agent](../../agents/conflict-review.agent.md) +- [resolve-merge-conflict skill](../resolve-merge-conflict/SKILL.md) +- [merge-details.instructions.md](../../instructions/merge/merge-details.instructions.md) diff --git a/.github/skills/resolve-merge-conflict/SKILL.md b/.github/skills/resolve-merge-conflict/SKILL.md new file mode 100644 index 000000000000..dadf00863389 --- /dev/null +++ b/.github/skills/resolve-merge-conflict/SKILL.md @@ -0,0 +1,168 @@ +--- +name: resolve-merge-conflict +description: | + WORKFLOW SKILL — Resolve a merge conflict (or a batch of them) when merging + upstream OpenSSH into this Windows fork, applying the fork's Windows-compat + conventions, and summarize the resolutions for the pull request. USE FOR: + deciding how to resolve a specific conflicted file, choosing between + take-upstream / #ifdef WINDOWS / #ifndef WINDOWS, catching upstream changes + that merged cleanly but still need Windows follow-up, syncing version.h / + version.rc, and writing the per-file "what/why/how" resolution notes that go + into the PR description. DO NOT USE FOR: the overall multi-batch merge + orchestration (that's the merge-upstream agent) or vcpkg dependency bumps + (use the update-vcpkg-port skill). +--- + +# Resolve Merge Conflict Skill + +## Purpose + +Give a consistent, correct procedure for resolving upstream→fork merge +conflicts on Windows, and for turning those resolutions into clear PR +documentation. This is the detailed "how do I resolve *this* file" companion to +the `merge-upstream` agent's batch orchestration. + +## When to Use + +- You hit conflicts during a batch merge on the scratch branch and need to + decide how to resolve each file. +- You want to double-check a resolution follows fork conventions before staging. +- You are assembling the conflict-resolution section of the PR description. + +## Core Principle: Prefer Upstream, Adapt for Windows + +**Default to taking the upstream change and adding Windows adjustments around +it — do not keep the fork's old behavior just because it was there.** Upstream +owns the protocol/logic direction; the fork's job is to make that work on +Windows, ideally via the `win32compat` layer and, where unavoidable, via +`#ifdef WINDOWS` guards. + +Anti-pattern to avoid: forcing upstream's relocated logic back to where the fork +used to have it. Example: OpenSSH split pre-auth / KEX work between +`sshd-session` and `sshd-auth`. The correct resolution **follows upstream's new +placement** and adds Windows-specific handling there; it does **not** drag the +work back into `sshd-session` for Windows just to minimize change. Fighting +upstream's structure creates state-ordering bugs (banner/KEX/post-auth failures) +and recurring future conflicts. + +## Resolution Strategies (in order of preference) + +1. **Take upstream verbatim.** Security fixes, bug fixes, algorithm/API changes, + removed deprecated features (e.g. DSA). No Windows divergence needed. + +2. **Take upstream + `win32compat`.** Upstream calls a POSIX API; provide/extend + a `w32_*` shim in `contrib/win32/win32compat/` so the upstream call site + stays unchanged. Prefer this over inline `#ifdef`. + +3. **Take upstream + `#ifdef WINDOWS`.** Both platforms need different code at + the same site. Keep upstream's code in the `#else` branch verbatim: + ```c + #ifdef WINDOWS + /* Windows implementation */ + #else + /* upstream code, unchanged */ + #endif /* WINDOWS */ + ``` + +4. **Exclude on Windows with `#ifndef WINDOWS`.** Upstream code genuinely does + not apply to Windows (Unix-only feature). Wrap it, don't delete it: + ```c + #ifndef WINDOWS + setup_unix_only_feature(); + #endif /* !WINDOWS */ + ``` + +**Never** delete upstream additions — removal guarantees the conflict returns on +every future merge. + +## Step-by-Step + +1. **Enumerate the conflicts.** From the merge result's `ConflictedFiles`, or + `git status`. + +2. **For each file, get three-way context.** For high-complexity files use + `mcp_openssh-server_Get_ConflictContext` (FilePath + the batch endpoint + CommitHash). It anchors by content, not line numbers, so it handles the + fork's line drift. Otherwise read the file and use + `Invoke-Git Operation="Show"` / `Operation="Diff"`. + +3. **Pick a strategy** from the list above. Preserve upstream intent; add the + minimal Windows adaptation. + +4. **Resolve in place and stage:** edit the file, then + `Invoke-Git Operation="Add" Path=""`. + +5. **Verify no markers remain:** `mcp_openssh-server_Test_MergeConflictMarkers`. + Any `<<<<<<<` / `=======` / `>>>>>>>` / `|||||||` left is a hard stop. + +6. **Hunt for silent, clean-merged changes that still need Windows work.** Git + only flags textual conflicts. Upstream changes can merge cleanly yet require + follow-up. After each batch, scan the diff (`Invoke-Git Operation="Diff" + Range=".." NameOnly=true`) and check: + - **ssh-agent:** changes to `ssh-agent.c` / agent protocol are **not** auto- + reflected in the separate Windows agent under + `contrib/win32/win32compat/ssh-agent/`. Port relevant logic by hand or + record a TODO. + - **config.h.vs:** new feature `#define`s upstream added to `config.h` / + detected by autoconf must be added to + `contrib/win32/openssh/config.h.vs` if Windows should have them. + - **Build system:** new source files in `Makefile.in` must be added to the + right `.vcxproj` (and solution) with `\r\n` line endings; removed files + must be dropped from the projects. + - **New POSIX usage:** fork/exec/signal/pipe/socket-option calls need a + `w32_*` equivalent in `win32compat`. + +7. **Regress tests.** For any touched `regress/*.sh` that already contains + `if [ "$os" == "windows" ]` blocks, apply the same Windows adaptation to any + **new** upstream test case in that file (commonly wrapping `diff` with + `diff --strip-trailing-cr`). Git won't flag these because the existing + Windows blocks are untouched. + +8. **version.h / version.rc.** If `version.h` conflicted, keep the Windows + fields (`SSH_WINDOWS_VERSION`, `SSH_WINDOWS_BANNER`) and take upstream's + `SSH_PORTABLE` / OpenBSD version tag. Then sync the resource file: + `mcp_openssh-server_Sync_VersionResource` (numbers follow version.h; + descriptive text and the patch-in-ProductVersion-text convention are + preserved automatically). + +9. **Optional second opinion.** Hand the batch to the `conflict-review` agent + for an independent audit before completing the merge. + +## Summarizing Resolutions for the Pull Request + +Keep a running note **per conflicted file** as you resolve it; these become the +PR's "Windows-Specific Resolutions" section. For each file capture: + +- **What** the upstream change was (one line). +- **Why** a Windows adaptation was or wasn't needed. +- **How** it was resolved (which strategy: took-upstream / win32compat / + `#ifdef WINDOWS` / `#ifndef WINDOWS` / manual rewrite). + +Example lines: + +```markdown +### Windows-Specific Resolutions +- `serverloop.c`: Took upstream's channel-handling refactor; wrapped the + Windows event-based wait in `#ifdef WINDOWS`, upstream select() path kept in `#else`. +- `sshd-auth.c`: Followed upstream's move of the banner exchange into sshd-auth; + added Windows post-auth message-ordering handling here (not in sshd-session). +- `auth2.c`: Accepted upstream security fix verbatim; no Windows change needed. +- `regress/cfgparse.sh`: New upstream MaxStartups case wrapped with + `diff --strip-trailing-cr` to match existing Windows blocks. +- `version.h` / `version.rc`: Kept Windows banner fields; synced FILEVERSION / + ProductVersion to the new upstream version. +``` + +Also note in the PR: +- **Silent follow-ups performed** (config.h.vs additions, .vcxproj updates, + win32compat shims, ssh-agent ports). +- **Deferred TODOs** for anything flagged but not ported (e.g. complex ssh-agent + changes needing Windows-team review). + +## Related Assets + +- [merge-upstream agent](../../agents/merge-upstream.agent.md) — batch orchestration. +- [conflict-review agent](../../agents/conflict-review.agent.md) — independent audit of resolutions. +- [merge-details.instructions.md](../../instructions/merge/merge-details.instructions.md) — full pattern library. +- Tools: `Get-ConflictContext`, `Test-MergeConflictMarkers`, `Sync-VersionResource`, + `Get-RemainingCommitCount`. diff --git a/.github/skills/update-vcpkg-port/SKILL.md b/.github/skills/update-vcpkg-port/SKILL.md new file mode 100644 index 000000000000..683700a0c69b --- /dev/null +++ b/.github/skills/update-vcpkg-port/SKILL.md @@ -0,0 +1,200 @@ +--- +name: update-vcpkg-port +description: | + WORKFLOW SKILL — Bump a vendored vcpkg dependency (libressl, libfido2, + libcbor, zlib) in this OpenSSH-Portable Windows fork to a new upstream + version. Orchestrates Update-VcpkgPort.ps1 (manifest, overlay manifest, + portfile SHA512, LibreSSL resource patch) and handles patch-rejection + decisions, validation via Install-VcpkgDependencies.ps1, build + validation, and commit-message drafting. USE FOR: routine version bumps, + responding to security fixes in vendored deps, satisfying a new minimum + required by an upstream OpenSSH merge. DO NOT USE FOR: adding a brand-new + dependency (touch vcpkg.json + add overlay port manually first), or for + general first-time vcpkg setup (use Install-VcpkgDependencies.ps1 + directly). +--- + +# Update vcpkg Port Skill + +## Purpose + +Bump one vendored vcpkg dependency in this repository to a new upstream +version, with all the side effects (overlay portfile SHA512, LibreSSL +resource patch, optional baseline) handled correctly, and validate the +result before handing the user a ready-to-paste commit message. + +## When to Use + +- An upstream OpenSSH merge requires a newer LibreSSL/libfido2/libcbor/zlib. +- A security fix has been released for a vendored dependency. +- Routine periodic refresh of vendored libraries. + +## When NOT to Use + +- Adding a brand-new dependency. The skill assumes the port already has an + entry in [vcpkg.json](../../../contrib/win32/openssh/vcpkg.json) + `overrides[]` (and an overlay folder if it's a custom port). For new + deps, edit those files manually first. +- First-time vcpkg setup. Use + [Install-VcpkgDependencies.ps1](../../tools/Install-VcpkgDependencies.ps1) + directly. +- Bulk multi-port bumps. Run the skill once per port so each diff is + reviewable. + +## Workflow + +### 1. Confirm scope with the user + +Ask the user: +- Which port? (`libressl`, `libfido2`, `libcbor`, `zlib`) +- What target version? +- Do they also want to bump the vcpkg `builtin-baseline`? (Usually no + unless the new port version requires a registry baseline newer than + what's pinned.) + +Also confirm the working tree is clean: + +```pwsh +# MCP: mcp_openssh-server_Invoke_Git Operation="Status" +``` + +If not clean, ask the user to commit/stash before continuing — the diff +this skill produces should stand alone for review. + +### 2. Dry run + +Always start with `-DryRun` so the user can review planned changes: + +```pwsh +.\.github\tools\Update-VcpkgPort.ps1 -Port -Version -DryRun +``` + +Surface the returned `FilesChanged`, `Sha512`, and `LibresslPatchUpdated` +fields to the user. Confirm before proceeding to the real run. + +### 3. Real run + +```pwsh +.\.github\tools\Update-VcpkgPort.ps1 -Port -Version +``` + +If the user opted into a baseline bump, add `-Baseline `. + +### 4. Validate the install + +Run a clean install for the default triplet: + +```pwsh +.\.github\tools\Install-VcpkgDependencies.ps1 -Clean +``` + +Three possible outcomes: + +#### 4a. Install succeeds +Proceed to step 5. + +#### 4b. LibreSSL version cross-check fails +The install tool reports: + +> LibreSSL version mismatch: vcpkg.json has X.Y.Z, patch file has A.B.C.D + +This means `Update-VcpkgPort.ps1` either didn't update +`add-version-file.patch` (e.g., for non-libressl ports — should not happen) +or the `Version` argument wasn't in `..` form. Fix +the patch by hand, then re-run install. + +#### 4c. vcpkg reports a rejected patch hunk +This is the common case for a non-trivial bump. vcpkg's output looks +like: + +``` +Applying patch .patch +error: patch failed: : +error: : patch does not apply +``` + +**Decision tree**: + +1. **Is the patched code still present in the new upstream source?** + - If yes → the patch needs its line offsets / context regenerated. + Extract the new source manually, apply the patch with + `git apply --3way`, resolve conflicts, regenerate the patch with + `git diff > .patch`. Then re-run install. + - If no → has upstream merged equivalent functionality? If yes, + **drop the patch**: remove it from the `PATCHES` list in + [portfile.cmake](../../../contrib/win32/openssh/vcpkg_overlay_ports) + and delete the patch file. Document the removal in the commit + message. If no, the bump may be too disruptive — ask the user + whether to abandon or invest in a port-side fix. +2. **For LibreSSL `add-version-file.patch` specifically**: if the patch's + resource file location moved upstream, the `diff --git` header and + `+++ b/` lines in the patch will need updating. The + `Update-VcpkgPort.ps1` script only rewrites version literals, not + paths. + +Stop and request user approval before dropping any patch — patches in +this repo carry security or signing-compliance value. + +### 5. Build validation + +```pwsh +# MCP: mcp_openssh-server_Start_OpenSSHBuild Configuration="Release" Architecture="x64" +``` + +If the build fails with linker errors referencing the bumped library, the +overlay port may need additional CMake option changes (e.g., new +`-DXYZ=OFF`). Inspect the failed compile/link command and update +`portfile.cmake` accordingly. + +### 6. Multi-arch parity (optional, recommended for major bumps) + +```pwsh +.\.github\tools\Install-VcpkgDependencies.ps1 -Architecture x64,x86,ARM,ARM64 -Clean +``` + +ARM64 in particular has carried its own LibreSSL patches historically; +verify all four triplets install before declaring success. + +### 7. Draft the commit message + +Produce a ready-to-paste message and present it to the user. Template: + +``` +Update to + +- Bumped override in contrib/win32/openssh/vcpkg.json from + to +- Refreshed SHA512 in + contrib/win32/openssh/vcpkg_overlay_ports//portfile.cmake +- [if libressl] Updated FileVersion/ProductVersion in + add-version-file.patch to ...0 +- [if patches were regenerated] Regenerated .patch against new + upstream source +- [if patches were dropped] Removed .patch — upstream + now provides equivalent functionality +- [if baseline bumped] Bumped vcpkg builtin-baseline to + +Validated: +- vcpkg install succeeds for +- Win32-OpenSSH build succeeds (Release, x64) +``` + +## Tools Used + +- [Update-VcpkgPort.ps1](../../tools/Update-VcpkgPort.ps1) — mechanical + edits. +- [Install-VcpkgDependencies.ps1](../../tools/Install-VcpkgDependencies.ps1) + — install + cross-check validation. +- [Start-OpenSSHBuild.ps1](../../tools/Start-OpenSSHBuild.ps1) — build + validation. +- `mcp_openssh-server_Invoke_Git` — status checks. + +## Reference + +- [vcpkg.instructions.md](../../instructions/vcpkg.instructions.md) — + layout, custom triplets, troubleshooting. +- Overlay ports: + [libressl](../../../contrib/win32/openssh/vcpkg_overlay_ports/libressl/), + [libfido2](../../../contrib/win32/openssh/vcpkg_overlay_ports/libfido2/). +- CI source of truth: + [.azdo/templates/install-vcpkg-dependencies.yml](../../../.azdo/templates/install-vcpkg-dependencies.yml). diff --git a/.github/tools/Get-CommitGroups.ps1 b/.github/tools/Get-CommitGroups.ps1 new file mode 100644 index 000000000000..ffa4523da808 --- /dev/null +++ b/.github/tools/Get-CommitGroups.ps1 @@ -0,0 +1,509 @@ +<# +.SYNOPSIS + Groups upstream OpenSSH commits into batches based on CI success status or CI presence. + +.DESCRIPTION + This script fetches commits from the openssh/openssh-portable repository on GitHub + and groups them into batches (chunks) based on CI test results. By default, each chunk + ends with a commit that has all CI tests passing (success or skipped). Alternatively, + when using -GroupByCIPresence, each chunk ends with any commit that has CI runs, + regardless of success or failure. + + The script is designed to help with incremental merging of upstream commits by + identifying safe stopping points where all tests pass (or where CI exists). + + When the total number of commits exceeds 250 (GitHub API limit), the script + automatically adjusts to fetch the first 250 commits in chronological order. + +.PARAMETER GitHubTag + The GitHub tag to start from (e.g., "V_10_0_P2"). Cannot be used with -StartCommit. + The script will find commits after this tag up to HEAD. + +.PARAMETER StartCommit + The commit SHA to start from (e.g., "6fb728df50c1afd338cb0223a84ce24579577eff"). + Cannot be used with -GitHubTag. The script will find commits after this commit up to EndCommit (or HEAD if not specified). + This is typically used when continuing from a previously merged commit. + +.PARAMETER EndCommit + The commit SHA to end at (e.g., "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0"). + If not specified, defaults to HEAD (most recent upstream commit). + This allows merging up to a specific commit rather than always merging to HEAD. + +.PARAMETER FirstChunkOnly + When specified, the script stops after finding the first chunk with a successful CI commit + (or first chunk with any CI when using -GroupByCIPresence). + This is useful for incremental processing where you want to merge one batch at a time. + +.PARAMETER GroupByCIPresence + When specified, groups commits by CI presence (any CI run exists) rather than CI success. + Each chunk ends with a commit that has any CI runs, regardless of pass/fail status. + Default behavior (without this flag) groups by CI success only. + +.OUTPUTS + Returns an array of chunk objects, each containing: + - ChunkNumber: Sequential number of the chunk + - StartIndex/EndIndex: Array indices for the chunk range + - StartCommit/EndCommit: Short SHA (7 chars) of first and last commits + - StartCommitFull/EndCommitFull: Full SHA of first and last commits + - CommitCount: Number of commits in the chunk + - StartMessage/EndMessage: Commit messages for first and last commits + +.EXAMPLE + .\Get-CommitGroups.ps1 -GitHubTag "V_10_0_P2" -FirstChunkOnly + + Finds the first batch of commits after the V_10_0_P2 tag that ends with passing CI. + +.EXAMPLE + .\Get-CommitGroups.ps1 -StartCommit "6fb728df50c1afd338cb0223a84ce24579577eff" -FirstChunkOnly + + Finds the first batch of commits after the specified commit that ends with passing CI. + Useful for continuing from where a previous merge left off. + +.EXAMPLE + .\Get-CommitGroups.ps1 -StartCommit "6fb728df50c1afd338cb0223a84ce24579577eff" + + Finds all batches of commits after the specified commit, grouping by CI success. + Each batch ends with a commit that has passing CI tests. + +.EXAMPLE + .\Get-CommitGroups.ps1 -GitHubTag "V_10_0_P2" -GroupByCIPresence -FirstChunkOnly + + Finds the first batch of commits after the V_10_0_P2 tag that ends with any commit + that has CI runs (regardless of success or failure). + +.EXAMPLE + .\Get-CommitGroups.ps1 -StartCommit "6fb728df50c1afd338cb0223a84ce24579577eff" -EndCommit "a1b2c3d4e5f6" -FirstChunkOnly + + Finds the first batch of commits between the specified start and end commits. + Useful for merging a specific range rather than all commits up to HEAD. + +.NOTES + - Requires internet access to query GitHub API + - Set GITHUB_TOKEN environment variable for authenticated API access (5,000 requests/hour) + - Without token: rate limited with 200ms delay between commits (60 requests/hour) + - Maximum 250 commits per API call (automatically handled) + - CI status is checked via GitHub check-runs API with pagination support + - Default mode: Commits with "success" or "skipped" CI conclusions are considered passing + - GroupByCIPresence mode: Any commit with CI runs (regardless of result) ends a chunk + +.LINK + https://github.com/openssh/openssh-portable +#> + +param( + [Parameter(Mandatory=$false)] + [string]$GitHubTag, + + [Parameter(Mandatory=$false)] + [string]$StartCommit, + + [Parameter(Mandatory=$false)] + [string]$EndCommit, + + [Parameter(Mandatory=$false)] + [switch]$FirstChunkOnly, + + [Parameter(Mandatory=$false)] + [switch]$GroupByCIPresence +) + +# Validate parameters +if (-not $GitHubTag -and -not $StartCommit) { + Write-Error "Either -GitHubTag or -StartCommit must be provided" + exit 1 +} + +if ($GitHubTag -and $StartCommit) { + Write-Error "Cannot specify both -GitHubTag and -StartCommit. Please provide only one." + exit 1 +} + +# Configuration +$repo = "openssh/openssh-portable" +$apiBase = "https://api.github.com/repos/$repo" + +# Check for GitHub token for authenticated API access +$script:githubToken = $env:GITHUB_TOKEN +if ($script:githubToken) { + Write-Host "Using authenticated GitHub API (higher rate limits)" -ForegroundColor Green +} else { + Write-Host "Using unauthenticated GitHub API (rate limited - consider setting GITHUB_TOKEN)" -ForegroundColor Yellow +} + +if ($GitHubTag) { + Write-Host "Fetching commits starting from tag: $GitHubTag" -ForegroundColor Cyan +} else { + Write-Host "Fetching commits starting from commit: $StartCommit" -ForegroundColor Cyan +} + +# Function to get GitHub API headers with optional authentication +function Get-GitHubHeaders { + $headers = @{ + "User-Agent" = "PowerShell" + "Accept" = "application/vnd.github+json" + } + + if ($script:githubToken) { + $headers["Authorization"] = "Bearer $script:githubToken" + } + + return $headers +} + +# Determine whether a caught error represents GitHub API rate-limit exhaustion. +# Handles both Windows PowerShell 5.1 (WebException) and PowerShell 7+ (HttpResponseException). +function Test-IsRateLimitError { + param($ErrorRecord) + + $statusCode = $null + try { $statusCode = [int]$ErrorRecord.Exception.Response.StatusCode } catch {} + + $remaining = $null + try { + $respHeaders = $ErrorRecord.Exception.Response.Headers + if ($respHeaders) { + $val = $respHeaders['X-RateLimit-Remaining'] + if ($val -is [System.Array]) { $val = $val[0] } + if ($null -ne $val) { $remaining = "$val" } + } + } catch {} + + $text = "$($ErrorRecord.Exception.Message) $($ErrorRecord.ErrorDetails.Message)" + + if ($statusCode -eq 429) { return $true } + if ($statusCode -eq 403 -and ($remaining -eq '0' -or $text -match 'rate limit')) { return $true } + if ($text -match 'API rate limit exceeded' -or $text -match 'secondary rate limit') { return $true } + return $false +} + +# Wrapper around Invoke-RestMethod that converts a GitHub rate-limit response into a +# terminating, clearly-marked error. This prevents the script from silently treating a +# rate-limited (unknown) commit as a valid CI boundary and emitting a bogus batch. +function Invoke-GitHubApi { + param([Parameter(Mandatory=$true)][string]$Uri) + + try { + return Invoke-RestMethod -Uri $Uri -Headers (Get-GitHubHeaders) -ErrorAction Stop + } catch { + if (Test-IsRateLimitError $_) { + throw "GITHUB_RATE_LIMIT_EXCEEDED: GitHub API rate limit exhausted while requesting $Uri. $($_.Exception.Message)" + } + throw + } +} + +# Get the starting commit SHA +try { + if ($GitHubTag) { + $tagInfo = Invoke-GitHubApi -Uri "$apiBase/git/refs/tags/$GitHubTag" + $startCommitSha = $tagInfo.object.sha + + # If it's an annotated tag, we need to get the actual commit + if ($tagInfo.object.type -eq "tag") { + $tagObject = Invoke-GitHubApi -Uri $tagInfo.object.url + $startCommitSha = $tagObject.object.sha + } + + Write-Host "Tag $GitHubTag points to commit: $startCommitSha" -ForegroundColor Green + } else { + # Validate the commit exists + $commitInfo = Invoke-GitHubApi -Uri "$apiBase/commits/$StartCommit" + $startCommitSha = $commitInfo.sha + Write-Host "Starting from commit: $startCommitSha" -ForegroundColor Green + } +} catch { + if ("$($_)" -match 'GITHUB_RATE_LIMIT_EXCEEDED') { + Write-Error "$_`nAborting: cannot reliably determine commit batches without GitHub API access. Set GITHUB_TOKEN (5,000 req/hr) or wait for the rate limit to reset, then re-run." + exit 1 + } + Write-Error "Failed to retrieve starting commit information: $_" + exit 1 +} + +# Function to check CI status for a commit +function Get-CommitCIStatus { + param( + [string]$sha, + [bool]$checkPresenceOnly = $false + ) + + try { + $allCheckRuns = @() + $page = 1 + $perPage = 100 + + # Fetch all pages of check runs + do { + $checkRunsUrl = "$apiBase/commits/$sha/check-runs?per_page=$perPage&page=$page" + $response = Invoke-GitHubApi -Uri $checkRunsUrl + + $allCheckRuns += $response.check_runs + $page++ + + } while ($response.check_runs.Count -eq $perPage) + + # Check if there are any check runs + if ($allCheckRuns.Count -eq 0) { + return "no_ci" + } + + # If only checking for presence, return has_ci + if ($checkPresenceOnly) { + return "has_ci" + } + + # Check if all check runs are successful or skipped + $allSuccessful = $true + foreach ($checkRun in $allCheckRuns) { + # Accept "success" or "skipped" as valid conclusions + if ($checkRun.conclusion -ne "success" -and $checkRun.conclusion -ne "skipped") { + $allSuccessful = $false + break + } + } + + if ($allSuccessful) { + return "success" + } else { + return "failure" + } + } catch { + # Rate-limit exhaustion must NOT be swallowed as "unknown" - re-throw so the + # whole script fails rather than fabricating a batch from incomplete CI data. + if ("$($_)" -match 'GITHUB_RATE_LIMIT_EXCEEDED') { throw } + Write-Warning "Could not get CI status for commit $sha : $_" + return "unknown" + } +} + +# Function to get commit details +function Get-CommitDetails { + param([string]$sha) + + try { + $commitUrl = "$apiBase/commits/$sha" + $commit = Invoke-GitHubApi -Uri $commitUrl + return @{ + Sha = $commit.sha.Substring(0, 7) + FullSha = $commit.sha + Message = $commit.commit.message.Split("`n")[0] + Author = $commit.commit.author.name + Date = $commit.commit.author.date + } + } catch { + # Re-throw rate-limit errors so the script aborts instead of dropping commits. + if ("$($_)" -match 'GITHUB_RATE_LIMIT_EXCEEDED') { throw } + Write-Warning "Could not get commit details for $sha" + return $null + } +} + +# Fetch commits starting from the tag using compare API +Write-Host "`nFetching commits from the repository..." -ForegroundColor Cyan + +try { + # Get commits after the starting commit (excluding the start commit itself) + $allCommits = @() + $page = 1 + $perPage = 250 # Compare API returns max 250 commits per page + + $endRef = if ($EndCommit) { $EndCommit } else { "HEAD" } + Write-Host "Fetching commits from $startCommitSha...$endRef" -ForegroundColor Gray + + # The Compare API doesn't support pagination, so we need to use commits API instead + # to get commits in the correct range with proper pagination + $compareUrl = "$apiBase/compare/${startCommitSha}...$endRef" + $comparison = Invoke-GitHubApi -Uri $compareUrl + + # The Compare API returns commits - need to verify order + # According to GitHub API docs, commits are in chronological order (oldest first) + $allCommits = @($comparison.commits) + + # If we hit the 250 commit limit, we need to get the actual first 250 commits + # by iteratively narrowing the range until we get 250 or fewer commits + while ($comparison.total_commits -gt 250) { + Write-Host "Warning: Total commits ($($comparison.total_commits)) exceeds API limit (250)." -ForegroundColor Yellow + Write-Host "Fetching first 250 commits by narrowing the range..." -ForegroundColor Cyan + + # Get the oldest commit SHA from the current batch (first in chronological order) + # Since the batch is limited to 250, this is approximately the 250th commit from start + $oldestCommitSha = $allCommits[0].sha + + # Now compare from start to this oldest commit to narrow down the range + $limitedCompareUrl = "$apiBase/compare/${startCommitSha}...${oldestCommitSha}" + Write-Host "Comparing $startCommitSha...$oldestCommitSha" -ForegroundColor Gray + $comparison = Invoke-GitHubApi -Uri $limitedCompareUrl + + $allCommits = @($comparison.commits) + Write-Host "Narrowed to $($comparison.total_commits) total commits ($($allCommits.Count) returned)" -ForegroundColor Green + } + + $startRef = if ($GitHubTag) { "tag $GitHubTag" } else { "commit $StartCommit" } + Write-Host "Found $($allCommits.Count) commits from $startRef" -ForegroundColor Green +} catch { + if ("$($_)" -match 'GITHUB_RATE_LIMIT_EXCEEDED') { + Write-Error "$_`nAborting: cannot reliably determine commit batches without GitHub API access. Set GITHUB_TOKEN (5,000 req/hr) or wait for the rate limit to reset, then re-run." + exit 1 + } + Write-Error "Failed to fetch commits: $_" + exit 1 +} + +# Process commits and check CI status +$statusCheckMessage = if ($GroupByCIPresence) { "Checking CI presence for each commit..." } else { "Checking CI status for each commit..." } +Write-Host "`n$statusCheckMessage" -ForegroundColor Cyan + +$commitsWithStatus = @() +$chunks = @() +$commitCount = 0 +$chunkStart = 0 + +# Proactive rate-limit budget check. CI status + commit details cost ~3 core API calls per +# commit. Failing now with a clear message is far better than exhausting the limit mid-scan +# and emitting an incomplete batch that looks valid. The /rate_limit endpoint itself is free. +try { + $rl = Invoke-RestMethod -Uri "https://api.github.com/rate_limit" -Headers (Get-GitHubHeaders) -ErrorAction Stop + $coreRemaining = [int]$rl.resources.core.remaining + $coreResetAt = [DateTimeOffset]::FromUnixTimeSeconds([long]$rl.resources.core.reset).LocalDateTime + $estimatedNeeded = [Math]::Max(1, $allCommits.Count) * 3 + Write-Host "GitHub API budget: $coreRemaining core requests remaining (need ~$estimatedNeeded for $($allCommits.Count) commits; resets $coreResetAt)" -ForegroundColor Gray + if ($coreRemaining -lt $estimatedNeeded) { + Write-Error ("GITHUB_RATE_LIMIT_EXCEEDED: Insufficient GitHub API budget to evaluate CI for all $($allCommits.Count) commits. " + + "Have $coreRemaining core requests, need ~$estimatedNeeded. Rate limit resets at $coreResetAt. " + + "Set GITHUB_TOKEN for a higher limit (5,000/hr) or wait for the reset. " + + "Aborting so an incomplete CI scan cannot be mistaken for a valid batch.") + exit 1 + } +} catch { + if ("$($_)" -match 'GITHUB_RATE_LIMIT_EXCEEDED') { + Write-Error "$_" + exit 1 + } + Write-Warning "Could not pre-check GitHub rate limit (continuing; the per-commit scan will still abort on exhaustion): $_" +} + +try { +foreach ($commit in $allCommits) { + $commitCount++ + Write-Host "Processing commit $commitCount of $($allCommits.Count): $($commit.sha.Substring(0,7))" -ForegroundColor Gray + + $status = Get-CommitCIStatus -sha $commit.sha -checkPresenceOnly $GroupByCIPresence + $details = Get-CommitDetails -sha $commit.sha + + if ($details) { + $commitsWithStatus += [PSCustomObject]@{ + Index = $commitCount - 1 + Sha = $details.Sha + FullSha = $details.FullSha + Message = $details.Message + Author = $details.Author + Date = $details.Date + CIStatus = $status + } + + # Check if this commit completes a chunk (based on grouping mode) + $targetStatus = if ($GroupByCIPresence) { "has_ci" } else { "success" } + if ($status -eq $targetStatus) { + $chunkEnd = $commitsWithStatus.Count - 1 + + $chunks += [PSCustomObject]@{ + ChunkNumber = $chunks.Count + 1 + StartIndex = $chunkStart + EndIndex = $chunkEnd + StartCommit = $commitsWithStatus[$chunkStart].Sha + EndCommit = $commitsWithStatus[$chunkEnd].Sha + StartCommitFull = $commitsWithStatus[$chunkStart].FullSha + EndCommitFull = $commitsWithStatus[$chunkEnd].FullSha + CommitCount = $chunkEnd - $chunkStart + 1 + StartMessage = $commitsWithStatus[$chunkStart].Message + EndMessage = $commitsWithStatus[$chunkEnd].Message + } + + $chunkStart = $commitsWithStatus.Count + + # If FirstChunkOnly is specified, stop after finding the first chunk + if ($FirstChunkOnly) { + $chunkFoundMessage = if ($GroupByCIPresence) { "Found first chunk with CI, stopping..." } else { "Found first successful chunk, stopping..." } + Write-Host $chunkFoundMessage -ForegroundColor Green + break + } + } + } + + # Rate limiting - only needed for unauthenticated requests + if (-not $script:githubToken) { + Start-Sleep -Milliseconds 200 + } +} +} catch { + # A rate-limit exhaustion bubbling up from Get-CommitCIStatus / Get-CommitDetails means the + # CI scan is incomplete. We must fail rather than return a batch derived from partial data. + if ("$($_)" -match 'GITHUB_RATE_LIMIT_EXCEEDED') { + Write-Error ("GITHUB_RATE_LIMIT_EXCEEDED: GitHub API rate limit was exhausted after processing " + + "$commitCount of $($allCommits.Count) commits. The CI scan is incomplete, so NO batch can be " + + "reliably determined. Set GITHUB_TOKEN (5,000/hr) or wait for the rate limit to reset, then re-run. Aborting.") + exit 1 + } + throw +} + +# Handle remaining commits that don't end with success (only if not FirstChunkOnly or no chunk found) +if (-not $FirstChunkOnly -and $chunkStart -lt $commitsWithStatus.Count) { + $chunkEnd = $commitsWithStatus.Count - 1 + $chunks += [PSCustomObject]@{ + ChunkNumber = $chunks.Count + 1 + StartIndex = $chunkStart + EndIndex = $chunkEnd + StartCommit = $commitsWithStatus[$chunkStart].Sha + EndCommit = $commitsWithStatus[$chunkEnd].Sha + StartCommitFull = $commitsWithStatus[$chunkStart].FullSha + EndCommitFull = $commitsWithStatus[$chunkEnd].FullSha + CommitCount = $chunkEnd - $chunkStart + 1 + StartMessage = $commitsWithStatus[$chunkStart].Message + EndMessage = $commitsWithStatus[$chunkEnd].Message + } +} + +Write-Host "`nGrouping complete." -ForegroundColor Cyan + +# Display results +$groupingMode = if ($GroupByCIPresence) { "CI Presence" } else { "CI Success" } +Write-Host "\n========================================" -ForegroundColor Cyan +Write-Host "COMMIT CHUNKS (Grouped by $groupingMode)" -ForegroundColor Cyan +Write-Host "========================================`n" -ForegroundColor Cyan + +foreach ($chunk in $chunks) { + Write-Host "Chunk $($chunk.ChunkNumber): $($chunk.CommitCount) commits" -ForegroundColor Yellow + Write-Host " Start: $($chunk.StartCommit) - $($chunk.StartMessage)" -ForegroundColor White + Write-Host " End: $($chunk.EndCommit) - $($chunk.EndMessage)" -ForegroundColor Green + Write-Host " Commit Pair: ($($chunk.StartCommitFull), $($chunk.EndCommitFull))" -ForegroundColor Magenta + Write-Host "" +} + +Write-Host "`nTotal Chunks: $($chunks.Count)" -ForegroundColor Cyan +Write-Host "Total Commits: $($commitsWithStatus.Count)" -ForegroundColor Cyan + +# Output detailed commit list +Write-Host "`n========================================" -ForegroundColor Cyan +Write-Host "DETAILED COMMIT LIST" -ForegroundColor Cyan +Write-Host "========================================`n" -ForegroundColor Cyan + +# Only show commits that are part of returned chunks +$maxIndex = if ($chunks.Count -gt 0) { $chunks[-1].EndIndex } else { -1 } +foreach ($commit in $commitsWithStatus) { + if ($commit.Index -le $maxIndex) { + $statusColor = switch ($commit.CIStatus) { + "success" { "Green" } + "has_ci" { "Green" } + "failure" { "Red" } + "no_ci" { "Yellow" } + "pending" { "Yellow" } + default { "Gray" } + } + + Write-Host "$($commit.Sha) | $($commit.CIStatus.PadRight(10)) | $($commit.Message.Substring(0, [Math]::Min(60, $commit.Message.Length)))" -ForegroundColor $statusColor + } +} + +# Return the chunks for potential further processing +return $chunks diff --git a/.github/tools/Get-ConflictContext.ps1 b/.github/tools/Get-ConflictContext.ps1 new file mode 100644 index 000000000000..46bab7be45b1 --- /dev/null +++ b/.github/tools/Get-ConflictContext.ps1 @@ -0,0 +1,490 @@ +<# +.SYNOPSIS + Retrieves three-way context for a conflicted file to aid complex conflict resolution. + +.DESCRIPTION + MCP-compatible tool that fetches three versions of a file involved in a merge or + cherry-pick conflict — the upstream file before the commit, the upstream file after + the commit, and our fork's version (via HEAD) — and extracts focused, line-numbered + excerpts centered on each changed hunk. + + For each hunk in the upstream diff, the tool locates the corresponding region in our + fork using two-tier content matching: + Tier 1: Sliding-window overlap score against unchanged context lines from the diff. + Tier 2: Fallback to searching for the function name from the @@ hunk header. + + This handles line-number divergence between upstream and our fork by finding the + region by content rather than by position. + + Use this tool ONLY when conflict complexity assessment returns HIGH_COMPLEXITY. + +.PARAMETER FilePath + Path to the conflicted file, relative to the repository root. + +.PARAMETER CommitHash + The upstream commit SHA that caused the conflict. During the scratch-branch merge + workflow, this is typically the batch endpoint commit passed to git merge. + +.PARAMETER ContextLines + Number of lines of context above and below each hunk match to include in excerpts. + Default: 40 + +.PARAMETER MaxTotalLines + Maximum total lines returned across all three versions combined (across all hunks). + Budget per version per hunk = max(10, floor(MaxTotalLines / 3 / hunkCount)). + The minimum floor of 10 lines per version per hunk is always enforced. + If the floor overrides the calculated budget, a warning is included in Message. + Default: 150 (approximately 50 lines per version) + +.OUTPUTS + Hashtable with: + Success [bool] Whether the operation completed without errors + Message [string] Human-readable summary (includes warnings about budget) + CommitMessage [string] The commit message of CommitHash + UpstreamDiff [string] Raw unified diff for the file from this commit + HunkCount [int] Number of hunks found in the upstream diff + IsBinary [bool] True if the file is binary (no excerpts returned) + Hunks [array] One entry per hunk: + HunkIndex [int] 1-based hunk number + HunkHeader [string] The @@ header line + FunctionName [string] Function name extracted from @@ header (may be empty) + UpstreamBefore [object] { Lines, StartLine, EndLine, Note } + UpstreamAfter [object] { Lines, StartLine, EndLine, Note } + OurFork [object] { Lines, StartLine, EndLine, Note } + + Each excerpt object: + Lines [string[]] The extracted lines (null if version unavailable) + StartLine [int] 1-based line number of first line in the excerpt + EndLine [int] 1-based line number of last line in the excerpt + Note [string] Explanation if unavailable or how region was located + +.EXAMPLE + # Get conflict context for a high-complexity conflict + # MCP Tool: mcp_openssh-server_Get_ConflictContext + # FilePath="auth.c", CommitHash="abc1234" + +.EXAMPLE + # Get context with increased budget for a file with many hunks + # MCP Tool: mcp_openssh-server_Get_ConflictContext + # FilePath="channels.c", CommitHash="abc1234", MaxTotalLines=300 +#> + +param( + [Parameter(Mandatory)] + [string]$FilePath, + + [Parameter(Mandatory)] + [string]$CommitHash, + + [int]$ContextLines = 40, + + [int]$MaxTotalLines = 150 +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +# ── Git process helper (same pattern as Invoke-Git.ps1) ────────────────────── + +function Invoke-GitCommand { + param([string[]]$Arguments) + + $processInfo = [System.Diagnostics.ProcessStartInfo]::new() + $processInfo.FileName = 'git' + $processInfo.Arguments = ($Arguments | ForEach-Object { + if ($_ -match '\s') { "`"$_`"" } else { $_ } + }) -join ' ' + $processInfo.UseShellExecute = $false + $processInfo.CreateNoWindow = $true + $processInfo.RedirectStandardInput = $true + $processInfo.RedirectStandardOutput = $true + $processInfo.RedirectStandardError = $true + + $process = [System.Diagnostics.Process]::new() + $process.StartInfo = $processInfo + $process.Start() | Out-Null + $process.StandardInput.Close() + + $stdoutTask = $process.StandardOutput.ReadToEndAsync() + $stderrTask = $process.StandardError.ReadToEndAsync() + + $completed = $process.WaitForExit(30000) + + if (-not $completed) { + $process.Kill() + return @{ + ExitCode = -1 + Success = $false + Output = '' + Error = "git $($Arguments -join ' ') timed out after 30 seconds" + } + } + + return @{ + ExitCode = $process.ExitCode + Success = ($process.ExitCode -eq 0) + Output = $stdoutTask.GetAwaiter().GetResult() + Error = $stderrTask.GetAwaiter().GetResult().TrimEnd() + } +} + +# ── Helper: fetch a file at a git ref ──────────────────────────────────────── + +function Get-FileAtRef { + param([string]$Ref, [string]$File) + + $r = Invoke-GitCommand -Arguments @('show', "${Ref}:${File}") + if (-not $r.Success) { + return @{ Lines = $null; Note = "File not available at ref '${Ref}': $($r.Error.Trim())" } + } + $lines = $r.Output -split "`n" + # Remove trailing empty element produced by split on a newline-terminated string + if ($lines.Count -gt 0 -and $lines[-1] -eq '') { + $lines = $lines[0..($lines.Count - 2)] + } + return @{ Lines = $lines; Note = $null } +} + +# ── Helper: slice a line-numbered excerpt centred on a 1-based line ────────── + +function Get-Excerpt { + param( + [string[]]$Lines, + [int]$CenterLine, # 1-based + [int]$Budget # max lines to return + ) + + if (-not $Lines) { return $null } + $half = [Math]::Floor($Budget / 2) + $start = [Math]::Max(0, $CenterLine - 1 - $half) + $end = [Math]::Min($Lines.Count - 1, $CenterLine - 1 + $half) + + # Expand toward the opposite edge if we hit a boundary before using the full budget + if (($end - $start + 1) -lt $Budget) { + if ($start -eq 0) { + $end = [Math]::Min($Lines.Count - 1, $Budget - 1) + } else { + $start = [Math]::Max(0, $end - $Budget + 1) + } + } + + return @{ + Lines = $Lines[$start..$end] + StartLine = $start + 1 + EndLine = $end + 1 + Note = $null + } +} + +# ── Helper: sliding-window content-anchor match ─────────────────────────────── +# Returns the 1-based centre line in $FileLines that best overlaps $AnchorLines. + +function Find-AnchorMatch { + param( + [string[]]$FileLines, + [string[]]$AnchorLines, + [int]$ExpectedCenter # 1-based fallback if no match found + ) + + $anchorSet = @{} + foreach ($a in $AnchorLines) { + $t = $a.Trim() + if ($t) { $anchorSet[$t] = $true } + } + + $windowSize = [Math]::Max($AnchorLines.Count, 5) + $bestScore = -1 + $bestCenter = $ExpectedCenter + + for ($i = 0; $i -le ($FileLines.Count - $windowSize); $i++) { + $score = 0 + for ($j = $i; $j -lt ($i + $windowSize) -and $j -lt $FileLines.Count; $j++) { + $trimmed = $FileLines[$j].Trim() + if ($trimmed -and $anchorSet.ContainsKey($trimmed)) { $score++ } + } + if ($score -gt $bestScore) { + $bestScore = $score + $bestCenter = $i + [Math]::Floor($windowSize / 2) + 1 # convert to 1-based + } + } + + return @{ + Center = $bestCenter + Score = $bestScore + MaxPossible = $anchorSet.Count + } +} + +# ── Helper: find the first line in $FileLines containing $FunctionName ─────── + +function Find-FunctionMatch { + param( + [string[]]$FileLines, + [string]$FunctionName + ) + + $pattern = "\b$([regex]::Escape($FunctionName))\b" + for ($i = 0; $i -lt $FileLines.Count; $i++) { + if ($FileLines[$i] -match $pattern) { + return $i + 1 # 1-based + } + } + return -1 +} + +# ── Helper: parse all @@ hunks from unified diff text ──────────────────────── + +function Parse-DiffHunks { + param([string]$DiffText) + + $hunks = @() + $lines = $DiffText -split "`n" + $currentHunk = $null + $contextAccum = @() + $inHunk = $false + + foreach ($line in $lines) { + if ($line -match '^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)$') { + + # Flush the previous hunk before starting a new one + if ($null -ne $currentHunk) { + $currentHunk['ContextLines'] = $contextAccum + $hunks += $currentHunk + } + + $upstreamStart = [int]$Matches[1] + $upstreamCount = if ($Matches[2]) { [int]$Matches[2] } else { 1 } + $afterStart = [int]$Matches[3] + $afterCount = if ($Matches[4]) { [int]$Matches[4] } else { 1 } + $funcTrailer = $Matches[5].Trim() + + # Extract function name from the optional trailer after @@ + $funcName = '' + if ($funcTrailer -match '(\w[\w_]*)\s*\(') { + $funcName = $Matches[1] + } elseif ($funcTrailer -match '(\w[\w_]+)') { + $funcName = $Matches[1] + } + + $currentHunk = @{ + Header = $line.Trim() + FunctionName = $funcName + UpstreamStart = $upstreamStart + UpstreamCount = $upstreamCount + AfterStart = $afterStart + AfterCount = $afterCount + } + $contextAccum = @() + $inHunk = $true + + } elseif ($inHunk) { + # Collect unchanged context lines (lines starting with a space) + if ($line -match '^ (.*)$') { + $contextAccum += $Matches[1] + } + } + } + + # Flush the last hunk + if ($null -ne $currentHunk) { + $currentHunk['ContextLines'] = $contextAccum + $hunks += $currentHunk + } + + return $hunks +} + +# ── Main ────────────────────────────────────────────────────────────────────── + +$warnings = @() + +# 1. Get the upstream diff for this file at this commit +$diffResult = Invoke-GitCommand -Arguments @('diff', "${CommitHash}^..${CommitHash}", '--', $FilePath) +if (-not $diffResult.Success -and $diffResult.ExitCode -ne 1) { + return @{ + Success = $false + Message = "Failed to get diff for '${FilePath}' at commit ${CommitHash}: $($diffResult.Error)" + CommitMessage = '' + UpstreamDiff = '' + HunkCount = 0 + IsBinary = $false + Hunks = @() + } +} + +$upstreamDiff = $diffResult.Output + +# 2. Binary file — return early with a note, no excerpts +if ($upstreamDiff -match 'Binary files .* differ') { + return @{ + Success = $true + Message = "Binary file — context not available for '${FilePath}'." + CommitMessage = '' + UpstreamDiff = $upstreamDiff + HunkCount = 0 + IsBinary = $true + Hunks = @() + } +} + +# 3. File not touched by this commit +if ([string]::IsNullOrWhiteSpace($upstreamDiff)) { + return @{ + Success = $true + Message = "File '${FilePath}' was not modified by commit ${CommitHash}." + CommitMessage = '' + UpstreamDiff = '' + HunkCount = 0 + IsBinary = $false + Hunks = @() + } +} + +# 4. Get the commit message +$commitMsgResult = Invoke-GitCommand -Arguments @('log', '-1', '--pretty=format:%s%n%n%b', $CommitHash) +$commitMessage = if ($commitMsgResult.Success) { $commitMsgResult.Output.Trim() } else { '' } + +# 5. Fetch the three file versions +# HEAD is our fork's version of the file during both merge and cherry-pick conflicts. +# CommitHash^ is the upstream state before the commit; CommitHash is after. +$upstreamBefore = Get-FileAtRef -Ref "${CommitHash}^" -File $FilePath +$upstreamAfter = Get-FileAtRef -Ref "${CommitHash}" -File $FilePath +$ourFork = Get-FileAtRef -Ref 'HEAD' -File $FilePath + +# 6. Parse hunks from the diff +$hunks = Parse-DiffHunks -DiffText $upstreamDiff +$hunkCount = $hunks.Count + +if ($hunkCount -eq 0) { + return @{ + Success = $true + Message = "No hunks found in diff for '${FilePath}' at commit ${CommitHash}." + CommitMessage = $commitMessage + UpstreamDiff = $upstreamDiff + HunkCount = 0 + IsBinary = $false + Hunks = @() + } +} + +# 7. Compute per-hunk line budget +# MaxTotalLines is split evenly across 3 versions and all hunks. +# Minimum floor of 10 lines per version per hunk is always enforced. +$MIN_LINES_PER_HUNK = 10 +$budgetPerHunk = [Math]::Floor($MaxTotalLines / 3 / $hunkCount) + +if ($budgetPerHunk -lt $MIN_LINES_PER_HUNK) { + $warnings += "MaxTotalLines=${MaxTotalLines} is too small for ${hunkCount} hunk(s) across 3 versions; " + + "minimum floor of ${MIN_LINES_PER_HUNK} lines applied — consider increasing MaxTotalLines." + $budgetPerHunk = $MIN_LINES_PER_HUNK +} + +# Never exceed the caller's ContextLines preference +$budgetPerHunk = [Math]::Min($budgetPerHunk, $ContextLines) + +# 8. Build per-hunk results +$ANCHOR_SCORE_THRESHOLD = 2 +$resultHunks = @() + +for ($h = 0; $h -lt $hunkCount; $h++) { + + $hunk = $hunks[$h] + $anchorLines = $hunk['ContextLines'] + + # ── upstream-before: line numbers are known from the diff header ────────── + $uBefore = @{ Lines = $null; StartLine = $null; EndLine = $null; Note = $upstreamBefore.Note } + if ($upstreamBefore.Lines) { + $center = $hunk['UpstreamStart'] + [Math]::Floor($hunk['UpstreamCount'] / 2) + $excerpt = Get-Excerpt -Lines $upstreamBefore.Lines -CenterLine $center -Budget $budgetPerHunk + if ($excerpt) { $uBefore = $excerpt } + } + + # ── upstream-after: line numbers are known from the diff header ─────────── + $uAfter = @{ Lines = $null; StartLine = $null; EndLine = $null; Note = $upstreamAfter.Note } + if ($upstreamAfter.Lines) { + $center = $hunk['AfterStart'] + [Math]::Floor($hunk['AfterCount'] / 2) + $excerpt = Get-Excerpt -Lines $upstreamAfter.Lines -CenterLine $center -Budget $budgetPerHunk + if ($excerpt) { $uAfter = $excerpt } + } + + # ── our fork: line numbers diverge — locate by content matching ────────── + $forkExcerpt = @{ Lines = $null; StartLine = $null; EndLine = $null; Note = $ourFork.Note } + + if ($ourFork.Lines) { + $forkCenter = $hunk['UpstreamStart'] # fallback: use upstream line number as estimate + $matchNote = $null + + if ($anchorLines.Count -ge 2) { + # Tier 1: sliding-window content match against unchanged context lines + $match = Find-AnchorMatch -FileLines $ourFork.Lines ` + -AnchorLines $anchorLines ` + -ExpectedCenter $forkCenter + + if ($match.Score -ge $ANCHOR_SCORE_THRESHOLD) { + $forkCenter = $match.Center + $matchNote = "Located via content-anchor match (score $($match.Score)/$($match.MaxPossible))." + } elseif ($hunk['FunctionName']) { + # Tier 2: anchor score too low — fall back to function name search + $fnLine = Find-FunctionMatch -FileLines $ourFork.Lines -FunctionName $hunk['FunctionName'] + if ($fnLine -gt 0) { + $forkCenter = $fnLine + $matchNote = "Located via function-name fallback ('$($hunk['FunctionName'])')." + } else { + $matchNote = "Could not locate region — anchor score too low and function " + + "'$($hunk['FunctionName'])' not found. Using upstream line number as estimate." + } + } else { + $matchNote = "Could not locate region — anchor score too low and no function name " + + "available. Using upstream line number as estimate." + } + + } elseif ($hunk['FunctionName']) { + # Too few anchor lines for sliding window — go straight to function-name search + $fnLine = Find-FunctionMatch -FileLines $ourFork.Lines -FunctionName $hunk['FunctionName'] + if ($fnLine -gt 0) { + $forkCenter = $fnLine + $matchNote = "Located via function-name fallback ('$($hunk['FunctionName'])') — " + + "insufficient anchor lines for content match." + } else { + $matchNote = "Insufficient anchor lines and function '$($hunk['FunctionName'])' not found. " + + "Using upstream line number as estimate." + } + } else { + $matchNote = "Insufficient anchor lines and no function name available. " + + "Using upstream line number as estimate." + } + + $excerpt = Get-Excerpt -Lines $ourFork.Lines -CenterLine $forkCenter -Budget $budgetPerHunk + if ($excerpt) { + $excerpt['Note'] = $matchNote + $forkExcerpt = $excerpt + } + } + + $resultHunks += @{ + HunkIndex = $h + 1 + HunkHeader = $hunk['Header'] + FunctionName = $hunk['FunctionName'] + UpstreamBefore = $uBefore + UpstreamAfter = $uAfter + OurFork = $forkExcerpt + } +} + +# 9. Return final result +$message = if ($warnings.Count -gt 0) { + "Context retrieved for ${hunkCount} hunk(s) in '${FilePath}' (commit ${CommitHash}). " + + "Warnings: $($warnings -join ' | ')" +} else { + "Context retrieved for ${hunkCount} hunk(s) in '${FilePath}' (commit ${CommitHash})." +} + +return @{ + Success = $true + Message = $message + CommitMessage = $commitMessage + UpstreamDiff = $upstreamDiff + HunkCount = $hunkCount + IsBinary = $false + Hunks = $resultHunks +} diff --git a/.github/tools/Get-RemainingCommitCount.ps1 b/.github/tools/Get-RemainingCommitCount.ps1 new file mode 100644 index 000000000000..4bb580df4dd0 --- /dev/null +++ b/.github/tools/Get-RemainingCommitCount.ps1 @@ -0,0 +1,147 @@ +<# +.SYNOPSIS + Counts how many upstream commits remain to be merged between a start ref and an end ref (tag or HEAD). + +.DESCRIPTION + MCP-compatible tool that reports the number of commits reachable from EndRef but not from + StartRef (i.e. `git rev-list --count ..`). It is used during an upstream + merge to answer "how many commits are left to merge to the target tag / HEAD?" so the agent + and user can gauge remaining work and estimate the number of batches. + + Both refs must be resolvable in the local repository. For an upstream merge, StartRef is + typically the last-merged upstream commit (or tag) and EndRef is the upstream target tag or + the tip of the upstream tracking branch. Run a fetch first so the refs are up to date, e.g. + `git fetch upstream --tags`. + +.PARAMETER StartRef + The ref (commit SHA, tag, or branch) that marks the last already-merged upstream point. + Commits reachable from this ref are excluded from the count. Required. + +.PARAMETER EndRef + The ref (commit SHA, tag, or branch) that marks the merge target. Defaults to 'HEAD'. + For an upstream merge this is usually the upstream target tag (e.g. 'V_10_3_P1') or the + upstream tracking branch tip (e.g. 'upstream/master'). + +.OUTPUTS + Hashtable with: + Success [bool] Whether both refs resolved and the count succeeded + Message [string] Human-readable summary + StartRef [string] Echoed StartRef + EndRef [string] Echoed EndRef + StartCommit [string] Resolved full SHA of StartRef (or empty on error) + EndCommit [string] Resolved full SHA of EndRef (or empty on error) + RemainingCount [int] Commits reachable from EndRef but not StartRef (StartRef..EndRef) + AlreadyMerged [bool] True if RemainingCount is 0 (nothing left to merge) + Errors [string[]] Any error messages + +.EXAMPLE + # How many commits remain between the last merged tag and the target tag + # MCP Tool: mcp_openssh-server_Get_RemainingCommitCount + # StartRef="V_10_0_P2", EndRef="V_10_3_P1" + +.EXAMPLE + # How many commits remain to the current upstream tip + # MCP Tool: mcp_openssh-server_Get_RemainingCommitCount + # StartRef="6fb728df50c1afd338cb0223a84ce24579577eff", EndRef="upstream/master" +#> + +param( + [Parameter(Mandatory)] + [string]$StartRef, + + [string]$EndRef = 'HEAD' +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +# ── Git process helper (same pattern as Get-ConflictContext.ps1 / Invoke-Git.ps1) ── +function Invoke-GitCommand { + param([string[]]$Arguments) + + $processInfo = [System.Diagnostics.ProcessStartInfo]::new() + $processInfo.FileName = 'git' + $processInfo.Arguments = ($Arguments | ForEach-Object { + if ($_ -match '\s') { "`"$_`"" } else { $_ } + }) -join ' ' + $processInfo.UseShellExecute = $false + $processInfo.CreateNoWindow = $true + $processInfo.RedirectStandardInput = $true + $processInfo.RedirectStandardOutput = $true + $processInfo.RedirectStandardError = $true + + $process = [System.Diagnostics.Process]::new() + $process.StartInfo = $processInfo + $process.Start() | Out-Null + $process.StandardInput.Close() + + $stdoutTask = $process.StandardOutput.ReadToEndAsync() + $stderrTask = $process.StandardError.ReadToEndAsync() + + $completed = $process.WaitForExit(30000) + + if (-not $completed) { + $process.Kill() + return @{ + ExitCode = -1 + Success = $false + Output = '' + Error = "git $($Arguments -join ' ') timed out after 30 seconds" + } + } + + return @{ + ExitCode = $process.ExitCode + Success = ($process.ExitCode -eq 0) + Output = $stdoutTask.GetAwaiter().GetResult().TrimEnd() + Error = $stderrTask.GetAwaiter().GetResult().TrimEnd() + } +} + +$result = @{ + Success = $false + Message = '' + StartRef = $StartRef + EndRef = $EndRef + StartCommit = '' + EndCommit = '' + RemainingCount = 0 + AlreadyMerged = $false + Errors = @() +} + +# Resolve both refs so we fail clearly if one is missing/unfetched. +$startResolve = Invoke-GitCommand @('rev-parse', '--verify', "$StartRef^{commit}") +if (-not $startResolve.Success) { + $result.Errors += "Could not resolve StartRef '$StartRef': $($startResolve.Error). Did you fetch upstream (git fetch upstream --tags)?" + $result.Message = "Failed to resolve StartRef '$StartRef'." + return $result +} +$result.StartCommit = $startResolve.Output + +$endResolve = Invoke-GitCommand @('rev-parse', '--verify', "$EndRef^{commit}") +if (-not $endResolve.Success) { + $result.Errors += "Could not resolve EndRef '$EndRef': $($endResolve.Error). Did you fetch upstream (git fetch upstream --tags)?" + $result.Message = "Failed to resolve EndRef '$EndRef'." + return $result +} +$result.EndCommit = $endResolve.Output + +$count = Invoke-GitCommand @('rev-list', '--count', "$StartRef..$EndRef") +if (-not $count.Success) { + $result.Errors += "git rev-list failed: $($count.Error)" + $result.Message = "Failed to count commits between '$StartRef' and '$EndRef'." + return $result +} + +$result.RemainingCount = [int]$count.Output +$result.AlreadyMerged = ($result.RemainingCount -eq 0) +$result.Success = $true + +if ($result.AlreadyMerged) { + $result.Message = "0 commits remain between '$StartRef' and '$EndRef' — the target is already merged (or EndRef is not ahead of StartRef)." +} else { + $result.Message = "$($result.RemainingCount) commit(s) remain to be merged from '$StartRef' to '$EndRef'." +} + +return $result diff --git a/.github/tools/Install-VcpkgDependencies.ps1 b/.github/tools/Install-VcpkgDependencies.ps1 new file mode 100644 index 000000000000..1db50e011b85 --- /dev/null +++ b/.github/tools/Install-VcpkgDependencies.ps1 @@ -0,0 +1,360 @@ +<# +.SYNOPSIS + MCP tool that bootstraps vcpkg and installs Win32-OpenSSH dependencies. + +.DESCRIPTION + This script automates the vcpkg setup required by the Win32-OpenSSH build. + It mirrors the recipe in .azdo/templates/install-vcpkg-dependencies.yml so + the same install path works locally and in CI. + + The script: + - Locates a vcpkg clone (parameter, $env:VCPKG_ROOT, or ..\vcpkg). + - Optionally bootstraps it (-Bootstrap). + - Verifies the LibreSSL vcpkg.json override matches the FileVersion field + in vcpkg_overlay_ports/libressl/add-version-file.patch (cross-check). + - Runs `vcpkg install` from contrib/win32/openssh against the manifest, + using --overlay-triplets=.\vcpkg_triplets and + --overlay-ports=.\vcpkg_overlay_ports. + - Verifies that vcpkg_installed//bin/libcrypto.dll was produced. + + Output is consumed by OpenSSHBuildHelper.psm1 which reads from + contrib\win32\openssh\vcpkg_installed\-custom\-custom\bin\. + +.PARAMETER Architecture + One or more architectures to install. Each value maps to the + corresponding `-custom` triplet. Default is 'x64' to match the + default of Start-OpenSSHBuild.ps1. Pass multiple values to install for + several triplets in one run, matching what CI builds. + +.PARAMETER VcpkgRoot + Path to a vcpkg clone. If omitted, the script tries (in order): + 1. $env:VCPKG_ROOT + 2. ..\vcpkg relative to the repo root + If neither exists, the script errors with a clone command. + +.PARAMETER Bootstrap + If specified, runs bootstrap-vcpkg.bat when vcpkg.exe is missing. + Without this switch, a missing vcpkg.exe is treated as an error. + +.PARAMETER Clean + If specified, deletes contrib/win32/openssh/vcpkg_installed before + installing. Forces a from-scratch install. + +.PARAMETER BinaryCache + Optional path to a vcpkg binary cache directory. When supplied, the + script sets VCPKG_BINARY_SOURCES=clear;files,,readwrite for the + install invocation, mirroring the AzDO pipeline. + +.PARAMETER SkipVersionCheck + Skip the LibreSSL vcpkg.json <-> add-version-file.patch cross-check. + Use only when intentionally bumping the manifest before regenerating + the patch. + +.OUTPUTS + Returns a hashtable with: + - Success: Boolean indicating overall success + - VcpkgRoot: Resolved vcpkg root path + - VcpkgExecutable: Path to vcpkg.exe used + - TripletsInstalled: Array of triplets that completed install + - InstalledPath: Path to vcpkg_installed + - VersionCheckPassed: Boolean (or $null if skipped) + - Errors: Array of error strings + - Message: Summary message + +.EXAMPLE + .\Install-VcpkgDependencies.ps1 -Bootstrap + + First-time setup. Bootstraps vcpkg if needed and installs the x64-custom + triplet. + +.EXAMPLE + .\Install-VcpkgDependencies.ps1 -Architecture x64,x86,ARM,ARM64 + + Installs all four custom triplets (matches CI artifact set). + +.EXAMPLE + .\Install-VcpkgDependencies.ps1 -Clean -BinaryCache C:\vcpkg-cache + + Wipes vcpkg_installed and reinstalls, using a shared binary cache. + +.NOTES + - Mirrors .azdo/templates/install-vcpkg-dependencies.yml. + - Must complete before Start-OpenSSHBuild.ps1. + - Does not run `vcpkg integrate install`; that is optional and global. +#> + +param( + [Parameter(Mandatory=$false)] + [ValidateSet('x64', 'x86', 'ARM', 'ARM64')] + [string[]]$Architecture = @('x64'), + + [Parameter(Mandatory=$false)] + [string]$VcpkgRoot, + + [Parameter(Mandatory=$false)] + [switch]$Bootstrap, + + [Parameter(Mandatory=$false)] + [switch]$Clean, + + [Parameter(Mandatory=$false)] + [string]$BinaryCache, + + [Parameter(Mandatory=$false)] + [switch]$SkipVersionCheck +) + +$ErrorActionPreference = 'Stop' + +$scriptRoot = $PSScriptRoot +if ([string]::IsNullOrEmpty($scriptRoot)) { + $scriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path +} +$repoRoot = (Get-Item $scriptRoot).Parent.Parent.FullName +$opensshDir = Join-Path $repoRoot 'contrib\win32\openssh' +$installedDir = Join-Path $opensshDir 'vcpkg_installed' +$overlayPortsDir = Join-Path $opensshDir 'vcpkg_overlay_ports' +$overlayTripletsDir = Join-Path $opensshDir 'vcpkg_triplets' +$manifestPath = Join-Path $opensshDir 'vcpkg.json' +$libresslPatchPath = Join-Path $overlayPortsDir 'libressl\add-version-file.patch' + +$result = @{ + Success = $false + VcpkgRoot = $null + VcpkgExecutable = $null + TripletsInstalled = @() + InstalledPath = $installedDir + VersionCheckPassed = $null + Errors = @() + Message = '' +} + +function Resolve-VcpkgRoot { + param([string]$Explicit, [string]$RepoRoot) + + $candidates = @() + if (-not [string]::IsNullOrWhiteSpace($Explicit)) { + $candidates += $Explicit + } + if (-not [string]::IsNullOrWhiteSpace($env:VCPKG_ROOT)) { + $candidates += $env:VCPKG_ROOT + } + $candidates += (Join-Path (Split-Path -Parent $RepoRoot) 'vcpkg') + + foreach ($candidate in $candidates) { + if (Test-Path -LiteralPath $candidate -PathType Container) { + return (Resolve-Path -LiteralPath $candidate).Path + } + } + return $null +} + +function Test-LibreSSLVersionMatch { + param([string]$ManifestPath, [string]$PatchPath) + + if (-not (Test-Path -LiteralPath $ManifestPath)) { + throw "vcpkg.json not found at $ManifestPath" + } + if (-not (Test-Path -LiteralPath $PatchPath)) { + throw "LibreSSL patch not found at $PatchPath" + } + + $manifest = Get-Content -LiteralPath $ManifestPath -Raw | ConvertFrom-Json + $manifestVersion = $manifest.overrides | + Where-Object { $_.name -eq 'libressl' } | + Select-Object -ExpandProperty version + + if ([string]::IsNullOrWhiteSpace($manifestVersion)) { + throw "No 'libressl' override found in $ManifestPath" + } + + $patchContent = Get-Content -LiteralPath $PatchPath -Raw + $match = [regex]::Match($patchContent, '"FileVersion",\s*"(\d+\.\d+\.\d+\.\d+)"') + if (-not $match.Success) { + throw "FileVersion field not found in $PatchPath" + } + $patchVersionFull = $match.Groups[1].Value + $patchVersionShort = ($patchVersionFull -split '\.')[0..2] -join '.' + + return [pscustomobject]@{ + ManifestVersion = $manifestVersion + PatchVersion = $patchVersionFull + PatchVersionShort = $patchVersionShort + Match = ($manifestVersion -eq $patchVersionShort) + } +} + +try { + Write-Host "========================================" -ForegroundColor Cyan + Write-Host "Install Win32-OpenSSH vcpkg Dependencies" -ForegroundColor Cyan + Write-Host "========================================" -ForegroundColor Cyan + Write-Host "Repository Root: $repoRoot" -ForegroundColor Gray + Write-Host "Architectures: $($Architecture -join ', ')" -ForegroundColor White + Write-Host "========================================`n" -ForegroundColor Cyan + + # Step 1: Resolve vcpkg root + Write-Host "[1/5] Locating vcpkg..." -ForegroundColor Cyan + $resolvedRoot = Resolve-VcpkgRoot -Explicit $VcpkgRoot -RepoRoot $repoRoot + if (-not $resolvedRoot) { + $msg = "vcpkg clone not found. Tried: -VcpkgRoot, `$env:VCPKG_ROOT, $(Join-Path (Split-Path -Parent $repoRoot) 'vcpkg').`n" + + "Clone it with: git clone https://github.com/Microsoft/vcpkg.git $(Join-Path (Split-Path -Parent $repoRoot) 'vcpkg')" + $result.Errors += $msg + Write-Host " ✗ $msg" -ForegroundColor Red + $result.Message = 'vcpkg clone not found.' + return $result + } + $result.VcpkgRoot = $resolvedRoot + Write-Host " ✓ vcpkg root: $resolvedRoot" -ForegroundColor Green + + $vcpkgExe = Join-Path $resolvedRoot 'vcpkg.exe' + $bootstrapScript = Join-Path $resolvedRoot 'bootstrap-vcpkg.bat' + + # Step 2: Bootstrap if needed + Write-Host "`n[2/5] Checking vcpkg.exe..." -ForegroundColor Cyan + if (-not (Test-Path -LiteralPath $vcpkgExe)) { + if ($Bootstrap) { + if (-not (Test-Path -LiteralPath $bootstrapScript)) { + $msg = "bootstrap-vcpkg.bat not found at $bootstrapScript" + $result.Errors += $msg + Write-Host " ✗ $msg" -ForegroundColor Red + $result.Message = 'Bootstrap script missing.' + return $result + } + Write-Host " → Bootstrapping vcpkg..." -ForegroundColor Yellow + Push-Location $resolvedRoot + try { + & $bootstrapScript + $bootstrapExit = $LASTEXITCODE + } finally { + Pop-Location + } + if ($bootstrapExit -ne 0 -or -not (Test-Path -LiteralPath $vcpkgExe)) { + $msg = "bootstrap-vcpkg.bat exited with code $bootstrapExit; vcpkg.exe still missing." + $result.Errors += $msg + Write-Host " ✗ $msg" -ForegroundColor Red + $result.Message = 'Bootstrap failed.' + return $result + } + Write-Host " ✓ vcpkg bootstrapped" -ForegroundColor Green + } else { + $msg = "vcpkg.exe not found at $vcpkgExe. Re-run with -Bootstrap to build it." + $result.Errors += $msg + Write-Host " ✗ $msg" -ForegroundColor Red + $result.Message = 'vcpkg.exe missing; pass -Bootstrap.' + return $result + } + } else { + Write-Host " ✓ vcpkg.exe found" -ForegroundColor Green + } + $result.VcpkgExecutable = $vcpkgExe + + # Step 3: LibreSSL version cross-check + Write-Host "`n[3/5] Verifying LibreSSL version cross-check..." -ForegroundColor Cyan + if ($SkipVersionCheck) { + Write-Host " ⊘ Skipped (-SkipVersionCheck)" -ForegroundColor Yellow + $result.VersionCheckPassed = $null + } else { + $versionInfo = Test-LibreSSLVersionMatch -ManifestPath $manifestPath -PatchPath $libresslPatchPath + if ($versionInfo.Match) { + Write-Host " ✓ LibreSSL versions match: $($versionInfo.ManifestVersion)" -ForegroundColor Green + $result.VersionCheckPassed = $true + } else { + $msg = "LibreSSL version mismatch: vcpkg.json has $($versionInfo.ManifestVersion), patch file has $($versionInfo.PatchVersion). " + + "Update FileVersion in $libresslPatchPath, or pass -SkipVersionCheck." + $result.Errors += $msg + $result.VersionCheckPassed = $false + Write-Host " ✗ $msg" -ForegroundColor Red + $result.Message = 'LibreSSL version cross-check failed.' + return $result + } + } + + # Step 4: Optional clean + Write-Host "`n[4/5] Preparing vcpkg_installed..." -ForegroundColor Cyan + if ($Clean -and (Test-Path -LiteralPath $installedDir)) { + Write-Host " → Removing $installedDir" -ForegroundColor Yellow + Remove-Item -LiteralPath $installedDir -Recurse -Force + } + Write-Host " ✓ Ready" -ForegroundColor Green + + # Step 5: Install per triplet + Write-Host "`n[5/5] Running vcpkg install..." -ForegroundColor Cyan + $previousBinarySources = $env:VCPKG_BINARY_SOURCES + if (-not [string]::IsNullOrWhiteSpace($BinaryCache)) { + if (-not (Test-Path -LiteralPath $BinaryCache)) { + New-Item -ItemType Directory -Path $BinaryCache -Force | Out-Null + } + $env:VCPKG_BINARY_SOURCES = "clear;files,$BinaryCache,readwrite" + Write-Host " Binary cache: $BinaryCache" -ForegroundColor Gray + } + + try { + foreach ($arch in $Architecture) { + $triplet = "$($arch.ToLowerInvariant())-custom" + Write-Host "`n → Installing triplet: $triplet" -ForegroundColor Yellow + Push-Location $opensshDir + try { + & $vcpkgExe install ` + --triplet $triplet ` + --overlay-triplets=$overlayTripletsDir ` + --overlay-ports=$overlayPortsDir + $exit = $LASTEXITCODE + } finally { + Pop-Location + } + + if ($exit -ne 0) { + $msg = "vcpkg install for triplet $triplet failed with exit code $exit" + $result.Errors += $msg + Write-Host " ✗ $msg" -ForegroundColor Red + continue + } + + # Verify expected artifact + $libcryptoPath = Join-Path $installedDir "$triplet\$triplet\bin\libcrypto.dll" + if (Test-Path -LiteralPath $libcryptoPath) { + Write-Host " ✓ $triplet installed (libcrypto.dll present)" -ForegroundColor Green + $result.TripletsInstalled += $triplet + } else { + $msg = "vcpkg install for $triplet completed but libcrypto.dll not found at $libcryptoPath" + $result.Errors += $msg + Write-Host " ✗ $msg" -ForegroundColor Red + } + } + } finally { + $env:VCPKG_BINARY_SOURCES = $previousBinarySources + } + + # Final evaluation + Write-Host "`n========================================" -ForegroundColor Cyan + Write-Host "INSTALL SUMMARY" -ForegroundColor Cyan + Write-Host "========================================" -ForegroundColor Cyan + $result.Success = ($result.Errors.Count -eq 0) -and ($result.TripletsInstalled.Count -eq $Architecture.Count) + if ($result.Success) { + Write-Host "✓ ALL TRIPLETS INSTALLED" -ForegroundColor Green + Write-Host " Triplets: $($result.TripletsInstalled -join ', ')" -ForegroundColor White + Write-Host " Output: $installedDir" -ForegroundColor Gray + $result.Message = "Installed $($result.TripletsInstalled.Count) triplet(s) successfully." + } else { + Write-Host "✗ INSTALL INCOMPLETE" -ForegroundColor Red + foreach ($err in $result.Errors) { + Write-Host " • $err" -ForegroundColor Red + } + $result.Message = "$($result.Errors.Count) error(s) during install." + } + Write-Host "" + + return $result + +} catch { + Write-Host "`n========================================" -ForegroundColor Red + Write-Host "ERROR" -ForegroundColor Red + Write-Host "========================================" -ForegroundColor Red + Write-Host $_.Exception.Message -ForegroundColor Red + Write-Host $_.ScriptStackTrace -ForegroundColor Gray + + $result.Success = $false + $result.Errors += "Tool error: $($_.Exception.Message)" + $result.Message = "Install failed with error: $($_.Exception.Message)" + return $result +} diff --git a/.github/tools/Invoke-Git.ps1 b/.github/tools/Invoke-Git.ps1 new file mode 100644 index 000000000000..b0e8e7fbee75 --- /dev/null +++ b/.github/tools/Invoke-Git.ps1 @@ -0,0 +1,444 @@ +<# +.SYNOPSIS + Executes a git operation and returns a structured result with exit code. + +.DESCRIPTION + MCP-compatible tool that runs git commands via System.Diagnostics.Process for + reliable exit code capture without interfering with the MCP server's stdio + transport. Async stream reads are started before WaitForExit to prevent deadlocks + when git output exceeds the stream buffer size. + + Returns a structured hashtable with Success, ExitCode, Output, Error, and + operation-specific fields so agents can make programmatic decisions without + text parsing. + +.PARAMETER Operation + The git operation to perform. One of: + CherryPick, CherryPickContinue, CherryPickAbort, + Merge, MergeContinue, MergeAbort, + Add, Checkout, CreateBranch, + Commit, Push, Fetch, + Config, Reset, Clean, + Status, Log, Diff, Show + +.PARAMETER CommitHash + A commit SHA or any git ref (branch name, tag, etc.). + Used by: CherryPick, Merge, Show. + +.PARAMETER Range + A git range expression (e.g. "abc123^..def456" or "HEAD..upstream/V_10_0_P2"). + Used by: Log (and Log with ShasOnly), Diff. + +.PARAMETER Message + Commit message text. + Used by: Commit. + +.PARAMETER Path + File path or directory to operate on. Defaults to '.'. + Used by: Add, Checkout (file restore), Diff, Show. + +.PARAMETER Remote + Remote name. Defaults to 'origin'. + Used by: Fetch, Push. + +.PARAMETER Branch + Branch name to create or push. + Used by: CreateBranch, Push. + +.PARAMETER StartPoint + Git ref (branch, tag, or commit) to base the new branch on. + Used by: CreateBranch. + +.PARAMETER Target + Branch, tag, commit ref, or file path to check out or reset to. + Used by: Checkout, Reset. + +.PARAMETER Key + Git config key (e.g. "core.editor"). + Used by: Config. + +.PARAMETER Value + Git config value to set. + Used by: Config. + +.PARAMETER Mode + Reset mode: 'soft', 'mixed' (default), or 'hard'. + Used by: Reset. + +.PARAMETER ShasOnly + When specified alongside Operation=Log, uses git rev-list --reverse instead of + git log --oneline. Returns commit SHAs in oldest-first order suitable for building + a cherry-pick loop. result.Commits will contain [{Hash: "", Message: ""}]. + +.OUTPUTS + Hashtable with: + Success [bool] Whether the command exited with code 0 + ExitCode [int] Raw process exit code + Output [string] Stdout from git + Error [string] Stderr from git + Message [string] Human-readable summary + Plus operation-specific fields: + CherryPick (on failure): ConflictedFiles [string[]] + Merge (on failure): ConflictedFiles [string[]] + Log / ShasOnly: Commits [{Hash, Message}] + Status: ConflictedFiles [string[]], ModifiedFiles [string[]] + Commit (on success): CommitHash [string] + +.EXAMPLE + # Cherry-pick a single commit + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="CherryPick", CommitHash="abc1234" + +.EXAMPLE + # Get ordered commit SHAs in a batch range for a cherry-pick loop + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Log", Range="abc123^..def456", ShasOnly=true + +.EXAMPLE + # Stage all changes after conflict resolution (Path defaults to '.') + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Add" + +.EXAMPLE + # Continue cherry-pick after resolving conflicts + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="CherryPickContinue" + +.EXAMPLE + # Abort an in-progress cherry-pick + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="CherryPickAbort" + +.EXAMPLE + # Restore paths.targets after a build modifies it + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Checkout", Target=".\contrib\win32\openssh\paths.targets" + +.EXAMPLE + # Create and check out a new merge branch + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="CreateBranch", Branch="merge-v10.0P2-20260306" + +.EXAMPLE + # Commit staged changes + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Commit", Message="Fix compilation errors for V_10_0_P2" + +.EXAMPLE + # Push a branch to origin + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Push", Remote="origin", Branch="merge-v10.0P2-20260306" + +.EXAMPLE + # Set a git config value + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Config", Key="core.editor", Value="true" + +.EXAMPLE + # Show differences between two refs for a specific file + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Diff", Range="upstream-pwsh/latestw_all..upstream/V_10_0_P2", Path="Makefile.in" + +.EXAMPLE + # Inspect a specific commit + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Show", CommitHash="abc1234" + +.EXAMPLE + # Check working directory status for conflicts and modifications + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Status" + +.EXAMPLE + # Hard-reset to HEAD (recovery) + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Reset", Target="HEAD", Mode="hard" + +.EXAMPLE + # Merge an upstream batch endpoint into the current branch + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Merge", CommitHash="6fb728df50c1afd338cb0223a84ce24579577eff" + +.EXAMPLE + # Continue a merge after resolving conflicts + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="MergeContinue" + +.EXAMPLE + # Abort an in-progress merge + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="MergeAbort" + +.EXAMPLE + # Remove untracked files (recovery) + # MCP Tool: mcp_openssh-server_Invoke_Git + # Operation="Clean" +#> + +param( + [Parameter(Mandatory)] + [ValidateSet( + 'CherryPick', 'CherryPickContinue', 'CherryPickAbort', + 'Merge', 'MergeContinue', 'MergeAbort', + 'Add', 'Checkout', 'CreateBranch', + 'Commit', 'Push', 'Fetch', + 'Config', 'Reset', 'Clean', + 'Status', 'Log', 'Diff', 'Show' + )] + [string]$Operation, + + # CherryPick, Merge, Show — accepts any git ref: commit SHA, branch name, tag, etc. + [string]$CommitHash = '', + + # Log (plain or ShasOnly), Diff — git range expression e.g. "abc123^..def456" + [string]$Range = '', + + # Commit — commit message text + [string]$Message = '', + + # Add, Checkout (file restore), Diff, Show — file/directory path + [string]$Path = '.', + + # Fetch, Push — remote name + [string]$Remote = 'origin', + + # CreateBranch, Push — branch name + [string]$Branch = '', + + # CreateBranch — starting ref for the new branch + [string]$StartPoint = '', + + # Checkout, Reset — target ref or file path + [string]$Target = '', + + # Config — key (e.g. "core.editor") + [string]$Key = '', + + # Config — value to set + [string]$Value = '', + + # Reset — reset mode + [ValidateSet('soft', 'mixed', 'hard')] + [string]$Mode = 'mixed', + + # Log — use git rev-list --reverse (SHAs only, oldest first) instead of git log --oneline + [switch]$ShasOnly +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +# --------------------------------------------------------------------------- +# Private helper — runs git via System.Diagnostics.Process. +# +# IMPORTANT: We use ProcessStartInfo rather than Start-Process because +# Start-Process with -RedirectStandardOutput/-RedirectStandardError conflicts +# with the MCP server's stdio transport, causing the process to hang. +# +# Async stream reads MUST be started BEFORE WaitForExit to prevent deadlocks: +# if git output exceeds the internal stream buffer, git blocks waiting for the +# buffer to drain while WaitForExit blocks waiting for git to exit. +# --------------------------------------------------------------------------- +function Invoke-GitCommand { + param([string[]]$Arguments) + + $processInfo = [System.Diagnostics.ProcessStartInfo]::new() + $processInfo.FileName = 'git' + $processInfo.Arguments = ($Arguments | ForEach-Object { + if ($_ -match '\s') { "`"$_`"" } else { $_ } + }) -join ' ' + $processInfo.UseShellExecute = $false + $processInfo.CreateNoWindow = $true + $processInfo.RedirectStandardInput = $true # Prevent git inheriting the MCP stdio pipe + $processInfo.RedirectStandardOutput = $true + $processInfo.RedirectStandardError = $true + + $process = [System.Diagnostics.Process]::new() + $process.StartInfo = $processInfo + $process.Start() | Out-Null + $process.StandardInput.Close() # Immediately close stdin so git never blocks on input + + # Begin async reads BEFORE blocking on WaitForExit + $stdoutTask = $process.StandardOutput.ReadToEndAsync() + $stderrTask = $process.StandardError.ReadToEndAsync() + + $completed = $process.WaitForExit(30000) # 30-second timeout + + if (-not $completed) { + $process.Kill() + return @{ + ExitCode = -1 + Success = $false + Output = '' + Error = "git $($Arguments -join ' ') timed out after 30 seconds" + } + } + + return @{ + ExitCode = $process.ExitCode + Success = ($process.ExitCode -eq 0) + Output = $stdoutTask.GetAwaiter().GetResult().TrimEnd() + Error = $stderrTask.GetAwaiter().GetResult().TrimEnd() + } +} + +# --------------------------------------------------------------------------- +# Operation dispatcher +# --------------------------------------------------------------------------- +$result = switch ($Operation) { + + 'CherryPick' { + if (-not $CommitHash) { throw 'CommitHash is required for CherryPick' } + $r = Invoke-GitCommand -Arguments @('cherry-pick', $CommitHash) + if (-not $r.Success) { + # Enrich failure result with list of conflicted files for agent reporting + $statusResult = Invoke-GitCommand -Arguments @('status', '--porcelain') + $r['ConflictedFiles'] = ($statusResult.Output -split "`n") | + Where-Object { $_ -match '^(UU|AA|DD|AU|UA|DU|UD)\s' } | + ForEach-Object { $_.Substring(3).Trim() } + } + $r + } + + 'CherryPickContinue' { + Invoke-GitCommand -Arguments @('cherry-pick', '--continue') + } + + 'CherryPickAbort' { + Invoke-GitCommand -Arguments @('cherry-pick', '--abort') + } + + 'Merge' { + if (-not $CommitHash) { throw 'CommitHash is required for Merge (target ref to merge)' } + $r = Invoke-GitCommand -Arguments @('merge', '--no-ff', $CommitHash) + if (-not $r.Success) { + $statusResult = Invoke-GitCommand -Arguments @('status', '--porcelain') + $r['ConflictedFiles'] = ($statusResult.Output -split "`n") | + Where-Object { $_ -match '^(UU|AA|DD|AU|UA|DU|UD)\s' } | + ForEach-Object { $_.Substring(3).Trim() } + } + $r + } + + 'MergeContinue' { + Invoke-GitCommand -Arguments @('merge', '--continue') + } + + 'MergeAbort' { + Invoke-GitCommand -Arguments @('merge', '--abort') + } + + 'Add' { + Invoke-GitCommand -Arguments @('add', $Path) + } + + 'Checkout' { + if (-not $Target) { throw 'Target is required for Checkout (branch name, tag, or file path)' } + Invoke-GitCommand -Arguments @('checkout', $Target) + } + + 'CreateBranch' { + if (-not $Branch) { throw 'Branch is required for CreateBranch' } + $args = @('checkout', '-b', $Branch) + if ($StartPoint) { $args += $StartPoint } + Invoke-GitCommand -Arguments $args + } + + 'Commit' { + if (-not $Message) { throw 'Message is required for Commit' } + $r = Invoke-GitCommand -Arguments @('commit', '-m', $Message) + if ($r.Success -and $r.Output -match '\[[\w/]+ ([0-9a-f]{7,})\]') { + $r['CommitHash'] = $Matches[1] + } + $r + } + + 'Push' { + $args = @('push', $Remote) + if ($Branch) { $args += $Branch } + Invoke-GitCommand -Arguments $args + } + + 'Fetch' { + $args = if ($Remote -eq 'all') { @('fetch', '--all') } else { @('fetch', $Remote) } + Invoke-GitCommand -Arguments $args + } + + 'Config' { + if (-not $Key) { throw 'Key is required for Config' } + $args = @('config', $Key) + if ($Value) { $args += $Value } + Invoke-GitCommand -Arguments $args + } + + 'Reset' { + if (-not $Target) { throw 'Target is required for Reset' } + Invoke-GitCommand -Arguments @('reset', "--$Mode", $Target) + } + + 'Clean' { + # -f (force) -d (include untracked directories) — standard recovery clean + Invoke-GitCommand -Arguments @('clean', '-fd') + } + + 'Status' { + $r = Invoke-GitCommand -Arguments @('status', '--porcelain') + $lines = if ($r.Output) { $r.Output -split "`n" } else { @() } + $r['ConflictedFiles'] = $lines | + Where-Object { $_ -match '^(UU|AA|DD|AU|UA|DU|UD)\s' } | + ForEach-Object { $_.Substring(3).Trim() } + $r['ModifiedFiles'] = $lines | + Where-Object { $_ -notmatch '^(UU|AA|DD|AU|UA|DU|UD)\s' -and $_ -match '^\S' } | + ForEach-Object { ($_ -replace '^\S+\s+', '').Trim() } + $r + } + + 'Log' { + if (-not $Range) { throw 'Range is required for Log (e.g. "abc123^..def456" or "HEAD..upstream/V_10_0_P2")' } + if ($ShasOnly) { + # Use rev-list --reverse to get SHAs in oldest-first (cherry-pick) order + $r = Invoke-GitCommand -Arguments @('rev-list', '--reverse', $Range) + $r['Commits'] = if ($r.Success -and $r.Output) { + ($r.Output -split "`n") | + Where-Object { $_ -match '^[0-9a-f]{7,}$' } | + ForEach-Object { @{ Hash = $_; Message = '' } } + } else { @() } + } else { + $logArgs = @('log', '--oneline', $Range) + if ($Path -and $Path -ne '.') { $logArgs += '--'; $logArgs += $Path } + $r = Invoke-GitCommand -Arguments $logArgs + $r['Commits'] = if ($r.Success -and $r.Output) { + ($r.Output -split "`n") | + Where-Object { $_ -match '^[0-9a-f]' } | + ForEach-Object { + if ($_ -match '^([0-9a-f]+)\s+(.+)$') { + @{ Hash = $Matches[1]; Message = $Matches[2] } + } + } + } else { @() } + } + $r + } + + 'Diff' { + $args = @('diff') + if ($Range) { $args += $Range } + if ($Path -and $Path -ne '.') { $args += '--'; $args += $Path } + Invoke-GitCommand -Arguments $args + } + + 'Show' { + $args = @('show') + if ($CommitHash) { $args += $CommitHash } + if ($Path -and $Path -ne '.') { $args += '--'; $args += $Path } + Invoke-GitCommand -Arguments $args + } +} + +$result['Message'] = if ($result.Success) { + "git $Operation completed successfully" +} else { + "git $Operation failed with exit code $($result.ExitCode): $($result.Error)" +} + +return $result diff --git a/.github/tools/Invoke-OpenSSHTests.ps1 b/.github/tools/Invoke-OpenSSHTests.ps1 new file mode 100644 index 000000000000..c07375600594 --- /dev/null +++ b/.github/tools/Invoke-OpenSSHTests.ps1 @@ -0,0 +1,368 @@ +<# +.SYNOPSIS + Runs the OpenSSH full CI test suite (unit tests, bash tests, and E2E/Pester tests). + +.DESCRIPTION + This script automates the full OpenSSH CI test workflow on Windows using the + OpenSSHTestHelper module. It supports running all test suites together or + individual suites, with optional single-test targeting for bash tests. + + Test suites: + - Unit: Runs unittest-*.exe binaries found under the binary path + - Bash: Runs upstream bash regression tests via Cygwin sh.exe + - E2E: Runs Windows Pester-based end-to-end tests (requires Pester < 5) + + The workflow is: + 1. Import OpenSSHTestHelper module + 2. Set-OpenSSHTestEnvironment (installs test accounts, sshd test service, etc.) + 3. Run selected test suites + 4. Clear-OpenSSHTestEnvironment (unless -NoCleanup) + + Reference: https://github.com/PowerShell/Win32-OpenSSH/wiki/Run-OpenSSH-Pester-Tests + +.PARAMETER Configuration + Build configuration. Valid values: 'Debug', 'Release'. Default: 'Release'. + +.PARAMETER Architecture + Target architecture. Valid values: 'x64', 'x86', 'ARM', 'ARM64'. Default: the host + machine's architecture (auto-detected). A mismatched explicit value is rejected unless + -AllowArchMismatch is specified. + +.PARAMETER AllowArchMismatch + Permit targeting an architecture that differs from the host machine's architecture. + +.PARAMETER TestSuite + Which test suites to run. Valid values: 'All', 'Unit', 'Bash', 'E2E'. + Default: 'All'. Multiple values allowed. + +.PARAMETER BashTestFilePath + Run a single bash test file instead of the full bash suite. + Must be an absolute path to a .sh file under the regress folder. + Example: C:\repos\openssh-portable\regress\banner.sh + Only applies when TestSuite includes 'Bash'. + +.PARAMETER BashShellPath + Path to sh.exe (Cygwin or WSL). Auto-detected from common Cygwin locations + if not specified. Example: C:\cygwin64\bin\sh.exe + +.PARAMETER NoCleanup + Skip Clear-OpenSSHTestEnvironment at the end. Useful for debugging failures. + +.PARAMETER SkipSetup + Skip Set-OpenSSHTestEnvironment. Use when environment is already configured. + +.EXAMPLE + .\Invoke-OpenSSHTests.ps1 + Runs all test suites with Release x64 binaries. + +.EXAMPLE + .\Invoke-OpenSSHTests.ps1 -TestSuite Unit + Runs only unit tests. + +.EXAMPLE + .\Invoke-OpenSSHTests.ps1 -TestSuite E2E -Configuration Debug + Runs only Pester E2E tests using Debug binaries. + +.EXAMPLE + .\Invoke-OpenSSHTests.ps1 -TestSuite Bash -BashTestFilePath C:\repos\openssh-portable\regress\banner.sh + Runs a single bash test. + +.NOTES + Requires Administrator privileges. + Pester < 5 required for E2E tests (the helper will install via chocolatey if needed). + Cygwin (sh.exe) required for bash tests. + + Known gotchas: + - cfginclude.sh calls powershell.exe; if running under pwsh.exe, edit the test to use pwsh.exe. + See https://github.com/PowerShell/PowerShell/issues/18530#issuecomment-1325691850 + - WSMan and Port Forwarding tests may be disallowed on some VMs by default. + Enable the features or skip the affected tests. +#> + +[CmdletBinding()] +param( + [Parameter()] + [ValidateSet('Debug', 'Release')] + [string]$Configuration = 'Release', + + [Parameter()] + [ValidateSet('x64', 'x86', 'ARM', 'ARM64')] + [string]$Architecture, + + [Parameter()] + [switch]$AllowArchMismatch, + + [Parameter()] + [ValidateSet('All', 'Unit', 'Bash', 'E2E')] + [string[]]$TestSuite = @('All'), + + [Parameter()] + [string]$BashTestFilePath = '', + + [Parameter()] + [string]$BashShellPath = '', + + [Parameter()] + [switch]$NoCleanup, + + [Parameter()] + [switch]$SkipSetup +) + +# ────────────────────────────────────────────────────────────────────────────── +# Resolve target architecture (default = host arch; forbid mismatch unless overridden) +# ────────────────────────────────────────────────────────────────────────────── +function Get-HostArchitecture { + $archEnv = $env:PROCESSOR_ARCHITEW6432 + if ([string]::IsNullOrEmpty($archEnv)) { $archEnv = $env:PROCESSOR_ARCHITECTURE } + switch (($archEnv | ForEach-Object { $_.ToUpperInvariant() })) { + 'AMD64' { 'x64' } + 'X86' { 'x86' } + 'ARM64' { 'ARM64' } + 'ARM' { 'ARM' } + default { 'x64' } + } +} + +$hostArch = Get-HostArchitecture +if (-not $PSBoundParameters.ContainsKey('Architecture') -or [string]::IsNullOrEmpty($Architecture)) { + $Architecture = $hostArch +} elseif ($Architecture -ne $hostArch -and -not $AllowArchMismatch) { + throw "Requested architecture '$Architecture' does not match the host architecture '$hostArch'. Tests must run against host-native binaries; re-run with -AllowArchMismatch only if the target binaries can execute here." +} + +# ────────────────────────────────────────────────────────────────────────────── +# Resolve paths +# ────────────────────────────────────────────────────────────────────────────── +$scriptRoot = Split-Path -Parent $PSCommandPath +$repoRoot = Split-Path -Parent (Split-Path -Parent $scriptRoot) +$binPath = Join-Path $repoRoot "bin\$Architecture\$Configuration" +$helperModule = Join-Path $repoRoot "contrib\win32\openssh\OpenSSHTestHelper.psm1" +$bashIterator = Join-Path $repoRoot "contrib\win32\openssh\bash_tests_iterator.ps1" +$regressPath = Join-Path $repoRoot "regress" + +# ────────────────────────────────────────────────────────────────────────────── +# Result object +# ────────────────────────────────────────────────────────────────────────────── +$result = [PSCustomObject]@{ + Success = $false + UnitTestsPassed = $null # $true/$false/$null (not run) + BashTestsPassed = $null + E2ETestsPassed = $null + UnitTestOutput = $null + BashTestOutput = $null + E2ETestOutput = $null + Errors = @() + Warnings = @() + Message = '' +} + +$moduleImported = $false +$setupCompleted = $false + +function Write-StepHeader([string]$msg) { + Write-Host "" + Write-Host "=== $msg ===" -ForegroundColor Cyan +} + +$runUnit = $TestSuite -contains 'All' -or $TestSuite -contains 'Unit' +$runBash = $TestSuite -contains 'All' -or $TestSuite -contains 'Bash' +$runE2E = $TestSuite -contains 'All' -or $TestSuite -contains 'E2E' + +try { + # ── Admin check ────────────────────────────────────────────────────────── + $isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole( + [Security.Principal.WindowsBuiltInRole]"Administrator") + if (-not $isAdmin) { + $result.Errors += "Administrator privileges required." + $result.Message = "FAILED: Must be run as Administrator." + Write-Host "✗ Administrator privileges required." -ForegroundColor Red + return $result + } + + # ── Verify binaries ────────────────────────────────────────────────────── + if (-not (Test-Path (Join-Path $binPath "ssh.exe"))) { + $result.Errors += "Binaries not found at $binPath. Build the project first." + $result.Message = "FAILED: Build artifacts not found at $binPath." + Write-Host "✗ Binaries not found at $binPath" -ForegroundColor Red + return $result + } + Write-Host "✓ Binaries found at $binPath" -ForegroundColor Green + + # ── Import helper module ───────────────────────────────────────────────── + Write-StepHeader "Importing OpenSSHTestHelper" + if (-not (Test-Path $helperModule)) { + $result.Errors += "OpenSSHTestHelper.psm1 not found at $helperModule" + $result.Message = "FAILED: OpenSSHTestHelper module not found." + Write-Host "✗ Module not found: $helperModule" -ForegroundColor Red + return $result + } + Import-Module $helperModule -Force + $moduleImported = $true + Write-Host "✓ Module imported" -ForegroundColor Green + + # ── Set-OpenSSHTestEnvironment ─────────────────────────────────────────── + if (-not $SkipSetup) { + Write-StepHeader "Setting Up Test Environment" + Write-Host " OpenSSHBinPath: $binPath" + Set-OpenSSHTestEnvironment -OpenSSHBinPath $binPath -Confirm:$false + $setupCompleted = $true + Write-Host "✓ Test environment configured" -ForegroundColor Green + } else { + Write-Host "⚠ Skipping Set-OpenSSHTestEnvironment (-SkipSetup specified)" -ForegroundColor Yellow + $result.Warnings += "Setup skipped — environment must already be configured." + } + + # ── Unit Tests ─────────────────────────────────────────────────────────── + if ($runUnit) { + Write-StepHeader "Running Unit Tests" + try { + # Force unit test discovery to the selected build output path. + $unitOutput = Invoke-OpenSSHUnitTest -UnitTestDirectory $binPath *>&1 | Tee-Object -Variable unitCapture + $unitText = $unitCapture | Out-String + $result.UnitTestOutput = $unitText + + # Detect failure: unit test runner writes "failed" to output or exits non-zero + if ($unitText -match 'failed') { + $result.UnitTestsPassed = $false + $result.Errors += "Unit tests reported failures. See UnitTestOutput for details." + Write-Host "✗ Unit tests: FAILED" -ForegroundColor Red + } else { + $result.UnitTestsPassed = $true + Write-Host "✓ Unit tests: PASSED" -ForegroundColor Green + } + } catch { + $result.UnitTestsPassed = $false + $result.Errors += "Unit test exception: $_" + Write-Host "✗ Unit tests threw an exception: $_" -ForegroundColor Red + } + } + + # ── Bash Tests ─────────────────────────────────────────────────────────── + if ($runBash) { + Write-StepHeader "Running Bash Tests" + $result.Warnings += "cfginclude.sh gotcha: calls powershell.exe; if running under pwsh, edit the test to use pwsh.exe (see https://github.com/PowerShell/PowerShell/issues/18530#issuecomment-1325691850)." + + try { + if (-not [string]::IsNullOrEmpty($BashTestFilePath)) { + # Single bash test via iterator. + $resolvedShellPath = $BashShellPath + if ([string]::IsNullOrEmpty($resolvedShellPath) -or -not (Test-Path $resolvedShellPath)) { + throw "BashShellPath is required for single-test mode." + } + + Write-Host " Shell: $resolvedShellPath" + Write-Host " Running single test: $BashTestFilePath" + $bashOutput = & $bashIterator ` + -OpenSSHBinPath $binPath ` + -BashTestsPath $regressPath ` + -ShellPath $resolvedShellPath ` + -TestFilePath $BashTestFilePath ` + *>&1 | Tee-Object -Variable bashCapture + } else { + # Full bash suite via helper (helper handles Cygwin install/detection). + Write-Host " Running full bash test suite..." + $bashOutput = Invoke-OpenSSHBashTests *>&1 | Tee-Object -Variable bashCapture + } + + $bashText = $bashCapture | Out-String + $result.BashTestOutput = $bashText + + if ($bashText -match 'FAILED|not ok') { + $result.BashTestsPassed = $false + $result.Errors += "Bash tests reported failures. See BashTestOutput for details." + Write-Host "✗ Bash tests: FAILED" -ForegroundColor Red + } else { + $result.BashTestsPassed = $true + Write-Host "✓ Bash tests: PASSED" -ForegroundColor Green + } + } catch { + $result.BashTestsPassed = $false + $result.Errors += "Bash test exception: $_" + Write-Host "✗ Bash tests threw an exception: $_" -ForegroundColor Red + } + } + + # ── E2E / Pester Tests ─────────────────────────────────────────────────── + if ($runE2E) { + Write-StepHeader "Running E2E Pester Tests" + $result.Warnings += "WSMan and Port Forwarding tests may fail on some VMs where those features are disabled. Enable them in Windows Features or skip those test files." + Write-Host " ⚠ Note: WSMan/Port Forwarding may need to be enabled on this machine." -ForegroundColor Yellow + + try { + $e2eOutput = Invoke-OpenSSHE2ETest *>&1 | Tee-Object -Variable e2eCapture + $e2eText = $e2eCapture | Out-String + $result.E2ETestOutput = $e2eText + + if ($e2eText -match 'Failed\s*:\s*[1-9]|Tests failed') { + $result.E2ETestsPassed = $false + $result.Errors += "E2E tests reported failures. See E2ETestOutput for details." + Write-Host "✗ E2E Pester tests: FAILED" -ForegroundColor Red + } else { + $result.E2ETestsPassed = $true + Write-Host "✓ E2E Pester tests: PASSED" -ForegroundColor Green + } + } catch { + $result.E2ETestsPassed = $false + $result.Errors += "E2E test exception: $_" + Write-Host "✗ E2E tests threw an exception: $_" -ForegroundColor Red + } + } + + # ── Overall result ─────────────────────────────────────────────────────── + $anyFailed = ($result.UnitTestsPassed -eq $false) -or + ($result.BashTestsPassed -eq $false) -or + ($result.E2ETestsPassed -eq $false) + + $result.Success = -not $anyFailed + $result.Message = if ($result.Success) { "All selected test suites passed." } ` + else { "One or more test suites failed. See Errors for details." } + +} catch { + $result.Errors += "Unexpected error: $_" + $result.Message = "FAILED: Unexpected error — $_" + Write-Host "✗ Unexpected error: $_" -ForegroundColor Red +} finally { + # ── Cleanup ────────────────────────────────────────────────────────────── + if (-not $NoCleanup -and -not $SkipSetup -and $moduleImported -and $setupCompleted) { + Write-StepHeader "Cleaning Up Test Environment" + try { + Clear-OpenSSHTestEnvironment + Write-Host "✓ Test environment cleaned up" -ForegroundColor Green + } catch { + $result.Warnings += "Cleanup warning: $_" + Write-Host "⚠ Cleanup encountered an issue: $_" -ForegroundColor Yellow + } + } elseif (-not $NoCleanup -and -not $SkipSetup -and (-not $moduleImported -or -not $setupCompleted)) { + $result.Warnings += "Cleanup skipped because setup did not complete." + Write-Host "⚠ Cleanup skipped because setup did not complete." -ForegroundColor Yellow + } elseif ($NoCleanup) { + Write-Host "⚠ Skipping cleanup (-NoCleanup specified). Run Clear-OpenSSHTestEnvironment manually." -ForegroundColor Yellow + } +} + +# ── Summary ─────────────────────────────────────────────────────────────────── +Write-Host "" +Write-Host "=== Test Summary ===" -ForegroundColor Cyan +Write-Host "Overall: $(if ($result.Success) { '✓ PASSED' } else { '✗ FAILED' })" -ForegroundColor $(if ($result.Success) { 'Green' } else { 'Red' }) +if ($null -ne $result.UnitTestsPassed) { + Write-Host "Unit Tests: $(if ($result.UnitTestsPassed) { '✓ PASSED' } else { '✗ FAILED' })" -ForegroundColor $(if ($result.UnitTestsPassed) { 'Green' } else { 'Red' }) +} +if ($null -ne $result.BashTestsPassed) { + Write-Host "Bash Tests: $(if ($result.BashTestsPassed) { '✓ PASSED' } else { '✗ FAILED' })" -ForegroundColor $(if ($result.BashTestsPassed) { 'Green' } else { 'Red' }) +} +if ($null -ne $result.E2ETestsPassed) { + Write-Host "E2E Tests: $(if ($result.E2ETestsPassed) { '✓ PASSED' } else { '✗ FAILED' })" -ForegroundColor $(if ($result.E2ETestsPassed) { 'Green' } else { 'Red' }) +} +if ($result.Warnings.Count -gt 0) { + Write-Host "" + Write-Host "Warnings:" -ForegroundColor Yellow + $result.Warnings | ForEach-Object { Write-Host " ⚠ $_" -ForegroundColor Yellow } +} +if ($result.Errors.Count -gt 0) { + Write-Host "" + Write-Host "Errors:" -ForegroundColor Red + $result.Errors | ForEach-Object { Write-Host " ✗ $_" -ForegroundColor Red } +} + +return $result diff --git a/.github/tools/Start-OpenSSHBuild.ps1 b/.github/tools/Start-OpenSSHBuild.ps1 new file mode 100644 index 000000000000..8b97b66d11c2 --- /dev/null +++ b/.github/tools/Start-OpenSSHBuild.ps1 @@ -0,0 +1,245 @@ +<# +.SYNOPSIS + MCP tool to build OpenSSH on Windows using Visual Studio. + +.DESCRIPTION + This script wraps the Start-OpenSSHBuild function from OpenSSHBuildHelper.psm1 + to provide a standardized MCP interface for building OpenSSH. It supports + incremental and clean builds, multiple architectures, and various build configurations. + + The tool invokes MSBuild on the Win32-OpenSSH.sln solution and captures + all build output to a log file. + +.PARAMETER Configuration + Build configuration type. Valid values: 'Debug', 'Release' + Default: 'Release' + +.PARAMETER Architecture + Target architecture for the build. Valid values: 'x64', 'x86', 'ARM', 'ARM64' + Default: the host machine's architecture (auto-detected). If you explicitly pass an + architecture that does not match the host, the build is refused unless -AllowArchMismatch + is also specified. + +.PARAMETER AllowArchMismatch + Permit building for an architecture that differs from the host machine's architecture + (e.g. cross-building ARM64 on an x64 host). Without this switch, a mismatched -Architecture + is rejected so you don't accidentally produce binaries you can't run or test locally. + +.PARAMETER Clean + When specified, performs a clean build by deleting existing build artifacts first. + Default: false (incremental build) + +.PARAMETER NoOpenSSL + Build without OpenSSL support. + Default: false + +.PARAMETER OneCore + Build for Windows OneCore API subset. + Default: false + +.OUTPUTS + Returns a hashtable with: + - Success: Boolean indicating build success + - ExitCode: MSBuild exit code + - LogFile: Path to build log file + - BuildPath: Path to build output directory + - Message: Status message + +.EXAMPLE + .\Start-OpenSSHBuild.ps1 -Configuration Release -Architecture x64 + + Performs an incremental release build for x64 architecture. + +.EXAMPLE + .\Start-OpenSSHBuild.ps1 -Configuration Debug -Architecture x64 -Clean + + Performs a clean debug build for x64 architecture. + +.EXAMPLE + .\Start-OpenSSHBuild.ps1 -Architecture ARM64 -OneCore + + Performs an incremental OneCore release build for ARM64. + +.NOTES + - Requires Visual Studio 2019 or later with C++ tools + - Requires Windows SDK 10.0.17763.0 or later + - Build artifacts output to: contrib\win32\openssh\{Architecture}\{Configuration}\ + - Build log written to: OpenSSH{Configuration}{Architecture}.log +#> + +param( + [Parameter(Mandatory=$false)] + [ValidateSet('Debug', 'Release')] + [string]$Configuration = 'Release', + + [Parameter(Mandatory=$false)] + [ValidateSet('x64', 'x86', 'ARM', 'ARM64')] + [string]$Architecture, + + [Parameter(Mandatory=$false)] + [switch]$AllowArchMismatch, + + [Parameter(Mandatory=$false)] + [switch]$Clean, + + [Parameter(Mandatory=$false)] + [switch]$NoOpenSSL, + + [Parameter(Mandatory=$false)] + [switch]$OneCore +) + +# ── Resolve target architecture (default = host arch; forbid mismatch unless overridden) ── +function Get-HostArchitecture { + $archEnv = $env:PROCESSOR_ARCHITEW6432 + if ([string]::IsNullOrEmpty($archEnv)) { $archEnv = $env:PROCESSOR_ARCHITECTURE } + switch (($archEnv | ForEach-Object { $_.ToUpperInvariant() })) { + 'AMD64' { 'x64' } + 'X86' { 'x86' } + 'ARM64' { 'ARM64' } + 'ARM' { 'ARM' } + default { 'x64' } + } +} + +$hostArch = Get-HostArchitecture +if (-not $PSBoundParameters.ContainsKey('Architecture') -or [string]::IsNullOrEmpty($Architecture)) { + $Architecture = $hostArch + Write-Host "Architecture not specified; defaulting to host architecture: $Architecture" -ForegroundColor Gray +} elseif ($Architecture -ne $hostArch -and -not $AllowArchMismatch) { + throw "Requested architecture '$Architecture' does not match the host architecture '$hostArch'. Re-run with -AllowArchMismatch to build for a different architecture on purpose." +} + +# Determine repository root (go up from .github\tools to repo root) +$scriptRoot = $PSScriptRoot +$repoRoot = Split-Path -Parent (Split-Path -Parent $scriptRoot) + +# Navigate to repository root +Push-Location $repoRoot + +try { + Write-Host "========================================" -ForegroundColor Cyan + Write-Host "OpenSSH Build Tool (MCP)" -ForegroundColor Cyan + Write-Host "========================================" -ForegroundColor Cyan + Write-Host "Configuration: $Configuration" -ForegroundColor White + Write-Host "Architecture: $Architecture" -ForegroundColor White + Write-Host "Clean Build: $Clean" -ForegroundColor White + Write-Host "No OpenSSL: $NoOpenSSL" -ForegroundColor White + Write-Host "OneCore: $OneCore" -ForegroundColor White + Write-Host "========================================`n" -ForegroundColor Cyan + + # Import OpenSSH build helper module + $buildHelperPath = Join-Path $repoRoot "contrib\win32\openssh\OpenSSHBuildHelper.psm1" + if (-not (Test-Path $buildHelperPath)) { + throw "OpenSSHBuildHelper.psm1 not found at: $buildHelperPath" + } + + Import-Module $buildHelperPath -Force -ErrorAction Stop + Write-Host "✓ Loaded OpenSSHBuildHelper module" -ForegroundColor Green + + # Define build output path + $buildPath = Join-Path $repoRoot "contrib\win32\openssh\$Architecture\$Configuration" + + # Perform clean if requested + if ($Clean -and (Test-Path $buildPath)) { + Write-Host "`nCleaning previous build artifacts..." -ForegroundColor Yellow + Remove-Item $buildPath -Recurse -Force -ErrorAction Stop + Write-Host "✓ Cleaned: $buildPath" -ForegroundColor Green + } + + # Build log file path (align with other tools under contrib\win32\openssh) + $logFile = Join-Path $repoRoot "contrib\win32\openssh\OpenSSH$Configuration$Architecture.log" + Write-Host "`nBuild log: $logFile" -ForegroundColor Gray + + # Prepare parameters for Start-OpenSSHBuild + $buildParams = @{ + Configuration = $Configuration + NativeHostArch = $Architecture + } + + if ($NoOpenSSL) { + $buildParams['NoOpenSSL'] = $true + } + + if ($OneCore) { + $buildParams['OneCore'] = $true + } + + # Execute build + Write-Host "`nStarting build..." -ForegroundColor Cyan + Write-Host "Command: Start-OpenSSHBuild -Configuration $Configuration -NativeHostArch $Architecture$(if($NoOpenSSL){' -NoOpenSSL'})$(if($OneCore){' -OneCore'})" -ForegroundColor Gray + + $buildResult = Start-OpenSSHBuild @buildParams + + # Determine build success primarily via log markers, not exit code + $successByLog = $null + $buildLogTime = $null + if (Test-Path $logFile) { + $buildLogTime = (Get-Item $logFile -ErrorAction SilentlyContinue).LastWriteTime + $logLines = Get-Content $logFile -ErrorAction SilentlyContinue + if ($logLines) { + $lastMarker = $null + foreach ($line in $logLines) { + if ($line -match '(?i)Build\s+(FAILED|Failed)') { $lastMarker = 'FAILED' } + elseif ($line -match '(?i)Build\s+(SUCCEEDED|Succeeded)') { $lastMarker = 'SUCCEEDED' } + } + if ($lastMarker) { $successByLog = ($lastMarker -eq 'SUCCEEDED') } + } + } + + $derivedSuccess = if ($successByLog -ne $null) { $successByLog } else { $buildResult -eq 0 } + + if ($derivedSuccess) { + Write-Host "`n========================================" -ForegroundColor Green + Write-Host "BUILD SUCCEEDED" -ForegroundColor Green + Write-Host "========================================" -ForegroundColor Green + Write-Host "Build artifacts: $buildPath" -ForegroundColor White + + $result = @{ + Success = $true + ExitCode = $buildResult + LogFile = $logFile + BuildPath = $buildPath + BuildLogTimestamp = $buildLogTime + Message = "Build completed successfully" + } + } else { + Write-Host "`n========================================" -ForegroundColor Red + Write-Host "BUILD FAILED" -ForegroundColor Red + Write-Host "========================================" -ForegroundColor Red + Write-Host "Exit code: $buildResult" -ForegroundColor Red + Write-Host "Check log file: $logFile" -ForegroundColor Yellow + + $result = @{ + Success = $false + ExitCode = $buildResult + LogFile = $logFile + BuildPath = $buildPath + BuildLogTimestamp = $buildLogTime + Message = "Build failed (determined from log markers or exit code). Check log file for details." + } + } + + # Output result as JSON for MCP consumption + return $result + +} catch { + Write-Host "`n========================================" -ForegroundColor Red + Write-Host "ERROR" -ForegroundColor Red + Write-Host "========================================" -ForegroundColor Red + Write-Host $_.Exception.Message -ForegroundColor Red + Write-Host $_.ScriptStackTrace -ForegroundColor Gray + + $result = @{ + Success = $false + ExitCode = -1 + LogFile = $logFile + BuildPath = $buildPath + Message = "Build tool error: $($_.Exception.Message)" + } + + return $result + +} finally { + Pop-Location +} diff --git a/.github/tools/Sync-VersionResource.ps1 b/.github/tools/Sync-VersionResource.ps1 new file mode 100644 index 000000000000..4a5e0a9deca3 --- /dev/null +++ b/.github/tools/Sync-VersionResource.ps1 @@ -0,0 +1,153 @@ +<# +.SYNOPSIS + Syncs the Windows version resource (version.rc) numbers to match the merged version.h. + +.DESCRIPTION + MCP-compatible tool used during an upstream merge after version.h has been resolved. + Upstream owns the OpenSSH version in version.h; this fork embeds the same version in the + Windows resource file contrib/win32/openssh/version.rc so the built binaries report the + correct FileVersion / ProductVersion. + + The tool reads the major/minor from SSH_WINDOWS_VERSION ("OpenSSH_for_Windows_.") + and the patch from SSH_PORTABLE ("p") in version.h, then rewrites version.rc: + + FILEVERSION ,,0,0 + PRODUCTVERSION ,,0,0 + VALUE "FileVersion", "..0.0" + VALUE "ProductVersion", "OpenSSH_.p for Windows" + + Design notes (per fork convention): + - The patch number (pN) is reflected ONLY in the ProductVersion text, not in the numeric + FILEVERSION/PRODUCTVERSION third field, which stays 0. + - The descriptive text ("OpenSSH for Windows" / "OpenSSH_for_Windows") is preserved. + - Existing line endings and encoding are preserved. + +.PARAMETER RepoRoot + Repository root. Defaults to two levels above this script (.github\tools -> repo root). + +.PARAMETER DryRun + Preview the changes without writing version.rc. + +.OUTPUTS + Hashtable with: + Success [bool] Whether parsing succeeded and (unless DryRun) the file was written + Message [string] Human-readable summary + Major/Minor/Patch [int] Parsed version components + VersionHPath [string] Path to version.h + VersionRcPath [string] Path to version.rc + Changed [bool] Whether version.rc content would change + Replacements [object[]] { Field, Old, New } for each substituted line + Errors [string[]] Any error messages + +.EXAMPLE + # After resolving version.h in a merge, sync the resource file + # MCP Tool: mcp_openssh-server_Sync_VersionResource + +.EXAMPLE + # Preview only + # MCP Tool: mcp_openssh-server_Sync_VersionResource + # DryRun=true +#> + +param( + [string]$RepoRoot, + [switch]$DryRun +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +if (-not $RepoRoot) { + $RepoRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot) +} + +$result = @{ + Success = $false + Message = '' + Major = 0 + Minor = 0 + Patch = 0 + VersionHPath = Join-Path $RepoRoot 'version.h' + VersionRcPath = Join-Path $RepoRoot 'contrib\win32\openssh\version.rc' + Changed = $false + Replacements = @() + Errors = @() +} + +if (-not (Test-Path $result.VersionHPath)) { + $result.Errors += "version.h not found at $($result.VersionHPath)" + $result.Message = 'version.h not found.' + return $result +} +if (-not (Test-Path $result.VersionRcPath)) { + $result.Errors += "version.rc not found at $($result.VersionRcPath)" + $result.Message = 'version.rc not found.' + return $result +} + +$versionH = [System.IO.File]::ReadAllText($result.VersionHPath) + +# Parse major.minor from SSH_WINDOWS_VERSION "OpenSSH_for_Windows_." +if ($versionH -notmatch 'SSH_WINDOWS_VERSION\s+"OpenSSH_for_Windows_(\d+)\.(\d+)"') { + $result.Errors += 'Could not parse SSH_WINDOWS_VERSION (expected "OpenSSH_for_Windows_.") in version.h' + $result.Message = 'Failed to parse major/minor from version.h.' + return $result +} +$result.Major = [int]$Matches[1] +$result.Minor = [int]$Matches[2] + +# Parse patch from SSH_PORTABLE "p" +if ($versionH -notmatch 'SSH_PORTABLE\s+"p(\d+)"') { + $result.Errors += 'Could not parse SSH_PORTABLE (expected "p") in version.h' + $result.Message = 'Failed to parse patch from version.h.' + return $result +} +$result.Patch = [int]$Matches[1] + +$major = $result.Major +$minor = $result.Minor +$patch = $result.Patch + +$fileVersionNumeric = "$major,$minor,0,0" +$fileVersionString = "$major.$minor.0.0" +$productVersionText = "OpenSSH_$major.${minor}p$patch for Windows" + +$rc = [System.IO.File]::ReadAllText($result.VersionRcPath) +$original = $rc + +function Set-RcField { + param( + [string]$Field, + [string]$Pattern, # regex with capture groups; $Builder receives the Match and returns the full replacement text + [scriptblock]$Builder + ) + $script:rc = [regex]::Replace($script:rc, $Pattern, { + param($m) + $newText = & $Builder $m + if ($m.Value -ne $newText) { + $script:result.Replacements += [pscustomobject]@{ Field = $Field; Old = $m.Value.Trim(); New = $newText.Trim() } + } + return $newText + }) +} + +# FILEVERSION 10,0,0,0 / PRODUCTVERSION 10,0,0,0 — group 1 is the "KEYWORD " prefix. +Set-RcField 'FILEVERSION' '(?m)^(\s*FILEVERSION\s+)\d+,\d+,\d+,\d+' { param($m) $m.Groups[1].Value + $fileVersionNumeric } +Set-RcField 'PRODUCTVERSION' '(?m)^(\s*PRODUCTVERSION\s+)\d+,\d+,\d+,\d+' { param($m) $m.Groups[1].Value + $fileVersionNumeric } +# VALUE "FileVersion", "..." — groups 1 and 2 are the surrounding literal text incl. quotes. +Set-RcField 'FileVersion' '(VALUE\s+"FileVersion",\s+")[^"]*(")' { param($m) $m.Groups[1].Value + $fileVersionString + $m.Groups[2].Value } +Set-RcField 'ProductVersion' '(VALUE\s+"ProductVersion",\s+")[^"]*(")' { param($m) $m.Groups[1].Value + $productVersionText + $m.Groups[2].Value } + +$result.Changed = ($rc -ne $original) + +if ($result.Changed -and -not $DryRun) { + # Preserve original encoding (no BOM change): write bytes back as-is UTF8 without BOM. + $utf8NoBom = [System.Text.UTF8Encoding]::new($false) + [System.IO.File]::WriteAllText($result.VersionRcPath, $rc, $utf8NoBom) +} + +$result.Success = $true +$verb = if ($DryRun) { 'Would update' } elseif ($result.Changed) { 'Updated' } else { 'No change needed for' } +$result.Message = "$verb version.rc to OpenSSH ${major}.${minor}p${patch} (FILEVERSION $fileVersionNumeric, ProductVersion `"$productVersionText`")." + +return $result diff --git a/.github/tools/Test-MergeConflictMarkers.ps1 b/.github/tools/Test-MergeConflictMarkers.ps1 new file mode 100644 index 000000000000..24a8cc60809f --- /dev/null +++ b/.github/tools/Test-MergeConflictMarkers.ps1 @@ -0,0 +1,207 @@ +<# +.SYNOPSIS + Verifies the working tree has no unresolved merge conflict markers. + +.DESCRIPTION + MCP-compatible tool that scans tracked files in the working tree for Git conflict markers + left behind by an incomplete conflict resolution: + <<<<<<< (start of ours) + ======= (divider) + >>>>>>> (end of theirs) + ||||||| (base, in diff3 mode) + + Use it as a gate before completing a merge (MergeContinue), before committing build fixes, + and before pushing the branch / opening the PR. The start/end markers (`<<<<<<<` and + `>>>>>>>`) are treated as authoritative signals of an unresolved conflict; a lone + `=======` line can legitimately appear (e.g. Markdown/RST underlines), so it is reported + but only fails the check when accompanied by start/end markers in the same file. + + Scanning is done with `git grep` over tracked files, so untracked scratch files are ignored. + It also reports any paths Git still considers unmerged (`git ls-files -u`). + +.PARAMETER Path + Optional path (file or directory, repo-relative) to limit the scan. Defaults to the whole + repository. + +.PARAMETER FailOnDivider + When set, a lone `=======` divider also fails the check even without start/end markers. + Off by default to avoid false positives on documentation. + +.PARAMETER IncludeAll + By default the scan excludes the merge documentation under .github/ (instructions, agents, + prompts, skills), which legitimately contains illustrative conflict-marker examples. Set + this switch to scan those paths too. + +.OUTPUTS + Hashtable with: + Success [bool] True when no unresolved conflict markers were found + Clean [bool] Alias of Success for readability + Message [string] Human-readable summary + UnmergedPaths [string[]] Paths Git still reports as unmerged (ls-files -u) + Conflicts [array] One entry per offending file: + File [string] Repo-relative path + StartCount [int] Number of <<<<<<< lines + EndCount [int] Number of >>>>>>> lines + DivCount [int] Number of ======= lines + BaseCount [int] Number of ||||||| lines + Lines [object[]] { Line, Text } for each marker line + Errors [string[]] Any error messages + +.EXAMPLE + # Gate before completing a merge + # MCP Tool: mcp_openssh-server_Test_MergeConflictMarkers + +.EXAMPLE + # Scope the scan to a single directory + # MCP Tool: mcp_openssh-server_Test_MergeConflictMarkers + # Path="contrib/win32/win32compat" +#> + +param( + [string]$Path, + + [switch]$FailOnDivider, + + [switch]$IncludeAll +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +function Invoke-GitCommand { + param([string[]]$Arguments) + + $processInfo = [System.Diagnostics.ProcessStartInfo]::new() + $processInfo.FileName = 'git' + $processInfo.Arguments = ($Arguments | ForEach-Object { + if ($_ -match '\s') { "`"$_`"" } else { $_ } + }) -join ' ' + $processInfo.UseShellExecute = $false + $processInfo.CreateNoWindow = $true + $processInfo.RedirectStandardInput = $true + $processInfo.RedirectStandardOutput = $true + $processInfo.RedirectStandardError = $true + + $process = [System.Diagnostics.Process]::new() + $process.StartInfo = $processInfo + $process.Start() | Out-Null + $process.StandardInput.Close() + + $stdoutTask = $process.StandardOutput.ReadToEndAsync() + $stderrTask = $process.StandardError.ReadToEndAsync() + + $completed = $process.WaitForExit(60000) + + if (-not $completed) { + $process.Kill() + return @{ ExitCode = -1; Success = $false; Output = ''; Error = "git $($Arguments -join ' ') timed out" } + } + + return @{ + ExitCode = $process.ExitCode + Success = ($process.ExitCode -eq 0) + Output = $stdoutTask.GetAwaiter().GetResult() + Error = $stderrTask.GetAwaiter().GetResult().TrimEnd() + } +} + +$result = @{ + Success = $false + Clean = $false + Message = '' + UnmergedPaths = @() + Conflicts = @() + Errors = @() +} + +# Unmerged paths per the index (authoritative "still conflicted" list). +$ls = Invoke-GitCommand @('ls-files', '-u') +if ($ls.Success -and $ls.Output.Trim()) { + $result.UnmergedPaths = @($ls.Output -split "`n" | ForEach-Object { + ($_ -split "`t")[-1] + } | Where-Object { $_ } | Sort-Object -Unique) +} + +# Grep tracked files for conflict markers. Anchored, exactly-7-char patterns. +# Note: `git grep` exits 1 (no matches) or 0 (matches) — both are "success" for our purposes. +$grepArgs = @('grep', '-nI', '-E', '-e', '^<{7}( |$)', '-e', '^={7}$', '-e', '^>{7}( |$)', '-e', '^\|{7}( |$)') +if ($Path) { + $grepArgs += @('--', $Path) +} elseif (-not $IncludeAll) { + # Exclude the merge documentation, which contains illustrative conflict-marker examples. + $grepArgs += @('--', + ':(exclude).github/instructions', + ':(exclude).github/agents', + ':(exclude).github/prompts', + ':(exclude).github/skills') +} + +$grep = Invoke-GitCommand $grepArgs + +# ExitCode 0 = matches found, 1 = no matches, >1 = real error. +if ($grep.ExitCode -gt 1) { + $result.Errors += "git grep failed: $($grep.Error)" + $result.Message = 'Conflict-marker scan failed to run.' + return $result +} + +$byFile = @{} +if ($grep.Output.Trim()) { + foreach ($line in ($grep.Output -split "`n")) { + if (-not $line.Trim()) { continue } + # Format: path:lineNumber:content + $firstColon = $line.IndexOf(':') + if ($firstColon -lt 0) { continue } + $secondColon = $line.IndexOf(':', $firstColon + 1) + if ($secondColon -lt 0) { continue } + + $file = $line.Substring(0, $firstColon) + $lineNo = [int]$line.Substring($firstColon + 1, $secondColon - $firstColon - 1) + $content = $line.Substring($secondColon + 1) + + if (-not $byFile.ContainsKey($file)) { + $byFile[$file] = @{ + File = $file; StartCount = 0; EndCount = 0; DivCount = 0; BaseCount = 0; Lines = @() + } + } + switch -Regex ($content) { + '^<{7}( |$)' { $byFile[$file].StartCount++ } + '^>{7}( |$)' { $byFile[$file].EndCount++ } + '^\|{7}( |$)' { $byFile[$file].BaseCount++ } + '^={7}$' { $byFile[$file].DivCount++ } + } + $byFile[$file].Lines += @{ Line = $lineNo; Text = $content } + } +} + +# Decide which files are real conflicts. +$conflicts = @() +foreach ($entry in $byFile.Values) { + $hasStartEnd = ($entry.StartCount -gt 0) -or ($entry.EndCount -gt 0) -or ($entry.BaseCount -gt 0) + $dividerOnly = -not $hasStartEnd -and ($entry.DivCount -gt 0) + + if ($hasStartEnd -or ($dividerOnly -and $FailOnDivider)) { + $conflicts += [pscustomobject]$entry + } +} + +$result.Conflicts = @($conflicts | Sort-Object File) + +$hasProblem = ($result.Conflicts.Count -gt 0) -or ($result.UnmergedPaths.Count -gt 0) +$result.Success = -not $hasProblem +$result.Clean = $result.Success + +if ($result.Success) { + $result.Message = 'No unresolved merge conflict markers found in tracked files.' +} else { + $parts = @() + if ($result.Conflicts.Count -gt 0) { + $parts += "$($result.Conflicts.Count) file(s) with conflict markers" + } + if ($result.UnmergedPaths.Count -gt 0) { + $parts += "$($result.UnmergedPaths.Count) unmerged path(s) in the index" + } + $result.Message = "Unresolved conflicts detected: $($parts -join '; '). Resolve them before continuing the merge." +} + +return $result diff --git a/.github/tools/Test-MergePrerequisites.ps1 b/.github/tools/Test-MergePrerequisites.ps1 new file mode 100644 index 000000000000..3cd75bd87657 --- /dev/null +++ b/.github/tools/Test-MergePrerequisites.ps1 @@ -0,0 +1,288 @@ +<# +.SYNOPSIS + MCP tool that verifies all prerequisites for starting an OpenSSH upstream merge. + +.DESCRIPTION + This script performs comprehensive pre-merge setup verification for the OpenSSH + upstream merge workflow. It checks: + - Required tools (Git, PowerShell, Visual Studio) + - Repository configuration (remotes, branch state) + - Target version identification + + This tool should be run before starting Phase 1 of the merge workflow to ensure + all prerequisites are met. It prevents wasted effort by catching configuration + issues early. + + To verify baseline build capability, use the Test-OpenSSHBuild MCP tool: + mcp_openssh-server_Test_OpenSSHBuild + +.PARAMETER TargetVersion + The upstream version/tag to merge (e.g., "V_10_0_P2", "V_9_9_P1") + This can be a tag name or branch name from the upstream repository. + +.OUTPUTS + Returns a hashtable with: + - Success: Boolean indicating all prerequisites passed + - GitInstalled: Boolean - Git is available + - PowerShellVersion: String - PowerShell version + - VSInstalled: Boolean - Visual Studio is available + - RemotesConfigured: Boolean - All required remotes configured + - TargetExists: Boolean - Target version/tag exists in upstream + - WorkingDirClean: Boolean - No uncommitted changes + - Issues: Array - List of any issues found + - Message: String - Summary message + +.EXAMPLE + .\Test-MergePrerequisites.ps1 -TargetVersion "V_10_0_P2" + + Verifies all prerequisites for merging upstream V_10_0_P2. + For baseline build verification, use Test-OpenSSHBuild MCP tool separately. + +.NOTES + - This is a Phase 1 Pre-Merge Setup verification tool + - Should be run before creating the merge branch + - For baseline build verification, use: mcp_openssh-server_Test_OpenSSHBuild + - Part of the OpenSSH upstream merge workflow automation +#> + +param( + [Parameter(Mandatory=$true)] + [string]$TargetVersion +) + +$scriptRoot = $PSScriptRoot +if ([string]::IsNullOrEmpty($scriptRoot)) { + $scriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path +} +$repoRoot = (Get-Item $scriptRoot).Parent.Parent.FullName + +$result = @{ + Success = $false + GitInstalled = $false + PowerShellVersion = $PSVersionTable.PSVersion.ToString() + VSInstalled = $false + RemotesConfigured = $false + TargetExists = $false + WorkingDirClean = $false + Issues = @() + Message = "" +} + +try { + Write-Host "========================================" -ForegroundColor Cyan + Write-Host "OpenSSH Merge Prerequisites Check" -ForegroundColor Cyan + Write-Host "========================================" -ForegroundColor Cyan + Write-Host "Target Version: $TargetVersion" -ForegroundColor White + Write-Host "Repository Root: $repoRoot" -ForegroundColor Gray + Write-Host "========================================`n" -ForegroundColor Cyan + + # Change to repository root + Push-Location $repoRoot + Write-Host "Working Directory: $(Get-Location)" -ForegroundColor Gray + Write-Host "" + + # Step 1: Verify Git + Write-Host "[1/6] Checking Git installation..." -ForegroundColor Cyan + try { + $gitPath = Get-Command git -ErrorAction SilentlyContinue + if ($gitPath) { + $result.GitInstalled = $true + Write-Host " ✓ Git found: $($gitPath.Source)" -ForegroundColor Green + } else { + $result.Issues += "Git is not installed or not in PATH" + Write-Host " ✗ Git not found" -ForegroundColor Red + } + } catch { + $result.Issues += "Git is not installed or not in PATH" + Write-Host " ✗ Git not found" -ForegroundColor Red + } + + # Step 2: Verify PowerShell version + Write-Host "`n[2/6] Checking PowerShell version..." -ForegroundColor Cyan + $psVersion = $PSVersionTable.PSVersion + if ($psVersion.Major -ge 5) { + Write-Host " ✓ PowerShell $($psVersion.ToString()) (>= 5.0)" -ForegroundColor Green + } else { + $result.Issues += "PowerShell version $($psVersion.ToString()) is too old (need >= 5.0)" + Write-Host " ✗ PowerShell $($psVersion.ToString()) is too old (need >= 5.0)" -ForegroundColor Red + } + + # Step 3: Verify Visual Studio + Write-Host "`n[3/6] Checking Visual Studio installation..." -ForegroundColor Cyan + $msBuildPaths = @( + "${env:ProgramFiles}\Microsoft Visual Studio\2022\*\MSBuild\Current\Bin\MSBuild.exe", + "${env:ProgramFiles}\Microsoft Visual Studio\2019\*\MSBuild\Current\Bin\MSBuild.exe", + "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2022\*\MSBuild\Current\Bin\MSBuild.exe", + "${env:ProgramFiles(x86)}\Microsoft Visual Studio\2019\*\MSBuild\Current\Bin\MSBuild.exe" + ) + + $msBuildFound = $false + foreach ($path in $msBuildPaths) { + $resolved = Resolve-Path $path -ErrorAction SilentlyContinue + if ($resolved) { + $msBuildFound = $true + $result.VSInstalled = $true + Write-Host " ✓ Visual Studio found: $($resolved.Path)" -ForegroundColor Green + break + } + } + + if (-not $msBuildFound) { + $result.Issues += "Visual Studio 2019 or later not found" + Write-Host " ✗ Visual Studio 2019 or later not found" -ForegroundColor Red + } + + # Step 4: Verify repository remotes + Write-Host "`n[4/6] Checking repository remotes..." -ForegroundColor Cyan + if ($result.GitInstalled) { + try { + $gitConfigPath = Join-Path $repoRoot ".git\config" + if (Test-Path $gitConfigPath) { + $gitConfig = Get-Content $gitConfigPath -Raw + $expectedRemotes = @('origin', 'upstream', 'upstream-pwsh') + $missingRemotes = @() + + foreach ($remote in $expectedRemotes) { + if ($gitConfig -match "\[remote `"$remote`"\]") { + Write-Host " ✓ $remote configured" -ForegroundColor Green + } else { + $missingRemotes += $remote + Write-Host " ✗ $remote not configured" -ForegroundColor Red + } + } + + if ($missingRemotes.Count -eq 0) { + $result.RemotesConfigured = $true + } else { + $result.Issues += "Missing remotes: $($missingRemotes -join ', ')" + } + } else { + $result.Issues += "Not a git repository" + Write-Host " ✗ Not a git repository" -ForegroundColor Red + } + } catch { + $result.Issues += "Error checking remotes: $($_.Exception.Message)" + Write-Host " ✗ Error checking remotes" -ForegroundColor Red + } + } else { + Write-Host " ⊘ Skipped (Git not available)" -ForegroundColor Yellow + } + + # Step 5: Verify target version exists + Write-Host "`n[5/6] Checking target version exists..." -ForegroundColor Cyan + if ($result.GitInstalled -and $result.RemotesConfigured) { + try { + # Check if tag/branch ref exists in .git directory + $tagPath = Join-Path $repoRoot ".git\refs\tags\$TargetVersion" + $upstreamBranchPath = Join-Path $repoRoot ".git\refs\remotes\upstream\$TargetVersion" + + if (Test-Path $tagPath) { + $result.TargetExists = $true + Write-Host " ✓ Target tag exists locally: $TargetVersion" -ForegroundColor Green + } elseif (Test-Path $upstreamBranchPath) { + $result.TargetExists = $true + Write-Host " ✓ Target branch exists: upstream/$TargetVersion" -ForegroundColor Green + } else { + $result.Issues += "Target version/tag '$TargetVersion' not found locally. Run 'git fetch upstream --tags' to update." + Write-Host " ✗ Target '$TargetVersion' not found locally" -ForegroundColor Red + Write-Host " Hint: Run 'git fetch upstream --tags' to fetch latest tags" -ForegroundColor Yellow + } + } catch { + $result.Issues += "Error checking target version: $($_.Exception.Message)" + Write-Host " ✗ Error checking target version" -ForegroundColor Red + } + } else { + Write-Host " ⊘ Skipped (prerequisites not met)" -ForegroundColor Yellow + } + + # Step 6: Verify working directory is clean + Write-Host "`n[6/6] Checking working directory status..." -ForegroundColor Cyan + if ($result.GitInstalled) { + try { + # Use Start-Job to run git status --porcelain + $job = Start-Job -ScriptBlock { + param($repoPath) + Set-Location $repoPath + git status --porcelain + } -ArgumentList $repoRoot + + $jobResult = Wait-Job $job -Timeout 10 + if ($jobResult) { + $statusOutput = Receive-Job $job + Remove-Job $job -Force + + if ([string]::IsNullOrWhiteSpace($statusOutput)) { + $result.WorkingDirClean = $true + Write-Host " ✓ Working directory is clean" -ForegroundColor Green + } else { + $result.Issues += "Working directory has uncommitted changes" + Write-Host " ✗ Working directory has uncommitted changes:" -ForegroundColor Red + $statusOutput | ForEach-Object { Write-Host " $_" -ForegroundColor Yellow } + Write-Host " Hint: Commit or stash changes before starting merge" -ForegroundColor Yellow + } + } else { + Remove-Job $job -Force + $result.Issues += "Git status check timed out" + Write-Host " ✗ Git status check timed out" -ForegroundColor Red + } + } catch { + $result.Issues += "Error checking working directory: $($_.Exception.Message)" + Write-Host " ✗ Error checking working directory status" -ForegroundColor Red + } + } else { + Write-Host " ⊘ Skipped (Git not available)" -ForegroundColor Yellow + } + + # Final evaluation + Write-Host "`n========================================" -ForegroundColor Cyan + Write-Host "PREREQUISITE CHECK SUMMARY" -ForegroundColor Cyan + Write-Host "========================================" -ForegroundColor Cyan + + $criticalChecks = @( + $result.GitInstalled, + $result.VSInstalled, + $result.RemotesConfigured, + $result.TargetExists, + $result.WorkingDirClean + ) + + $result.Success = ($criticalChecks | Where-Object { $_ -eq $false }).Count -eq 0 + + if ($result.Success) { + Write-Host "✓ ALL PREREQUISITES MET" -ForegroundColor Green + Write-Host "`nYou are ready to begin the merge process:" -ForegroundColor White + $result.Message = "All prerequisites met. Ready to start merge." + } else { + Write-Host "✗ PREREQUISITES NOT MET" -ForegroundColor Red + Write-Host "`nIssues found:" -ForegroundColor Yellow + foreach ($issue in $result.Issues) { + Write-Host " • $issue" -ForegroundColor Red + } + $result.Message = "$($result.Issues.Count) issue(s) found. Fix issues before starting merge." + } + + Write-Host "" + + # Return result + return $result + +} catch { + Write-Host "`n========================================" -ForegroundColor Red + Write-Host "ERROR" -ForegroundColor Red + Write-Host "========================================" -ForegroundColor Red + Write-Host $_.Exception.Message -ForegroundColor Red + Write-Host $_.ScriptStackTrace -ForegroundColor Gray + + $result.Success = $false + $result.Issues += "Tool error: $($_.Exception.Message)" + $result.Message = "Prerequisite check failed with error: $($_.Exception.Message)" + + # Return result + return $result +} finally { + try { + Pop-Location + } catch { + # Ignore Pop-Location errors in MCP context + } +} diff --git a/.github/tools/Test-OpenSSHBuild.ps1 b/.github/tools/Test-OpenSSHBuild.ps1 new file mode 100644 index 000000000000..5b51c07f6d10 --- /dev/null +++ b/.github/tools/Test-OpenSSHBuild.ps1 @@ -0,0 +1,347 @@ +<# +.SYNOPSIS + MCP tool to test OpenSSH build artifacts and parse build errors. + +.DESCRIPTION + This script tests that all expected OpenSSH executables were built successfully + and parses the build log file for any compilation or linker errors using regex patterns. + + Expected artifacts (14 executables): + - ssh.exe, sshd.exe, sshd-auth.exe, sshd-session.exe + - ssh-agent.exe, ssh-add.exe, ssh-keygen.exe, ssh-keyscan.exe + - scp.exe, sftp.exe, sftp-server.exe + - ssh-pkcs11-helper.exe, ssh-shellhost.exe, ssh-sk-helper.exe + +.PARAMETER Configuration + Build configuration type that was used. Valid values: 'Debug', 'Release' + Default: 'Release' + +.PARAMETER Architecture + Target architecture that was built. Valid values: 'x64', 'x86', 'ARM', 'ARM64' + Default: the host machine's architecture (auto-detected). An explicit mismatched value is + rejected unless -AllowArchMismatch is also specified. + +.PARAMETER AllowArchMismatch + Permit targeting an architecture that differs from the host machine's architecture. + +.PARAMETER LogFile + Optional path to the build log file. If not specified, uses default pattern: + OpenSSH{Configuration}{Architecture}.log in repository root. + +.OUTPUTS + Returns a hashtable with: + - Success: Boolean indicating if all artifacts present and no errors + - ArtifactsFound: Array of executables that exist + - ArtifactsMissing: Array of expected executables that are missing + - TotalArtifacts: Count of artifacts found + - ExpectedArtifacts: Count of artifacts expected (14) + - Errors: Array of parsed error objects with file, line, code, message + - Warnings: Array of parsed warning objects + - LogFile: Path to log file analyzed + - Message: Summary message + +.EXAMPLE + .\Test-OpenSSHBuild.ps1 -Configuration Release -Architecture x64 + + Tests release build artifacts for x64 architecture. + +.EXAMPLE + .\Test-OpenSSHBuild.ps1 -Configuration Debug -Architecture x86 -LogFile "C:\build\custom.log" + + Tests debug build artifacts for x86 using a custom log file location. + +.NOTES + - Expected build artifact location: bin\{Architecture}\{Configuration}\ + - Error parsing regex (file/line form): ^(?.+?)\((?\d+)[,)].*?\s(?fatal error|error)\s+(?(?:C|LNK|MSB)\d+)\s*:\s*(?.+)$ + - Error parsing regex (generic/no line): ^(?:.*?:\s*)?(?fatal error|error)\s+(?(?:C|LNK|MSB)\d+)\s*:\s*(?.+)$ + - Warning parsing regex (file/line form): ^(?.+?)\((?\d+)[,)].*?\swarning\s+(?(?:C|LNK|MSB)\d+)\s*:\s*(?.+)$ + - Warning parsing regex (generic/no line): ^(?:.*?:\s*)?warning\s+(?(?:C|LNK|MSB)\d+)\s*:\s*(?.+)$ +#> + +param( + [Parameter(Mandatory=$false)] + [ValidateSet('Debug', 'Release')] + [string]$Configuration = 'Release', + + [Parameter(Mandatory=$false)] + [ValidateSet('x64', 'x86', 'ARM', 'ARM64')] + [string]$Architecture, + + [Parameter(Mandatory=$false)] + [switch]$AllowArchMismatch, + + [Parameter(Mandatory=$false)] + [string]$LogFile +) + +# ── Resolve target architecture (default = host arch; forbid mismatch unless overridden) ── +function Get-HostArchitecture { + $archEnv = $env:PROCESSOR_ARCHITEW6432 + if ([string]::IsNullOrEmpty($archEnv)) { $archEnv = $env:PROCESSOR_ARCHITECTURE } + switch (($archEnv | ForEach-Object { $_.ToUpperInvariant() })) { + 'AMD64' { 'x64' } + 'X86' { 'x86' } + 'ARM64' { 'ARM64' } + 'ARM' { 'ARM' } + default { 'x64' } + } +} + +$hostArch = Get-HostArchitecture +if (-not $PSBoundParameters.ContainsKey('Architecture') -or [string]::IsNullOrEmpty($Architecture)) { + $Architecture = $hostArch +} elseif ($Architecture -ne $hostArch -and -not $AllowArchMismatch) { + throw "Requested architecture '$Architecture' does not match the host architecture '$hostArch'. Re-run with -AllowArchMismatch to target a different architecture on purpose." +} + +# Determine repository root (go up from .github\tools to repo root) +$scriptRoot = $PSScriptRoot +$repoRoot = Split-Path -Parent (Split-Path -Parent $scriptRoot) + +# Define expected artifacts (14 executables) +$expectedArtifacts = @( + "ssh.exe", + "sshd.exe", + "sshd-auth.exe", + "sshd-session.exe", + "ssh-agent.exe", + "ssh-add.exe", + "ssh-keygen.exe", + "ssh-keyscan.exe", + "scp.exe", + "sftp.exe", + "sftp-server.exe", + "ssh-pkcs11-helper.exe", + "ssh-shellhost.exe", + "ssh-sk-helper.exe" +) + +try { + Write-Host "========================================" -ForegroundColor Cyan + Write-Host "OpenSSH Build Test Tool (MCP)" -ForegroundColor Cyan + Write-Host "========================================" -ForegroundColor Cyan + Write-Host "Configuration: $Configuration" -ForegroundColor White + Write-Host "Architecture: $Architecture" -ForegroundColor White + Write-Host "========================================`n" -ForegroundColor Cyan + + # Define build output path + $buildPath = Join-Path $repoRoot "bin\$Architecture\$Configuration" + + if (-not (Test-Path $buildPath)) { + Write-Host "Build path does not exist: $buildPath" -ForegroundColor Red + + $result = @{ + Success = $false + ArtifactsFound = @() + ArtifactsMissing = $expectedArtifacts + TotalArtifacts = 0 + ExpectedArtifacts = $expectedArtifacts.Count + Errors = @() + Warnings = @() + LogFile = $LogFile + Message = "Build path does not exist: $buildPath" + } + + return $result + } + + Write-Host "Build path: $buildPath" -ForegroundColor Gray + + # Check for artifacts + Write-Host "`nChecking for expected artifacts..." -ForegroundColor Cyan + + $artifactsFound = @() + $artifactsMissing = @() + + foreach ($artifact in $expectedArtifacts) { + $artifactPath = Join-Path $buildPath $artifact + if (Test-Path $artifactPath) { + $artifactsFound += $artifact + Write-Host " ✓ $artifact" -ForegroundColor Green + } else { + $artifactsMissing += $artifact + Write-Host " ✗ $artifact (MISSING)" -ForegroundColor Red + } + } + + Write-Host "`nArtifacts: $($artifactsFound.Count) of $($expectedArtifacts.Count) found" -ForegroundColor $(if ($artifactsMissing.Count -eq 0) { "Green" } else { "Yellow" }) + + # Parse build log if available + $errors = @() + $warnings = @() + + if (-not $LogFile) { + $LogFile = Join-Path $repoRoot "contrib\win32\openssh\OpenSSH$Configuration$Architecture.log" + } + + if (Test-Path $LogFile) { + Write-Host "`nParsing build log: $LogFile" -ForegroundColor Cyan + + $logContent = Get-Content $LogFile -ErrorAction SilentlyContinue + $logTime = (Get-Item $LogFile -ErrorAction SilentlyContinue).LastWriteTime + + if ($logContent) { + # Find the first build status marker and, if failed, only scan lines after it + $buildStatusIndex = $null + $buildFailed = $false + for ($i = 0; $i -lt $logContent.Count; $i++) { + $line = $logContent[$i] + if ($line -match 'Build\s+(FAILED|Failed)') { + $buildStatusIndex = $i + $buildFailed = $true + break + } elseif ($line -match 'Build\s+(SUCCEEDED|Succeeded)') { + $buildStatusIndex = $i + break + } + } + + $linesToScan = $logContent + if ($buildFailed -and $buildStatusIndex -ne $null -and $buildStatusIndex + 1 -lt $logContent.Count) { + $linesToScan = $logContent[($buildStatusIndex + 1)..($logContent.Count - 1)] + } + + # Broadened regex patterns to support linker/MSBuild messages without line numbers + $errorWithFileRegex = '^(?.+?)\((?\d+)[,)].*?\s(?fatal error|error)\s+(?(?:C|LNK|MSB)\d+)\s*:\s*(?.+)$' + $genericErrorRegex = '^(?:.*?:\s*)?(?fatal error|error)\s+(?(?:C|LNK|MSB)\d+)\s*:\s*(?.+)$' + $warningWithFileRegex = '^(?.+?)\((?\d+)[,)].*?\swarning\s+(?(?:C|LNK|MSB)\d+)\s*:\s*(?.+)$' + $genericWarningRegex = '^(?:.*?:\s*)?warning\s+(?(?:C|LNK|MSB)\d+)\s*:\s*(?.+)$' + + foreach ($line in $linesToScan) { + # Errors with file/line + if ($line -match $errorWithFileRegex) { + $errors += [PSCustomObject]@{ + File = $matches['file'] + Line = [int]$matches['line'] + Code = $matches['code'] + Message = $matches['message'] + RawLine = $line + } + continue + } + # Generic errors (e.g., LINK/MSBuild without line numbers) + if ($line -match $genericErrorRegex) { + $errors += [PSCustomObject]@{ + File = '' + Line = $null + Code = $matches['code'] + Message = $matches['message'] + RawLine = $line + } + continue + } + # Warnings with file/line + if ($line -match $warningWithFileRegex) { + $warnings += [PSCustomObject]@{ + File = $matches['file'] + Line = [int]$matches['line'] + Code = $matches['code'] + Message = $matches['message'] + RawLine = $line + } + continue + } + # Generic warnings + if ($line -match $genericWarningRegex) { + $warnings += [PSCustomObject]@{ + File = '' + Line = $null + Code = $matches['code'] + Message = $matches['message'] + RawLine = $line + } + } + } + + if ($errors.Count -gt 0) { + Write-Host "`nFound $($errors.Count) error(s) in build log:" -ForegroundColor Red + foreach ($e in $errors) { + if ([string]::IsNullOrEmpty($e.File)) { + Write-Host " error $($e.Code): $($e.Message)" -ForegroundColor Red + } else { + $lineSuffix = if ($e.Line -ne $null) { "(" + $e.Line + ")" } else { "" } + Write-Host (" {0}{1}: error {2}: {3}" -f $e.File, $lineSuffix, $e.Code, $e.Message) -ForegroundColor Red + } + } + } else { + Write-Host "`n✓ No errors found in build log" -ForegroundColor Green + } + + if ($warnings.Count -gt 0) { + Write-Host "`nFound $($warnings.Count) warning(s) in build log:" -ForegroundColor Yellow + foreach ($warning in $warnings | Select-Object -First 10) { + if ([string]::IsNullOrEmpty($warning.File)) { + Write-Host " warning $($warning.Code): $($warning.Message)" -ForegroundColor Yellow + } else { + $lineSuffix = if ($warning.Line -ne $null) { "(" + $warning.Line + ")" } else { "" } + Write-Host (" {0}{1}: warning {2}: {3}" -f $warning.File, $lineSuffix, $warning.Code, $warning.Message) -ForegroundColor Yellow + } + } + if ($warnings.Count -gt 10) { + Write-Host " ... and $($warnings.Count - 10) more warnings" -ForegroundColor Gray + } + } + } else { + Write-Host "Log file is empty or could not be read" -ForegroundColor Yellow + } + + # Timestamp freshness checks removed; rely on build log parsing instead + } else { + Write-Host "`nBuild log not found: $LogFile" -ForegroundColor Yellow + } + + # Determine overall success + $success = ($artifactsMissing.Count -eq 0) -and ($errors.Count -eq 0) + + # Build summary message + if ($success) { + $message = "All $($expectedArtifacts.Count) artifacts built successfully with no errors" + } elseif ($artifactsMissing.Count -gt 0 -and $errors.Count -gt 0) { + $message = "$($artifactsMissing.Count) artifacts missing and $($errors.Count) error(s) found" + } elseif ($artifactsMissing.Count -gt 0) { + $message = "$($artifactsMissing.Count) artifacts missing" + } else { + $message = "$($errors.Count) error(s) found in build log" + } + + Write-Host "`n========================================" -ForegroundColor $(if ($success) { "Green" } else { "Red" }) + Write-Host $(if ($success) { "TEST PASSED" } else { "TEST FAILED" }) -ForegroundColor $(if ($success) { "Green" } else { "Red" }) + Write-Host "========================================" -ForegroundColor $(if ($success) { "Green" } else { "Red" }) + Write-Host $message -ForegroundColor White + + $result = @{ + Success = $success + ArtifactsFound = $artifactsFound + ArtifactsMissing = $artifactsMissing + TotalArtifacts = $artifactsFound.Count + ExpectedArtifacts = $expectedArtifacts.Count + Errors = $errors + Warnings = $warnings + LogFile = $LogFile + # BuildLogTimestamp and stale artifact checks removed + Message = $message + } + + return $result + +} catch { + Write-Host "`n========================================" -ForegroundColor Red + Write-Host "ERROR" -ForegroundColor Red + Write-Host "========================================" -ForegroundColor Red + Write-Host $_.Exception.Message -ForegroundColor Red + Write-Host $_.ScriptStackTrace -ForegroundColor Gray + + $result = @{ + Success = $false + ArtifactsFound = @() + ArtifactsMissing = $expectedArtifacts + TotalArtifacts = 0 + ExpectedArtifacts = $expectedArtifacts.Count + Errors = @() + Warnings = @() + LogFile = $LogFile + Message = "Test tool error: $($_.Exception.Message)" + } + + return $result +} diff --git a/.github/tools/Test-OpenSSHFunctionality.ps1 b/.github/tools/Test-OpenSSHFunctionality.ps1 new file mode 100644 index 000000000000..3217ed0747fa --- /dev/null +++ b/.github/tools/Test-OpenSSHFunctionality.ps1 @@ -0,0 +1,526 @@ +<# +.SYNOPSIS + Tests OpenSSH functionality by installing the SSH service, creating a test user, + and attempting a password-authenticated SSH connection. + +.DESCRIPTION + This script performs end-to-end functional testing of OpenSSH on Windows by: + 1. Verifying Administrator privileges + 2. Creating a temporary local user with a random password + 3. Installing the SSH service using install-sshd.ps1 + 4. Starting the SSH service + 5. Configuring Windows Firewall (optional) + 6. Testing SSH connection with password authentication + 7. Cleaning up all resources (user, service, firewall rule) + + The test is successful if an SSH connection can execute "echo hello world" successfully. + +.PARAMETER Configuration + Build configuration type. Valid values: 'Debug', 'Release' + Default: 'Release' + +.PARAMETER Architecture + Target architecture. Valid values: 'x64', 'x86', 'ARM', 'ARM64' + Default: the host machine's architecture (auto-detected). A mismatched explicit value is + rejected unless -AllowArchMismatch is specified (functionality tests run host-native binaries). + +.PARAMETER AllowArchMismatch + Permit targeting an architecture that differs from the host machine's architecture. + +.PARAMETER SkipFirewall + Skip Windows Firewall configuration. Use this if firewall rules already exist + or if testing on a system without firewall enabled. + +.PARAMETER NoCleanup + Skip cleanup of created resources (test user, firewall rule, temp files). + Useful when debugging failures. + +.EXAMPLE + .\Test-OpenSSHFunctionality.ps1 + Tests using default Release x64 build with firewall configuration + +.EXAMPLE + .\Test-OpenSSHFunctionality.ps1 -Configuration Debug -Architecture x64 + Tests using Debug x64 build + +.EXAMPLE + .\Test-OpenSSHFunctionality.ps1 -SkipFirewall + Tests without modifying firewall rules + +.NOTES + Requires Administrator privileges. + Creates temporary user with prefix "openssh_test_" which is removed after testing. +#> + +[CmdletBinding()] +param( + [Parameter()] + [ValidateSet('Debug', 'Release')] + [string]$Configuration = 'Release', + + [Parameter()] + [ValidateSet('x64', 'x86', 'ARM', 'ARM64')] + [string]$Architecture, + + [Parameter()] + [switch]$AllowArchMismatch, + + [Parameter()] + [switch]$SkipFirewall, + + [Parameter()] + [switch]$NoCleanup +) + +# ── Resolve target architecture (default = host arch; forbid mismatch unless overridden) ── +function Get-HostArchitecture { + $archEnv = $env:PROCESSOR_ARCHITEW6432 + if ([string]::IsNullOrEmpty($archEnv)) { $archEnv = $env:PROCESSOR_ARCHITECTURE } + switch (($archEnv | ForEach-Object { $_.ToUpperInvariant() })) { + 'AMD64' { 'x64' } + 'X86' { 'x86' } + 'ARM64' { 'ARM64' } + 'ARM' { 'ARM' } + default { 'x64' } + } +} + +$hostArch = Get-HostArchitecture +if (-not $PSBoundParameters.ContainsKey('Architecture') -or [string]::IsNullOrEmpty($Architecture)) { + $Architecture = $hostArch +} elseif ($Architecture -ne $hostArch -and -not $AllowArchMismatch) { + throw "Requested architecture '$Architecture' does not match the host architecture '$hostArch'. Functionality tests must run against host-native binaries; re-run with -AllowArchMismatch only if you know the target binaries can execute here." +} + +# Helper function to generate a random password +function New-RandomPassword { + [CmdletBinding()] + param( + [Parameter()] + [int]$Length = 20 + ) + + # Character sets for password complexity + $lowercase = 'abcdefghijklmnopqrstuvwxyz' + $uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + $numbers = '0123456789' + $special = '!@#$%^&*()_+-=[]{}|;:,.<>?' + + # Ensure at least one character from each set + $password = @( + $lowercase[(Get-Random -Maximum $lowercase.Length)] + $uppercase[(Get-Random -Maximum $uppercase.Length)] + $numbers[(Get-Random -Maximum $numbers.Length)] + $special[(Get-Random -Maximum $special.Length)] + ) + + # Fill the rest with random characters from all sets + $allChars = $lowercase + $uppercase + $numbers + $special + for ($i = $password.Count; $i -lt $Length; $i++) { + $password += $allChars[(Get-Random -Maximum $allChars.Length)] + } + + # Shuffle the password + $shuffled = $password | Sort-Object {Get-Random} + + return -join $shuffled +} + +# Initialize result object +$result = [PSCustomObject]@{ + Success = $false + ServiceInstalled = $false + ServiceStarted = $false + ConnectionSuccessful = $false + CommandOutput = $null + TestUser = $null + Errors = @() + Message = "" +} + +# Variables for cleanup tracking +$testUser = $null +$testUserSid = $null +$serviceWasInstalled = $false +$firewallRuleCreated = $false + +try { + Write-Host "=== OpenSSH Functionality Test ===" -ForegroundColor Cyan + Write-Host "Configuration: $Configuration" -ForegroundColor Gray + Write-Host "Architecture: $Architecture" -ForegroundColor Gray + Write-Host "" + + # Step 1: Verify Administrator privileges + Write-Host "[1/6] Checking Administrator privileges..." -ForegroundColor Yellow + $isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") + + if (-not $isAdmin) { + $result.Errors += "Administrator privileges required" + $result.Message = "FAILED: This script must be run as Administrator for service installation and user management." + Write-Host "✗ Administrator privileges required" -ForegroundColor Red + Write-Host " Please restart PowerShell or VS Code as Administrator" -ForegroundColor Yellow + return $result + } + Write-Host "✓ Running with Administrator privileges" -ForegroundColor Green + + # Step 2: Locate build artifacts and scripts + $scriptRoot = Split-Path -Parent $PSCommandPath + $repoRoot = Split-Path -Parent (Split-Path -Parent $scriptRoot) + $buildPath = Join-Path $repoRoot "bin\$Architecture\$Configuration" + $askPassExe = Join-Path $repoRoot "regress\pesterTests\utilities\askpass_util\askpass_util.exe" + + # Verify build artifacts exist + $sshdExe = Join-Path $buildPath "sshd.exe" + $sshExe = Join-Path $buildPath "ssh.exe" + $installScript = Join-Path $buildPath "install-sshd.ps1" + + if (-not (Test-Path $sshdExe) -or -not (Test-Path $sshExe)) { + $result.Errors += "Build artifacts not found at $buildPath" + $result.Message = "FAILED: Build artifacts not found. Please build the project first." + Write-Host "✗ Build artifacts not found at $buildPath" -ForegroundColor Red + return $result + } + + if (-not (Test-Path $installScript)) { + $result.Errors += "install-sshd.ps1 not found at $buildPath" + $result.Message = "FAILED: install-sshd.ps1 script not found." + Write-Host "✗ install-sshd.ps1 not found at $buildPath" -ForegroundColor Red + return $result + } + + # Step 3: Create temporary test user + Write-Host "`n[2/6] Creating temporary test user..." -ForegroundColor Yellow + $testUsername = "openssh_test_" + (Get-Random -Minimum 1000 -Maximum 9999) + $testPassword = New-RandomPassword -Length 24 + $securePassword = ConvertTo-SecureString $testPassword -AsPlainText -Force + + try { + Import-Module Microsoft.PowerShell.LocalAccounts -UseWindowsPowerShell + $newUser = New-LocalUser -Name $testUsername -Password $securePassword -Description "Temporary user for OpenSSH testing" -ErrorAction Stop + $testUser = $testUsername + # Capture the SID now so the user's profile folder can be reliably removed + # during cleanup, even after the local account itself has been deleted. + $testUserSid = $newUser.SID.Value + $result.TestUser = $testUsername + $env:ASKPASS_PASSWORD = $testPassword + $env:SSH_ASKPASS_REQUIRE = "force" + if (-not (Test-Path $askPassExe)) { + throw "SSH_ASKPASS helper not found at '$askPassExe'" + } + $env:SSH_ASKPASS = $askPassExe + Write-Host "✓ Created test user: $testUsername" -ForegroundColor Green + } + catch { + $result.Errors += "Failed to create test user: $_" + $result.Message = "FAILED: Could not create temporary test user." + Write-Host "✗ Failed to create test user: $_" -ForegroundColor Red + return $result + } + + # Step 4: Install SSH service + Write-Host "`n[3/6] Installing SSH service..." -ForegroundColor Yellow + Push-Location $buildPath + try { + # Check if service already exists + $existingService = Get-Service sshd -ErrorAction SilentlyContinue + if ($existingService) { + Write-Host " SSH service already exists, uninstalling first..." -ForegroundColor Gray + $uninstallScript = Join-Path $buildPath "uninstall-sshd.ps1" + if (Test-Path $uninstallScript) { + & $uninstallScript 2>&1 | Out-Null + Start-Sleep -Seconds 2 + } + } + + # Install the service + & $installScript 2>&1 | Out-Null + $serviceWasInstalled = $true + + # Verify installation + $service = Get-Service sshd -ErrorAction SilentlyContinue + if ($service) { + $result.ServiceInstalled = $true + Write-Host "✓ SSH service installed successfully" -ForegroundColor Green + } + else { + throw "Service installation completed but service not found" + } + } + catch { + $result.Errors += "Failed to install SSH service: $_" + $result.Message = "FAILED: SSH service installation failed." + Write-Host "✗ Failed to install SSH service: $_" -ForegroundColor Red + return $result + } + finally { + Pop-Location + } + + # Step 5: Start SSH service + Write-Host "`n[4/6] Starting SSH service..." -ForegroundColor Yellow + try { + Start-Service sshd -ErrorAction Stop + Start-Sleep -Seconds 2 + + $service = Get-Service sshd + if ($service.Status -eq 'Running') { + $result.ServiceStarted = $true + Write-Host "✓ SSH service started successfully" -ForegroundColor Green + } + else { + throw "Service status is $($service.Status), expected Running" + } + } + catch { + $result.Errors += "Failed to start SSH service: $_" + $result.Message = "FAILED: Could not start SSH service." + Write-Host "✗ Failed to start SSH service: $_" -ForegroundColor Red + return $result + } + + # Step 6: Configure Windows Firewall (if not skipped) + if (-not $SkipFirewall) { + Write-Host "`n[5/6] Configuring Windows Firewall..." -ForegroundColor Yellow + try { + # Check if rule already exists + $existingRule = Get-NetFirewallRule -DisplayName "SSH Server (sshd) - Test" -ErrorAction SilentlyContinue + if ($existingRule) { + Remove-NetFirewallRule -DisplayName "SSH Server (sshd) - Test" -ErrorAction SilentlyContinue + } + + New-NetFirewallRule -DisplayName "SSH Server (sshd) - Test" -Direction Inbound -Port 22 -Protocol TCP -Action Allow -ErrorAction Stop | Out-Null + $firewallRuleCreated = $true + Write-Host "✓ Firewall rule created" -ForegroundColor Green + } + catch { + # Non-critical error, continue with test + Write-Host "⚠ Firewall configuration failed (non-critical): $_" -ForegroundColor Yellow + } + } + else { + Write-Host "`n[5/6] Skipping firewall configuration (as requested)" -ForegroundColor Gray + } + + # Step 7: Test SSH connection + Write-Host "`n[6/6] Testing SSH connection..." -ForegroundColor Yellow + + # Prepare connection test + $sshClientPath = Join-Path $buildPath "ssh.exe" + $hostname = "localhost" + $testCommand = "echo hello world" + + # Create temporary files for password input and output capture + $tempPasswordFile = [System.IO.Path]::GetTempFileName() + $tempOutputFile = [System.IO.Path]::GetTempFileName() + $tempErrorFile = [System.IO.Path]::GetTempFileName() + + try { + # Write password to temp file (for potential use, though we'll use environment variable) + Set-Content -Path $tempPasswordFile -Value $testPassword -NoNewline + + # Build SSH command with password authentication forced + # Note: Windows SSH doesn't support stdin password directly, so we rely on interactive prompt handling + # For automated testing, we'll use SSH with key-based auth disabled and capture output + + $processInfo = New-Object System.Diagnostics.ProcessStartInfo + $processInfo.FileName = $sshClientPath + $processInfo.Arguments = "-o StrictHostKeyChecking=no -o UserKnownHostsFile=NUL -o PubkeyAuthentication=no -o PasswordAuthentication=yes $testUsername@$hostname `"$testCommand`"" + $processInfo.RedirectStandardInput = $true + $processInfo.RedirectStandardOutput = $true + $processInfo.RedirectStandardError = $true + $processInfo.UseShellExecute = $false + $processInfo.CreateNoWindow = $true + + $process = New-Object System.Diagnostics.Process + $process.StartInfo = $processInfo + + Write-Host " Attempting SSH connection to $testUsername@$hostname..." -ForegroundColor Gray + + $process.Start() | Out-Null + + # Begin async reads BEFORE blocking on WaitForExit — prevents deadlock when + # SSH output exceeds the internal stream buffer size (same issue as MCP stdio). + $stdoutTask = $process.StandardOutput.ReadToEndAsync() + $stderrTask = $process.StandardError.ReadToEndAsync() + + $completed = $process.WaitForExit(30000) # 30-second timeout + + if (-not $completed) { + $process.Kill() + throw "SSH connection timed out after 30 seconds" + } + + $stdout = $stdoutTask.GetAwaiter().GetResult() + $stderr = $stderrTask.GetAwaiter().GetResult() + $exitCode = $process.ExitCode + + # Check result + if ($exitCode -eq 0 -and $stdout -match "hello world") { + $result.ConnectionSuccessful = $true + $result.CommandOutput = $stdout.Trim() + $result.Success = $true + $result.Message = "SUCCESS: SSH connection test passed. Command executed successfully." + Write-Host "✓ SSH connection successful" -ForegroundColor Green + Write-Host " Command output: $($stdout.Trim())" -ForegroundColor Gray + } + else { + $result.Errors += "SSH connection failed with exit code $exitCode" + if ($stderr) { + $result.Errors += "SSH error: $stderr" + } + $result.Message = "FAILED: SSH connection test failed." + Write-Host "✗ SSH connection failed (exit code: $exitCode)" -ForegroundColor Red + if ($stderr) { + Write-Host " Error: $stderr" -ForegroundColor Red + } + } + } + catch { + $result.Errors += "SSH connection test error: $_" + $result.Message = "FAILED: SSH connection test encountered an error." + Write-Host "✗ SSH connection test error: $_" -ForegroundColor Red + } + finally { + # Clean up temp files + if (Test-Path $tempPasswordFile) { Remove-Item $tempPasswordFile -Force -ErrorAction SilentlyContinue } + if (Test-Path $tempOutputFile) { Remove-Item $tempOutputFile -Force -ErrorAction SilentlyContinue } + if (Test-Path $tempErrorFile) { Remove-Item $tempErrorFile -Force -ErrorAction SilentlyContinue } + } +} +finally { + # Cleanup: Always attempt to clean up resources + Write-Host "`n=== Cleanup ===" -ForegroundColor Cyan + + if ($NoCleanup) { + Write-Host "⚠ NoCleanup specified - leaving resources in place for investigation." -ForegroundColor Yellow + if ($testUser) { + Write-Host " Test user: $testUser" -ForegroundColor Yellow + Write-Host " Test user profile folder: $(Join-Path $env:SystemDrive "Users\$testUser") (if a login occurred)" -ForegroundColor Yellow + } + if ($serviceWasInstalled) { + Write-Host " SSH service may still be installed/running (sshd)." -ForegroundColor Yellow + } + if ($firewallRuleCreated) { + Write-Host " Firewall rule: SSH Server (sshd) - Test" -ForegroundColor Yellow + } + Write-Host ""; + } else { + # Stop and uninstall SSH service + if ($serviceWasInstalled) { + Write-Host "Stopping SSH service..." -ForegroundColor Gray + try { + Stop-Service sshd -Force -ErrorAction SilentlyContinue + Start-Sleep -Seconds 1 + } + catch { + Write-Host "⚠ Warning: Failed to stop service: $_" -ForegroundColor Yellow + } + + Write-Host "Uninstalling SSH service..." -ForegroundColor Gray + $uninstallScript = Join-Path $buildPath "uninstall-sshd.ps1" + if (Test-Path $uninstallScript) { + Push-Location $buildPath + try { + & $uninstallScript 2>&1 | Out-Null + Write-Host "✓ SSH service uninstalled" -ForegroundColor Green + } + catch { + Write-Host "⚠ Warning: Failed to uninstall service: $_" -ForegroundColor Yellow + } + finally { + Pop-Location + } + } + } + + # Remove firewall rule + if ($firewallRuleCreated) { + Write-Host "Removing firewall rule..." -ForegroundColor Gray + try { + Remove-NetFirewallRule -DisplayName "SSH Server (sshd) - Test" -ErrorAction SilentlyContinue + Write-Host "✓ Firewall rule removed" -ForegroundColor Green + } + catch { + Write-Host "⚠ Warning: Failed to remove firewall rule: $_" -ForegroundColor Yellow + } + } + + # Remove test user + if ($testUser) { + Write-Host "Removing test user..." -ForegroundColor Gray + try { + Remove-LocalUser -Name $testUser -ErrorAction Stop + Write-Host "✓ Test user removed" -ForegroundColor Green + } + catch { + Write-Host "⚠ Warning: Failed to remove test user: $_" -ForegroundColor Yellow + Write-Host " You may need to manually remove user: $testUser" -ForegroundColor Yellow + } + + # Remove the user's profile folder (e.g. C:\Users\openssh_test_1234). + # Windows creates this directory the first time the account logs in (via SSH), + # and Remove-LocalUser does NOT delete it. Use the Win32_UserProfile CIM class + # so the registry profile entry and the on-disk folder are both cleaned up. + Write-Host "Removing test user profile..." -ForegroundColor Gray + try { + $userProfile = $null + if ($testUserSid) { + $userProfile = Get-CimInstance -ClassName Win32_UserProfile -Filter "SID='$testUserSid'" -ErrorAction SilentlyContinue + } + if (-not $userProfile) { + # Fall back to matching by the profile's on-disk path. + $userProfile = Get-CimInstance -ClassName Win32_UserProfile -ErrorAction SilentlyContinue | + Where-Object { $_.LocalPath -and ($_.LocalPath.Split('\')[-1] -eq $testUser) } + } + + if ($userProfile) { + $profilePath = $userProfile.LocalPath + $userProfile | Remove-CimInstance -ErrorAction Stop + # Remove-CimInstance deletes the profile registration; ensure the + # folder itself is gone in case any files were left behind. + if ($profilePath -and (Test-Path $profilePath)) { + Remove-Item -Path $profilePath -Recurse -Force -ErrorAction SilentlyContinue + } + Write-Host "✓ Test user profile removed" -ForegroundColor Green + } + else { + # No profile was ever created (e.g. SSH login never completed). + $fallbackPath = Join-Path $env:SystemDrive "Users\$testUser" + if (Test-Path $fallbackPath) { + Remove-Item -Path $fallbackPath -Recurse -Force -ErrorAction Stop + Write-Host "✓ Test user profile folder removed" -ForegroundColor Green + } + else { + Write-Host " No profile folder found for $testUser" -ForegroundColor Gray + } + } + } + catch { + Write-Host "⚠ Warning: Failed to remove test user profile: $_" -ForegroundColor Yellow + Write-Host " You may need to manually remove folder: $(Join-Path $env:SystemDrive "Users\$testUser")" -ForegroundColor Yellow + } + } + + Write-Host "" + } +} + +# Output summary +Write-Host "=== Test Summary ===" -ForegroundColor Cyan +Write-Host "Status: $(if ($result.Success) { 'PASSED' } else { 'FAILED' })" -ForegroundColor $(if ($result.Success) { 'Green' } else { 'Red' }) +Write-Host "Service Installed: $($result.ServiceInstalled)" -ForegroundColor Gray +Write-Host "Service Started: $($result.ServiceStarted)" -ForegroundColor Gray +Write-Host "Connection Successful: $($result.ConnectionSuccessful)" -ForegroundColor Gray +if ($result.CommandOutput) { + Write-Host "Command Output: $($result.CommandOutput)" -ForegroundColor Gray +} +if ($result.Errors.Count -gt 0) { + Write-Host "Errors:" -ForegroundColor Red + foreach ($e in $result.Errors) { + Write-Host " - $e" -ForegroundColor Red + } +} +Write-Host "" + +# Return result object +return $result diff --git a/.github/tools/Update-VcpkgPort.ps1 b/.github/tools/Update-VcpkgPort.ps1 new file mode 100644 index 000000000000..029e7d5cd5b8 --- /dev/null +++ b/.github/tools/Update-VcpkgPort.ps1 @@ -0,0 +1,339 @@ +<# +.SYNOPSIS + Bumps a vendored vcpkg dependency to a new upstream version. + +.DESCRIPTION + This script automates the mechanical parts of updating a vendored vcpkg + dependency in this repository. It is normally invoked through the + `update-vcpkg-port` skill (.github/skills/update-vcpkg-port/SKILL.md), + which adds the orchestration and decision logic around it. + + For all supported ports it updates the matching entry in + contrib/win32/openssh/vcpkg.json `overrides[]`. Optionally bumps the + `builtin-baseline`. + + For overlay ports (libressl, libfido2) it additionally: + - Updates contrib/win32/openssh/vcpkg_overlay_ports//vcpkg.json + `version`. + - Downloads the new source archive, computes its SHA512, and rewrites + the SHA512 line in portfile.cmake. + + For libressl it additionally rewrites FILEVERSION / PRODUCTVERSION / + "FileVersion" / "ProductVersion" in + vcpkg_overlay_ports/libressl/add-version-file.patch so the + cross-check enforced by Install-VcpkgDependencies.ps1 stays green. + + Patch *re-application* is intentionally NOT automated. After this tool + runs, invoke Install-VcpkgDependencies.ps1; if vcpkg reports a + rejected hunk, the patch must be regenerated by hand. The skill walks + the user through that decision tree. + +.PARAMETER Port + One of: libressl, libfido2, zlib, libcbor. + +.PARAMETER Version + New target version (e.g. '4.3.0', '1.17.0'). + +.PARAMETER SourceUrl + Optional explicit URL to download the source archive from. Required + only if the port's existing portfile.cmake doesn't expose a derivable + URL for the new version (rare). + +.PARAMETER Baseline + Optional new value for vcpkg.json `builtin-baseline`. If omitted, the + baseline is left untouched. + +.PARAMETER DryRun + Print all planned changes without modifying any files. + +.OUTPUTS + Returns a hashtable with: + - Success: Boolean + - Port: Port name + - OldVersion / NewVersion + - FilesChanged: Array of file paths that would be / were modified + - Sha512: Computed SHA512 (overlay ports only) + - LibresslPatchUpdated: Boolean (libressl only) + - DryRun: Boolean + - Errors: Array of error strings + - Message: Summary message + +.EXAMPLE + .\Update-VcpkgPort.ps1 -Port libfido2 -Version 1.17.0 -DryRun + + Show what changes would be made for a libfido2 bump. + +.EXAMPLE + .\Update-VcpkgPort.ps1 -Port libressl -Version 4.3.0 + + Bump libressl, refresh SHA512, update add-version-file.patch, write + files to disk. Validate afterwards with Install-VcpkgDependencies.ps1. + +.NOTES + - Network access required for overlay ports (downloads source archive). + - Does NOT run vcpkg install. Validate by running + Install-VcpkgDependencies.ps1 after this tool succeeds. + - Always run on a clean working tree so the diff is easy to review. +#> + +param( + [Parameter(Mandatory=$true)] + [ValidateSet('libressl', 'libfido2', 'zlib', 'libcbor')] + [string]$Port, + + [Parameter(Mandatory=$true)] + [string]$Version, + + [Parameter(Mandatory=$false)] + [string]$SourceUrl, + + [Parameter(Mandatory=$false)] + [string]$Baseline, + + [Parameter(Mandatory=$false)] + [switch]$DryRun +) + +$ErrorActionPreference = 'Stop' + +$scriptRoot = $PSScriptRoot +if ([string]::IsNullOrEmpty($scriptRoot)) { + $scriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path +} +$repoRoot = (Get-Item $scriptRoot).Parent.Parent.FullName +$opensshDir = Join-Path $repoRoot 'contrib\win32\openssh' +$manifestPath = Join-Path $opensshDir 'vcpkg.json' +$overlayPortsDir = Join-Path $opensshDir 'vcpkg_overlay_ports' +$overlayPortDir = Join-Path $overlayPortsDir $Port +$overlayManifestPath = Join-Path $overlayPortDir 'vcpkg.json' +$overlayPortfilePath = Join-Path $overlayPortDir 'portfile.cmake' +$libresslPatchPath = Join-Path $overlayPortsDir 'libressl\add-version-file.patch' + +$result = @{ + Success = $false + Port = $Port + OldVersion = $null + NewVersion = $Version + FilesChanged = @() + Sha512 = $null + LibresslPatchUpdated = $false + DryRun = [bool]$DryRun + Errors = @() + Message = '' +} + +function Get-PortDownloadUrl { + param([string]$Port, [string]$Version, [string]$Override) + + if (-not [string]::IsNullOrWhiteSpace($Override)) { + return $Override + } + switch ($Port) { + 'libressl' { return "https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-$Version.tar.gz" } + 'libfido2' { return "https://github.com/Yubico/libfido2/archive/refs/tags/$Version.tar.gz" } + default { return $null } + } +} + +function Get-Sha512OfUrl { + param([string]$Url) + + $tmp = New-TemporaryFile + try { + Write-Host " Downloading $Url" -ForegroundColor Gray + Invoke-WebRequest -Uri $Url -OutFile $tmp.FullName -UseBasicParsing + $hash = (Get-FileHash -Path $tmp.FullName -Algorithm SHA512).Hash + return $hash.ToLowerInvariant() + } finally { + Remove-Item -LiteralPath $tmp.FullName -Force -ErrorAction SilentlyContinue + } +} + +function Update-JsonFile { + param( + [string]$Path, + [scriptblock]$Mutator + ) + + $raw = Get-Content -LiteralPath $Path -Raw + $obj = $raw | ConvertFrom-Json + & $Mutator $obj + $newRaw = ($obj | ConvertTo-Json -Depth 20) + if ($raw.EndsWith("`n") -and -not $newRaw.EndsWith("`n")) { + $newRaw += "`n" + } + return $newRaw +} + +try { + Write-Host "========================================" -ForegroundColor Cyan + Write-Host "Update vcpkg Port: $Port -> $Version" -ForegroundColor Cyan + Write-Host "========================================" -ForegroundColor Cyan + Write-Host "Repository Root: $repoRoot" -ForegroundColor Gray + if ($DryRun) { + Write-Host "Mode: DRY RUN (no files written)" -ForegroundColor Yellow + } + Write-Host "========================================`n" -ForegroundColor Cyan + + # Step 1: Read current manifest, capture old version + Write-Host "[1/4] Reading manifest..." -ForegroundColor Cyan + if (-not (Test-Path -LiteralPath $manifestPath)) { + throw "vcpkg.json not found at $manifestPath" + } + $manifest = Get-Content -LiteralPath $manifestPath -Raw | ConvertFrom-Json + $override = $manifest.overrides | Where-Object { $_.name -eq $Port } + if (-not $override) { + throw "No override entry for '$Port' in $manifestPath. Add it to overrides[] manually first." + } + $result.OldVersion = $override.version + Write-Host " Current: $Port $($override.version)" -ForegroundColor White + Write-Host " Target : $Port $Version" -ForegroundColor White + + if ($override.version -eq $Version) { + Write-Host " ⊘ Version already matches; nothing to do." -ForegroundColor Yellow + $result.Success = $true + $result.Message = 'No changes; version already matches.' + return $result + } + + # Step 2: Compute new SHA512 if overlay port + Write-Host "`n[2/4] Computing SHA512..." -ForegroundColor Cyan + $isOverlay = Test-Path -LiteralPath $overlayPortDir + if ($isOverlay) { + $url = Get-PortDownloadUrl -Port $Port -Version $Version -Override $SourceUrl + if (-not $url) { + throw "No default download URL for port '$Port'. Provide -SourceUrl explicitly." + } + $result.Sha512 = Get-Sha512OfUrl -Url $url + Write-Host " SHA512: $($result.Sha512)" -ForegroundColor Green + } else { + Write-Host " ⊘ Skipped (no overlay port for '$Port')" -ForegroundColor Yellow + } + + # Step 3: Plan edits + Write-Host "`n[3/4] Planning edits..." -ForegroundColor Cyan + $edits = @() + + # 3a: top-level manifest override + $newManifestRaw = Update-JsonFile -Path $manifestPath -Mutator { + param($m) + ($m.overrides | Where-Object { $_.name -eq $Port }).version = $Version + if (-not [string]::IsNullOrWhiteSpace($Baseline)) { + $m.'builtin-baseline' = $Baseline + } + }.GetNewClosure() + $edits += @{ Path = $manifestPath; NewContent = $newManifestRaw } + $result.FilesChanged += $manifestPath + Write-Host " • $manifestPath" -ForegroundColor White + + if ($isOverlay) { + # 3b: overlay manifest version + if (Test-Path -LiteralPath $overlayManifestPath) { + $newOverlayRaw = Update-JsonFile -Path $overlayManifestPath -Mutator { + param($m) + $m.version = $Version + }.GetNewClosure() + $edits += @{ Path = $overlayManifestPath; NewContent = $newOverlayRaw } + $result.FilesChanged += $overlayManifestPath + Write-Host " • $overlayManifestPath" -ForegroundColor White + } + + # 3c: portfile.cmake SHA512 line + if (Test-Path -LiteralPath $overlayPortfilePath) { + $portfileText = Get-Content -LiteralPath $overlayPortfilePath -Raw + $shaPattern = '(?m)^(\s*SHA512\s+)[0-9a-fA-F]+' + if ([regex]::IsMatch($portfileText, $shaPattern)) { + $newPortfile = [regex]::Replace($portfileText, $shaPattern, "`${1}$($result.Sha512)") + $edits += @{ Path = $overlayPortfilePath; NewContent = $newPortfile } + $result.FilesChanged += $overlayPortfilePath + Write-Host " • $overlayPortfilePath (SHA512)" -ForegroundColor White + } else { + $result.Errors += "Could not find a SHA512 line to update in $overlayPortfilePath" + } + } + + # 3d: libressl resource-file patch + if ($Port -eq 'libressl' -and (Test-Path -LiteralPath $libresslPatchPath)) { + $parts = $Version -split '\.' + if ($parts.Count -lt 3) { + $result.Errors += "LibreSSL version '$Version' must be in .. form to update add-version-file.patch." + } else { + $major = $parts[0]; $minor = $parts[1]; $patch = $parts[2] + $commaForm = "$major,$minor,$patch,0" + $dotForm = "$major.$minor.$patch.0" + $patchText = Get-Content -LiteralPath $libresslPatchPath -Raw + + $updated = $patchText + $updated = [regex]::Replace($updated, '(?m)^(\+\s*FILEVERSION\s+)\d+,\d+,\d+,\d+', "`${1}$commaForm") + $updated = [regex]::Replace($updated, '(?m)^(\+\s*PRODUCTVERSION\s+)\d+,\d+,\d+,\d+', "`${1}$commaForm") + $updated = [regex]::Replace($updated, '("FileVersion",\s*")\d+\.\d+\.\d+\.\d+(")', "`${1}$dotForm`${2}") + $updated = [regex]::Replace($updated, '("ProductVersion",\s*")\d+\.\d+\.\d+\.\d+(")', "`${1}$dotForm`${2}") + + if ($updated -ne $patchText) { + $edits += @{ Path = $libresslPatchPath; NewContent = $updated } + $result.FilesChanged += $libresslPatchPath + $result.LibresslPatchUpdated = $true + Write-Host " • $libresslPatchPath (FileVersion -> $dotForm)" -ForegroundColor White + Write-Host " NOTE: line offsets in this patch may also need adjustment after a major LibreSSL bump." -ForegroundColor Yellow + } else { + Write-Host " ⊘ $libresslPatchPath already at $dotForm" -ForegroundColor Yellow + } + } + } + } + + if (-not [string]::IsNullOrWhiteSpace($Baseline)) { + Write-Host " • vcpkg.json builtin-baseline -> $Baseline" -ForegroundColor White + } + + # Step 4: Apply (or dry-run) + Write-Host "`n[4/4] Writing changes..." -ForegroundColor Cyan + if ($DryRun) { + Write-Host " ⊘ DryRun: no files written" -ForegroundColor Yellow + } else { + foreach ($edit in $edits) { + Set-Content -LiteralPath $edit.Path -Value $edit.NewContent -NoNewline + Write-Host " ✓ Wrote $($edit.Path)" -ForegroundColor Green + } + } + + # Final + Write-Host "`n========================================" -ForegroundColor Cyan + Write-Host "UPDATE SUMMARY" -ForegroundColor Cyan + Write-Host "========================================" -ForegroundColor Cyan + $result.Success = ($result.Errors.Count -eq 0) + if ($result.Success) { + Write-Host "✓ Port ${Port}: $($result.OldVersion) -> $Version" -ForegroundColor Green + Write-Host " Files changed: $($result.FilesChanged.Count)" -ForegroundColor White + foreach ($f in $result.FilesChanged) { + Write-Host " $f" -ForegroundColor Gray + } + Write-Host "`nNext steps:" -ForegroundColor White + Write-Host " 1. Review the diff (git diff $opensshDir)." -ForegroundColor Gray + Write-Host " 2. Validate: .\.github\tools\Install-VcpkgDependencies.ps1 -Clean" -ForegroundColor Gray + Write-Host " 3. If vcpkg reports a rejected patch hunk, regenerate the patch from a fresh source extract." -ForegroundColor Gray + Write-Host " 4. Build: .\.github\tools\Start-OpenSSHBuild.ps1" -ForegroundColor Gray + $result.Message = "Bumped $Port from $($result.OldVersion) to $Version (DryRun=$DryRun)." + } else { + Write-Host "✗ UPDATE FAILED" -ForegroundColor Red + foreach ($err in $result.Errors) { + Write-Host " • $err" -ForegroundColor Red + } + $result.Message = "$($result.Errors.Count) error(s) during update." + } + Write-Host "" + + return $result + +} catch { + Write-Host "`n========================================" -ForegroundColor Red + Write-Host "ERROR" -ForegroundColor Red + Write-Host "========================================" -ForegroundColor Red + Write-Host $_.Exception.Message -ForegroundColor Red + Write-Host $_.ScriptStackTrace -ForegroundColor Gray + + $result.Success = $false + $result.Errors += "Tool error: $($_.Exception.Message)" + $result.Message = "Update failed: $($_.Exception.Message)" + return $result +} diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml index a88a4cc36332..0c8d539c1935 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/c-cpp.yml @@ -1,11 +1,21 @@ -name: C/C++ CI +name: CI + +# For testing, you can set variables in your repo (Repo -> Settings -> +# Security -> Actions -> Variables) to restrict the tests that are run. +# The supported variables are: +# +# RUN_ONLY_TARGET_CONFIG: Run only the single matching target and config, +# separated by spaces, eg "ubuntu-latest default". All other tests will +# fail immediately. +# +# LTESTS: Override the set of tests run. on: workflow_dispatch: # disable for win32-openssh fork # push: - # paths: [ '**.c', '**.h', '**.m4', '**.sh', '**/Makefile.in', 'configure.ac', '.github/configs', '.github/workflows/c-cpp.yml' ] + # paths: [ '**.c', '**.h', '**.m4', '**.sh', '**/Makefile.in', 'configure.ac', '.github/configs', '.github/*.sh', '.github/workflows/c-cpp.yml' ] # pull_request: - # paths: [ '**.c', '**.h', '**.m4', '**.sh', '**/Makefile.in', 'configure.ac', '.github/configs', '.github/workflows/c-cpp.yml' ] + # paths: [ '**.c', '**.h', '**.m4', '**.sh', '**/Makefile.in', 'configure.ac', '.github/configs', '.github/*.sh', '.github/workflows/c-cpp.yml' ] jobs: ci: @@ -23,14 +33,14 @@ jobs: - macos-13 - macos-14 - macos-15 - - windows-2019 - windows-2022 + - windows-2025 config: [default] # Then we include any extra configs we want to test for specific VMs. # Valgrind slows things down quite a bit, so start them first. include: - - { target: windows-2019, config: cygwin-release } - { target: windows-2022, config: cygwin-release } + - { target: windows-2025, config: cygwin-release } - { target: ubuntu-22.04, config: c89 } - { target: ubuntu-22.04, config: clang-11 } - { target: ubuntu-22.04, config: clang-12-Werror } @@ -62,46 +72,41 @@ jobs: - { target: ubuntu-latest, config: boringssl } - { target: ubuntu-latest, config: aws-lc } - { target: ubuntu-latest, config: libressl-master } - - { target: ubuntu-latest, config: libressl-3.2.6 } + - { target: ubuntu-latest, config: libressl-3.2.7 } - { target: ubuntu-latest, config: libressl-3.3.6 } - { target: ubuntu-latest, config: libressl-3.4.3 } - - { target: ubuntu-latest, config: libressl-3.5.3 } - - { target: ubuntu-latest, config: libressl-3.6.1 } - - { target: ubuntu-latest, config: libressl-3.7.2 } + - { target: ubuntu-latest, config: libressl-3.5.4 } + - { target: ubuntu-latest, config: libressl-3.6.3 } + - { target: ubuntu-latest, config: libressl-3.7.3 } - { target: ubuntu-latest, config: libressl-3.8.4 } - { target: ubuntu-latest, config: libressl-3.9.2 } - { target: ubuntu-latest, config: libressl-4.0.0 } + - { target: ubuntu-latest, config: libressl-4.1.0 } - { target: ubuntu-latest, config: openssl-master } - { target: ubuntu-latest, config: openssl-noec } - { target: ubuntu-latest, config: openssl-1.1.1 } - { target: ubuntu-latest, config: openssl-1.1.1t } - { target: ubuntu-latest, config: openssl-1.1.1w } - { target: ubuntu-latest, config: openssl-3.0.0 } - - { target: ubuntu-latest, config: openssl-3.0.15 } + - { target: ubuntu-latest, config: openssl-3.0.18 } - { target: ubuntu-latest, config: openssl-3.1.0 } - - { target: ubuntu-latest, config: openssl-3.1.7 } - - { target: ubuntu-latest, config: openssl-3.2.3 } - - { target: ubuntu-latest, config: openssl-3.3.2 } + - { target: ubuntu-latest, config: openssl-3.1.8 } + - { target: ubuntu-latest, config: openssl-3.2.6 } + - { target: ubuntu-latest, config: openssl-3.3.5 } - { target: ubuntu-latest, config: openssl-3.4.0 } + - { target: ubuntu-latest, config: openssl-3.4.3 } + - { target: ubuntu-latest, config: openssl-3.5.0 } + - { target: ubuntu-latest, config: openssl-3.5.3 } # keep + - { target: ubuntu-latest, config: openssl-3.5.4 } - { target: ubuntu-latest, config: openssl-1.1.1_stable } - { target: ubuntu-latest, config: openssl-3.0 } # stable branch - { target: ubuntu-latest, config: openssl-3.1 } # stable branch - { target: ubuntu-latest, config: openssl-3.2 } # stable branch - { target: ubuntu-latest, config: openssl-3.3 } # stable branch - - { target: ubuntu-latest, config: putty-0.71 } - - { target: ubuntu-latest, config: putty-0.72 } - - { target: ubuntu-latest, config: putty-0.73 } - - { target: ubuntu-latest, config: putty-0.74 } - - { target: ubuntu-latest, config: putty-0.75 } - - { target: ubuntu-latest, config: putty-0.76 } - - { target: ubuntu-latest, config: putty-0.77 } - - { target: ubuntu-latest, config: putty-0.78 } - - { target: ubuntu-latest, config: putty-0.79 } - - { target: ubuntu-latest, config: putty-0.80 } - - { target: ubuntu-latest, config: putty-0.81 } - - { target: ubuntu-latest, config: putty-0.82 } - - { target: ubuntu-latest, config: putty-0.83 } - - { target: ubuntu-latest, config: putty-snapshot } + - { target: ubuntu-latest, config: openssl-3.4 } # stable branch + - { target: ubuntu-latest, config: openssl-3.5 } # stable branch + - { target: ubuntu-latest, config: openssl-3.6 } # stable branch + - { target: ubuntu-latest, config: putty-versions } - { target: ubuntu-latest, config: zlib-develop } - { target: ubuntu-latest, config: tcmalloc } - { target: ubuntu-latest, config: musl } @@ -111,16 +116,26 @@ jobs: - { target: macos-14, config: pam } - { target: macos-15, config: pam } runs-on: ${{ matrix.target }} + env: + EPHEMERAL_VM: yes steps: + - name: check RUN_ONLY_TARGET_CONFIG + if: vars.RUN_ONLY_TARGET_CONFIG != '' + run: sh -c 'if [ "${{ vars.RUN_ONLY_TARGET_CONFIG }}" != "${{ matrix.target }} ${{matrix.config }}" ]; then exit 1; else exit 0; fi' - name: set cygwin git params if: ${{ startsWith(matrix.target, 'windows') }} run: git config --global core.autocrlf input - name: install cygwin + id: cygwin_install if: ${{ startsWith(matrix.target, 'windows') }} uses: cygwin/cygwin-install-action@master + env: + CYGWIN: "winsymlinks:native" - uses: actions/checkout@main - name: setup CI system - run: sh ./.github/setup_ci.sh ${{ matrix.config }} + run: sh ./.github/setup_ci.sh ${{ matrix.config }} ${{ matrix.target }} + env: + CYGWIN_SETUP: ${{ steps.cygwin_install.outputs.setup }} - name: autoreconf run: sh -c autoreconf - name: configure @@ -139,6 +154,18 @@ jobs: env: TEST_SSH_UNSAFE_PERMISSIONS: 1 TEST_SSH_HOSTBASED_AUTH: yes + LTESTS: ${{ vars.LTESTS }} + - name: test OpenSSL3 ABI compatibility + if: ${{ startsWith(matrix.config, 'openssl-3') }} + run: | + sh .github/install_libcrypto.sh -a ${{ matrix.config }} /opt/openssl + sh .github/run_test.sh ${{ matrix.config }} + - name: show logs + if: failure() + run: for i in regress/failed*.log; do echo ====; echo logfile $i; echo =====; cat $i; done + - name: chown logs + if: failure() + run: test -x "$(which sudo 2>&1)" && sudo chown -R "${LOGNAME}" regress - name: save logs if: failure() uses: actions/upload-artifact@main @@ -147,8 +174,4 @@ jobs: path: | config.h config.log - regress/*.log - regress/valgrind-out/ - regress/asan.log.* - regress/msan.log.* - regress/log/* + regress/ diff --git a/.github/workflows/selfhosted.yml b/.github/workflows/selfhosted.yml index f2f27577a928..a34b67e337f7 100644 --- a/.github/workflows/selfhosted.yml +++ b/.github/workflows/selfhosted.yml @@ -1,9 +1,9 @@ -name: C/C++ CI self-hosted +name: CI self-hosted on: workflow_dispatch: # disable for win32-openssh fork # push: - # paths: [ '**.c', '**.h', '**.m4', '**.sh', '**/Makefile.in', 'configure.ac', '.github/configs', '.github/workflows/selfhosted.yml' ] + # paths: [ '**.c', '**.h', '**.m4', '**.sh', '**/Makefile.in', 'configure.ac', '.github/configs', '.github/run_tests.sh', '.github/workflows/selfhosted.yml' ] jobs: selfhosted: @@ -12,7 +12,6 @@ jobs: runs-on: ${{ matrix.host }} timeout-minutes: 600 env: - DEBUG_ACTIONS: false HOST: ${{ matrix.host }} TARGET_HOST: ${{ matrix.target }} TARGET_CONFIG: ${{ matrix.config }} @@ -22,7 +21,7 @@ jobs: REMOTE: ${{ startsWith(matrix.host, 'remote') }} VM: ${{ startsWith(matrix.host, 'libvirt') || startsWith(matrix.host, 'persist') }} SSHFS: ${{ startsWith(matrix.host, 'libvirt') || startsWith(matrix.host, 'persist') || startsWith(matrix.host, 'remote') }} - BIGENDIAN: ${{ matrix.target == 'aix51' || matrix.target == 'fbsd14-ppc64' || matrix.target == 'openwrt-mips' }} + BIGENDIAN: ${{ matrix.target == 'aix51' || matrix.target == 'nbsd-arm64be' || matrix.target == 'openwrt-mips' }} strategy: fail-fast: false # We use a matrix in two parts: firstly all of the VMs are tested with the @@ -50,8 +49,9 @@ jobs: - obsd51 - obsd67 - obsd72 - - obsd73 - obsd74 + - obsd76 + - obsd77 - obsdsnap - obsdsnap-i386 - omnios @@ -64,7 +64,6 @@ jobs: include: # Long-running/slow tests have access to high priority runners. - { target: aix51, config: default, host: libvirt-hipri } - - { target: fbsd14-ppc64, config: default, host: libvirt-hipri } - { target: openindiana, config: pam, host: libvirt-hipri } - { target: sol10, config: default, host: libvirt-hipri } - { target: sol10, config: pam, host: libvirt-hipri } @@ -101,6 +100,7 @@ jobs: - { target: debian-riscv64, config: default, host: remote-debian-riscv64 } - { target: openwrt-mips, config: default, host: remote-openwrt-mips } - { target: openwrt-mipsel, config: default, host: remote-openwrt-mipsel } + - { target: nbsd-arm64be, config: default, host: remote-nbsd-arm64be } steps: - name: shutdown VM if running if: env.VM == 'true' @@ -130,6 +130,9 @@ jobs: - name: make tests run: vmrun ./.github/run_test.sh ${{ matrix.config }} timeout-minutes: 600 + - name: show logs + if: failure() + run: vmrun 'for i in regress/failed*.log; do echo ====; echo logfile $i; echo =====; cat $i; done' - name: save logs if: failure() uses: actions/upload-artifact@main diff --git a/.github/workflows/upstream.yml b/.github/workflows/upstream.yml index d08eae5d8ebe..c5d0291bf2a2 100644 --- a/.github/workflows/upstream.yml +++ b/.github/workflows/upstream.yml @@ -1,4 +1,4 @@ -name: Upstream self-hosted +name: OpenBSD on: workflow_dispatch: # disable for win32-openssh fork @@ -12,7 +12,6 @@ jobs: if: github.repository == 'openssh/openssh-portable-selfhosted' runs-on: ${{ matrix.host }} env: - DEBUG_ACTIONS: true EPHEMERAL: true HOST: ${{ matrix.host }} TARGET_HOST: ${{ matrix.target }} @@ -24,11 +23,11 @@ jobs: host: - libvirt target: [ obsdsnap, obsdsnap-i386 ] - config: [ default, without-openssl, ubsan ] + config: [ default, without-openssl ] # TODO: restore 'ubsan' once fixed include: - { host: libvirt-arm64, target: obsdsnap-arm64, config: default } - { host: libvirt-arm64, target: obsdsnap-arm64, config: without-openssl } - - { host: libvirt-arm64, target: obsdsnap-arm64, config: ubsan } + # - { host: libvirt-arm64, target: obsdsnap-arm64, config: ubsan } steps: - name: unmount stale workspace run: fusermount -u ${GITHUB_WORKSPACE} || true @@ -44,7 +43,9 @@ jobs: run: sshfs_mount working-directory: ${{ runner.temp }} - name: update source - run: vmrun "cd /usr/src && cvs up -dPA usr.bin/ssh regress/usr.bin/ssh" + run: vmrun "cd /usr/src && cvs -q up -dPA usr.bin/ssh regress/usr.bin/ssh usr.bin/nc" + - name: update netcat + run: vmrun "cd /usr/src/usr.bin/nc && make clean all && sudo make install" - name: make clean run: vmrun "cd /usr/src/usr.bin/ssh && make obj && make clean && cd /usr/src/regress/usr.bin/ssh && make obj && make clean && sudo chmod -R g-w /usr/src /usr/obj" - name: make diff --git a/.github/workflows/vm.yml b/.github/workflows/vm.yml new file mode 100644 index 000000000000..9dcf5fcca764 --- /dev/null +++ b/.github/workflows/vm.yml @@ -0,0 +1,371 @@ +# For testing, you can set variables in your repo (Repo -> Settings -> +# Security -> Actions -> Variables) to restrict the tests that are run +# The supported variables are: +# +# RUN_ONLY_TARGET_CONFIG: Run only the single matching target and config, +# separated by spaces, eg "ubuntu-latest default". All other tests will +# fail immediately. +# +# LTESTS: Override the set of tests run. + +name: CI VM +on: + push: + paths: [ '**.c', '**.h', '**.m4', '**.sh', '**/Makefile.in', 'configure.ac', '.github/configs', '.github/workflows/vm.yml' ] + pull_request: + paths: [ '**.c', '**.h', '**.m4', '**.sh', '**/Makefile.in', 'configure.ac', '.github/configs', '.github/workflows/vm.yml' ] + +jobs: + dragonflybsd: + name: "dragonflybsd-${{ matrix.target }}" + if: github.repository != 'openssh/openssh-portable-selfhosted' + strategy: + fail-fast: false + matrix: + # First we test all OSes in the default configuration. + target: + - "6.4.2" + config: [default] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: autoreconf + run: sh -c autoreconf + + - name: start DragonFlyBSD ${{ matrix.target }} VM + uses: vmactions/dragonflybsd-vm@v1 + with: + release: ${{ matrix.target }} + usesh: true + prepare: | + pkg install -y sudo + pw useradd builder -m + echo "builder ALL=(ALL:ALL) NOPASSWD: ALL" >>/usr/local/etc/sudoers + mkdir -p /var/empty /usr/local/etc + cp $GITHUB_WORKSPACE/moduli /usr/local/etc/moduli + + - name: set file perms + shell: dragonflybsd {0} + run: cd $GITHUB_WORKSPACE && chown -R builder . + - name: configure + shell: dragonflybsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder ./configure --with-ssl-dir=/usr/local + - name: make clean + shell: dragonflybsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make clean + - name: make + shell: dragonflybsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make -j4 + - name: make tests + shell: dragonflybsd {0} + run: | + cd $GITHUB_WORKSPACE + sudo -u builder env SUDO=sudo make tests + + - name: "PAM: configure" + shell: dragonflybsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder ./configure --with-ssl-dir=/usr/local --with-pam + - name: "PAM: make clean" + shell: dragonflybsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make clean + - name: "PAM: make" + shell: dragonflybsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make -j4 + - name: "PAM: make tests" + shell: dragonflybsd {0} + run: | + cd $GITHUB_WORKSPACE + sudo -u builder env SUDO=sudo SSHD_CONFOPTS="UsePam yes" make tests + + freebsd: + name: "freebsd-${{ matrix.target }}" + if: github.repository != 'openssh/openssh-portable-selfhosted' + strategy: + fail-fast: false + matrix: + # First we test all OSes in the default configuration. + target: + - "13.5" + - "14.3" + # - "15.0" # "pkg" breaks with a libutil.so error... + config: [default] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: autoreconf + run: sh -c autoreconf + + - name: start FreeBSD ${{ matrix.target }} VM + uses: vmactions/freebsd-vm@v1 + with: + release: ${{ matrix.target }} + usesh: true + prepare: | + pkg install -y sudo + pw useradd builder -m + echo "builder ALL=(ALL:ALL) NOPASSWD: ALL" >>/usr/local/etc/sudoers + mkdir -p /var/empty /usr/local/etc + cp $GITHUB_WORKSPACE/moduli /usr/local/etc/moduli + + - name: set file perms + shell: freebsd {0} + run: cd $GITHUB_WORKSPACE && chown -R builder . + - name: configure + shell: freebsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder ./configure + - name: make clean + shell: freebsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make clean + - name: make + shell: freebsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make -j4 + - name: make tests + shell: freebsd {0} + run: | + cd $GITHUB_WORKSPACE + sudo -u builder env SUDO=sudo make tests + + - name: "PAM: configure" + shell: freebsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder ./configure --with-pam + - name: "PAM: make clean" + shell: freebsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make clean + - name: "PAM: make" + shell: freebsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make -j4 + - name: "PAM: make tests" + shell: freebsd {0} + run: | + cd $GITHUB_WORKSPACE + sudo -u builder env SUDO=sudo SSHD_CONFOPTS="UsePam yes" make tests + + + netbsd: + name: "netbsd-${{ matrix.target }}" + if: github.repository != 'openssh/openssh-portable-selfhosted' + strategy: + fail-fast: false + matrix: + # First we test all OSes in the default configuration. + target: + - "9.0" + - "9.4" + - "10.0" + - "10.1" + config: [default] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: autoreconf + run: sh -c autoreconf + + - name: start NetBSD ${{ matrix.target }} VM + uses: vmactions/netbsd-vm@v1 + with: + release: ${{ matrix.target }} + usesh: true + prepare: | + /usr/sbin/pkg_add sudo + /usr/sbin/useradd -m builder + echo "builder ALL=(ALL:ALL) NOPASSWD: ALL" >>/usr/pkg/etc/sudoers + mkdir -p /var/empty /usr/local/etc + cp $GITHUB_WORKSPACE/moduli /usr/local/etc/moduli + + - name: set file perms + shell: netbsd {0} + run: cd $GITHUB_WORKSPACE && /sbin/chown -R builder . + - name: configure + shell: netbsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder ./configure + - name: make clean + shell: netbsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make clean + - name: make + shell: netbsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make -j4 + - name: make tests + shell: netbsd {0} + run: | + cd $GITHUB_WORKSPACE + sudo -u builder env SUDO=sudo make tests + + - name: "PAM: configure" + shell: netbsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder ./configure --with-pam + - name: "PAM: make clean" + shell: netbsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make clean + - name: "PAM: make" + shell: netbsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make -j4 + - name: "PAM: make tests" + shell: netbsd {0} + run: | + cd $GITHUB_WORKSPACE + sudo -u builder env SUDO=sudo SSHD_CONFOPTS="UsePam yes" make tests + + + ominios: + name: "omnios-${{ matrix.target }}" + if: github.repository != 'openssh/openssh-portable-selfhosted' + strategy: + fail-fast: false + matrix: + # First we test all OSes in the default configuration. + target: + - "r151054" + config: [default] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: autoreconf + run: sh -c autoreconf + + - name: start OmniOS ${{ matrix.target }} VM + uses: vmactions/omnios-vm@v1 + with: + release: ${{ matrix.target }} + usesh: true + prepare: | + set -x + pfexec pkg refresh + pfexec pkg install build-essential + useradd -m builder + sed -e "s/^root.*ALL$/root ALL=(ALL) NOPASSWD: ALL/" /etc/sudoers >>/tmp/sudoers + mv /tmp/sudoers /etc/sudoers + echo "builder ALL=(ALL) NOPASSWD: ALL" >>/etc/sudoers + mkdir -p /var/empty /usr/local/etc + cp $GITHUB_WORKSPACE/moduli /usr/local/etc/moduli + + - name: set file perms + shell: omnios {0} + run: cd $GITHUB_WORKSPACE && chown -R builder . + - name: configure + shell: omnios {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder ./configure + - name: make clean + shell: omnios {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make clean + - name: make + shell: omnios {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make + - name: make tests + shell: omnios {0} + run: | + cd $GITHUB_WORKSPACE + sudo -u builder make tests + + + openbsd: + name: "openbsd-${{ matrix.target }}" + if: github.repository != 'openssh/openssh-portable-selfhosted' + strategy: + fail-fast: false + matrix: + # First we test all OSes in the default configuration. + target: + - "7.3" + - "7.5" + - "7.6" + - "7.7" + config: [default] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: autoreconf + run: sh -c autoreconf + + - name: start OpenBSD ${{ matrix.target }} VM + uses: vmactions/openbsd-vm@v1 + with: + release: ${{ matrix.target }} + usesh: true + prepare: | + env PKG_PATH=https://ftp.openbsd.org/pub/OpenBSD/${{matrix.target}}/packages/amd64 pkg_add sudo-- + useradd -m builder + echo "builder ALL=(ALL:ALL) NOPASSWD: ALL" >>/etc/sudoers + mkdir -p /var/empty /usr/local/etc + cp $GITHUB_WORKSPACE/moduli /usr/local/etc/moduli + + - name: set file perms + shell: openbsd {0} + run: cd $GITHUB_WORKSPACE && chown -R builder . + - name: configure + shell: openbsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder ./configure + - name: make clean + shell: openbsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make clean + - name: make + shell: openbsd {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make -j4 + - name: make tests + shell: openbsd {0} + run: | + cd $GITHUB_WORKSPACE + sudo -u builder env SUDO=sudo make tests + + + solaris: + name: "solaris-${{ matrix.target }}" + if: github.repository != 'openssh/openssh-portable-selfhosted' + strategy: + fail-fast: false + matrix: + # First we test all OSes in the default configuration. + target: + - "11.4-gcc" + config: [default] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@main + - name: autoreconf + run: sh -c autoreconf + + - name: start Solaris ${{ matrix.target }} VM + uses: vmactions/solaris-vm@v1 + with: + release: ${{ matrix.target }} + usesh: true + prepare: | + set -x + useradd -m builder + sed -e "s/^root.*ALL$/root ALL=(ALL) NOPASSWD: ALL/" /etc/sudoers >>/tmp/sudoers + mv /tmp/sudoers /etc/sudoers + echo "builder ALL=(ALL) NOPASSWD: ALL" >>/etc/sudoers + mkdir -p /var/empty /usr/local/etc + cp $GITHUB_WORKSPACE/moduli /usr/local/etc/moduli + + - name: set file perms + shell: solaris {0} + run: cd $GITHUB_WORKSPACE && chown -R builder . + - name: configure + shell: solaris {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder ./configure + - name: make clean + shell: solaris {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make clean + - name: make + shell: solaris {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make + - name: make tests + shell: solaris {0} + run: | + cd $GITHUB_WORKSPACE + sudo -u builder make tests + + - name: "PAM: configure" + shell: solaris {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder ./configure --with-pam + - name: "PAM: make clean" + shell: solaris {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make clean + - name: "PAM: make" + shell: solaris {0} + run: cd $GITHUB_WORKSPACE && sudo -u builder make + - name: "PAM: make tests" + shell: solaris {0} + run: | + cd $GITHUB_WORKSPACE + sudo -u builder make tests diff --git a/.gitignore b/.gitignore index 94dc0f7f9aa6..71a21e7a0485 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ config.log config.status openbsd-compat/Makefile openbsd-compat/regress/Makefile +openbsd-compat/include openssh.xml opensshd.init survey.sh diff --git a/.skipped-commit-ids b/.skipped-commit-ids index 7988e25006f4..138ca3d019f9 100644 --- a/.skipped-commit-ids +++ b/.skipped-commit-ids @@ -1,3 +1,5 @@ +747219d54565030ff7c45298b9f5e971801f6cb2 moduli-gen Makefile tweak +c2eb57285424f819f9520fa33e0d6d3c4a361a5e moduli-gen.sh tweak 509bb19bb9762a4b3b589af98bac2e730541b6d4 clean sshd random relinking kit 5317f294d63a876bfc861e19773b1575f96f027d remove libssh from makefiles a337e886a49f96701ccbc4832bed086a68abfa85 Makefile changes @@ -39,6 +41,11 @@ fb39324748824cb0387e9d67c41d1bef945c54ea Makefile change 112aacedd3b61cc5c34b1fa6d9fb759214179172 Makefile change a959fc45ea3431b36f52eda04faefc58bcde00db groupaccess.c changes 6d07e4606997e36b860621a14dd41975f2902f8f Makefile.inc +c7246a6b519ac390ca550719f91acfdaef1fa0f0 Makefile relink change +ef7ecdb6dd2542f42fa7236d17ac0b144851f0b5 ssh-keygen, fixup'ed into 21682417 +da414a364c25b187fc686da7aacec2c35d29238a ssh-keygen, fixup'ed into 21682417 +a05e13a7e2c0b65bb4b47184fef731243431c6ff Makefile.inc +7e8178786157e863f6ff63c5d55200d7b6b04f9e remove old sandbox files Old upstream tree: diff --git a/.vscode/mcp.json b/.vscode/mcp.json new file mode 100644 index 000000000000..b108480eb6a8 --- /dev/null +++ b/.vscode/mcp.json @@ -0,0 +1,24 @@ +{ + "servers": { + "openssh-server": { + "type": "stdio", + "command": "pwsh", + "args": [ + "-noprofile", + "-c", + "MCPServerPS\\Start-MyMCP -ScriptRoot ./.github/tools" + ], + "env": { + "GITHUB_TOKEN": "${input:github_token}" + } + } + }, + "inputs": [ + { + "id": "github_token", + "type": "promptString", + "description": "GitHub Personal Access Token (used for commit-group CI status queries)", + "password": true + } + ] +} diff --git a/ChangeLog b/ChangeLog index 60a06386e42d..e690f70726a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7464 +1,9331 @@ -commit 8725dbc5b5fcc3e326fc71189ef8dba4333362cc +commit 476bab6259d5a6ea0402ec79bc47ed61e2c15e86 Author: Damien Miller -Date: Wed Apr 9 17:02:17 2025 +1000 +Date: Mon Oct 6 12:52:25 2025 +1100 - update version numbers + depend -commit cc7feb9458ad3b893b53dc9c7500d1affd208bde +commit af956575eba6bf6b6d6bc817e1aa6ed73a365984 +Author: Damien Miller +Date: Mon Oct 6 12:51:13 2025 +1100 + + update versions + +commit 2fd0945913a30fbbe7c02503347961df03f28e66 +Author: Damien Miller +Date: Mon Oct 6 12:48:16 2025 +1100 + + sync ssh-copy-id to upstream version 527be673f4d + +commit 981bb32bc6062fa5d6f11de7ffb732967463bf57 Author: djm@openbsd.org -Date: Wed Apr 9 07:00:21 2025 +0000 +Date: Mon Oct 6 01:45:22 2025 +0000 - upstream: openssh-10.0 + upstream: openssh-10.1 - OpenBSD-Commit-ID: db5b4a1f1c9e988f8f166b56dc5643606294b403 + OpenBSD-Commit-ID: 2a232c2d2fc05a23519f69bc29e6d8c076b97d97 -commit fc86875e6acb36401dfc1dfb6b628a9d1460f367 -Author: djm@openbsd.org -Date: Wed Apr 9 07:00:03 2025 +0000 +commit b9a640a1a0dccfb56be684cc7ade402f57cf7ebd +Author: dtucker@openbsd.org +Date: Fri Oct 3 01:03:45 2025 +0000 - upstream: Fix logic error in DisableForwarding option. This option + upstream: If write() returned short, the subsequent write would restart - was documented as disabling X11 and agent forwarding but it failed to do so. - Spotted by Tim Rice. + from the beginning of the buffer not the end of what was written. Fix, since + we want modpipe to corrupt data for testing purposes deliberately not + accidentally. ok djm@ - OpenBSD-Commit-ID: fffc89195968f7eedd2fc57f0b1f1ef3193f5ed1 + OpenBSD-Regress-ID: 50ca74d287445c58944f070bb92dc13b1d054b43 -commit dd73459e351b0a2908aed90910c8ff9b0b381c6d +commit a0e5446ac85aca5a3ef9844eeedf787300fdb8b3 +Author: naddy@openbsd.org +Date: Sat Oct 4 21:41:35 2025 +0000 + + upstream: typos: a ssh* -> an ssh* + + ok dtucker@ + + OpenBSD-Commit-ID: a70fd2e1b23089260e8f5a7921b0debc06b011cb + +commit ade92f53c3bd4ad7dcd95334a194add57ec9ff71 Author: djm@openbsd.org -Date: Wed Apr 9 01:24:40 2025 +0000 +Date: Fri Oct 3 00:09:26 2025 +0000 - upstream: oops, I accidentally backed out the typo fix + upstream: stray newline - OpenBSD-Commit-ID: f485f79bf3e9ebbe1de13ac96150cf458956cfd8 + OpenBSD-Commit-ID: b47ed4fa93b781c7ec8ae2936526a290f4e17e1f -commit 0cb945891944bada5850e85d60afa3c807cf1af6 +commit a9cbe10da2be5be76755af0cea029db0f9c1f263 Author: djm@openbsd.org -Date: Wed Apr 9 01:23:47 2025 +0000 +Date: Fri Oct 3 00:08:02 2025 +0000 - upstream: typo + upstream: include openssl/bn.h explicitly in files where we use BN_* - OpenBSD-Commit-ID: f912725c7d303720706b3ccfb2cb846d46296d13 + makes things simpler for portable; from Mike Frysinger + + OpenBSD-Commit-ID: 717e93403fd1108e175afd7451b5a4ab46a598fe -commit cd4a6bd50b658d707867caa1f5aa40b35c2b6c19 -Author: Damien Miller -Date: Wed Apr 9 09:49:55 2025 +1000 +commit 3957cc2914cdc88932c972413853f8b68c1ffba5 +Author: dtucker@openbsd.org +Date: Thu Oct 2 08:38:43 2025 +0000 - initialise websafe_allowlist in agent fuzzer + upstream: Relax array check slightly. Prevents compiler warnings + + in -portable when there are no kbdint devices present. ok djm@ + + OpenBSD-Commit-ID: c1c050cecd642d6073c792201908fd225191df93 -commit 55b7cb48af96c1102ef8ab5a73bb329cbed30945 +commit 6a239b057be2897d7a597daaf5394f2e7312dc65 Author: djm@openbsd.org -Date: Tue Apr 8 23:10:46 2025 +0000 +Date: Thu Oct 2 04:23:11 2025 +0000 - upstream: typo + upstream: backout r1.243 (fix for fatal during tab-completion with - OpenBSD-Regress-ID: 08477b936d1d0c1e8a98aa1c0e1bdde8871894c9 + some multibyte sequences) as it breaks the common case for tab completion. + + Will deal with it properly after release. + + OpenBSD-Commit-ID: 196d00f5ff19579214de45357f16a1fb2d624be1 -commit 985d8cbcd3438cc36b4e709476f1783e358ddfb1 -Author: djm@openbsd.org -Date: Tue Apr 8 23:10:08 2025 +0000 +commit b9f6a84ea383d811216de38219472214963c10b2 +Author: Darren Tucker +Date: Thu Oct 2 10:48:04 2025 +1000 - upstream: typo + Pass COMPATINCLUDES down to openbsd-compat too. - OpenBSD-Commit-ID: 6e683e13e72bf1e43bbd3bbc6a8332d5a98bdc99 + Fixes build on Solaris, AIX and probably others. -commit 000c3d14e94d8f7597087c457260ea9417045b65 +commit 047e0221eaf9815775e8ea78c6d6add5ab0f68c7 +Author: Darren Tucker +Date: Wed Oct 1 14:34:02 2025 +1000 + + Pass new "compat includes" path via AC_SUBST. + + This fixes the build when the directory path containing a space. + Found by Sevan Janiyan, tested by Job Snijders. This doesn't fix + "make tests", however that is a different, pre-existing problem + that needs to be addressed separately. + +commit 5c50ddbe4deac83995edc1d014e9ba0d5efa18a6 +Author: Darren Tucker +Date: Wed Oct 1 13:37:35 2025 +1000 + + Remove compat "include" dir during distclean. + +commit aceabd62ce5833716dd2e99d4be4fcb603d263cc Author: dtucker@openbsd.org -Date: Mon Apr 7 08:12:22 2025 +0000 +Date: Wed Oct 1 00:33:37 2025 +0000 - upstream: Include time.h for time(). + upstream: Set keys to NULL after freeing in tests where the - Fixes warning on some platforms when building without openssl. + variables will be used again. Should prevent Coverity "potential use after + free" warnings. - OpenBSD-Commit-ID: 04ca29b8eaae1860c7adde3e770baa1866e30a54 + OpenBSD-Regress-ID: 24d141657d25977e41dfb0c58e9b74ab093972bf -commit 49b8b9bf829e08af22366530614a5e59ac341ca9 -Author: tb@openbsd.org -Date: Wed Apr 2 04:28:03 2025 +0000 +commit eb30a0d1493a97b5c14728846576dc6af5d442da +Author: dtucker@openbsd.org +Date: Wed Oct 1 00:30:19 2025 +0000 - upstream: Wrap #include in #ifdef WITH_DSA + upstream: Get rid of utf8 droppings in commment since it confuses - ok djm + older shells. From Sevan Janiyan via openssh-unix-dev. - OpenBSD-Commit-ID: ed01a7c102243f84e4a317aefb431916d98aab15 + OpenBSD-Regress-ID: 67c11a5cff6ef23538c77e9b29d538e175e6cfe3 -commit f80fb819e5521e13f167edbcc3eed66e22ad0c2a -Author: Damien Miller -Date: Thu Apr 3 09:10:19 2025 +1100 +commit d478e250230e917eeb5032238df0b9af357404ee +Author: Darren Tucker +Date: Wed Oct 1 12:17:54 2025 +1000 - remove all instances of -pie from LDFLAGS + Update OpenSSL & LibreSSL versions we test against. + +commit 2c504a74ed81d13c8198a89ed1040d0fc5f73129 +Author: djm@openbsd.org +Date: Tue Sep 30 00:10:42 2025 +0000 + + upstream: during sftp uploads, avoid a condition where a failed write - Previously only the first instance of this flag was removed. - Unbreaks build on OpenSUSE Tumbleweed. Patch from Antonio Larrosa + could be ignored if a subsequent write succeeded. + + This is unlikely but technically possible because sftp servers are + allowed to reorder requests. + + Reported by Graziano Stefani, ok tb@ + + OpenBSD-Commit-ID: 03904bce2c7f787223d01d7e1179fde15753eca3 -commit 6c9872faa1c297a84c6d3e3b95a927be99eadbf6 +commit 1f7556753869654ba5e2bf61e384c5da2db5ca6a Author: djm@openbsd.org -Date: Tue Apr 1 23:23:20 2025 +0000 +Date: Tue Sep 30 00:06:06 2025 +0000 - upstream: remove ability to enable DSA support. Actual code will be + upstream: avoid a fatal() when sftp tab-completes filenames that - g/c'd separately. ok deraadt@ + share common utf-8 characters that don't encode to a complete codepoint - OpenBSD-Commit-ID: 2a032b75156c4d922e8343fa97ff6bc227f09819 + from menthu.zhou via GHPR#587; ok dtucker@ + + OpenBSD-Commit-ID: e07e4d8a8cac032ab536570b8214e6ef6839b585 -commit 8460aaa4e1f8680f03cc5334556b9440b401f010 -Author: dtucker@openbsd.org -Date: Fri Mar 28 21:45:55 2025 +0000 +commit 42b14ff1e06fd683c7d15a6b2816c16108873a5a +Author: djm@openbsd.org +Date: Tue Sep 30 00:03:09 2025 +0000 - upstream: Add TEST_SSH_SSHD_ENV to sshd lines here too. + upstream: fix memory leak in mux_client_request_stdio_fwd GHPR#575 - OpenBSD-Regress-ID: 045f2c88b42d694b404db51c5de5eca20d748ff1 + by Boris Tonofa; ok dtucker + + OpenBSD-Commit-ID: 410cdd05242304bd0196b9172ce5fcaf89d2d8ce -commit 5e60f5937b9c33190b9d7614f72d85d4a9b38d3d -Author: dtucker@openbsd.org -Date: Fri Mar 28 06:04:07 2025 +0000 +commit e5055ef26abcffd3f99669e411ea6b35ca166111 +Author: Allison Karlitskaya +Date: Wed Sep 3 20:07:55 2025 +0200 - upstream: Pass "ControlMaster no" to ssh when invoked by scp & sftp. + Don't log audit messages with UNKNOWN hostname - If you have ControlMaster auto (or yes) in your config, and the - first connection you make is via scp or sftp, then you may get a - few unexpected options applied to it (eg ForwardX11 no), since sftp - and sftp explicitly disable those for reasons. These effects will - persist beyond the initial scp or sftp command. + The `host` parameter to audit_log_acct_message() is documented as + follows: - This explicitly disables persistent session *creation* by scp and sftp. - It will not prevent them from using an existing session if one has - already been created. + host - The hostname if known. If not available pass a NULL. - From Github PR#557, ok djm@ kn@ + but we pass the string "UNKNOWN" in case we don't know the hostname. + Make sure we pass NULL instead. - OpenBSD-Commit-ID: 9dad7c737466837e0150c4318920f46d844770c4 + This avoids having the audit system attempt to perform a DNS lookup on + the hostname "UNKNOWN", which tends to result in long delays when + attempting to login. -commit bbd36869dfb4b770cc9e6a345c04a585a0955aec -Author: dtucker@openbsd.org -Date: Fri Mar 28 05:41:15 2025 +0000 +commit d343df4019b4369ce7f87e9bf6bbc80b81cd263d +Author: zhangjun +Date: Fri Aug 22 16:49:07 2025 +0800 - upstream: Set sshd environment variables during sshd test run too. + ensure struct passwd fields are non-NULL in pwcopy - OpenBSD-Regress-ID: 50cb325d92c390a2909662c901f6ac5d80b6f74d + Android libc can return NULL pw_gecos, for example. -commit 98f05b1484daddef2f56b79e24540523b5016143 +commit 893a579e4b37e6bd89d206dc8e7ac2a906ccf114 Author: dtucker@openbsd.org -Date: Fri Mar 28 05:36:24 2025 +0000 +Date: Mon Sep 29 21:37:52 2025 +0000 - upstream: Add TEST_SSH_SSHD_ENV variable which is added to sshd's + upstream: Add explicit check for array overflow. - environment. Will be used in Portable to tweak behaviour of tcmalloc's - debugging. + The array is bounded by a NULL sentinel which already prevents this, + however since we check the bit vector for overflow Coverity assumes that + check is for the devices array and flags it as a potential overflow. + Adding this additional check on the array placates CID 896018. ok djm@ + deraadt@ - OpenBSD-Regress-ID: 67e38c3c4517ddb72c8a3549a3325a166d7bb6d6 + OpenBSD-Commit-ID: e92fff41341b38e4206a70655cc9acaaa032ebee -commit 8cd9ed4df0eccc825eca0c45354a37332e125e38 +commit 90f49a185ac1a786d9f7e9a710b369afb3692a65 Author: dtucker@openbsd.org -Date: Fri Mar 28 05:33:30 2025 +0000 +Date: Mon Sep 29 21:30:15 2025 +0000 - upstream: chown log directory in addition to log files. + upstream: Move ifdef to start of file. Removes diff vs portable. - OpenBSD-Regress-ID: b520d54a0bbf2c6554413c798218bda26b385ad9 + OpenBSD-Commit-ID: 55058ac3d477e4c696575039f5b275522b99ffea -commit e32de6bf4f3229d4838beb127de45eed1377ccc5 -Author: Darren Tucker -Date: Fri Mar 28 16:47:58 2025 +1100 +commit 2f71b44d48dc8da7fb743d6ffe609aea5a645edb +Author: dtucker@openbsd.org +Date: Mon Sep 29 21:29:22 2025 +0000 - Be explicit about environment variables for tests. + upstream: Include misc.h. Removes diff vs portable. - This will make it easier to reproduce a test failure by cut-and-paste of - the corresponding line from the github log. + OpenBSD-Commit-ID: 8aa48451fe5c37f04a339450c4ed9cfb8f4c288f -commit 77a3e6ba47381547b3fe4b29223256f276fbd07e -Author: Darren Tucker -Date: Fri Mar 28 16:46:40 2025 +1100 +commit dfb991bdd826517bbce1cf62ce07bcb3e48a2f27 +Author: dtucker@openbsd.org +Date: Mon Sep 29 21:28:33 2025 +0000 - Add tcmalloc flags to TEST_SSH_SSHD_ENV. + upstream: Sort headers as per KNF. Removes diff vs portable. - This will get passed to sshd via test-exec.sh. + OpenBSD-Commit-ID: 55f5b9eaeb826a25cfb506a78136094275a71bcb -commit a73890e340fbd6121251854b658a72d738b86c84 -Author: Darren Tucker -Date: Thu Mar 27 23:04:44 2025 +1100 +commit c82f4dd6b723a8365b4c538d7c99fe8e46985ed0 +Author: dtucker@openbsd.org +Date: Mon Sep 29 07:40:55 2025 +0000 - Add PuTTY 0.81, 0.82 and 0.83 to tests. + upstream: Null out keys after freeing in tests in the case where we + + potentially reuse the variable. Fixes Coverity CID 405057. + + OpenBSD-Regress-ID: c52e86502b33bfa6e448448a74a0217dd519dd58 -commit 90a28de0d49570324d1695c0b4686354ef3bcae0 -Author: Darren Tucker -Date: Thu Mar 27 22:30:40 2025 +1100 +commit fda31e1e5179b4e70c27094ebb303ee47c11a5a7 +Author: djm@openbsd.org +Date: Mon Sep 29 03:17:54 2025 +0000 - Include TCMALLOC_STACKTRACE_METHOD in output. + upstream: avoid spurious error message when loading certificates - If TCMALLOC_STACKTRACE_METHOD happens to be set, include it in the debug - output to make reproducing test cases easier. + only bz3869 + + OpenBSD-Commit-ID: e7848fec50d15cc142fed946aa8f79abef3c5be7 -commit fd5a6bb6dd7657c4bd8cd0ee11d5c8ddf0d927b2 -Author: Darren Tucker -Date: Thu Mar 27 20:15:11 2025 +1100 +commit bcd88ded2fff97652d4236405a3354ca66f90f7e +Author: djm@openbsd.org +Date: Mon Sep 29 02:32:15 2025 +0000 - Test with-linux-memlock-onfault in kitchensink. + upstream: kbd-interactive device names should be matched against + + the full device name, not a prefix. Doesn't matter in practice as there is + only one kbd-int device supported (PAM xor BSD auth), and an attacker would + still need to successfully authenticate against an incorrectly-selected + device. + + reported by ashamedbit, NobleMathews; ok deraadt@ + + OpenBSD-Commit-ID: cf75d4f99405fbb41354c4ae724a3b39a3b58f82 -commit 22330711e2459c23d9736ee16e0e2ee0fcc30b9a -Author: Collin Funk -Date: Wed Mar 26 18:24:59 2025 -0700 +commit b1c4bf5c2f1c2b30698dbaadc5d823862213f1fc +Author: jsg@openbsd.org +Date: Thu Sep 25 12:52:21 2025 +0000 - Include fcntl.h so AT_FDCWD does not get redefined. + upstream: avoid use-after-free in update_krl_from_file() found with + + clang scan-build, ok dtucker@ + + OpenBSD-Commit-ID: 8ec86eca573740c94d5bc7e252959174555f4eb8 -commit 6c49e5f7dcaf886b4a702a6c003cae9dca04d3ea -Author: Daniil Tatianin -Date: Thu Feb 27 11:37:13 2025 +0300 +commit b06a150bc903a0cf898406384d5a34059d0f2d8f +Author: Darren Tucker +Date: Sat Sep 27 20:20:34 2025 +1000 - Add support for locking memory on Linux + Stop testing OpenBSD ubsan until fixed upstream. + +commit 97b32fa2af25c16aec4de85c5cbb63fd038b4dfa +Author: dtucker@openbsd.org +Date: Fri Sep 26 04:40:45 2025 +0000 + + upstream: Use $OBJ for temp file in maxstartups idempotence test. - Linux wakes up kcompactd threads in order to make more contiguous memory - available on the system, it does this by migrating live movable pages - (actively modifying live processes' page tables and constantly flooding - them with page invalidation IPIs, which can be up to millions per - second), which causes the process to become unresponsive for up to - seconds or even minutes in some severe cases. In case of sshd, we want - to always be able to connect to the system, even if it's under heavy - kcompactd load. + Fixes test in -portable when run out-of-tree. - Introduce an option to protect sshd and its children sessions from being - compacted by kcompactd (this works in cojunction with - compact_unevictable_allowed = 0). Note that we depend on MCL_ONFAULT - being available, which was introduced in linux 4.4. MCL_ONFAULT allows - the system to lock pages lazily, thus drastically reducing memory usage - of a locked process (without MCL_ONFAULT, every existing mapping in the - process is instantly write-faulted). + OpenBSD-Regress-ID: 8578be08238af4abe2dc91af1c199f7f71f1a7a2 -commit fdc4853c5b1567934d43ab13282f03033cc21325 -Author: Daniil Tatianin -Date: Thu Feb 27 11:46:25 2025 +0300 +commit b4ceca952b85752958d849508294afdc56dfcb9f +Author: Darren Tucker +Date: Fri Sep 26 22:28:13 2025 +1000 - platform: introduce a way to hook new session start + Shorten workflow names to fit in a single line. + +commit 9824ec515ed6256c1a98d66049471053f965b75e +Author: Darren Tucker +Date: Fri Sep 26 22:26:33 2025 +1000 + + Update link to oss-fuzz bug tracker. - Previously this was possible via post_fork_child, but ever since sshd - was split into multiple binaries, this is now no longer possible becase - of execv. + Remove 9.8 branch. -commit 1b311b6b17be81577514c38e8be4f5740d7df496 +commit 37d996bd0537837f15fc540d5aebb1ef2faf2268 Author: dtucker@openbsd.org -Date: Wed Mar 19 06:11:15 2025 +0000 +Date: Thu Sep 25 22:17:29 2025 +0000 - upstream: Prevent theoretical NULL deref in throughlocal_sftp. + upstream: Check return codes of sshbuf functions. - Coverity CID 405019, although at the moment it's not reachable. ok djm@ + Fixes Coverity CIDs 405059 and 405061. - OpenBSD-Commit-ID: 630d46c1021b69fbb470e349976c70e9a48b7644 + OpenBSD-Regress-ID: defa55d32892172251bbd5efd15731ce55888247 -commit 96493ebd6ff48bbb802576e208794a26928569b0 +commit 6c3c9f03c3c2cc4e40decbb49b8486abfb9e57df Author: Darren Tucker -Date: Wed Mar 19 17:35:10 2025 +1100 +Date: Fri Sep 26 08:23:21 2025 +1000 - Fix workflow syntax again. + Replace hand-rolled modulo with arc4random_uniform. + + Fixes potential modulo-by-zero UB flagged by Coverity CID 405068 -commit 575c43fd4c44d376b1771c0fdaf4941021ba88c9 +commit e914e61eb88e22e5b725c399698256c54589ca32 Author: Darren Tucker -Date: Tue Mar 18 20:54:48 2025 +1100 +Date: Thu Sep 25 17:50:07 2025 +1000 - Differentiate logfiles better. + Remove status bits from OpenSSL >=3 version check. + + OpenSSL traditionally did not guarantee ABI compatibility across release + (and development) versions. Because of this, OpenSSH checked the lower 4 + "status" bits returned by OpenSSL_version_num(), which were originally + set to 0 for development versions and 0xf for release versions and, if + they did not match, would report the discrepancy and exit. + + OpenSSL (unintentionally) changed these bits in the 3.0.0 and subsequent + 3.x releases, setting them to zero in the release versions (which happened + to also match the documentation), then changed them back in the 3.5.3 + release. If OpenSSL was upgraded to (or from) this version without + recompiling OpenSSH, it would cause OpenSSH flag it as potentially + incompatible and refuse to use it. Ultimately OpenSSL rolled this + back, but the check now has no value so is being removed for OpenSSL + versions >=3. + + bz#3865 and https://github.com/openssl/openssl/issues/28575, ok djm@ -commit 8a1294638f3a47d46263ea574fa85c8e115ea893 +commit 35f3e2a41c2afe7a68a8a4efb3eb385e7f8d247d Author: Darren Tucker -Date: Tue Mar 18 20:27:46 2025 +1100 +Date: Thu Sep 25 18:06:55 2025 +1000 - Fix another typo in workflow. + Update pledge() interface to match current OpenBSD. + + ok djm@ -commit bd9e6bbcc864b3e10c4e11f5aec1b3a5e3a89b55 +commit 7ce3823547578a3b083085744c1fea39237197a2 Author: Darren Tucker -Date: Tue Mar 18 18:16:12 2025 +1100 +Date: Tue Sep 23 22:12:19 2025 +1000 - Fix syntax error in workflow. + Merge all putty tests into a single test. + + The lets us reuse the built OpenSSH binaries and replaces 12*4min of + tests with a single 14min one. -commit ce88a1bb4a2e6425752094f7a2eb4adfb0ca7971 +commit 1362f6c0f4ca3306a201a6572bb9ec0d47d8edb3 Author: Darren Tucker -Date: Tue Mar 18 18:13:14 2025 +1100 +Date: Thu Sep 25 18:20:53 2025 +1000 - Identify each logfile while printing them. + Add #ifdefs in pwfree to match those in pwcopy. + + Fixes build on many platforms. -commit b58e429960c4791fc4e30bb7c70d1f77d538b546 +commit 8235dc3d82c0ac347a3600df0907c6573720fbaa Author: djm@openbsd.org -Date: Tue Mar 18 04:53:14 2025 +0000 +Date: Thu Sep 25 07:05:11 2025 +0000 - upstream: fix NULL dereference for Match conditions missing + upstream: fix some one-off leaks in ssh.c; ok dtucker@ - arguments, e.g. "Match user". Spotted by Coverity (CID 477813) + OpenBSD-Commit-ID: bf3c27ffe4b3cccb6553b554ec4c04929065a2bc + +commit 846987d1233f24bbe87ebed347e328f45525388a +Author: djm@openbsd.org +Date: Thu Sep 25 07:04:38 2025 +0000 + + upstream: fix some one-off leaks in ssh-keygen; ok dtucker@ - OpenBSD-Commit-ID: 13584281cfa23b8ebc41f9d128a6b9464ae960d4 + OpenBSD-Commit-ID: 32f51289c93246474659aa49067926fcab9e02e8 -commit 0ce5281f017c3ad7bdcc2bbd9745119a73e0cbb8 -Author: tb@openbsd.org -Date: Fri Mar 14 09:49:49 2025 +0000 +commit a1a7df8b3694fdd7b55ad6bb8fa7b3d5d7f5b89a +Author: djm@openbsd.org +Date: Thu Sep 25 07:00:43 2025 +0000 - upstream: Fix EVP_CIPHER_CTX_ctrl() return checks + upstream: fix some leaks in ssh-add; feedback/ok dtucker@ - While this API tries to translate negative return values (i.e. -1) to 0 - in BoringSSL and LibreSSL, it is still possible for it to return negative - values in prinicple. We even incorrectly document that -1 can be returned - while Boring and OpenSSL plead the Fifth. + OpenBSD-Commit-ID: 441302917de31a128c1d6d63acccc67042fcf349 + +commit a8a2702bcd9e81a086e6d2c278f1b62f9d8bf3a1 +Author: djm@openbsd.org +Date: Thu Sep 25 06:57:54 2025 +0000 + + upstream: fix some leaks; feedback/ok dtucker@ - In OpenSSL 3 there are now code paths that explicitly return -1 and they - started shifting their return checks to <= 0 - of course they do this in - inconsistent and sometimes incorrect manner. While these paths aren't - reachable from ssh right now, who can really tell what happens in the two - hundred lines of inscrutable bloated mess this has become. + OpenBSD-Commit-ID: 05bdbc2e494b87a4a79e509020bd8249c86a4ff0 + +commit a071af0682d686de85cf471f5e04deaee4d90adb +Author: djm@openbsd.org +Date: Thu Sep 25 06:45:50 2025 +0000 + + upstream: wait for the unprivileged sshd-auth process to exit - So error check with <= 0 to ensure that we don't accidentally translate an - error to success. + before closing the fd it uses to report log messages - ok markus schwarze + This avoids a race where the child process notices the + fd was closed before exiting and spams the logs. - OpenBSD-Commit-ID: a855c833cf4ecfce43bedc761f26ad924f70483c + ok dtucker@ + + OpenBSD-Commit-ID: 7cddaa41be3b955e6bed570900db7ab8817b1e76 -commit 2e81100763d5885e500f065b04c16ed87ce74318 +commit 4fddebe7f524b3403c876c3b399d5ce7ce3390a6 +Author: djm@openbsd.org +Date: Thu Sep 25 06:33:19 2025 +0000 + + upstream: add some functions to free various structs, including + + channels data and packet state; ok dtucker@ tb@ + + OpenBSD-Commit-ID: a8b3705309d632cdae370d4147a03e703087b0d1 + +commit d0c1e73d408a24b2db18c0aa1a0108bea0f24210 +Author: djm@openbsd.org +Date: Thu Sep 25 06:31:42 2025 +0000 + + upstream: fix leaks of config objects in + + mm_decode_activate_server_options ok dtucker@ tb@ + + OpenBSD-Commit-ID: 211f4d7d02e847bd1bcb460f6beb11658809a742 + +commit b62aa85dcbc8f03bf91d26d14fbf8fd5e172d882 +Author: djm@openbsd.org +Date: Thu Sep 25 06:25:38 2025 +0000 + + upstream: clarify intent and avoid (harmess, defined behaviour) + + unsigned underflow. ok tb@ + + OpenBSD-Commit-ID: b73bf5f1f381c3e4561a6cc706fb1cd77c939cd8 + +commit 6f28a935cc7d073e6647643e81d98b5831df204f +Author: jsg@openbsd.org +Date: Thu Sep 25 06:23:19 2025 +0000 + + upstream: consistently use NULL for null pointer constants found + + with sparse, ok djm@ + + OpenBSD-Commit-ID: 1067504b63732d809d0d57ad4bc626818d112772 + +commit 0af7e5b690e2cfe8824f04f154b0e543509dbefd +Author: jsg@openbsd.org +Date: Thu Sep 25 02:15:39 2025 +0000 + + upstream: remove unneeded externs ok djm@ + + OpenBSD-Commit-ID: fe553193e910a122505142a4e1db7358cc1ae653 + +commit ae62a16118bb96a8e449ef25f5e55ef86a52cefb +Author: jsg@openbsd.org +Date: Thu Sep 25 02:12:16 2025 +0000 + + upstream: remove prototype for removed ssh_packet_set_tos() ok + + djm@ + + OpenBSD-Commit-ID: 396f82995074ef4d7b9ce44168266ef4640d9985 + +commit d8588478850463f8945aa18d0358b2b227f8b57a +Author: jsg@openbsd.org +Date: Wed Sep 24 00:51:28 2025 +0000 + + upstream: spelling; ok dtucker@ + + OpenBSD-Commit-ID: 93870117b0153859dd8baa80b97e44d4558c786b + +commit eff358890a7cab1e7c2fec62e5b9914d2c1c8703 Author: Darren Tucker -Date: Mon Mar 17 21:35:55 2025 +1100 +Date: Tue Sep 23 16:51:34 2025 +1000 - Fix debug log path. + Merge VM tests into a single workflow file. + + Should make it easier to manage, although it may cause a few extra runs. -commit 442a44970179d70ebb62bba792699eaec978a1db +commit d00015d21190517a1f505eb8120f716b1c2e4055 Author: Darren Tucker -Date: Fri Mar 14 16:24:06 2025 +1100 +Date: Tue Sep 23 16:38:45 2025 +1000 - Also lazily unmount workspace in case of straggers. + Test openssl-3.6 branch not beta1. -commit 20427f6735fe5ddab31911ce5315adc71acf47d8 +commit 31fce4fc5aaf79b9a4bccf09467e86c56b482bde Author: Darren Tucker -Date: Fri Mar 14 16:17:39 2025 +1100 +Date: Tue Sep 23 15:51:14 2025 +1000 - Make sure upstream tests run on correct hardware. + Test openssl-3.6.0-beta1. -commit 91a2f70a56827ae31649baf17227b0914ac5aa36 +commit b94e7251a17a497669e825cb70ac79c96bdc3472 Author: Darren Tucker -Date: Fri Mar 14 13:47:27 2025 +1100 +Date: Tue Sep 23 11:32:57 2025 +1000 - Add OpenBSD upstream test on obsdsnap-arm64. + Specify rpath when building OpenSSL. -commit c20f7413525602b0ea786d8974d03a81f7ca2a92 -Author: Damien Miller -Date: Thu Mar 13 10:45:53 2025 +1100 +commit 83853aa5e35f3da0690bccd2983764d4e749a670 +Author: Darren Tucker +Date: Mon Sep 22 15:26:17 2025 +1000 - rebuild .depend + Factor out OpenSSL install and test more versions. + + Move OpenSSL installation into its own script with a "-a" option to + install the "next" version to test for ABI compatibility. -commit d47ef958b89c6fa809302d654009d3dfabe11b75 +commit 2c1d38f7ffc8b8ec244bfe17ec8a85b3d737dcab +Author: Darren Tucker +Date: Mon Sep 22 16:55:49 2025 +1000 + + Exclude generated openbsd-compat/include directory. + +commit 67b3ed101a18348b564507f55e3ed4b7e0d23ff9 +Author: Darren Tucker +Date: Sat Sep 20 15:07:36 2025 +1000 + + Add OpenSSL 3.x ABI cross-compatibility test. + +commit c682c9f45a10ee0dc37fd716cfccd42271f92ddc +Author: Darren Tucker +Date: Sat Sep 20 15:05:19 2025 +1000 + + Add tests for OpenSSL 3.4 and 3.5 versions. + +commit 1659d0ac095608b809fd3173d2c48b7b39d40b02 +Author: Darren Tucker +Date: Sat Sep 20 15:53:04 2025 +1000 + + Build OpenSSL with -j4 to speed it up. + +commit ca9ac1109e2c875ea33da6818c1841aa2181e962 +Author: Darren Tucker +Date: Sat Sep 20 15:16:30 2025 +1000 + + Rerun tests if run_tests.sh changes. + +commit bc328144f149af07139a0f2c1329018cd85b86b7 Author: djm@openbsd.org -Date: Wed Mar 12 22:43:44 2025 +0000 +Date: Fri Sep 19 01:32:45 2025 +0000 - upstream: remove assumption that the sshd_config and any configs + upstream: log at level INFO when PerSourcePenalties actually blocks - included from it can fit in a (possibly enlarged) socket buffer, by having - the sshd listener mainloop actively manage sending the configuration to the - sshd-session subprocess. + access to a source address range. Previously this was logged at level + VERBOSE, which hid enforcement actions under default config settings. - work by markus@ w/ a little feedback from me; - ok me and committing on his behalf + ok dtucker, markus - OpenBSD-Commit-ID: 8f54451483f64951853074adb76bc4f838eaf3ae + OpenBSD-Commit-ID: ea2b0d7c2253ff5205719d74b526cf2870df894d -commit 9c90b563943c16418d737433ac478974b8761ee5 -Author: dtucker@openbsd.org -Date: Tue Mar 11 11:46:44 2025 +0000 +commit 80993390bed15bbd1c348f3352e55d0db01ca0fd +Author: Darren Tucker +Date: Wed Sep 17 17:41:41 2025 +1000 - upstream: Prime caches for DNS names needed for tests. - - When running the SSHFP tests, particularly on an ephemeral VM, the first - query or two can fail for some reason, presumably because something isn't - fully initialized or something. To work around this, issue queries for the - names we'll need before we need them. - - OpenBSD-Regress-ID: 900841133540e7dead253407db5a874a6ed09eca + Whitespace. -commit 10124eefe875a3e4e1cfb84ebe6a613ed3213b78 -Author: dtucker@openbsd.org -Date: Tue Mar 11 09:06:50 2025 +0000 +commit fc704057ce6b75637645a4b9c917565b3563e21b +Author: Darren Tucker +Date: Wed Sep 17 17:33:25 2025 +1000 - upstream: Some dd's don't understand "1m", so handle seperately. - - OpenBSD-Regress-ID: 1d983b27c96f28f69d3a288c19e8d8c58e1b2ee3 + Move Gihub VMs to their own status line. -commit c21c8fc319376c2f5e0da166e9e89a97a245ae72 +commit 2202e5f9008003044cac01ed70d83deec42ad4e0 Author: Darren Tucker -Date: Tue Mar 11 19:17:46 2025 +1100 +Date: Tue Sep 16 23:00:14 2025 +1000 - Lazily unmount github workspace at end of workflow. - - Sometimes when a test times out the workspace is still busy when we try - to unmount it, which leaves the runner unusable until it's cleaned up - manually. We try to unmount this in the first step, but that usually - doesn't work since it fails during setup before it starts our workflow. - Move it to the end and make it a lazy unmount so it hopefully works - eventually. + Use relative URLs for status -commit 4bcbac742968f5086cfd4c570a51de25ef77931f -Author: dtucker@openbsd.org -Date: Tue Mar 11 07:50:20 2025 +0000 +commit 7c32e09ea3e5c7e1fa0b7e2d4ddc83f8beadafed +Author: Darren Tucker +Date: Mon Sep 15 17:21:15 2025 +1000 - upstream: Add regress test for sftp resume. - - OpenBSD-Regress-ID: 37f629b3014338fa23a85df1e1bb320ea12282e1 + Add VM test targets via vmaction on Github. -commit e2c4f070b43a4fd7d59a9350e2fe78df605830b5 -Author: dtucker@openbsd.org -Date: Tue Mar 11 07:46:02 2025 +0000 +commit a4aa090a3d40dddb07d5ebebc501f6457541a501 +Author: djm@openbsd.org +Date: Mon Sep 15 03:00:22 2025 +0000 - upstream: Use ssh binary instead of the (smaller) script when + upstream: memory leaks in unit tests - preparing test data files since it's faster. + OpenBSD-Regress-ID: af11ac7b8034b99ca324af4dae1ef5cd7700b273 + +commit 6f5942454ad6756355f3b4983ab882cf15e44440 +Author: djm@openbsd.org +Date: Mon Sep 15 05:17:37 2025 +0000 + + upstream: fix leaks of struct sftp_conn in scp; ok dtucker@ - OpenBSD-Regress-ID: 4215e42682fdb73e131e10645d4a1a23a91d64f5 + OpenBSD-Commit-ID: 76bea50b5b87b750c3771bf80feb6067d994a9d2 -commit 62f02e95ba5cda4649c482d30f4370e2360eb94d -Author: dtucker@openbsd.org -Date: Tue Mar 11 07:43:45 2025 +0000 +commit 52f38c76fcb38dfe619d8caa3bb4bb782c785026 +Author: djm@openbsd.org +Date: Mon Sep 15 04:52:41 2025 +0000 - upstream: Set up dbclient's known_hosts as it expects. + upstream: leak of principals file lines; ok dtucker@ - OpenBSD-Regress-ID: 9e0898e8423237ce5023be53787bb4062e0d0418 + OpenBSD-Commit-ID: 918bf1b70e5a969059300f3c23d45911690d9015 -commit 395284bd52887dbaf7e78200c857d7f2d9ce398e -Author: dtucker@openbsd.org -Date: Tue Mar 11 07:43:03 2025 +0000 +commit b9464cee0fd084d89d91696a17b3621b4cf512bf +Author: djm@openbsd.org +Date: Mon Sep 15 04:52:12 2025 +0000 - upstream: Use $DBCLIENT to access dbclient for consistency. + upstream: leak of authentication options at exit; ok dtucker@ - OpenBSD-Regress-ID: 81e1b41e1ffc49aba1e6fcaeb6242f3b7875ea3c + OpenBSD-Commit-ID: ba559799c2ff9b10afc3abefb1797c0843a6ff24 -commit 97e10c0005a784622c61cb4e8bb7858b410bbcc6 -Author: dtucker@openbsd.org -Date: Tue Mar 11 07:42:08 2025 +0000 +commit 0bb37080c86674de7cdfb56c80add3cd316c68a8 +Author: djm@openbsd.org +Date: Mon Sep 15 04:51:35 2025 +0000 - upstream: Check if dbclient supports SHA1 before trying SHA1-based + upstream: memleak of keys not used for authentication; ok - KEX. + dtucker@ - Dropbear 2025.87 removed SHA1 support by default, which means - diffie-hellman-group14-sha1 is not available. Unfortunately there isn't a - flag to query supported KEX, so instead check MACs and if it doesn't have - SHA1 methods, assuming SHA1 based KEXes are likewise not available. Spotted - by anton@. + OpenBSD-Commit-ID: ddfda79d243150fbd382d8f2cd75a90a072b3669 + +commit ee99f6e93e0ee90eedbd27ffb9b7f9fef7b98010 +Author: djm@openbsd.org +Date: Mon Sep 15 04:50:42 2025 +0000 + + upstream: memleak of certificate path; ok dtucker@ - OpenBSD-Regress-ID: acfa8e26c001cb18b9fb81a27271c3b51288d304 + OpenBSD-Commit-ID: 90dc5390f2756ba339e2e6df54d4b8651d64c1e7 -commit 29a5127f808d00aa539fd27d83a65c2c56179b0e -Author: dtucker@openbsd.org -Date: Tue Mar 11 07:48:51 2025 +0000 +commit 42fc6b6f9fbf58293b070f4de377c7695c275a8a +Author: djm@openbsd.org +Date: Mon Sep 15 04:49:41 2025 +0000 - upstream: Set highwater when resuming a "put". Prevents bogus "server + upstream: memleak of hostkey when downgrading host cert->key; ok - reordered acks" debug message. ok djm@ + dtucker - OpenBSD-Commit-ID: aa7f6d0fc2e893c8c278ea3e6e0974c2eca83f5d + OpenBSD-Commit-ID: f6f1f38a8ec144fb615434f6877066cf4610b826 -commit 6575859d7acb110acf408707f98ed9744ca7d692 -Author: dtucker@openbsd.org -Date: Mon Mar 3 06:54:37 2025 +0000 +commit bc60bd55cbc1f8139c840668733b51475cbefd93 +Author: djm@openbsd.org +Date: Mon Sep 15 04:49:00 2025 +0000 - upstream: Test for %-token and env var expansion in SetEnv. + upstream: memleak of editline history; ok dtucker@ - OpenBSD-Regress-ID: bd6139a6177ac4afb29a0ce4afc23567b22ef9f9 + OpenBSD-Commit-ID: a244c54eb074cf7fbe28f7ac4f03ace270f7a999 -commit fd7ad8d7bf7dbdeb8f11a8b51aa9d31df1a17e52 -Author: dtucker@openbsd.org -Date: Sun Mar 2 07:41:06 2025 +0000 +commit ee77ab9b2ca2d70daf8d4352f5daffa8036ece64 +Author: djm@openbsd.org +Date: Mon Sep 15 04:48:29 2025 +0000 - upstream: Also test User expansions when supplied via -l option and + upstream: memleak of rfwd callback context; ok dtucker@ - user@host. + OpenBSD-Commit-ID: 70b2aafeaace90703dd16a44a2a0b723d9155f33 + +commit 0088b3f0ab2c615ae95b9f374963abaa0ab837ec +Author: djm@openbsd.org +Date: Mon Sep 15 04:47:49 2025 +0000 + + upstream: memleaks of request packet and hostkeys blob; ok - OpenBSD-Regress-ID: 56415859260b53ef0dd20f71225ba5fdf6320f50 + dtucker@ + + OpenBSD-Commit-ID: 313b13a8e36b4ca8e064ee56792e67e0670a386a -commit e6cfd783f1491b502db9322aa970822c63f1667d -Author: dtucker@openbsd.org -Date: Sat Mar 1 06:12:47 2025 +0000 +commit d68451a25808c4eee74b898873cd4761f73651ed +Author: djm@openbsd.org +Date: Mon Sep 15 04:41:20 2025 +0000 - upstream: Tests for User expansion of %-tokens and environment + upstream: memleak of KRL revoked certs struct; ok dtucker - variables. + OpenBSD-Commit-ID: f319868e0b2de49c41c735e75b87c403f009f5f9 + +commit 67940cc2f329427d3acb64d4893faf4527e58d5c +Author: djm@openbsd.org +Date: Mon Sep 15 04:40:34 2025 +0000 + + upstream: memleak of kex->server_sig_algs; ok dtucker@ - OpenBSD-Regress-ID: 7ed21dd0e09fb1f3537b8b177f171018aa501628 + OpenBSD-Commit-ID: 41a3f64edd2c9b8addb2e445514ae25c24819e2c -commit 197e503b8e4b642ce0f405a5d65da4256fa96431 +commit fae8e41741d23298c94a1ea3ef8704a1cc186cb5 Author: djm@openbsd.org -Date: Fri Dec 6 16:25:58 2024 +0000 +Date: Mon Sep 15 04:39:58 2025 +0000 - upstream: use glob(3) wildcards in AuthorizedKeys/PrincipalsFile + upstream: fix memleak of channel forwarding permissions; ok - tests to exercise this feature; ok dtucker + dtucker@ - OpenBSD-Regress-ID: 7f7b19c0b05b1862cc6521ce61b2b301a3f9cc3b + OpenBSD-Commit-ID: 069745547109bc8fcc09fab5b19c53599cae99fd -commit 396202180180a4ac16788d469508a348789dafa1 +commit 03872018c14ed943bc01a4e88be59195a742f106 Author: djm@openbsd.org -Date: Fri Dec 6 10:37:42 2024 +0000 +Date: Mon Sep 15 04:39:15 2025 +0000 - upstream: implement attestation verification for ED25519 keys + upstream: when merging auth options into the active set, don't - OpenBSD-Regress-ID: c44fa5cdb434375a8b5545fdb4fc651061afca1f + leak the old struct sshauthopt; ok dtucker@ + + OpenBSD-Commit-ID: c6bfd7bc2932e37f811b3c53272c3b919d33e75b -commit b49875428cda9c16c5bd52552100da2b419cda5f -Author: dtucker@openbsd.org -Date: Mon Mar 3 06:53:09 2025 +0000 +commit efed5da4ced88170cf474246eff771dd16c7092f +Author: djm@openbsd.org +Date: Mon Sep 15 04:38:00 2025 +0000 - upstream: Add %-token and environment variable expansion to SetEnv. + upstream: fix memleak when applying certificate options; ok - feedback deraadt@ jmc@, nits and ok djm@ + dtucker - OpenBSD-Commit-ID: 2f6e5070481cb73e6f35fd1c6608c1eeff88a5c1 + OpenBSD-Commit-ID: 36c219dcc05f4df82a0f9c500bdf5dbfea925289 -commit b6bba67e6c31d268480773e4fed16d0a32b4218e +commit edc601707b583a2c900e49621e048c26574edd3a Author: djm@openbsd.org -Date: Sun Mar 2 22:44:00 2025 +0000 +Date: Thu Sep 11 07:23:32 2025 +0000 - upstream: fix PerSourcePenalty incorrectly using "crash" penalty when + upstream: disable ssh-add autoexpiry of certificates when testing - LoginGraceTime was exceeded. Reported by irwin AT princeton.edu via bz3797 + expired certificates - OpenBSD-Commit-ID: 1ba3e490a5a9451359618c550d995380af454d25 + OpenBSD-Regress-ID: 64aadd23d37fd0b3a06498151f2cf83be7ac342c -commit 38d69fee1b06948f160d94abd07b6b297630d30a -Author: Damien Miller -Date: Sun Mar 2 22:06:53 2025 +1100 +commit c60153e4878f3a6700af69adbdd1863003e78abf +Author: djm@openbsd.org +Date: Thu Sep 11 07:22:37 2025 +0000 - include __builtin_popcount replacement function + upstream: correct getopt() string - Some systems/compilers lack __builtin_popcount(), so replace it as - necessary. Reported by Dennis Clarke; ok dtucker@ + OpenBSD-Commit-ID: 05ef9581a3dab32ec93aa5b9c3349ed1e7da9ec8 -commit c94138d02a45dda5015f38f5a60b0bdde29019c1 +commit 7a4738af45201c115a9e20f830f30ed38ce6be76 Author: djm@openbsd.org -Date: Sun Mar 2 11:03:13 2025 +0000 +Date: Thu Sep 11 03:29:58 2025 +0000 - upstream: whitespace + upstream: need time.h for time(3) - OpenBSD-Commit-ID: 1bd8953a37451ef7e0991f9fceec5e8005fe986a + OpenBSD-Commit-ID: 530964039cccab679432b6c5b28d2b0aa9760b00 -commit 65d2c59628e68e166046efa69e76c1d395a8df6e -Author: dtucker@openbsd.org -Date: Sun Mar 2 07:02:49 2025 +0000 +commit 0c719c6aabc061f02a907fc96c390d0449b49f26 +Author: djm@openbsd.org +Date: Thu Sep 11 02:54:42 2025 +0000 - upstream: Make a copy of the user when handling ssh -l, so that + upstream: When adding certificates to an agent, set the expiry to - later during User token expansion we don't end up freeing a member of argv. - Spotted by anton@'s regress tests. + the certificate expiry time plus a short (5 min) grace period. - OpenBSD-Commit-ID: 2f671a4f5726b66d123b88b1fdd1a90581339955 + This will cause the agent to automtically remove certificates shortly + after they expire. + + A new ssh-add -N option disables this behaviour. + + Feedback/ok deraadt@ + + OpenBSD-Commit-ID: 92fed1bba1025069ad45deebb534be7530e181df -commit bd30cf784d6e825ef71592fb723c41d4f2fd407b -Author: dtucker@openbsd.org -Date: Sat Mar 1 06:11:26 2025 +0000 +commit e9dcccc3541b0ae1c43581ed26215d5cc82e4be0 +Author: jsg@openbsd.org +Date: Mon Sep 8 00:31:54 2025 +0000 - upstream: Allow %-token and environment variable expansion in User, + upstream: remove unused 0-sized files; ok deraadt@ - with the exception of %r and %C which are self-referential. Requested in - bz#3477, ok djm@, man page improvements jmc@ + OpenBSD-Commit-ID: 7e8178786157e863f6ff63c5d55200d7b6b04f9e + +commit d16b1b484a024ee6b35094e7d9d55bf96b96253b +Author: dtucker@openbsd.org +Date: Fri Sep 5 10:34:35 2025 +0000 + + upstream: Tabs->spaces. Removes diff vs portable. - OpenBSD-Commit-ID: caeb46251ee073662f6f5864c6f7b92d8ac80fa8 + OpenBSD-Commit-ID: 06598021a9f08188dab29ac956b2baa002a0ff85 -commit 94f59dcfc57f95ae044f75c3ce544329c8956c35 +commit 3d8ae7f235b96da604b08c44ae83420e367eeab4 +Author: Tim Rice +Date: Mon Sep 8 12:53:10 2025 -0700 + + modified: regress/rekey.sh + Fix for when building out of tree. + +commit 54abadd3f286efea0dbbdbfea8011d5e1e30c074 Author: Darren Tucker -Date: Sat Mar 1 10:28:59 2025 +1100 +Date: Sun Sep 7 13:35:22 2025 +1000 - Rebuild config files if Makefile changes. + Accept OpenSSL 4.0.0-dev versions. - This ensures paths are updated if they are changed by re-running configure. - Patch from rapier at psc.edu. + They seem to work, at least for now. -commit dfd9880585db1570656022f9fe1519df673f7b8a +commit 67a8bf4e4057597170bfa923fe2ce5bf90c43974 +Author: Maxim Khon +Date: Mon Aug 18 12:05:42 2025 +0000 + + Use SSH_TUN_COMPAT_AF on FreeBSD. + + Otherwise tun forwarding from other OSes fails as soon as the first IPv6 + message is sent by the other side (which is usually a Router Solicitation + ICMPv6 message which is sent as soon as the interface is up): all other + OS'es use SSH_TUN_COMPAT_AF or SSH_TUN_PREPEND_AF which effectively uses + OpenBSD AF_INET/AF_INET6 values. + +commit 3ca274e44cb2c2351376fc14e4c3e92ba4a8f87b Author: Darren Tucker -Date: Wed Feb 26 18:16:03 2025 +1100 +Date: Fri Sep 5 21:32:30 2025 +1000 - Check for le32toh, le64toh, htole64 individually. + Check for nlist function. - It appears that at least some versions of endian.h in glibc do not have - the latter two, so check for and replace each one individually. - bz#3794, ok djm@ + Check for nlist function presence before attenmpting to use it instead + of relying on the presence of the nlist.h header. Mac OS X, in particular + has the header, but only has the function in the 32bit libraries. -commit cb99e8eb228df366af33f4fe88d7a9dd0dbf0756 -Author: djm@openbsd.org -Date: Tue Feb 25 06:25:30 2025 +0000 +commit ee32a36c62424f13907023595bfa8b23a528ced1 +Author: dtucker@openbsd.org +Date: Fri Sep 5 10:23:55 2025 +0000 - upstream: ressurect fix for "match invalid-user" that got clobbered + upstream: Order includes as per KNF and add time.h. Removes diff - by 1.423 + vs portable. - OpenBSD-Commit-ID: d18bf0945976e0f3467d710d4bc8bdbe181c0567 + OpenBSD-Commit-ID: 38043f0bfa17c48ef6d1a744c2834b4405bc9311 -commit 487cf4c18c123b66c1f3f733398cd37e6b2ab6ab -Author: deraadt@openbsd.org -Date: Fri Feb 21 18:22:41 2025 +0000 +commit 0ac179c9540e2b05b4c1194db69ce01306c253d3 +Author: dtucker@openbsd.org +Date: Fri Sep 5 10:17:21 2025 +0000 - upstream: Also prohibit , (comma) in hostnames, proposed by David - - Leadbeater ok djm millert + upstream: Order headers as per KNF. Removes diff vs portable. - OpenBSD-Commit-ID: 2837fa31dc6e81976f510f0a259edaa559b20b07 + OpenBSD-Commit-ID: 4df519fd9fa13ce9653adf7a3d1076e20591d886 -commit 3bc6de98c830bd5207f6c371ba69c5874f06305b -Author: Damien Miller -Date: Mon Feb 24 17:27:50 2025 +1100 +commit e80322284f3ee70b6b760a9f83179470d675e5ba +Author: dtucker@openbsd.org +Date: Fri Sep 5 10:01:35 2025 +0000 - Try to fix github tcmalloc target failure + upstream: Order headers as per KNF. - tcmalloc may, depending on the stacktrace generator it uses, create - pipe(2) fds during shared library initialisation. These will later - get clobbered by ssh/sshd calling closefrom() and chaos will ensue. - Tell tcmalloc to use an unwinder that doesn't pull this stuff. + OpenBSD-Commit-ID: 7156b69b0364c68e181e0f6fa17c0f05c72e8670 -commit 922e54bbfe8c8479453693ef52350338f0c19124 -Author: Damien Miller -Date: Fri Feb 21 13:44:35 2025 +1100 +commit bb8ac0515e68cab63db2d026eb60127185a3d2b8 +Author: Darren Tucker +Date: Fri Sep 5 20:39:16 2025 +1000 - cleanup last mention of ubuntu-20.04 + Resync header order with upstream. -commit bc4b3f6dc1738d389e5c9dcca8c56d7e153fee49 -Author: Damien Miller -Date: Fri Feb 21 13:44:13 2025 +1100 +commit 024b694249482698b0c73d24da0eaec696fca8c8 +Author: Darren Tucker +Date: Fri Sep 5 20:37:04 2025 +1000 - prune gcc/clang versions to be tested + Resync header order with upstream. + +commit aed6a958bc108faab64bc2855d6ed93894cfc6ff +Author: Darren Tucker +Date: Fri Sep 5 20:30:20 2025 +1000 + + Sync includes with upstream. + +commit 22cfd2dd32f34f0cea218dd651f3aa9544b6e3b5 +Author: Darren Tucker +Date: Fri Sep 5 20:26:14 2025 +1000 + + Move ssh-pkcs11.h include to match upstream. + +commit b34c16bc4cac2962cc6a7517efbc4fed2c8a2d9a +Author: Darren Tucker +Date: Fri Sep 5 20:20:27 2025 +1000 + + Reorder includes to match upstream. + +commit 441a8fa9a0178704bce497bff92ca43fcf04bf7a +Author: dtucker@openbsd.org +Date: Fri Sep 5 09:58:08 2025 +0000 + + upstream: Order headers as per KNF. Removes diff vs portable. - Test only the oldest and latest versions of each + OpenBSD-Commit-ID: db72be57429418f6a4319bbe34c98fc103e11ce0 -commit 94b73755f931d592a612ef5cb998694643eab5ff -Author: Damien Miller -Date: Fri Feb 21 11:30:22 2025 +1100 +commit 19d6a7afb256c4afc571dbf56a013ef91cd9596f +Author: dtucker@openbsd.org +Date: Fri Sep 5 09:49:26 2025 +0000 - Update AWS-LC version number + upstream: Order headers as per KNF. Also removes diff vs - Patch from Shubham Mittal bz bz3792 + -portable. + + OpenBSD-Commit-ID: 2061307dc938712e524bc9da48a52f545e43670e -commit 6887099fae6d9f3482e1075d034e9343dc413200 -Author: Damien Miller -Date: Fri Feb 21 11:22:34 2025 +1100 +commit 932e9f200bd48b7568eb21ec456c67ec92d517e2 +Author: dtucker@openbsd.org +Date: Fri Sep 5 09:31:31 2025 +0000 - adjust workflows for ubuntu version transition + upstream: Remove unused rmd160.h header. ripemd160 support was - remove workflows for unsupported compilers, add a few for additional - supported compilers, move some workflows to run on ubuntu-latest + removed in 2017. + + OpenBSD-Commit-ID: 937fca21498b921adf6e04bac120f4a2e7975b3c -commit 33bb47e6f74f2ca8093946e6f462d655a9ae46d3 -Author: Damien Miller -Date: Thu Feb 20 17:10:32 2025 +1100 +commit f93de828b9b0f29bff51d38ea92d0759595ec30b +Author: Darren Tucker +Date: Fri Sep 5 20:07:16 2025 +1000 - Add ubuntu-*-arm test runners + Create replacement nlist.h if needed. + + Remove #ifdef HAVE_NLIST_H wrapper. ok djm@ -commit a0c95fbb215b2168fa51b15906e2d6990d7fef6b -Author: Damien Miller -Date: Thu Feb 20 17:03:28 2025 +1100 +commit 6aac2beaa53467e83f6a137376b6dcf423ab6f6c +Author: Darren Tucker +Date: Fri Sep 5 19:55:20 2025 +1000 - remove ubuntu-20.04 Github action runners + Create replacement endian.h if needed. - ubuntu-20.04 is deprecated now, so migrate all its unique runners - to ubuntu-22.04. + Remove #ifdef HAVE_ENDIAN_H wrapper. ok djm@ + +commit a60721c894f0a2ce973876d0f55617e187e6fab1 +Author: Darren Tucker +Date: Fri Sep 5 19:52:48 2025 +1000 + + Add /* WITH_OPENSSL */ comments. - ok dtucker@ + Removes diffs vs upstream. -commit 0cbeedba81b57c56379e1d202b9ccd3b72af7ddc -Author: Damien Miller -Date: Tue Feb 18 19:03:42 2025 +1100 +commit c729a833298d9d55ffb22771cf1400dfdc640164 +Author: Darren Tucker +Date: Fri Sep 5 19:22:37 2025 +1000 - openssh-9.9p2 + Move sys/time.h include to match upstream. -commit 0832aac79517611dd4de93ad0a83577994d9c907 -Author: djm@openbsd.org -Date: Tue Feb 18 08:02:48 2025 +0000 +commit caa973dd06a7be43c29353b256c9a473f5ad9882 +Author: Darren Tucker +Date: Fri Sep 5 19:13:52 2025 +1000 - upstream: Fix cases where error codes were not correctly set + Create replacement netgroup.h if needed. - Reported by the Qualys Security Advisory team. ok markus@ + Remove #ifdef HAVE_NETGROUP_H wrapper. ok djm@ + +commit 7d30526b7df14d960a5de63d6af823ffdab86518 +Author: Darren Tucker +Date: Fri Sep 5 18:24:59 2025 +1000 + + Remove stray #endif left from previous. + +commit 4911f2600fdbb1959311bb1886bfe51f7dd4a74e +Author: Darren Tucker +Date: Fri Sep 5 18:08:51 2025 +1000 + + Create replacement libgen.h if needed. - OpenBSD-Commit-ID: 7bcd4ffe0fa1e27ff98d451fb9c22f5fae6e610d + Remove #ifdef HAVE_LIBGEN_H wrapper. ok djm@ -commit 6ce00f0c2ecbb9f75023dbe627ee6460bcec78c2 -Author: djm@openbsd.org -Date: Tue Feb 18 08:02:12 2025 +0000 +commit 65dcdb56f5daee519ec824ae17e64412d2492f90 +Author: Darren Tucker +Date: Fri Sep 5 18:05:15 2025 +1000 - upstream: Don't reply to PING in preauth phase or during KEX + Create replacement sys/un.h if needed. - Reported by the Qualys Security Advisory team. ok markus@ + Remove #ifdef HAVE_SYS_UN_H wrapper. ok djm@ + +commit 60334af5a908ac3b263d2ec696f9977e20b739cb +Author: Darren Tucker +Date: Fri Sep 5 18:03:55 2025 +1000 + + Reformat replacement header check one per line. + +commit cd9ba068e36b0f37374d2eba2d19dacc7ea9a167 +Author: Darren Tucker +Date: Fri Sep 5 17:55:33 2025 +1000 + + Create replacement time.h if needed. - OpenBSD-Commit-ID: c656ac4abd1504389d1733d85152044b15830217 + Remove #ifdef HAVE_TIME_H wrapper. ok djm@ -commit 9e5bd74a85192c00a842f63d7ab788713b4284c3 -Author: jmc@openbsd.org -Date: Sat Feb 15 06:48:56 2025 +0000 +commit ea586edbcbec7089f768ed682a79a399eaa1e5b1 +Author: Darren Tucker +Date: Fri Sep 5 17:50:18 2025 +1000 - upstream: - use \& when contructs like "e.g." end a line, to avoid + Create replacement sys/stat.h if needed. - double spacing - macro is Qq not Oq + Remove #ifdef HAVE_SYS_STAT_H wrapper. ok djm@ + +commit 59b80707c6cf45230597a800e7d2ce6b00ce35b5 +Author: Darren Tucker +Date: Fri Sep 5 17:44:07 2025 +1000 + + Create replacement sys/time.h if needed. - OpenBSD-Commit-ID: 17e5d2d7f288cc7fc536e3af252224525f9fb43a + Remove #ifdef HAVE_SYS_TIME_H wrapper. ok djm@ -commit f519e71fb7a46314ae16e2a75490649dc0bd01a2 -Author: Damien Miller -Date: Sat Feb 15 13:12:40 2025 +1100 +commit 82fed5110fe09e9af258a8f5a2f92ffb397fff5b +Author: Darren Tucker +Date: Fri Sep 5 17:31:15 2025 +1000 - depend + Create replacement ifaddrs.h if needed. + + Remove #ifdef HAVE_IFADDRS_H wrapper. ok djm@ -commit 9131ac64b0ebe66dc1de9d44bf8d1bd64a24c350 -Author: djm@openbsd.org -Date: Sat Feb 15 01:52:07 2025 +0000 +commit 53887d8ebc583b51e996cb2bdeb11e054d36343b +Author: Darren Tucker +Date: Fri Sep 5 17:27:43 2025 +1000 - upstream: add "Match version" support to ssh_config. Allows + Create replacement util.h if needed. - matching on the local version of OpenSSH, e.g. "Match version OpenSSH_10.*" + Remove #ifdef HAVE_UTIL_H wrapper. ok djm@ + +commit 5f09983d1e724097bd577097fb0f2c00c2436f21 +Author: Darren Tucker +Date: Fri Sep 5 17:24:50 2025 +1000 + + Create replacement paths.h if needed. - ok markus@ + Remove #ifdef HAVE_PATHS_H wrapper. ok djm@ + +commit d45b17dc5a0598dda2b11dc89598203408d2d59c +Author: Darren Tucker +Date: Fri Sep 5 17:17:52 2025 +1000 + + Create replacement poll.h if needed. - OpenBSD-Commit-ID: c0cb504d0b9e43ccf12e68a544a7cd625e89758d + Remove #ifdef HAVE_POLL_H wrapper. ok djm@ -commit 192a20df00c8a56fe7d92ffa23d959c865d7fb9e -Author: djm@openbsd.org -Date: Sat Feb 15 01:50:47 2025 +0000 +commit 9b2c5a2db0650e394597839ef00d797f57568937 +Author: Darren Tucker +Date: Fri Sep 5 17:06:14 2025 +1000 - upstream: Add support for "Match sessiontype" to ssh_config. Allows + Fill in missing system header files. - matching on the type of session requested, either "shell" for interactive - sessions, "exec" for command execution sessions, "subsystem" for subsystem - requests, such as sftp, or "none" for transport/forwarding-only sessions. + Create replacement header files inside openbsd-compat for common headers + that are missing on a given platform. Usually these are just empty, + but in some cases they'll include the equivalent file. This avoids + having to wrap those includes in '#ifdef HAVE_FOO_H' and reduces the + diff vs OpenBSD. - ok markus@ + If we create any such headers, add the path to includes. - OpenBSD-Commit-ID: eff5c001aecb2283d36639cfb28c0935a8bfd468 + Initially just stdint.h, more to follow. + + ok djm@ -commit caa3c0c77082888236b0b0c4feb3e6879731b3ba +commit f64701ca25795548a61614d0b13391d6dfa7f38c Author: djm@openbsd.org -Date: Sat Feb 15 01:48:30 2025 +0000 +Date: Thu Sep 4 03:04:44 2025 +0000 - upstream: "Match command ..." support for ssh_config to allow + upstream: repair test after changes to percent expansion of usernames - matching on the remote command specified on the commandline. + on the commandline. - Also relaxes matching rules for `Match tagged` to allow - `Match tagged ""` to match an empty tag value. This also works - for command. + Test more cases that should/shouldn't expand and lightly test + username validity checks. - ok markus@ + OpenBSD-Regress-ID: ad4c12c70bdf1f959abfebd1637ecff1b49a484c + +commit 45698669d49949868b1f3d13dfda1b7cb70060ad +Author: djm@openbsd.org +Date: Thu Sep 4 00:37:10 2025 +0000 + + upstream: unit tests for sshbuf_equals and sshbuf_dtourlb64; ok - OpenBSD-Commit-ID: 00dcfea425bf58d824bf5e3464cfc2409121b60d + deraadt@ + + OpenBSD-Regress-ID: bab54e2d4caa813036a63ee67e92c93e6712a5b9 -commit 38f6000e9851a00e2e4b8e1eb4ea6a243ef7e6a3 -Author: Damien Miller -Date: Tue Feb 11 10:32:26 2025 +1100 +commit 4be445116f1b56f14254b98d8b132bb25777e160 +Author: djm@openbsd.org +Date: Thu Sep 4 00:34:17 2025 +0000 - depend + upstream: unit tests for a bunch of misc.c functions; ok deraadt@ + + OpenBSD-Regress-ID: 886cf142605405e777ee77a96b48694dc2e9235d -commit aa1409e7a0a5605f0127651a3ba5a348666325bc +commit e3699ff47df336f57da2e78188d0057f8368af56 Author: djm@openbsd.org -Date: Mon Feb 10 23:19:26 2025 +0000 +Date: Thu Sep 4 00:32:31 2025 +0000 - upstream: include arguments the command was invoked with, and + upstream: fix sshbuf_dtourlb64() to not choke on empty buffers; - operating system name, version and architecture in startup debugging output; - ok dtucker + previously it incorrectly returned an error in this situation; ok deraadt - OpenBSD-Commit-ID: 2a509d319aaf31a6bf9998e1842832883fbc3edd + OpenBSD-Commit-ID: e62773d6e8cb95a19aab54f0af0edbcd47b345c0 -commit 857ac20f5fe19f183defba5dbf4b7d9e6400230c +commit 8e85ad33cfcc71e03594e53f2e19d8ce2e27dcc6 Author: djm@openbsd.org -Date: Mon Feb 10 23:16:51 2025 +0000 +Date: Thu Sep 4 00:31:49 2025 +0000 - upstream: include line number in Match debug messages, makes it a + upstream: fix rtrim() function to not attempt to delete whitespace - little easier to see what's going on + inside a string, just at the end. ok deraadt@ - OpenBSD-Commit-ID: 1fcf4aa2ee667711b9497ded0fa52d757c69b1df + OpenBSD-Commit-ID: d44deaa43580cd88de978dd5509b14e905b67b84 -commit af49d474e481d2d78b2f06b06a06b0b37629358e +commit 43b3bff47bb029f2299bacb6a36057981b39fdb0 Author: djm@openbsd.org -Date: Mon Feb 10 23:00:29 2025 +0000 +Date: Thu Sep 4 00:30:06 2025 +0000 - upstream: fix "Match invalid-user" from incorrectly being activated + upstream: don't allow \0 characters in url-encoded strings. - in initial configuration pass when no other predicates were present on the - match line + Suggested by David Leadbeater, ok deraadt@ - OpenBSD-Commit-ID: 02703b4bd207fafd03788bc4e7774bf80be6c9a8 + OpenBSD-Commit-ID: c92196cef0f970ceabc1e8007a80b01e9b7cd49c -commit 1c67bae3f5834e48ded71c406f2039dea6e536db -Author: schwarze@openbsd.org -Date: Sun Feb 9 18:24:08 2025 +0000 +commit 35d5917652106aede47621bb3f64044604164043 +Author: djm@openbsd.org +Date: Thu Sep 4 00:29:09 2025 +0000 - upstream: In a section 1 manual, use the plain English words + upstream: Improve rules for %-expansion of username. - "standard output" rather than the overly technical abbreviation "stdout" - we - are not talking about a device file or a FILE * object here. Issue reported - by on the groff mailing list. + Usernames passed on the commandline will no longer be subject to + % expansion. Some tools invoke ssh with connection information + (i.e. usernames and host names) supplied from untrusted sources. + These may contain % expansion sequences which could yield + unexpected results. - OpenBSD-Commit-ID: a0816999f970e6159523bed8484f62c42ec93109 + Since openssh-9.6, all usernames have been subject to validity + checking. This change tightens the validity checks by refusing + usernames that include control characters (again, these can cause + surprises when supplied adversarially). + + This change also relaxes the validity checks in one small way: + usernames supplied via the configuration file as literals (i.e. + include no % expansion characters) are not subject to these + validity checks. This allows usernames that contain arbitrary + characters to be used, but only via configuration files. This + is done on the basis that ssh's configuration is trusted. + + Pointed out by David Leadbeater, ok deraadt@ + + OpenBSD-Commit-ID: e2f0c871fbe664aba30607321575e7c7fc798362 -commit 85b3d68dd931416ede657f371f1d60cdc3a66f34 -Author: dtucker@openbsd.org -Date: Fri Jan 17 00:09:41 2025 +0000 +commit f38a552dc71f20df2544338099e3fe2563f1a9ca +Author: Damien Miller +Date: Wed Sep 3 09:42:39 2025 +1000 - upstream: Fix debug logging of user specific delay. Patch from + missing header + +commit cc4eb3d6943cb57e08ab3abbcf92644deb429e46 +Author: djm@openbsd.org +Date: Tue Sep 2 11:08:34 2025 +0000 + + upstream: simplify algorithm list functions using xextendf(); ok - Achim Leitner (fjl5) via github PR#552. + dtucker@ - OpenBSD-Commit-ID: 834a869ed9b15058d3c1ef0cd75402ef989255d8 + OpenBSD-Commit-ID: ffc5f8d0c25b95705a8a66c8b634f98d23bd92dc -commit e4e5b06fdf4532705669c0ae944b364022d16b9d -Author: dtucker@openbsd.org -Date: Thu Jan 16 06:37:10 2025 +0000 +commit 8866d24cdd1d6e73bb3220b753f94e255c49ff96 +Author: djm@openbsd.org +Date: Tue Sep 2 11:04:58 2025 +0000 - upstream: Call log_init in sshd-auth and sshd-session immediately - - after parsing the config file so that any log settings set in the config file - take effect immediately. Move version banners to immediately after that, and - make them distinct per binary. ok djm@ + upstream: unit test for xextendf() - OpenBSD-Commit-ID: acf3d090638edf9b6e6f78eed96b537fe671f0f5 + OpenBSD-Regress-ID: ddb3b4db1a52dda23696b967470882fe2b9c3af7 -commit 0643994b20f2cc54bca80842a984b3052ff1a6a9 -Author: dtucker@openbsd.org -Date: Wed Jan 15 22:23:13 2025 +0000 +commit 2f369d3fd0ff3715c2b32dff5cb35c0330272445 +Author: djm@openbsd.org +Date: Tue Sep 2 09:41:23 2025 +0000 - upstream: Use strprefix helper when processing sshd -C test args + upstream: fix comment on sshbuf_froms() - it *returns* an error - instead of counting bytes by hand. ok djm@ + code, the allocated buffer is passed via argument - OpenBSD-Commit-ID: 2866d369d96fe04bf76112260ac37e489f98a9a9 + OpenBSD-Commit-ID: b2b0a76df71328f39c3e2ad941a4d87085d8335d -commit 66efd0fbb6b8b95f8a520f2cdf8ede14e62b30b3 -Author: Damien Miller -Date: Thu Feb 6 09:38:09 2025 +1100 +commit 6fd93060bb2ec35a7f0bf96d1a74104bab49e017 +Author: djm@openbsd.org +Date: Tue Sep 2 09:40:19 2025 +0000 - add support for AWS-LC (AWS libcrypto) + upstream: GssStrictAcceptor was missing from sshd -T output; fix - Patch from Shubham Mittal via bz3784; ok dtucker + OpenBSD-Commit-ID: 6014049ccfedc48a208e37d5488ade6bdc2d1c44 -commit 826483d51a9fee60703298bbf839d9ce37943474 -Author: Tim Rice -Date: Mon Dec 16 15:36:54 2024 -0800 +commit d94a9a8c54e9036961c1100c6f445c50ab9b6b40 +Author: Damien Miller +Date: Tue Sep 2 19:38:39 2025 +1000 - fix old typo (s/SYSVINITSTOPT/SYSVINITSTOP/) + portable-specific comment grammer/spelling fixes -commit 1a8ce460f1d0c3f7304edba0733783b57b430e21 -Author: dtucker@openbsd.org -Date: Thu Dec 12 09:09:09 2024 +0000 +commit a0b095fa03d3c08d723a803ce25540fddd955c53 +Author: djm@openbsd.org +Date: Tue Sep 2 09:34:48 2025 +0000 - upstream: Plug leak on error path, spotted by Coverity. ok djm@ + upstream: grammar and typos in comments - OpenBSD-Commit-ID: b1859959374b4709569760cae0866d22a16606d3 + OpenBSD-Commit-ID: de954daffcd0147ce142d55e8a374810cd19d7ed -commit 924f996144fc0ae1a659fadcfc2237d1ae935fc4 -Author: Xavier Hsinyuan -Date: Mon Dec 9 11:21:05 2024 +0800 +commit 23a2bb750547a9a5251cbc44c5ceb1d05303befe +Author: Damien Miller +Date: Tue Sep 2 19:30:07 2025 +1000 - Add $(srcdir) for standalone sk-libfido2 make target. + replace remaining manual logging of __func__ - Fix out-of-tree build failure due to incorrect path for `sk-usbhid.c`. + Use the appropriate log macro that prepends the function name + (e.g. logit_f/debug2_f/etc). -commit bbc9c18e84de29c83fa03e69290979fcca54a2b2 +commit a9b0b69f15e63bc4e8c8b38e24ee85ea076a7e11 Author: djm@openbsd.org -Date: Sat Dec 7 10:12:19 2024 +0000 +Date: Tue Sep 2 09:26:21 2025 +0000 - upstream: replace bespoke logging of MaxSessions enforcement with - - new ratelimited logging infrastructure. - - Add ratelimits to logging of connections dropped by PerSourcePenalties + upstream: replace remaining cases where we manually included __func__ - ok dtucker + in a debug or error log with the respective *_f log variant - OpenBSD-Commit-ID: f22fe7c39607e4361aadf95e33773ffd68c59489 + OpenBSD-Commit-ID: 46a280d78bcc0bc98f28e65a30b613366600328f -commit 5a6ddf946cf105189c2c99a04f86ce95edc55fc5 +commit 19f7cb39eecb4b8f768f37e8294dc3a9142e022b Author: djm@openbsd.org -Date: Sat Dec 7 10:05:36 2024 +0000 +Date: Mon Sep 1 23:55:29 2025 +0000 - upstream: add infrastructure for ratelimited logging; feedback/ok + upstream: test MaxStatups idempotency; ok dtucker@ - dtucker - - OpenBSD-Commit-ID: 18a83e5ac09d59aaf1e834fd6b796db89dd842e7 + OpenBSD-Regress-ID: b5d713c2709000fa5e41d82c0cf8627e13cb43f9 -commit 85f0c1e75e8f6c5d83b8070918ee2f6ab16d403e +commit c357c4a1e626feba9a968b5f0cb832b989b2d433 Author: djm@openbsd.org -Date: Fri Dec 6 16:24:27 2024 +0000 +Date: Thu Aug 21 05:55:30 2025 +0000 - upstream: allow glob(3) patterns for sshd_config AuthorizedKeysFile + upstream: benchmark more diffie-hellman-group* KEXs - and AuthorizedPrincipalsFile directives; bz2755 ok dtucker + use current KEX names, i.e. remove the "@openssh.com" where the KEX + has been standardised - OpenBSD-Commit-ID: 3e3e05a17fca39bba78b993a07b44664519adf7f + OpenBSD-Regress-ID: a67e9da4efd9a971d39cb2481093f836046f9b7f -commit 9a9ffee6e10bcd039f1f9385599577441ebe542a +commit 9313233a735733821dfd170b70782fb7da492962 Author: djm@openbsd.org -Date: Fri Dec 6 16:21:48 2024 +0000 +Date: Tue Sep 2 01:03:43 2025 +0000 - upstream: support VersionAddendum in the client, mirroring the - - option of the same name in the server; bz2745 ok dtucker@ + upstream: fix previous - OpenBSD-Commit-ID: 6ff7905b3f9806649bde750515786553fb89cdf4 + OpenBSD-Commit-ID: 09d95dfb5e064a1d0e74afba8d77474cc1d110a4 -commit 41ab0ccecd68232e196efae5e224b31ca104c423 +commit 683d0abe596b069a896f1688f86256f1beeb0cdc Author: djm@openbsd.org -Date: Fri Dec 6 16:02:12 2024 +0000 +Date: Mon Sep 1 23:53:16 2025 +0000 - upstream: clarify encoding of options/extensions; bz2389 + upstream: Make MaxStartups and PerSourceNetBlockSize first-match-wins - OpenBSD-Commit-ID: c4e92356d44dfe6d0a4416deecb33d1d1eba016c + as advertised. bz3859 reported by jan.v.hofmann; ok dtucker + + OpenBSD-Commit-ID: 08f7786f1b3b4a05a106cdbd2dc5f1f2d8299447 -commit 5488810359f0fd91e2f7b919c70a3798e46376cb +commit a9a3f025d76f06a6601e6e8d52b468ec467865d9 Author: djm@openbsd.org -Date: Fri Dec 6 15:17:15 2024 +0000 +Date: Fri Aug 29 03:50:38 2025 +0000 - upstream: ignore SIGPIPE here; some downstreams have had this for + upstream: remove experimental support for XMSS keys; - years... + ok deraadt markus - OpenBSD-Commit-ID: 73674ee4f8ceb8fc9cb8de71d8ddea0c721eb035 + OpenBSD-Commit-ID: 38eaf4df6189acad9e46eddf7cf32d7f6d07df35 -commit 4389a792d9078212366eba124a3eed36e009d09e -Author: djm@openbsd.org -Date: Fri Dec 6 15:12:56 2024 +0000 +commit 908e9d55139bed19ed87d6fec749974eb42702c6 +Author: caspar@openbsd.org +Date: Mon Aug 18 18:39:33 2025 +0000 - upstream: sync -o option lists with ssh.1; requested jmc@ + upstream: ssh_config.5: say "post-quantum" instead of "post quantum - OpenBSD-Commit-ID: a7ac295b444da7b2ca7a33a52370594f6897f6bb + safe", and rephrase the sentence to make it easier to read. + + Input djm@, input and OK deraadt@, OK dtucker@ + + OpenBSD-Commit-ID: c3ee4d1cafdcfc20cc0d2f086021efce4b19c075 -commit 6b9cd095565ddc5402d5096dce248fa0521dbda3 -Author: Fabio Pedretti -Date: Mon Oct 16 17:12:24 2023 +0200 +commit ceca966bde4ab38b2434876416da12fe16747459 +Author: job@openbsd.org +Date: Mon Aug 18 09:16:36 2025 +0000 - Remove ancient RHL 6.x config in RPM spec. + upstream: Delete unused accessor function - It looks like build6x options were intended for RHL 6.x - (the Red Hat distro predating Fedora, not RHEL), but were - then applied to RHEL. + OK dtucker@ - Completely remove support for this ancient configuration. + OpenBSD-Commit-ID: 93b59ac088fb254e1189729ece5bb9656d6e810b + +commit 3ef1a87d0a29eac94f32371af628e81eb2e2d817 +Author: Damien Miller +Date: Mon Aug 18 17:00:26 2025 +1000 + + Fix pledge(2) special casing - Successfully built, installed and run on RHEL 6. This also - remove a build warning about deprecation of PreReq. + Unbreaks non-OpenBSD platforms -commit 5cacfa798f92b707491375fed748d1d1bcb33ec9 -Author: Darren Tucker -Date: Fri Dec 6 23:54:45 2024 +1100 +commit 5e9ca80fe65e407428dc46ed45804724d08b91b7 +Author: Damien Miller +Date: Mon Aug 18 16:47:23 2025 +1000 - Add new hardware-backed signing key for myself. + Match version instead of groups in connect-bigconf - Retire old non-hardware based signing key. + The connect-bigconf makes a giant config file to test config passing + between the sshd subprocesses. Previously it used a bunch of "Match + group" lines to construct a large file. However checking group + membership can be expensive (e.g. if a large groups database is + present or if group lookup is remote via NSS). This could be slow + enough to exceed LoginGraceTime. + + This switches it to "Match version" which is just a string compare + and does just as well for making a giant nonsense config file. -commit f129b6ee1d4361799e65307216e3a4d5544356b7 -Author: Jonas 'Sortie' Termansen -Date: Sat Nov 2 22:05:45 2024 +0100 +commit 6c84609e5f9ddd49e250d5cf190b2820dbeca178 +Author: Damien Miller +Date: Mon Aug 18 16:47:00 2025 +1000 - Fix configure implicit declaration and format warnings. + depend -commit 11a5e5179077f73c2d45bcdf3f60153ae3f17815 -Author: dtucker@openbsd.org -Date: Fri Dec 6 07:05:54 2024 +0000 +commit 9184fa363687fcb5dac056b093fb3b8e9d327242 +Author: Damien Miller +Date: Mon Aug 18 16:45:15 2025 +1000 - upstream: Expand $SSH to absolute path if it's not already. + check for setsockopt IP_TOS in OpenBSD pledge - Prevents problem later in increase_datafile_size if ssh is not in - the path. Patch from quaresmajose via GHPR#510. + OpenBSD has recently relaxed the pledge(2) sandbox to allow some + setsockopt options to be changed without the "inet" promise. - OpenBSD-Regress-ID: 2670a66af8b827410ca7139f0a89f4501cece77b + This adds compatibility for OpenBSD that predates this relaxation. -commit dc2ef8f0944a4ff7ba19e52fd17b4654e6bd9b93 -Author: dtucker@openbsd.org -Date: Fri Dec 6 06:55:28 2024 +0000 +commit ae44cd74f3a4ac711152f50b2712803ccf785593 +Author: djm@openbsd.org +Date: Mon Aug 18 04:50:35 2025 +0000 - upstream: Change "login again" to "log in again" - - in password change message. From ThinLinc-Zeijlon via github PR#532. + upstream: cast - OpenBSD-Commit-ID: fea5e9bc04caf613a118c419f16863733b340cf1 + OpenBSD-Commit-ID: d69bd2328513c2dcd99f4f346b77e2bd90cf1964 -commit 8252f346eb21cd6b30816f905b7d94f10962373e -Author: naddy@openbsd.org -Date: Thu Dec 5 22:45:03 2024 +0000 +commit c2c8bae39380392449ac3297061cbfc486126ad5 +Author: djm@openbsd.org +Date: Mon Aug 18 04:38:21 2025 +0000 - upstream: catch up documentation: AES-GCM is preferred to AES-CTR + upstream: missing set_log_handler() call in ssh-auth.c, exposed after - OpenBSD-Commit-ID: 63360924b6834507fe70020edb936f5075043a9e + last commit + + OpenBSD-Commit-ID: 09f5c3cf33c18b8ad321edbf96c30ae3deada2b0 -commit 9a2f4c75081769bd45eba2bf3fab0a32b25f1879 -Author: Darren Tucker -Date: Fri Dec 6 17:56:17 2024 +1100 +commit 056022261e6cf7eb65bbacac72afe5f4d5945f2c +Author: Damien Miller +Date: Mon Aug 18 14:22:32 2025 +1000 - Change text from "login to" to "log in to". + depend + +commit b7ee13fbbb4ebafcf71f29685f053ecb97d1bcef +Author: Damien Miller +Date: Mon Aug 18 14:22:18 2025 +1000 + + wrap SIGINFO in ifdef + +commit 289239046b2c4b0076c14394ae9703a879e78706 +Author: djm@openbsd.org +Date: Mon Aug 18 03:43:01 2025 +0000 + + upstream: Make ssh(1) and sshd(8) set IP QoS (aka IP_TOS, IPV6_TCLASS) - From ThinLinc-Zeijlon via GHPR#532. + continually at runtime based on what sessions/channels are open. + + Previously, ssh(1) and sshd(8) would pick a QoS value when they + were started and use it for the whole connection. This could + produce suboptimal choices for the QoS value, e.g. for multiplexed + sessions that started interactive but picked up a sftp client, + or sessions that moved large amounts of data via port forwarding. + + Now the QoS value will change to the non-interactive IPQoS whenever + a "non-interactive" channel is open; basically any channel that lacks + a tty other than agent forwarding. + + This is important now that the default interactive IPQoS is EF + (Expedited Forwarding), as many networks are configured to allow + only relatively small amounts of traffic of this class and they will + aggressively deprioritise the entire connection if this is exceeded. + + NB. because ssh(1) and sshd(8) now change IP_TOS/IPV6_TCLASS + continually via setsockopt(), this commit requires a recent pledge(2) + change that landed recently in the OpenBSD kernel. Please ensure + you have updated to a kernel from within the last two weeks before + updating OpenSSH. + + with job@ deraadt@ + + OpenBSD-Commit-ID: 325fc41717eecdf5e4b534bfa8d66817425b840f -commit 24dcf368d816b06136a02845ebd0c7846bf18927 -Author: Xavier Hsinyuan -Date: Fri Dec 6 11:56:34 2024 +0800 +commit dc5147028ff19213a32281dad07bba02e58da3fa +Author: djm@openbsd.org +Date: Mon Aug 18 03:29:11 2025 +0000 - Fix configure message typo in sk-libfido2 standalone. + upstream: SIGINFO handler for sshd(8) to dump active + + channels/sessions ok deraadt@ + + OpenBSD-Commit-ID: 9955cb6d157c6d7aa23a819e8ef61b1edabc8b7d -commit 1a0cac2f3411a22d69ae6918eff48456b805e73b -Author: Alexander Kanavin -Date: Thu Dec 5 16:26:46 2024 +0100 +commit f807a598c96be683d97810481e954ec9db6b0027 +Author: djm@openbsd.org +Date: Mon Aug 18 03:28:36 2025 +0000 - Skip 2038 key expiry test on 64 bit time_t systems. + upstream: SIGINFO handler for ssh(1) to dump active - This allows testing Y2038 with system time set to after that (i.e. 2040), - so that actual Y2038 issues can be exposed, and not masked by key expiry - errors. + channels/sessions ok deraadt@ - Signed-off-by: Alexander Kanavin + OpenBSD-Commit-ID: 12f88a5044bca40ef5f41ff61b1755d0e25df901 -commit 6b4611dc1232c5d2c8e43201f580f19aab320c87 -Author: Darren Tucker -Date: Fri Dec 6 01:45:52 2024 +1100 +commit 9b61679d73a8a001c25ab308db8a3162456010cf +Author: djm@openbsd.org +Date: Mon Aug 18 03:28:02 2025 +0000 - Skip 64bit expiry time test on 32bit time_t. + upstream: add channel_report_open() to report (to logs) open + + channels; ok deraadt@ (as part of bigger diff) + + OpenBSD-Commit-ID: 7f691e25366c5621d7ed6f7f9018d868f7511c0d -commit c9b7866a7dc5e6c30f5aa9d22dd0bbafda0d496f -Author: dtucker@openbsd.org -Date: Thu Dec 5 14:28:39 2024 +0000 +commit 80b5ffd22abd4093201939e31d1ea6dc8cc7913a +Author: djm@openbsd.org +Date: Mon Aug 18 01:59:53 2025 +0000 - upstream: Add key expiry test in the 64bit time_t range for additional + upstream: make -E a no-op in sshd-auth. Redirecting logging to a - coverage. From Alexander Kanavin via bz#3684. + file doesn't work in this program as logging already goes via the parent + sshd-session process. ok dtucker@ - OpenBSD-Regress-ID: bdf6eb3c2421f2e1e11483d03b34c7931d1bccf7 + OpenBSD-Commit-ID: 73325b9e69364117c18305f896c620a3abcf4f87 -commit 790c913b5fc6ee93ae14793443dc85a0f574b7eb +commit 3a039108bd25ff10047d7fa64750ed7df10c717c Author: Damien Miller -Date: Thu Dec 5 19:24:56 2024 +1100 +Date: Mon Aug 18 13:46:37 2025 +1000 - typo + allow some socket syscalls in seccomp sandbox + + Allow getsockname(2), getpeername(2) and getsockopt(2). + + Also allow setsockopt(2) but only IP_TOS and IPV6_TCLASS. + + Note that systems that use the older socketcall(2) mux syscall will + not have IP_TOS and IPV6_TCLASS allowlisted. On these platforms, + these calls will be soft-blocked (i.e. will fail rather than + terminate the whole process with a sandbox violation). + + Needed for upcoming IPQoS change; ok dtucker@ -commit d23a23aaeeabc228792e3fd7eb5f2fa6ae13c482 +commit a00f5b02e171bc6d6fb130050afb7a08f5ece1d8 Author: Damien Miller -Date: Thu Dec 5 08:47:02 2024 +1100 +Date: Mon Aug 18 13:44:53 2025 +1000 - add a Makefile target for ssh-verify-attestation + handle futex_time64 properly in seccomp sandbox - Not built by default, but easier than doing it by hand + Previously we only allowed __NR_futex, but some 32-bit systems + apparently support __NR_futex_time64. We had support for this + in the sandbox, but because of a macro error only __NR_futex was + allowlisted. + + ok dtucker@ -commit d0ac63d0f8b5f778d5fd326701ef4489bc27635e +commit 32deb00b38b4ee2b3302f261ea1e68c04e020a08 Author: dtucker@openbsd.org -Date: Thu Dec 5 06:49:26 2024 +0000 +Date: Thu Aug 14 10:03:44 2025 +0000 - upstream: De-magic the x11 base port number into a define. ok djm@ + upstream: Cast serial no for %lld to prevent compiler warnings on some - OpenBSD-Commit-ID: 23b85ca9d222cb739b9c33ee5e4d6ac9fdeecbfa + platforms. + + OpenBSD-Commit-ID: afadd741622f16c6733d461c0d6053ed52868a57 -commit 9998c93d57bf0f1df2bc93e0bc2d8112c6f8c720 +commit 883886c959ecab152650e231335857eb3193c662 Author: dtucker@openbsd.org -Date: Thu Dec 5 06:47:00 2024 +0000 +Date: Thu Aug 14 09:44:39 2025 +0000 - upstream: Prevent integer overflow in x11 port handling. These are + upstream: Cast serial no for %lld to prevent compiler warnings on some - theoretically possible if the admin misconfigures X11DisplayOffset or the - user misconfigures their own $DISPLAY, but don't happen in normal operation. - From Suhov Roman via bz#3730, ok djm@ + platforms. - OpenBSD-Commit-ID: e9e3860f1a19b862ccf07dc8ecbe8f1e1034f4ed + OpenBSD-Commit-ID: 46c6063284d318f7e4dc922479a3e394c94b0588 -commit 8c9ee046d40e4254c6c1711783ea11027b72c3e9 -Author: djm@openbsd.org -Date: Wed Dec 4 16:42:49 2024 +0000 +commit fde5a4d2cd01bea700439fa6d5bbad88e65c99bd +Author: dtucker@openbsd.org +Date: Thu Aug 14 09:26:53 2025 +0000 - upstream: add a work-in-progress tool to verify FIDO attestation + upstream: Cast serial no for %lld to prevent compiler warnings on some - blobs that ssh-keygen can write when enrolling FIDO keys. + platforms. - OpenBSD-Regress-ID: 6c97bf3f46e48866677ad69f54b77683eb92437f + OpenBSD-Commit-ID: 15644234b58abc9c6da2994f0422a5aa344a9e89 -commit 50c640d874d0246dd0a0d949398c3d7f757c716a -Author: dtucker@openbsd.org -Date: Wed Dec 4 10:51:13 2024 +0000 +commit ab5074dfb614e3801fecbd376d8ed4cea613c629 +Author: sthen@openbsd.org +Date: Tue Aug 12 11:09:48 2025 +0000 - upstream: Don't assume existence of SK provider in test. Patch from - - balu.gajjala at gmail via bz#3402. + upstream: fix typo, ok markus dtucker - OpenBSD-Regress-ID: d571932016d07d135b54433d07520b9e1901db43 + OpenBSD-Commit-ID: 8f223da7633752162c64a659c6cf55202703d870 -commit 73d782693144262570d3585b62f16b183170c014 -Author: djm@openbsd.org -Date: Wed Dec 4 14:37:55 2024 +0000 +commit 8b6c1f402feb9eb6438003a312d7ffe8d5669896 +Author: deraadt@openbsd.org +Date: Mon Aug 11 14:37:43 2025 +0000 - upstream: sync the list of options accepted by -o with ssh_config.5 + upstream: Handle localtime_r() failure by return "UNKNOWN-TIME" - prompted by bz3455 + which is only used in user-visible contexts. freebsd 288773 shows their + localtime_r() has failed at least once for unknown reason. discussed with djm - OpenBSD-Commit-ID: 0ecbfa70aea6c769bcc259defe07182edf461f57 + OpenBSD-Commit-ID: 68f4c92d46b2578d4594b0ed940958d597fd61ac -commit 6993d9f0959534b0b7d52e17b95e9e79fb0b3d0a +commit 0e1b8aa27f7c86d412c9e54ad9e2cae30d9ddab4 Author: djm@openbsd.org -Date: Wed Dec 4 14:24:20 2024 +0000 +Date: Mon Aug 11 10:55:38 2025 +0000 - upstream: don't screw up ssh-keygen -l output when the file + upstream: ssh(1): add a warning when the connection negotiates a - contains CR characters; GHPR236 bz3385, fix from Dmitry Belyavskiy + non-post quantum safe key agreement algorithm. - OpenBSD-Commit-ID: e458cf6b0adcea5b69ef4c7ba38e590841d02ef4 + Controlled via a new WarnWeakCrypto ssh_config option, defaulting + to on. This option might grow additional weak crypto warnings in + the future. + + More details at https://openssh.com/pq.html + + mostly by deraadt@ feedback dtucker@ ok deraadt@ + + OpenBSD-Commit-ID: 974ff243a1eccceac6a1a9d8fab3bcc89d74a2a4 -commit c0b03c2534946fc114880092177aa4a3683ced2d -Author: jsg@openbsd.org -Date: Tue Dec 3 22:30:03 2024 +0000 +commit 2ebc6384258b58ace0ad2adb2593744f62749235 +Author: djm@openbsd.org +Date: Wed Aug 6 23:44:09 2025 +0000 - upstream: spelling; ok djm@ + upstream: all state related to the ssh connection should live in - OpenBSD-Commit-ID: c8ff3f70020451eef214e598117b7ce1a29853ef + struct ssh or struct packet_state; one static int escaped this rule, so move + it to struct packet_state now. + + ok millert tb + + OpenBSD-Commit-ID: bd6737168bf61a836ffbdc99ee4803468db90a53 -commit 97eb247f40167f44324e88a537d5b4fe771a63b2 +commit 60b909fb110f77c1ffd15cceb5d09b8e3f79b27e Author: dtucker@openbsd.org -Date: Tue Dec 3 16:27:53 2024 +0000 +Date: Wed Aug 6 11:22:53 2025 +0000 - upstream: Remove fallback to compiled-in gropup for dhgex when the - - moduli file exists, but does not contain moduli within the client-requested - range. The fallback behaviour remains for the case where the moduli file does - not exist (typically, running tests prior to installing). From bz#2793, based - in part on patch from Joe Testa, ok djm@ + upstream: Improve sentence. ok djm@ - OpenBSD-Commit-ID: b1a8c5dbbedf249b42474679ebaf14db7332b1ab + OpenBSD-Commit-ID: 9c481ddd6bad110af7e530ba90db41f6d5fe2273 -commit 30c746265ebde29806dba77c92fb1fd3803cbf5c -Author: tb@openbsd.org -Date: Tue Dec 3 15:53:51 2024 +0000 +commit 9ffa98111dbe53bf86d07da8e01ded8c5c25456b +Author: djm@openbsd.org +Date: Wed Aug 6 04:53:04 2025 +0000 - upstream: Remove redundant field of definition check + upstream: when refusing a certificate for user authentication, log - This will allow us to get rid of EC_GROUP_method_of() in the near future. + enough information to identify the certificate in addition to the reason why + it was being denied. Makes debugging certificate authz problems a bit easier. - ok djm + ok dlg@ - OpenBSD-Commit-ID: b4a3d2e00990cf5c2ec6881c21ddca67327c2df8 + OpenBSD-Commit-ID: 4c4621b2e70412754b3fe7540af8f4bf02b722b1 -commit eaa1744f34c30740328fd0a0d84b5f2f9e6918c1 -Author: Damien Miller -Date: Thu Dec 5 00:59:19 2024 +1100 +commit 2a31009c36eb2da412c2784fe131fcb6ba800978 +Author: job@openbsd.org +Date: Tue Aug 5 09:08:16 2025 +0000 - don't ignore changes in regress Makefiles + upstream: Use the operating system default DSCP marking for - reported by Torben Hansen in bz2880 + non-interactive traffic + + It seems the CS1 traffic class mark is considered ambiguous and therefore + somewhat unhelpful (see RFC 8622 for more considerations). But, the new + 'LE' scavenger class (also proposed in RFC 8622) offers high probability + of excessive delays & high packet loss, which would be inappropriate + for use with, for example, X11 forwardings. In fact, it is not known to + SSH what's appropriate because SSH is not aware of the content of what + passing through session forwardings. Therefore, no marking is appropriate. + Non-interactive traffic simply is best effort. + + OK djm@ deraadt@ + + OpenBSD-Commit-ID: db1da1a432ecd53fc28feb84287aedb6bec80b01 -commit 66e986880b2472fefaad781f10113b138b65ff27 -Author: Damien Miller -Date: Thu Dec 5 00:01:33 2024 +1100 +commit 6ebd472c391a73574abe02771712d407c48e130d +Author: djm@openbsd.org +Date: Tue Aug 5 04:00:15 2025 +0000 - Support systemd-style socket activation in agent + upstream: a bunch of the protocol extensions we support now have RFCs - Adds support for systemd LISTEN_PID/LISTEN_FDS socket activation to - ssh-agent. Activated when these environment variables are set and - the agent is started with the -d or -D option and no socket path - is set. + and I-Ds that are more complete and detailed than what we have in the + PROTOCOL.* files. Refer to these when possible instead of documenting them + here. - Based on GHPR502 by Daniel Kahn Gillmor, ok dtucker + OpenBSD-Commit-ID: 4fa5b0fcf5d5f24093d33d9e82c7ca4850d50d70 -commit 9b57c099f57152e6c94f633c114f544087f4bdaa -Author: Darren Tucker -Date: Wed Dec 4 21:36:01 2024 +1100 +commit ec3465f59c651405e395092f3ad606f8992328d8 +Author: job@openbsd.org +Date: Thu Jul 31 11:23:39 2025 +0000 - Update readme files to better reflect reality. + upstream: Deprecate support for IPv4 type-of-service (TOS) IPQoS - Prompted by bz#3738, ok djm@. - -commit ffa885db1b960451d426455045d2f51288e48ee8 -Author: dtucker@openbsd.org -Date: Tue Dec 3 14:12:47 2024 +0000 - - upstream: Improve description of KbdInteractiveAuthentication. + keywords - Based on bz#3658, fixes jmc@ ok markus@ djm@. + Type of Service (ToS) was deprecated in the late nineties and replaced + with the Differentiated Services architecture. Diffserv has significant + advantages for operators because this mechanism offers more granularity. - OpenBSD-Commit-ID: 9fadb56b9afed554d501acbba911c685acd6ffc2 + OpenSSH switched its default IPQoS from ToS to DSCP values in 2018. + + IPQoS configurations with 'lowdelay', 'reliability', or 'throughput' will be + ignored and instead the system default QoS settings apply. Additionally, a + debug message is logged about the deprecation with a suggestion to use DSCP. + + with/OK deraadt@ sthen@ djm@ + + OpenBSD-Commit-ID: 40c8c0c5cb20151a348728703536af2ec1c754ba -commit b460f82a67795bba37c6cc6c78f788e5b435b4cb -Author: Jonas 'Sortie' Termansen -Date: Sat Nov 2 17:53:23 2024 +0100 +commit 65909fa114e7dd7511800db2b7bacb8774afe887 +Author: job@openbsd.org +Date: Thu Jul 31 09:38:41 2025 +0000 - Inherit DESTDIR from the environment. + upstream: Set default IPQoS for interactive sessions to Expedited - autoconf packages conventionally inherit the DESTDIR variable from the - environment. + Forwarding (EF) + + Marking interactive session data with DSCP value EF (RFC3246, RFC3247) + helps inform the network on relative priority compared to other traffic. + This is especially useful for differentiated treatment over wireless media. + + Following the reconciled IETF Diffserv to IEEE 802.11 mappings (RFC 8325), + traffic marked with DSCP value EF maps to User Priority 6 in QoS Control, + in turn mapping to the high priority WMM AC_VO access category. + + OK djm@ + + OpenBSD-Commit-ID: aadda7b9da794d70d7c6b381a861a0610afce1b3 -commit 9da7fa7c7464df241ae5d17da94e4ebed9013719 -Author: Jonas 'Sortie' Termansen -Date: Sat Nov 2 22:10:39 2024 +0100 +commit d1c6c67a50fc957010fa027c6ab970424e9b9142 +Author: Darren Tucker +Date: Sat Aug 2 14:49:00 2025 +1000 - Define u_short and u_long if needed. + Disable security key tests for bigendian interop -commit d3a7ff7cecbc23cc37044bdf02e7118d05bf3c35 -Author: djm@openbsd.org -Date: Tue Dec 3 08:31:49 2024 +0000 +commit e85248df3f1073343da87a6b00512e6a1e4a863d +Author: Darren Tucker +Date: Sat Aug 2 12:51:42 2025 +1000 - upstream: support FIDO tokens that return no attestation data, e.g. + Comment out atime restore test. - recent WinHello. From Michael Braun via GHPR542 + This works on filesystems mounted 'noatime', but on others the stat() + resets atime causing the test to fail. + +commit b1c4cedbee107dc611ce091f27ea9f1de28ee378 +Author: Darren Tucker +Date: Fri Aug 1 19:29:00 2025 +1000 + + Replace fbsd64ppc VM with physical host. - OpenBSD-Commit-ID: a71b0542f2f7819ba0e33a88908e01b6fc49e4ce + Run 64bit bigendian interop test on NetBSD arm64be instead. -commit 96b64056c812620014b65371a9e3ac86bfcd08d5 -Author: Thorsten Kukuk -Date: Tue Nov 19 10:53:28 2024 +0100 +commit 284abbed9a8d815b1ec5e96aff885d77e26537e7 +Author: dtucker@openbsd.org +Date: Wed Jul 30 10:17:13 2025 +0000 - Add wtmpdb support as Y2038 safe wtmp replacement + upstream: Plug leak in case where sigp is passed as NULL. Coverity CID + + 483725, ok djm@ + + OpenBSD-Commit-ID: 47cf7b399c84e102b670b9f97ab6926c9a7256b5 -commit 1d9563a56f2ad5b0c0aeef20e19c1a03ad54f88a +commit dc630e6d81be8aa495254839731e4f3521cf9e31 Author: djm@openbsd.org -Date: Mon Dec 2 14:06:42 2024 +0000 +Date: Wed Jul 30 04:27:42 2025 +0000 - upstream: unbreak + upstream: unbreak WITH_OPENSSL=no builds, also allowing ed25519 - OpenBSD-Commit-ID: 05b6c31f4a6e385338f43cc0e08776cea75802a1 + keys to be used via PKCS#11 when OpenSSH is built without libcrypto. + + OpenBSD-Commit-ID: ecf26fdf7591bf2c98bac5136fbc36e0b59c3fc2 -commit d75837b9f6d0d6cc18ed5078789ea0f3dad08f00 +commit a5bec2cdfc4f38ddb6211809851aae29ba99a35a Author: djm@openbsd.org -Date: Mon Dec 2 13:37:18 2024 +0000 +Date: Wed Jul 30 04:19:17 2025 +0000 - upstream: prefer AES-GCM to AES-CTR; ok deraadt markus + upstream: fix variable name in disabled code - OpenBSD-Commit-ID: 8366a72e0f300ee31c5dab2c95025387ec15bbc9 + OpenBSD-Commit-ID: 5612e979575d5da933c8b720d296423fd84392f5 -commit e19cd494b567a73dc390e09b47c1e21545e6116b -Author: Shiva Kaul -Date: Mon Dec 2 02:04:20 2024 -0500 +commit 5e4bfe6c16924b1c21a733f3e218cfcba98e301e +Author: Damien Miller +Date: Sat Jul 26 19:19:46 2025 +1000 - Fix compilation with DEBUG_SK enabled - - In `ssh_ecdsa_sk_verify`, the `datalen` variable was renamed to `dlen` -- but not in this debugging block. + more ec/ed25519 fixing -commit 67ace92be0718df7e0f52c0a76684fc2ebae4089 -Author: dtucker@openbsd.org -Date: Fri Nov 29 00:13:36 2024 +0000 +commit 2603098959eff55cbe188c3dfcbe5302808a80fc +Author: Damien Miller +Date: Sat Jul 26 14:27:53 2025 +1000 - upstream: Import regenerated moduli. - - OpenBSD-Commit-ID: 311d271bf0fab8a119e84f4f696d8cd40731692f + repair build for libcrypto without ed25519 support -commit ca0697a90e5720ba4d76cb0ae9d5572b5260a16c -Author: Jeremy Stott -Date: Sat Oct 19 12:10:52 2024 +1300 +commit a729163c56ecc002c0cb04db56e7d86ceec2e8b0 +Author: djm@openbsd.org +Date: Sat Jul 26 01:53:31 2025 +0000 - Add make target for standalone sk-libfido2 - - Add a Makefile target for sk-libfido2, the standalone fido2 security - key shared library, suitable for use with the SecurityKeyProvider - option. + upstream: regression tests for Ed25519 keys in PKCS#11 tokens - Add a new configure option `--with-security-key-standalone` that - optionally sets the shared library target sk-libfido2$(SHLIBEXT), and - adds it to $(TARGETS). + OpenBSD-Regress-ID: 50067c0716abfea3a526b4a0c8f1fe15e7665c0f + +commit 361ff0ca308ac02449e71689fc5ea72114db43db +Author: djm@openbsd.org +Date: Sat Jul 26 01:51:44 2025 +0000 + + upstream: Support ed25519 keys hosted on PKCS#11 tokens. - misc.h is required when SK_STANDALONE is defined, because of the use - of `monotime_tv` in `sk_select_by_touch`. + Tested on Yubikeys and against SoftHSM2. - Sets the shared library extension for sk-libfido2 is by setting - `SHLIBEXT` depending on the platform in configure.ac. + feedback/ok tb@ - Add the shared library to the CI builds in the `sk` target config to - make sure it can compile under the same conditions as - `--with-security-key-builtin`. + OpenBSD-Commit-ID: 90ddb6529f2e12e98e8bba21d8592e60579ce2e4 + +commit 2b530cc3005a71c5ba6b712978872fc9c147439c +Author: djm@openbsd.org +Date: Fri Jul 25 13:06:07 2025 +0000 + + upstream: update our PKCS#11 API header to v3.0; - Add a libssh-pic.a static library that compiles with `-fPIC` reusing - .c.lo method in sk-dummy.so for use in the shared library sk-libfido2. + feedback/ok tb@ - Note, a separate static library libssh-pic.a is needed, since defining - -DSK_STANDALONE excludes some symbols needed in sshkey.lo. + OpenBSD-Commit-ID: e67fa6a26e515c2b1fb7b0d1519d138aafb3e017 -commit 74d70841efbf41b9fcc8e6f6f4777d2e9d7e2004 -Author: Arnout Engelen -Date: Fri Oct 18 13:42:38 2024 +0200 +commit 550d2a4a66c50f7641563a63b900761d99efb24a +Author: Damien Miller +Date: Fri Jul 25 23:04:33 2025 +1000 - mdoc2man: balance nested square brackets - - I noticed the square brackets in `destination [command [argument...]` - in the synopsis for the `ssh.1` manpage were not balanced, - this balances them. + another attempt at fixing !EC builds + +commit ed1e370d84e9dc39bc31c19cca12222d991fdc6f +Author: dtucker@openbsd.org +Date: Fri Jul 25 11:50:45 2025 +0000 + + upstream: Don't snprintf a NULL since not all platforms support it. - Signed-off-by: Arnout Engelen + OpenBSD-Commit-ID: 6e0c268e40047e96fab6bc56dc340580b537183b -commit 8eabd2ae2ca1d7756417a1ee5b41f09c5d997634 +commit eedab8db12d57c4f4583f6b60e48a4ce25b47b9c +Author: Damien Miller +Date: Fri Jul 25 16:21:43 2025 +1000 + + unbreak !EC builds + +commit 203f5ac6cfa0e257db7509d4bb830e8a4bba6211 Author: djm@openbsd.org -Date: Wed Nov 27 16:07:08 2024 +0000 +Date: Thu Jul 24 06:04:47 2025 +0000 - upstream: fix argument of "Compression" directive in ssh -G config + upstream: test code now needs to link ssh-pkcs11-client.c any time - dump, which used to work but broke in 9.8 + sshkey.c is included - OpenBSD-Commit-ID: c79936242d29c70d01941b28d2d07fd0b85fe46f + OpenBSD-Regress-ID: 9d07188eae9a96801c3150b3433bb220626d4443 -commit 53c03961769d8879a81398074ea3cb36253d4f2e -Author: djm@openbsd.org -Date: Wed Nov 27 13:27:34 2024 +0000 +commit 33b4f05c8ddab24aa6c47afb313b8cbd0d4b77f4 +Author: Damien Miller +Date: Fri Jul 25 12:47:17 2025 +1000 - upstream: new name/link for agent I-D - - OpenBSD-Commit-ID: e3420f3925a297a1b2ab7dfe7c7d274cfc8e1193 + update clang-16 -> clang-19 -commit 785e3c9110df8f2d30e42ce8b45969c49700f35b +commit 03e9e993ef1ef5accc6457152278cab5988f9b3d +Author: Damien Miller +Date: Fri Jul 25 12:46:59 2025 +1000 + + include ssh-pkcs11-client.o as common dep + +commit 2f5269938a8e4769f484c9d45419a86529078ede +Author: Damien Miller +Date: Fri Jul 25 12:46:10 2025 +1000 + + remove vestigial stub + +commit bf33a73c40522ce60961d4fff316a7187fb06ca0 Author: djm@openbsd.org -Date: Wed Nov 27 13:00:23 2024 +0000 +Date: Thu Jul 24 23:27:04 2025 +0000 - upstream: mention that biometrics may be used for FIDO key user + upstream: this should include stdlib.h explicitly - verification as well as PIN. Prompted by Zack Newman, ok jmc@ - - OpenBSD-Commit-ID: b774a4438c9be70012661ee278450790d21277b8 + OpenBSD-Commit-ID: 1c0cc5c3838344b33ae4ab7aa62c01530357bf29 -commit fd2e64c9ec9ea3e89e396be0db41aaf982ae1210 +commit 9f8ccc3b81b53324cc489f3fe00f03c329c0acb2 Author: djm@openbsd.org -Date: Tue Nov 26 22:05:51 2024 +0000 +Date: Thu Jul 24 06:59:51 2025 +0000 - upstream: g/c outdated XXX comments + upstream: less stale reference to PKCS#1 1.5 hash OIDs; feedback - OpenBSD-Commit-ID: 74d0c0b74994d9a4343c4d7ea4948cb34f609a6c + from tb@ + + OpenBSD-Commit-ID: 9fda77978491a130a7b77d87d40c79277b796721 -commit 0ad34a6193357d286042322ea7347262a6fb0778 +commit 1641ab8744f500f55f12155d03f1a3116aaea374 Author: djm@openbsd.org -Date: Tue Nov 26 22:02:28 2024 +0000 +Date: Thu Jul 24 06:12:08 2025 +0000 - upstream: regression test for UpdateHostkeys with multiple keys backed + upstream: factor out encoding of a raw ed25519 signature into its - by ssh-agent. Patch from Maxime Rey. + ssh form into a separate function - OpenBSD-Regress-ID: 1777ab6e639e57c0e20cbcb6df60455b49fd8bb3 + OpenBSD-Commit-ID: 3711c6d6b52dde0bd1f17884da5cddb8716f1b64 -commit 84023656d91b78f1ef86c8321ec563f2e90f7227 +commit a8c0e5c871c0c7ee5ae93e353b1499a53c09c71d Author: djm@openbsd.org -Date: Tue Nov 26 22:01:37 2024 +0000 +Date: Thu Jul 24 05:44:55 2025 +0000 - upstream: Explicitly specify the signature algorithm when signing + upstream: Help OpenSSH's PKCS#11 support kick its meth habit. - hostkeys-prove requests. + The PKCS#11 code in OpenSSH used the libcrypto public key method API + (e.g. the delightfully named RSA_meth_free()) to delegate signing + operations to external keys. This had one advantage - that it was + basically transparent to callers, but also had a big disadvantage - + that we'd manually have to track the method implementations, their + state and their relationships to the underlying PKCS#11 objects. - Fixes a corner-case triggered by UpdateHostKeys with one or more unknown - host keys stored in ssh-agent where sshd refuses to accept the signature - coming back from the agent. + This rips this out and replaces it with explicit delegation to + PKCS#11 code for externally hosted keys via the ssh-pkcs11-helper + subprocess. This is very similar to how we handle FIDO keys in + OpenSSH (i.e. via ssh-sk-helper). All we need to track now is a + much simpler mapping of public key -> helper subprocess. - Report/fix from Maxime Rey + Kicking our libcrypto meth dependency also makes it much easier + to support Ed25519 keys in PKCS#11, which will happen in a subsequent + commit. - OpenBSD-Commit-ID: 460c7d527a24f92b7e5f68ca1a2fa242ebf0d086 + feedback / ok tb@ + + OpenBSD-Commit-ID: a5a1eaf57971cf15e0cdc5a513e313541c8a35f0 -commit d1c1cfc5e4e9b43593d4642810ea8135e4c7db49 +commit 259c66aebe4e1f9d60e548f728ff74083bcccddf +Author: Darren Tucker +Date: Thu Jul 24 22:02:49 2025 +1000 + + Remove DEBUG_ACTIONS variable. + + If needed it can be set in github if needed. + +commit 40fb2dc4ece76c8f0c624d90a17bc1bbf47f3729 Author: djm@openbsd.org -Date: Tue Nov 26 21:23:35 2024 +0000 +Date: Wed Jul 23 05:07:19 2025 +0000 - upstream: when using RSA keys to sign messages, select the + upstream: add a ssh_config RefuseConnection option that, when - signature algorithm based on the requested hash algorithm ("-Ohashalg=xxx"). + encountered while processing an active section in a configuration file, + terminates ssh(1) with an error message that contains the argument to the + option. - This allows using something other than rsa-sha2-512, which may not - be supported on all signing backends, e.g. some smartcards only - support SHA256. + This may be useful for expressing reminders or warnings in config + files, for example: - Patch from Morten Linderud; ok markus@ + Match host foo + RefuseConnection "foo is deprecated, use splork instead" - OpenBSD-Commit-ID: 246353fac24e92629263996558c6788348363ad7 + ok djg + + OpenBSD-Commit-ID: 5b0072fcd08ad3932ab21e27bbaa66b008d44237 -commit ac7544654441280071b90a4129a47467d40f2389 -Author: djm@openbsd.org -Date: Sun Nov 24 23:47:50 2024 +0000 +commit defc806574d2256036d69a291caf0f3484844de6 +Author: miod@openbsd.org +Date: Sat Jul 12 05:28:33 2025 +0000 - upstream: turn off CDIAGFLAGS and turn back on INSTALL_STRIP + upstream: Add missing inter-library dependencies to LDADD and - accidentally changed in last commit + DPADD. ok tb@ deraadt@ - OpenBSD-Commit-ID: 6d07e4606997e36b860621a14dd41975f2902f8f + OpenBSD-Commit-ID: a05e13a7e2c0b65bb4b47184fef731243431c6ff -commit 953fa5b59afb04c3c74ed82d7bace65c13cd8baa -Author: Darren Tucker -Date: Sat Nov 9 11:41:44 2024 +1100 +commit e6805e2a6b33e001e1a7257b85ab779fd592a578 +Author: Jan Tojnar +Date: Thu May 18 16:30:35 2023 +0200 - Disable security key for bigendian interop. + Add gnome-ssh-askpass4 for GNOME 40+ - It doesn't currently work. It's not clear why, but I suspect - sk-dummy.so ends up being built for the wrong architecture. + GTK 3 has been in maintenance mode for a while now, and it is on the road + to being abandoned. As a result, the dialogue looks out of place on modern + systems. + + We could port it to GTK 4 but without the program being registered as an + application (i.e. having a .desktop file), GNOME Shell would ask for + permission to grab input every time. + + Let’s instead use the GNOME Shell’s native prompt through the unstable + Gcr API. -commit a80eb71c428c474098087c672398f200be8fabdf -Author: Darren Tucker -Date: Sat Nov 9 05:14:16 2024 +1100 +commit f9dc519259804702cab0fa0ca8b193a360e3ec38 +Author: Damien Miller +Date: Fri Jul 11 17:20:27 2025 -0700 - Reshuffle OpenWRT test configs. + let ga_init() fail gracefully if getgrouplist does - Move the the flags used by the OpenWRT distro to mipsel target and - enable OpenSSL on all targets to improve coverage. + Apparently getgrouplist() can fail on OSX for when passed a non-existent + group name. Other platforms seem to return a group list consisting of + the numeric gid passed to the function. - Explicitly disable security key and openssl on mips target so that host - end of the bigendian interop tests don't attempt them and fail (since - they're not enabled on the target side). + This makes ga_init() handle this failure case gracefully, where it will + return success but with an empty group list array. + + bz3848; ok dtucker@ -commit d2709c461359e4129311cdff81ee05242d6c53cd -Author: Darren Tucker -Date: Sat Nov 9 03:26:08 2024 +1100 +commit f01a899b92ab8c5e6ff71214658bd09636c47e87 +Author: djm@openbsd.org +Date: Fri Jul 11 23:26:59 2025 +0000 - Add keytype to bigendian interop test. + upstream: add a "Match Group NoSuchGroup" to exercise groupaccess.c + + OpenBSD-Regress-ID: 7ff58e6f0eb21eb9064dd0cfa78c3b6f34b5f713 -commit 50ac0f0e0627d29fd9becf5e15e8ceca5ad18078 -Author: Darren Tucker -Date: Sat Nov 9 03:24:29 2024 +1100 +commit 1052fa62b35e0bb25b0c1efb9fdd7870e4a68ab6 +Author: Damien Miller +Date: Fri Jul 11 15:36:49 2025 -0700 - Ignore chown failure, eg due to dangling symlinks. + more diagnostics when getgrouplist fails -commit 9e528e65a03245cf28e814f09b88c701bec935d1 -Author: Darren Tucker -Date: Sat Nov 2 18:05:41 2024 +1100 +commit eddd1d2daa64a6ab1a915ca88436fa41aede44d4 +Author: djm@openbsd.org +Date: Fri Jul 4 09:51:01 2025 +0000 - Test bigendian interop. + upstream: Fix mistracking of MaxStartups process exits in some - Where our test target is a bigendian system, do an additional build on - the runner host (which is little endian) and test interop between the two. - Should hopefully catch obvious endianness bugs. + situations. At worst, this can cause all MaxStartups slots to fill and sshd + to refuse new connections. + + Diagnosis by xnor; ok dtucker@ + + OpenBSD-Commit-ID: 10273033055552557196730f898ed6308b36a78d -commit dd416f5bfa96ac1ff44b27a93f7b55ee627c6baf +commit c971f3d93efe4c00d73b276cdbab66e7c66c9b5c Author: Darren Tucker -Date: Fri Nov 1 19:44:29 2024 +1100 +Date: Sat Jul 5 20:50:50 2025 +1000 - Allow overridding TEST_SSH_SSHD. + Add include for gssapi definitions. - This will allow tests to specify an alternative sshd, eg on a remote - machine with different endianness. + Patch from dbelyavs at redhat.com via bz#3846. -commit 82662d562cf54829df8a941cdfb2fd307e1d9a90 +commit 007b69f21cf9e64125b241d4411a5e47f5028aa8 Author: djm@openbsd.org -Date: Wed Nov 6 22:51:26 2024 +0000 +Date: Fri Jul 4 07:52:17 2025 +0000 - upstream: ssh-agent implemented an all-or-nothing allow-list of + upstream: add a regress test for configurations > 256KB - FIDO application IDs for security key-backed keys, to prevent web key handles - from being used remotely as this would likely lead to unpleasant surprises. - By default, only application IDs that start with "ssh:*" are allowed. + mostly by Dmitry Belyavskiy - This adds a -Owebsafe-allow=... argument that can override the default - list with a more or less restrictive one. The default remains unchanged. + OpenBSD-Regress-ID: fcedb249e4cf2447e078a839877f99730ee79024 + +commit 0cf38d74463bcf80510e7fd1b3d9328e7d91eb00 +Author: djm@openbsd.org +Date: Fri Jul 4 07:47:35 2025 +0000 + + upstream: the messaging layer between sshd-session and sshd-auth had a - ok markus@ + maximum message size of 256KB. Some people apparently have configurations + larger than this and would hit this limit. - OpenBSD-Commit-ID: 957c1ed92a8d7c87453b9341f70cb3f4e6b23e8d + Worse, there was no good logging that could help diagnose what was + going wrong. + + So this bumps the maximum message size to 4MB and implements an early + check (usable via the sshd -t test mode) that will report it to the + user where it is hopefully more visible. + + bz3808, reported by Dmitry Belyavskiy, ok dtucker@ + + OpenBSD-Commit-ID: 69c303fb68cbd1a4735936835d67a71e7b57f63b -commit 593a0b65c55c1e06a8c22b084aefc395aedb0127 -Author: jca@openbsd.org -Date: Mon Nov 4 21:59:15 2024 +0000 +commit fd10cea0f16e928ae2b52fbeadccd475d0438eb4 +Author: djm@openbsd.org +Date: Fri Jul 4 00:17:55 2025 +0000 - upstream: Ignore extra groups that don't fit in the buffer passed + upstream: mux: fix incorrect return value check in local forward - to getgrouplist(3) + cancellation - Our kernel supports 16 groups (NGROUPS_MAX), but nothing prevents - an admin from adding a user to more groups. With that tweak we'll keep - on ignoring them instead of potentially reading past the buffer passed to - getgrouplist(3). That behavior is explicitely described in initgroups(3). + channel_cancel_lport_listener() returns 1 on success and 0 on failure. + The previous code incorrectly checked for `== -1`, a value the function + never returns, so failure was not detected and the "port not found" + error message was never shown when cancelling dynamic or local port + forwards. - ok millert@ gilles@ + From: Boris Tonofa - OpenBSD-Commit-ID: a959fc45ea3431b36f52eda04faefc58bcde00db + OpenBSD-Commit-ID: 3e9d2252a4d0bd318d4f25e2b518afb44acea170 -commit e7adebeff3a9d038d0eaeeb0fcefedf29acb7e90 +commit 29cf521486bf97ab9de5b9b356f812107e0671bc Author: Damien Miller -Date: Mon Nov 4 14:39:27 2024 +1100 +Date: Wed Jul 2 13:47:38 2025 +1000 - Add git signing key for Tim Rice + wrap some autoconf macros in AC_CACHE_CHECK + + This allows skipping/overriding the OSSH_CHECK_CFLAG_COMPILE and + OSSH_CHECK_CFLAG_LINK macros used to discover supported compiler + or linker flags. E.g. + + $ ./configure ossh_cv_cflag__fzero_call_used_regs_used=no + [...] + checking if cc supports compile flag -ftrapv and linking succeeds... yes + checking if cc supports compile flag -fzero-call-used-regs=used and linking succeeds... (cached) no + checking if cc supports compile flag -ftrivial-auto-var-init=zero... yes + + Patch from Colin Watson, ok dtucker@ -commit da4b84845e874f12af7e0686170fa391c919d1df +commit b28e91aff80fd24341de8cb3c34dc454d6b75228 +Author: dtucker@openbsd.org +Date: Sun Jun 29 08:20:21 2025 +0000 + + upstream: Add shebang path to askpass script. Required for exec on + + some platforms (musl, probably others). + + OpenBSD-Regress-ID: 35cdeed12ae701afcb812f800c04d817325cd22a + +commit 83d3ffc0fc0f5e4473ab43f0d42a1cf9497ce0b5 +Author: dtucker@openbsd.org +Date: Sun Jun 29 05:35:00 2025 +0000 + + upstream: Check dropbear server version for required features. + + Dropbear added the '-D' flag in version 2025.87. We need that for the + dropbear-server test, so skip on older versions. + + OpenBSD-Regress-ID: 9db0b84edd54d3c00ab17db1dc6d62af4644c550 + +commit 0b17d564cfae82f2a52e9b4d588657da47ea4e43 Author: Darren Tucker -Date: Fri Nov 1 18:51:22 2024 +1100 +Date: Sun Jun 29 14:34:48 2025 +1000 - Correct path to c-cpp.yml file in workflow config. + Encrypt temporary password we're setting. + + Now that we want to actually use the random password for tests, we need + to correctly encrypt it, instead of just setting it to a random string + that's not the "locked" value. -commit 28740aa2c75392a9c4191eb9523f9b20853e2932 +commit 700205bd861c25cc7564010cf63d984d8db5098a Author: Darren Tucker -Date: Fri Nov 1 18:44:42 2024 +1100 +Date: Sun Jun 29 11:27:17 2025 +1000 - Test new OpenSSL and LibreSSL releases.` + Fix env again. -commit a74809fe06540f16231b354ffe21fcbf39e81f73 +commit 223a1beac7b7be9252f69055781c9c15f4d8a607 Author: Darren Tucker -Date: Fri Nov 1 18:44:00 2024 +1100 +Date: Sun Jun 29 11:24:42 2025 +1000 - Add nbsd10 default test config. + Move env again. -commit 88b35cbdc1500efece65cd6a9a20a72cf7e46eaa -Author: Damien Miller -Date: Wed Oct 30 14:25:14 2024 +1100 +commit d32614b448528ac08a65caac323a34b4f559a204 +Author: Darren Tucker +Date: Sun Jun 29 11:22:00 2025 +1000 - fix uint64_t types; reported by Tom G. Christensen + Move env to where it (hopefully) belongs. -commit ef7c26cd2f0f9a8222f851d1e551f6dfd3113f8b -Author: Damien Miller -Date: Sun Oct 27 13:28:11 2024 +1100 +commit 8a9384de483b8fb69a800e0347273686a5715fc3 +Author: Darren Tucker +Date: Sun Jun 29 11:14:18 2025 +1000 - htole64() etc for systems without endian.h + Enable password tests on Github ephemeral VMs. -commit 0c3927c45f8a57b511c874c4d51a8c89414f74ef +commit bcfe7340d9b622ecd978c87dbf885c8b5a503ca2 +Author: dtucker@openbsd.org +Date: Sat Jun 28 13:34:08 2025 +0000 + + upstream: Add simple regression test for dropbear as a server. + + OpenBSD-Regress-ID: 7abe1f6607d0cd49839918aade8f135d2462d389 + +commit 838d5ec4b12fb519ed9db76e5beccf11b7ee212f +Author: dtucker@openbsd.org +Date: Tue Jun 24 12:28:23 2025 +0000 + + upstream: Add simple test for password auth. Requires some setup + + so does not run by default. + + OpenBSD-Regress-ID: d5ded47a266b031fc91f99882f07161ab6d1bb70 + +commit 57fb460165ae3b2d591f2468d7fe13cc1abda26d Author: djm@openbsd.org -Date: Sun Oct 27 02:06:59 2024 +0000 +Date: Tue Jun 17 01:24:32 2025 +0000 - upstream: explicitly include endian.h + upstream: add RCS ID - OpenBSD-Commit-ID: 13511fdef7535bdbc35b644c90090013da43a318 + OpenBSD-Regress-ID: 6e30094e3bf0a1c65efb75c67a87093304a3e619 -commit cf3e48ee8ba1beeccddd2f203b558fa102be67a2 +commit 688fa02728f2efbf18388bc1a8e94e7ba7ee4f11 Author: djm@openbsd.org -Date: Sun Oct 27 02:06:01 2024 +0000 +Date: Tue Jun 24 09:22:03 2025 +0000 - upstream: fix ML-KEM768x25519 KEX on big-endian systems; spotted by + upstream: make "Match !final" not trigger a 2nd pass ssh_config - jsg@ feedback/ok deraadt@ + parsing pass (unless hostname canonicalisation or a separate "Match final" + does). bz3843 - OpenBSD-Commit-ID: 26d81a430811672bc762687166986cad40d28cc0 + ok dtucker@ + + OpenBSD-Commit-ID: ce82b6034828888f0f3f1c812e08f5e87400d802 -commit ae566d51b64fa3dce7063e7745b9b35f8f47abde -Author: naddy@openbsd.org -Date: Fri Oct 25 21:53:24 2024 +0000 +commit 5ba8391d697740a838fd8811434f707f0e079baa +Author: djm@openbsd.org +Date: Thu Jun 19 05:49:05 2025 +0000 - upstream: mlkem768x25519-sha256 has been promoted to default key + upstream: better debug diagnostics when loading keys. Will now list - exchange + key fingerprint and algorithm (not just algorithm number) as well as making + it explicit which keys didn't load. - OpenBSD-Commit-ID: 5a3259a193fd42108a869ebf650b95b5f2d08dcf + OpenBSD-Commit-ID: ee3e77a0271ab502e653922c6d161b1e091f8fee -commit 3af1dba1384ca896df6e973c70398c41d36de1ea -Author: Darren Tucker -Date: Fri Oct 25 19:04:30 2024 +1100 +commit b360f3a675e24b0dbb2ec30d985e3b6756996c0d +Author: djm@openbsd.org +Date: Tue Jun 17 01:20:17 2025 +0000 - Retire the minix3 test config. + upstream: whitespace - It got broken by the sshd-auth change, it's not obvious why, and the - platform lacks the debugging tools (eg gdb, strace) to figure it out. - The upstream project seems effectively dead (6 years since the last - commit, 10 since the last release). It was useful while it lasted - (we found a real bug because of it) but its time seems to have passed. + OpenBSD-Commit-ID: 6e96814bcf70d0edbb0749ec61cc4fd8707f286d -commit 3b240cc44b8de9175280ddbe59331317d427b0e3 -Author: Preetish Amballi -Date: Mon Oct 21 14:07:02 2024 +0000 +commit ad38ec5f1b6768944d64ed7709da8706538b5509 +Author: djm@openbsd.org +Date: Tue Jun 17 01:19:27 2025 +0000 - Updated gitignore to ignore sshd-session and sshd-auth targets + upstream: fix leak on error path; Coverity CID 481976 + + OpenBSD-Commit-ID: 963dba2c804e2fd8efea2256092899874d0dbc7b -commit 326495744f06a0ab18ee0d16f87b3fe91cac92fb +commit 5f761cdb2331a12318bde24db5ca84ee144a51d1 Author: Darren Tucker -Date: Fri Oct 25 19:01:02 2024 +1100 +Date: Tue Jun 17 21:46:37 2025 +1000 - Simplify pselect shim and remove side effects. + Update obsd tests to use current images. + +commit 1e8347e3543a415067ccc556aefea97656ecafb7 +Author: Damien Miller +Date: Tue Jun 17 09:48:47 2025 +1000 + + add sshd-auth to RPM spec files + +commit dd800444943bd64913507f6005586136d49f63db +Author: dtucker@openbsd.org +Date: Mon Jun 16 09:09:42 2025 +0000 + + upstream: Limit each moduli size to a max of 100 entries. - Instead of maintaing state (pipe descriptors, signal handlers) across - pselect-on-select invocations, set up and restore them each call. - This prevents outside factors (eg a closefrom or signal handler - installation) from potentially causing problems. This does result in a - drop in throughput of a couple of percent on geriatric platforms without - a native pselect due to the extra overhead. Tweaks & ok djm@ + OpenBSD-Commit-ID: 747219d54565030ff7c45298b9f5e971801f6cb2 -commit e53b615f3934ffac1efb3c1e491d126b9b09fd24 -Author: djm@openbsd.org -Date: Fri Oct 25 01:34:18 2024 +0000 +commit 05f7bf46d1e2c101e9cbdd3df2ccee484bed969f +Author: dtucker@openbsd.org +Date: Mon Jun 16 09:07:08 2025 +0000 - upstream: promote mlkem768x25519-sha256 to be the default key exchange; + upstream: Now that ssh-keygen defaults to the maximum memory for - ok markus@ + moduli generation we no longer need to run it twice to get enough. Use mkdir + -p instead of a conditional, which allows "make -jN" to work without error. - OpenBSD-Commit-ID: fc673065e6505bb06b2e2b9362f78ccb4200a828 + OpenBSD-Commit-ID: c2eb57285424f819f9520fa33e0d6d3c4a361a5e -commit de644b1831b970f6655f871c051774cc871e8e74 -Author: djm@openbsd.org -Date: Thu Oct 24 03:28:34 2024 +0000 +commit df3f903d616763a105570610a616dacf0f83438e +Author: dtucker@openbsd.org +Date: Mon Jun 16 09:02:19 2025 +0000 - upstream: test SIGUSR1 dropping all keys from ssh-agent + upstream: Fix overflow check in sshbuf_dup_string. It's already - OpenBSD-Regress-ID: 8654b9aa8eb695b1499fffc408c25319592bf0e0 + constrained by SSHBUF_SIZE_MAX, but still worth fixing the check. Patch from + afonot via github PR#573, with & ok djm@ + + OpenBSD-Commit-ID: 438888498e66472fc6a48133196d6538d27bff18 -commit e86d7a077ce9a2b9ee9d4138c358a17cbdb786f9 -Author: djm@openbsd.org -Date: Thu Oct 24 03:15:47 2024 +0000 +commit 80916d0d3794e2f92dd6998d7c45daba484e4f18 +Author: dtucker@openbsd.org +Date: Mon Jun 16 08:53:04 2025 +0000 - upstream: amake ssh-agent drop all keys when it receives SIGUSR1; + upstream: Plug mem leak. Patch from afonot via github PR#574, ok djm@ - let's users zap keys without access to $SSH_AUTH_SOCK + OpenBSD-Commit-ID: 65619f14ef206028ce39bc31f704b832a0609688 + +commit bd1bd7e8296aa51a4b3958cef2fbb17894ba94e9 +Author: dtucker@openbsd.org +Date: Mon Jun 16 08:49:27 2025 +0000 + + upstream: Save return value from sshbuf_len instead of calling it - ok deraadt@ + multiple times. Fixes Coverity CID 470521. - OpenBSD-Commit-ID: dae9db0516b1011e5ba8c655ac702fce42e6c023 + OpenBSD-Regress-ID: 356b8b43c8a232deaf445c1ff7526577b177a8e9 -commit 94cdfebec852a2429c008cc2a55f8e4183f36972 -Author: djm@openbsd.org -Date: Thu Oct 24 03:14:37 2024 +0000 +commit 2827b6ac304ded8f99e8fbc12e7299133fadb2c2 +Author: dtucker@openbsd.org +Date: Fri Jun 13 07:35:14 2025 +0000 - upstream: relax valid_domain() checks to allow an underscore as the + upstream: Plug leak. Coverity CID 405058. - first character. ok deraadt@ + OpenBSD-Regress-ID: 7fb2fce68d2cb063cdb94d5d66f84fa3a2902792 + +commit 9cdc72b829e9f0e24dedc533cbe87291d8a88c9e +Author: dtucker@openbsd.org +Date: Fri Jun 13 07:23:07 2025 +0000 + + upstream: Remove dead code flagged by Coverity CID 307783. ok djm@ - OpenBSD-Commit-ID: 3f8be6d32496e5596dd8b14e19cb067ddd7969ef + OpenBSD-Regress-ID: e579f5ec2fd2eb2fe2bad654d16f2ba655a3e035 -commit 1b05d5437bf45bee5e3104772dea06ed51764f1b +commit 930a45ee759728c8ba711c45a2a985b8191bd297 Author: dtucker@openbsd.org -Date: Tue Oct 22 07:13:28 2024 +0000 +Date: Thu Jun 12 10:09:39 2025 +0000 - upstream: Remove sshd logfile in start_sshd + upstream: Set user, host and path to NULL immediately before calling - ... and ssh and sshd log wrappers before recreating them. Prevents "can't - create" errors during tests when running tests without SUDO after having - run them with SUDO. + parse_user_host_path in tests. This ensures that we don't accidentally use + the previous value if the function under test doesn't set them Also fixes + Coverity CIDs 405056 405065 405066. - OpenBSD-Regress-ID: 2f0a83532e3dccd673a9bf0291090277268c69a6 + OpenBSD-Regress-ID: 43678ff59001712f32214fe303b1c21c163c2960 -commit 307ab3c7720f8879b835614b02687358ee4df9b9 +commit 2314d87f9b8b430532111fd6e5e8df0cf9068c9c Author: dtucker@openbsd.org -Date: Tue Oct 22 06:16:26 2024 +0000 +Date: Thu Jun 12 09:26:57 2025 +0000 - upstream: Add a sshd debug wrapper + upstream: Plug mem leak on error path here too. - ... to run all of the subprograms from the build directory while - developing and debugging. Should help prevent accidentally testing - against unchanged installed sshd-auth and sshd-session binaries. ok djm@ + Coverity CID 307781. - OpenBSD-Commit-ID: 61760cdc98c2bc8f1e9f83a6f97cca0f66b52e69 + OpenBSD-Regress-ID: 18e053d9b661fbb4227d3db03172077c1216bb2e -commit 87bd1cb3ccba5e91d2650eb7f753c898ee43858e +commit 567ef4e7ddc5c1e7a461560963a1dc759669821d Author: dtucker@openbsd.org -Date: Tue Oct 22 06:13:00 2024 +0000 +Date: Thu Jun 12 09:19:43 2025 +0000 - upstream: Make debug call printf("%s", NULL) safe. + upstream: Plug mem leak on error path. - Prevents problems on platforms where this isn't safe (which it's not - required to be). ok djm@ + Coverity CID 307776. - OpenBSD-Commit-ID: 8fa4ce3ad90915c925b81b99a79ab920b0523387 + OpenBSD-Regress-ID: c44246690973e1b8643e51079a2faa7ace26490c -commit c44c349edd157b2c00c42bd5ef5f9dfb37de26f3 +commit 5d415897ac04e237f1fa73b9dcb9ba8fb3ac812b +Author: dtucker@openbsd.org +Date: Wed Jun 11 13:27:11 2025 +0000 + + upstream: Remove dead code ternary. We always report at least + + KB/s, so B/s is never used. Coverity CID 291809, ok djm@ + + OpenBSD-Commit-ID: a67c5bcc9e19c8965bfeace0e337b13660efa058 + +commit 4b3d27032ba88dd089b721f3bbe3e4a8d23b4ae1 +Author: dtucker@openbsd.org +Date: Wed Jun 11 13:24:05 2025 +0000 + + upstream: Improve termination condition of while loop to compare + + size_t's. Assuming read() does what it's supposed to this shouldn't matter, + but should be more robust. Flagged by Coverity CID 470514, ok djm@ + + OpenBSD-Commit-ID: d7b5ad60feb797b3464964b9ea67fd78fb9d6cc6 + +commit 5530e5f83b3cd3425ea3dbab02da15140befdd91 Author: Darren Tucker -Date: Tue Oct 22 17:48:32 2024 +1100 +Date: Tue Jun 10 18:40:56 2025 +1000 - Resync cvsid missed in commit 6072e4c9. + Replace Windows 2019 runners with 2025 ones. + + The windows-2019 runners are being decomissioned. -commit fe4305c37ffe53540a67586854e25f05cf615849 -Author: djm@openbsd.org -Date: Fri Oct 18 05:53:26 2024 +0000 +commit a22ff3c6f11edd00c19981f9cb85d3b25d305a56 +Author: Darren Tucker +Date: Wed Jun 4 18:33:52 2025 +1000 - upstream: mention that LocalForward and RemoteForward can accept Unix + Disable _FORTIFY_SOURCE during snprintf test. - domain socket paths; GHPR115 + Prevents mistakenly detecting snprintf as broken on FreeBSD 15 with + _FORTIFY_SOURCE enabled. bz#3809, patch from jlduran at gmail.com + +commit 203bb886797677aa5d61b57be83cfdc1b634bc9c +Author: dtucker@openbsd.org +Date: Mon Jun 2 14:09:34 2025 +0000 + + upstream: Fix x11_channel_used_recently() to return true when channel - OpenBSD-Commit-ID: a8a34d0a0c51a9ddab3dfce615f9878fa76ef842 + has been used within the last second, instead of more than a second ago. + Should fix ~5s delay on X client startup when ObscureKeystrokeTiming is + enabled. bz#3820, ok (& sigh) djm@ + + OpenBSD-Commit-ID: b741011e81fb3e3d42711d9bd3ed8a959924dee4 -commit 9c97b6af8e052ab5ffe0f9096fadc8f9a4d0ed0f -Author: djm@openbsd.org -Date: Fri Oct 18 05:45:40 2024 +0000 +commit dc6c134b48ba4bcfadedcea17b4eddac329601d9 +Author: dtucker@openbsd.org +Date: Thu May 29 13:27:27 2025 +0000 - upstream: remove duplicate check; GHPR392 from Pedro Martelletto + upstream: When there's more than one x11 channel in use, return - OpenBSD-Commit-ID: 597ab7dd3f0e78939d2659fc1904d0f39ee95487 + lastused of most recently used x11 channel instead of the last one found. ok + djm@ + + OpenBSD-Commit-ID: 94a72bf988d40a5bae2e38608f4e117f712569fe -commit d9cd208e89a471a3ff8adfcec68d6210af9e9fd5 +commit 73ef0563a59f90324f8426c017f38e20341b555f Author: djm@openbsd.org -Date: Fri Oct 18 05:37:24 2024 +0000 +Date: Sat May 24 11:41:51 2025 +0000 - upstream: allow "-" as output file for moduli screening + upstream: replace xmalloc+memset(0) with xcalloc(); from AZero13 via - based on GHPR393 + GHPR417 - OpenBSD-Commit-ID: 1517763764eb55d03a6092dd120d2909c6fef0e1 + OpenBSD-Commit-ID: 921079436a4900325d22bd3b6a90c8d0d54f62f8 -commit 5eb5c4b2820d0636b1eccee646fb32ec946c4a95 +commit 3a61f5ed66231881bee432c7e7c6add066c086af Author: djm@openbsd.org -Date: Fri Oct 18 05:32:51 2024 +0000 +Date: Sat May 24 09:46:16 2025 +0000 - upstream: ssh-keyscan doesn't need it's own sshfatal() definition, it + upstream: fix punctuation around host key fingerprints to make them - can use the shared one from fatal.c + easier to copy and paste. - based on GHPR401 from lengyijun + Patch from Till Maas via GHPR556; ok dtucker@ - OpenBSD-Commit-ID: 8ea75ea99f27f464c9223cbc89cb046ccf9cd5c4 + OpenBSD-Commit-ID: c0100182a30b6925c8cdb2225b18140264594b7b -commit 0a1e75499e2c6fc258ee903645c878480949f362 -Author: djm@openbsd.org -Date: Fri Oct 18 05:14:51 2024 +0000 +commit b12d4ab1e16f57c6c348b483b1dbdd4530aaaddd +Author: dtucker@openbsd.org +Date: Sat May 24 08:13:29 2025 +0000 - upstream: in _ssh_order_hostkeyalgs() consider ECDSA curve type when + upstream: Replace strncmp + byte count with strprefix in Penalty - arranging the hostkey algorithms. AFAIK this code is unused in OpenSSH, but I - guess others are using it - - based on GHPR387 from Pawel Jakub Dawidek + config parsing. ok kn@, djm@ - OpenBSD-Commit-ID: 4d462495ac0c40f7b7dd66178e0005b9b2128225 + OpenBSD-Commit-ID: 34a41bb1b9ba37fb6c7eb29a7ea909547bf02a5a -commit d01ee7a88c5f4b1aa8c75a7c739f8f3bc1ad8bde -Author: djm@openbsd.org -Date: Fri Oct 18 05:03:34 2024 +0000 +commit a356d978e30dd9870c0b3a7d8edca535b0cd2809 +Author: dtucker@openbsd.org +Date: Sat May 24 08:09:32 2025 +0000 - upstream: require control-escape character sequences passed via the '-e + upstream: Make the display number check relative to - ^x' commandline to be exactly two characters long. Avoids one by OOB read if - ssh is invoked as "ssh -e^ ..." + X11DisplayOffset. - Spotted by Maciej Domanski in GHPR368 + This will allows people to use X11DisplayOffset to configure much higher + port ranges if they really want, while not changing the default behaviour. + Patch from Roman Gubarev via github PR#559, ok djm@ - OpenBSD-Commit-ID: baa72bc60898fc5639e6c62de7493a202c95823d + OpenBSD-Commit-ID: e0926af5dc0c11e364452b624c3ad0cda88550b5 -commit 74ff6382f5743e09930e6cbd195dac65cd6062c9 -Author: djm@openbsd.org -Date: Fri Oct 18 04:30:09 2024 +0000 +commit e18983d03ab969e2f12485d5c0ee61e6d745a649 +Author: Darren Tucker +Date: Sat May 24 17:20:57 2025 +1000 - upstream: remove addr.[ch] functions that are unused and + Remove progressmeter.o from libssh.a. - visbility-restrict ones that are unused outside the implementation itself; - based on GHPR#282 by tobias@ + It's now explicitly included by the binaries that need it (scp & sftp). + bz#3810, patch from jlduran at gmail.com + +commit f8967045ad9d588bc11426642070bf8549065e62 +Author: dtucker@openbsd.org +Date: Sat May 24 06:50:28 2025 +0000 + + upstream: Null out keys between test runs. - OpenBSD-Commit-ID: a0140f2418b4d46cfaa7b33febc0a0931f9b2744 + BENCH_START and BENCH_FINISH are actually a while() loop in disguise, + so if sshkey_generate does not reset the key pointer on failure the test + may incorrectly pass. It also confuses Coverity (CID 551234). + + OpenBSD-Regress-ID: bf4d32079fc6df6dce1f26c2025f4ed492f13936 -commit a9d6d7d93c533fa729f08b405e786d912553f33e +commit a26091ecdb2a3d72b77baf3c253e676a3c835a24 Author: djm@openbsd.org -Date: Fri Oct 18 04:14:59 2024 +0000 +Date: Sat May 24 04:41:12 2025 +0000 - upstream: unreachable POLLERR case; from ya0guang via GHPR485 + upstream: add some verbosity - OpenBSD-Commit-ID: b3c82655190532b01eb817e532742cfaa4687eff + OpenBSD-Regress-ID: 11c86cda4435b5f9ab6172c4742b95899666c977 -commit d76424bf279ff951383e21213eb3759ea4090674 +commit 484563ec70e30472ab4484d49bca9a83771d785c Author: djm@openbsd.org -Date: Fri Oct 18 04:11:54 2024 +0000 +Date: Sat May 24 04:41:03 2025 +0000 - upstream: s/Sx/Cm/ for external references; from Domen Puncer + upstream: use start_ssh_agent() to ensure we get logging - Kugler via GHPR501 + add some verbosity - OpenBSD-Commit-ID: f864a34feb5d5ff17160cf7c42ad0f7744fe8a3f + OpenBSD-Regress-ID: a89bf64696b9fb1b91be318e6b8940c9ab21c616 -commit ca204b994e2981e7bf95627b3105408917105649 -Author: naddy@openbsd.org -Date: Mon Oct 14 23:53:34 2024 +0000 +commit e3c58113ebb3397b252ff26e0e94f726b7db7a8a +Author: djm@openbsd.org +Date: Sat May 24 04:40:37 2025 +0000 - upstream: mention SshdAuthPath option; ok djm@ + upstream: add a start_ssh_agent() function that sets up an agent - OpenBSD-Commit-ID: 9a5d3add25e4e77bd3805bc5583a842ecf34d85c + with logging + + OpenBSD-Regress-ID: 7f9f30f9c64acbd4b418a5e1a19140cc988071a8 -commit be27770e840c4dd9d9fcad1aa879400c727d7c2f -Author: Darren Tucker -Date: Fri Oct 18 13:37:55 2024 +1100 +commit 3de011ef7a761751afe28ac7ef97fe330d784595 +Author: dtucker@openbsd.org +Date: Sat May 24 06:43:37 2025 +0000 - Remove references to systrace and pledge sandboxes. + upstream: Plug leak of startup_pollfd in debug and child paths. - ok djm@ + Coverity CID 405024, ok djm@ + + OpenBSD-Commit-ID: db46047229253e9c4470c8bbf5f82706ac021377 -commit 49e64bf63fbf2f14961062dafe8ef08cb816bb08 -Author: Pavel Miadzvedzeu -Date: Wed Apr 24 10:19:56 2024 +0300 +commit d0245389bc55f16082cadd0a39dda5af1c415dfa +Author: Darren Tucker +Date: Sat May 24 17:11:38 2025 +1000 - Fix "undeclared 'ut'" error by replacing it with 'utx' + ssh-keygen changes were fixup'ed into single commit. -commit 67f684733f60f66479854a2867b953de731e71b2 -Author: Darren Tucker -Date: Thu Oct 17 20:50:29 2024 +1100 +commit 140bae1df2b7246bb43439d039bf994159973585 +Author: Marco Trevisan (Treviño) +Date: Mon Sep 30 13:14:11 2024 +0200 - Seed RNG when starting up sshd-auth. + auth-pam: Check the user didn't change during PAM transaction - Makes builds configured --without-openssl work again since otherwise - the first use of the RNG comes after the sandbox init and it can't - open /dev/random. - -commit c06c681aeebbe8e84e7410095514e7ee91f7e6cb -Author: Darren Tucker -Date: Thu Oct 17 19:18:23 2024 +1100 - - MacOS 12 runners are deprecated, replace with 15. + PAM modules can change the user during their execution, in such case ssh + would still use the user that has been provided giving potentially + access to another user with the credentials of another one. + + So prevent this to happen, by ensuring that the final PAM user is + matching the one that initiated the transaction. -commit 39db1f23bafb48a7c0cc9c65c716a0370f4cc677 -Author: Damien Miller -Date: Thu Oct 17 13:28:47 2024 +1100 +commit 216824172724a50a4a75439fb2b4b8edccf5b733 +Author: dtucker@openbsd.org +Date: Sat May 24 03:37:40 2025 +0000 - Fix lookup path for sshd-auth; bz3745 + upstream: Remove ssh-keygen's moduli screen -Omemory option. + + This vaguely made sense 20 years ago, but these days you'd be hard + pressed to *find* a machine small enough to not support the maximum + (127MB), and no one is screening moduli on such machines anyway, + so just use the max. This also fixes Coverity CID 470522 by deleting + code in question. "kill it with fire" djm@. + + OpenBSD-Commit-ID: 39036aa406a99f0a91923aa3a96afff1205558e6 -commit c537eeb1ae5f069450053b0027e64efe5bdb37d2 -Author: Damien Miller -Date: Wed Oct 16 08:28:21 2024 +1100 +commit f5cd14e81fa29b4924959cb2e1f9c206aae2d502 +Author: dtucker@openbsd.org +Date: Sat May 24 02:33:33 2025 +0000 - fix breakage; missing saved_argc symbol + upstream: Fix compile error on 32bit platforms. + + Spotted by & ok tb@ + + OpenBSD-Commit-ID: cbcf518247886f3c7518fc54cb3bd911ffc69db7 -commit 98a0883bdef28a06c7e017f27adf21ba57898bf4 -Author: Damien Miller -Date: Mon Oct 14 17:17:50 2024 +1100 +commit eccc15014fe146e8590568e6737a3097bfac3415 +Author: dtucker@openbsd.org +Date: Sat May 24 02:01:28 2025 +0000 - fix capsicum sandbox + upstream: Use pointer from strprefix in error message, + + missed in previous. + + OpenBSD-Commit-ID: d2cdec6cf0fcd4b0ee25e4e3fad8bc8cf0ee657d -commit 164ea4380564a2a83713eacf71908e3946e5e4e4 -Author: Damien Miller -Date: Mon Oct 14 17:16:41 2024 +1100 +commit 91903511d0597c3bea218167f9ca5a176fa0dc20 +Author: dtucker@openbsd.org +Date: Fri May 23 12:52:45 2025 +0000 - put back some portable bits for sshd-auth.c + upstream: Replace strncmp and strncasecmp with hand-counting bytes + + with strprefix. nits lucas@, ok lucas@ djm@ + + OpenBSD-Commit-ID: f0888807f151ea2bdaf6fed36303ae81f259d1d4 -commit f8edf08c258ee2918689872c4702302052729726 -Author: Damien Miller -Date: Mon Oct 14 14:49:25 2024 +1100 +commit 0c64d69e4e24a3ab06f7922ef389e7399c4dfb88 +Author: dtucker@openbsd.org +Date: Fri May 23 11:54:50 2025 +0000 - there's only one sandbox, move to a static global + upstream: Include stdint.h for UINT32_MAX. + + OpenBSD-Commit-ID: edc29ed67e8bd03bac729d9b4849066d1d3a8cb9 -commit 4482f0042b41d3d63c3845d7ba9fcf47c9252a84 -Author: Damien Miller -Date: Mon Oct 14 14:49:20 2024 +1100 +commit 3e11478f585408888defa56fa47e8dc6567378d0 +Author: dtucker@openbsd.org +Date: Fri May 23 11:25:35 2025 +0000 - depend + upstream: Ensure args to nh_update() fit within uint32, which it + + should always anyway. Placates Coverity CID 470520. While there, fix the + upstream URL. ok djm@ + + OpenBSD-Commit-ID: 2478e89fde089a49fa02f9faf6287d35959c9f92 -commit 74856204a353a187dc6e7706c6cf84b7f14d775d -Author: djm@openbsd.org -Date: Mon Oct 14 03:02:08 2024 +0000 +commit f097d7bd07da4634c1a723d1dc4fcf56e7d0e147 +Author: dtucker@openbsd.org +Date: Fri May 23 09:26:25 2025 +0000 - upstream: regress support for split sshd-auth binary + upstream: Don't leak the args list. Coverity CIDs 481569 & 481570, - OpenBSD-Regress-ID: df7d18a87b475f70004770f0f4e404adba5f6ab7 + ok job@ tb@. + + OpenBSD-Commit-ID: becabcd00513d13d1435b68b7ccffa7151b72393 -commit 461741083d7254595fecea274e60fe3ebf3ce3f9 -Author: djm@openbsd.org -Date: Fri Sep 27 01:05:54 2024 +0000 +commit a4ea7f6042f25b41061a83445016a1ea4f470f7b +Author: dtucker@openbsd.org +Date: Fri May 23 08:40:13 2025 +0000 - upstream: test some more Match syntax, including criteria=arg and + upstream: Explictly set LC_ALL=C on each sort invocation. - negations + Remove it from sshd_config (where it could be overridden by shell startup + scripts, eg on macos-15) causing random test failures. with & ok djm@ - OpenBSD-Regress-ID: 67476baccc60bf1a255fd4e329ada950047b8b8d + OpenBSD-Regress-ID: ad0a6678964784096e9a9e6d15ead36beed92f18 -commit 6072e4c9385713e9c166f32cfca6a7e603d4f0b8 -Author: djm@openbsd.org -Date: Mon Oct 14 01:57:50 2024 +0000 +commit 7674c03caed80cb3565d14690c92068a14051967 +Author: Darren Tucker +Date: Fri May 23 16:39:18 2025 +1000 - upstream: Split per-connection sshd-session binary + Allow setting LTESTS in repo variables. + +commit d8b5bd36078e5b6d78da4633f0cc9b90ffda8b50 +Author: Darren Tucker +Date: Fri May 23 16:26:20 2025 +1000 + + Rename debugging variable RUN_ONLY_TEST. - This splits the user authentication code from the sshd-session - binary into a separate sshd-auth binary. This will be executed by - sshd-session to complete the user authentication phase of the - protocol only. + to RUN_ONLY_TARGET_CONFIG to make it more obvious what it matches. + +commit a79a2c1190bd3124da21d9e1582dd94877c7f972 +Author: Darren Tucker +Date: Fri May 23 16:11:48 2025 +1000 + + chown regress logs before uploading. + +commit 24889a33071086b6f1f62568b0c2bd0a4955ac49 +Author: dtucker@openbsd.org +Date: Fri May 23 01:14:35 2025 +0000 + + upstream: Import regenerated moduli. - Splitting this code into a separate binary ensures that the crucial - pre-authentication attack surface has an entirely disjoint address - space from the code used for the rest of the connection. It also - yields a small runtime memory saving as the authentication code will - be unloaded after thhe authentication phase completes. + OpenBSD-Commit-ID: 07e29dc891e29b31e03e2e5493658b4a9ac19431 + +commit 4b8bee62d72ffb3c419c9ead6c9fb1a586283868 +Author: deraadt@openbsd.org +Date: Fri May 23 00:40:45 2025 +0000 + + upstream: use "const char * const" for malloc_options here also - Joint work with markus@ feedback deraadt@ + OpenBSD-Commit-ID: 869715b9c7e1dd5b85efd07814e7e53f0286eea2 + +commit 6629eee21ca9d0a597a04dcac744a1ad882f912e +Author: dtucker@openbsd.org +Date: Thu May 22 12:14:19 2025 +0000 + + upstream: Adjust debug message to prevent (unsigned) integer overflow. - Tested in snaps since last week + Fixes Coverity CID 481110, ok djm@ - OpenBSD-Commit-ID: 9c3b2087ae08626ec31b4177b023db600e986d9c + OpenBSD-Commit-ID: 26178bf3b812707fb498ea85d076cadd1f2eb686 -commit fe6c6330c1a94c7a537efe9069853ce7a275c50a -Author: djm@openbsd.org -Date: Sun Oct 13 22:20:06 2024 +0000 +commit 7acb70e05e9977ceca7b33df84ceaea337b1efef +Author: bluhm@openbsd.org +Date: Thu May 22 04:34:18 2025 +0000 - upstream: don't start the ObscureKeystrokeTiming mitigations if + upstream: Fix OpenBSD RCS ID typos. from Andrius V - there has been traffic on a X11 forwarding channel recently. + OpenBSD-Regress-ID: 5c03a2ef5323969fc4978f2eec4f1a25c48c572a + +commit 2b2a7a2a0d70023b439080bb2770ff36522dbea8 +Author: Darren Tucker +Date: Thu May 22 22:09:48 2025 +1000 + + Remove debug change accidentally commited. - Should fix X11 forwarding performance problems when this setting is - enabled. Patch from Antonio Larrosa via bz3655 + Fixes Coverity CID 481160. + +commit 450a8a1df1577ddbe68fe8da1fb8514d3781ef32 +Author: Darren Tucker +Date: Thu May 22 21:16:37 2025 +1000 + + Collect all of regress dir on failure. - OpenBSD-Commit-ID: 820284a92eb4592fcd3d181a62c1b86b08a4a7ab + This may allow us to sort through its entrails and determine the cause + of some types of failures. -commit 538cd28598ae942c94b99855b06fdd937e2e7381 -Author: jsg@openbsd.org -Date: Sat Oct 12 10:50:37 2024 +0000 +commit de25e739781c4c09d20abd410f50f0a6f192dc72 +Author: Damien Miller +Date: Thu May 22 18:42:44 2025 +1000 - upstream: remove duplicate misc.h include ok dtucker@ + minimal shims for fstatat(2)/unlinkat(2) in agent - OpenBSD-Commit-ID: fdd056e7854294834d54632b4282b877cfe4c12e + Add some very minimal and task-specific replacements for + fstatat(2) and unlinkat(2) in the ssh-agent socket cleanup + loop, for platforms that lack these functions. ok dtucker@ -commit 0051381a8c33740a77a1eca6859efa1c78887d80 -Author: djm@openbsd.org -Date: Sun Oct 6 23:37:17 2024 +0000 +commit 6d192645a613aa814d51050b0458f37265b90d6c +Author: dtucker@openbsd.org +Date: Thu May 22 04:22:03 2025 +0000 - upstream: Turn off finite field (a.k.a modp) Diffie-Hellman key + upstream: Output the current name for PermitRootLogin's - exchange in sshd by default. Specifically, this removes the - diffie-hellman-group* and diffie-hellman-group-exchange-* methods. The client - is unchanged and continues to support these methods by default. + "prohibit-password" in sshd -T instead of its deprecated alias + "without-password". bz#3788, patch from cjwatson at debian.org. - Finite field Diffie Hellman is slow and computationally expensive for - the same security level as Elliptic Curve DH or PQ key agreement while - offering no redeeming advantages. + OpenBSD-Commit-ID: 2d5df18d5ad33a9b6c7547ec78a8e6ea13813df9 + +commit 1ccf42378df202472e7254f37f7dabb2f5723955 +Author: dtucker@openbsd.org +Date: Thu May 22 03:53:46 2025 +0000 + + upstream: Copy arg to be passed to dirname(). - ECDH has been specified for the SSH protocol for 15 years and some - form of ECDH has been the default key exchange in OpenSSH for the last - 14 years. + POSIX allows dirname() to modify its args and return a pointer into it, + so this prevents an overlapping strlcpy. bz#3819, patch from cjwatson + at debian.org - ok markus@ + OpenBSD-Commit-ID: c32e496e6a1618aba31c8b7a9d4e1376c5ea6aa1 + +commit b5877b7b3e597f47578ade9dbe7e4332f112dfc4 +Author: dtucker@openbsd.org +Date: Thu May 22 03:41:10 2025 +0000 + + upstream: Add $OpenBSD$ marker for easier syncing. - OpenBSD-Commit-ID: 4e238ad480a33312667cc10ae0eb6393abaec8da + OpenBSD-Commit-ID: 27ff3e1e2e6610d9981ebe43ae9b783236800035 -commit 67a115e7a56dbdc3f5a58c64b29231151f3670f5 +commit 58d094c7cb974d7bd3ba6eb1059b186a2ac3dd55 Author: djm@openbsd.org -Date: Thu Sep 26 23:55:08 2024 +0000 +Date: Wed May 21 12:12:20 2025 +0000 - upstream: fix previous change to ssh_config Match, which broken on + upstream: Correct FILES section to mention new default path to - negated Matches; spotted by phessler@ ok deraadt@ + agent sockets. Spotted by / ok jmc@ - OpenBSD-Commit-ID: b1c6acec66cd5bd1252feff1d02ad7129ced37c7 + OpenBSD-Commit-ID: 91d736d78d71a4276c9cbb075b1462bbc3df55a6 -commit 220b6c1290042acd5180d783dea01efe1365c265 -Author: jsg@openbsd.org -Date: Wed Sep 25 23:01:39 2024 +0000 +commit d1d5c8b9b8de8283618c18d0dafdec6a209911cc +Author: Darren Tucker +Date: Thu May 22 12:25:35 2025 +1000 - upstream: remove some unused defines; ok djm@ + Fix nc install some more. + +commit 49a2412ad23162e44be9e0b2cb12f6daf6b666d7 +Author: Darren Tucker +Date: Thu May 22 12:21:11 2025 +1000 + + Fix cvs up of nc. + +commit df22801b3f0ae245f825cf9c9dbb4543e41a7c5c +Author: Darren Tucker +Date: Thu May 22 11:34:04 2025 +1000 + + Install nc during upstream test. - OpenBSD-Commit-ID: 3a63e4e11d455704f684c28715d61b17f91e0996 + This ensures that the installed nc matches the expectations of the + regress tests. -commit 3ef4f6e8a4d774f73852391fdccbb95f39fc71bf -Author: jmc@openbsd.org -Date: Wed Sep 25 06:13:01 2024 +0000 +commit e391c5289c2b687ff886cf780dc8fcb426e4d5d2 +Author: Darren Tucker +Date: Thu May 22 10:52:31 2025 +1000 - upstream: remove some unneeded Xo/Xc calls; from evan silberman the + Remove 9.7 branch from CI status page. - original diff had a couple of errors, which i've fixed + It's been obsolete long enough that github no longer reports its + status. + +commit b71773c20d566fa5dcaf9edf3139bdcb3f2c4bc2 +Author: Damien Miller +Date: Wed May 21 19:14:47 2025 +1000 + + pull a small netcat SOCKS4A fix from upstream + +commit 0adb2db25eff3fe1c90c55654387ae1e4e18a396 +Author: djm@openbsd.org +Date: Wed May 21 08:41:52 2025 +0000 + + upstream: test SOCKS4A; ok tb - OpenBSD-Commit-ID: f37ad5888adbc0d4e1cd6b6de237841f4b1e650d + OpenBSD-Regress-ID: d880b75280295cd581a86e39bb0996d347f122d2 -commit 3f02368e8e9121847727c46b280efc280e5eb615 +commit 5699f4e9553c6a228fd9dc578d99e3aa6451c014 Author: djm@openbsd.org -Date: Wed Sep 25 01:24:04 2024 +0000 +Date: Wed May 21 08:36:39 2025 +0000 - upstream: fix regression introduced when I switched the "Match" + upstream: remove log tarballing "it seemed like a good idea at the - criteria tokeniser to a more shell-like one. Apparently the old tokeniser - (accidentally?) allowed "Match criteria=argument" as well as the "Match - criteria argument" syntax that we tested for. + time" - dtucker@ - People were using this syntax so this adds back support for - "Match criteria=argument" + ensure that log files have correct perms when running under sudo/doas - bz3739 ok dtucker + ok dtucker@ - OpenBSD-Commit-ID: d1eebedb8c902002b75b75debfe1eeea1801f58a + OpenBSD-Regress-ID: 20588c14b05de9519f85d638b374b66ae0678c89 -commit 9517cc58577f85a0ba5f8bb46778dff625f0688f +commit 0c14e6b69a20f20d602e0e72559ca3f4dbc797fb Author: djm@openbsd.org -Date: Tue Sep 24 02:28:17 2024 +0000 +Date: Wed May 21 06:44:24 2025 +0000 - upstream: some extra paranoia, reminded by jsg@ + upstream: use logit_f("...") instead of logit("func: ...") - OpenBSD-Commit-ID: 22072bfa1df1391858ae7768a6c627e08593a91e + OpenBSD-Commit-ID: c8d49eb39a9abff3cbcaeaf7df9d48468a5a0695 -commit 815a94e86a68c1000b8310cb47695cea9329516c -Author: Damien Miller -Date: Wed Sep 25 11:15:45 2024 +1000 +commit 1743589d038476f28dc4dfb1f69317649ae22ac5 +Author: djm@openbsd.org +Date: Wed May 21 06:43:48 2025 +0000 - gss-serv.c needs sys/param.h + upstream: function to make a sshbuf from a hex string; useful in - From Void Linux + tests + + also constify some arguments + + OpenBSD-Commit-ID: 00f9c25b256be0efd73f2d8268ff041bc45ffb2c -commit 76a618d2842c34c16cd21a4efc7230e2f459008d +commit 83729cf503289104d7e64a69be14579523988cb6 Author: Damien Miller -Date: Wed Sep 25 11:13:05 2024 +1000 +Date: Wed May 21 18:47:46 2025 +1000 - build construct_utmp() when USE_BTMP is set + merge netcat SOCKS4A support from OpenBSD - Fixes compile error on Void Linux/Musl + Not a full sync of this file as we have diverged substantially + from upstream (it has libtls support, etc.) -commit d3aee17f6d395202eaa42a0c449b6da41f61527c +commit 750f1867476bda36879f69e25e8f52cb45c58807 Author: Darren Tucker -Date: Tue Sep 24 18:41:44 2024 +1000 +Date: Tue May 20 22:17:02 2025 +1000 - Test the flags from OpenWRT's package. + Include OpenSSL compat shim where needed. -commit 0f5d19e6fe4b58a89e6dc8c71a2aae30365d193e -Author: Christoph Ostarek -Date: Wed Jul 3 12:46:59 2024 +0200 +commit 6fb728df50c1afd338cb0223a84ce24579577eff +Author: Darren Tucker +Date: Tue May 20 19:28:55 2025 +1000 - fix utmpx ifdef + Run all tests on Cygwin again. - 02e16ad95fb1f56ab004b01a10aab89f7103c55d did a copy-paste for - utmpx, but forgot to change the ifdef appropriately + ... now that we've fixed ci-setup on Cygwin. -commit e03239f999acf9dc3da0f2f72bde36abbe678911 -Author: jsg@openbsd.org -Date: Sun Sep 22 12:56:21 2024 +0000 +commit 648a3a008cf1cfa54631d2f0457b5313c455f484 +Author: Darren Tucker +Date: Tue May 20 18:48:23 2025 +1000 - upstream: remove some unused defines; ok djm@ + Use USERNAME rather than LOGNAME on Cygwin. - OpenBSD-Commit-ID: 81869ee6356fdbff19dae6ff757095e6b24de712 + LOGNAME is specified by POSIX, but Windows (or at least, github's + Windows images) don't set it. -commit a35f543d3a6275fef781e515c262d1c687c3bc28 -Author: jsg@openbsd.org -Date: Fri Sep 20 02:00:46 2024 +0000 +commit 0214e53124c09528b6ee29b9a551442b5611a454 +Author: Darren Tucker +Date: Tue May 20 18:28:52 2025 +1000 - upstream: remove unneeded semicolons; checked by millert@ - - OpenBSD-Commit-ID: 3fb621a58e04b759a875ad6a33f35bb57ca80231 + Add debug output when setting up CI environment. -commit 1641f2d4d6e05d2147913442864cae546e64f08b +commit 9d9a2c0369419f3b4952e597db7b8696f54e7f3a Author: Darren Tucker -Date: Mon Sep 23 20:52:31 2024 +1000 +Date: Tue May 20 19:16:38 2025 +1000 - Add 9.9 branch to CI status console. + Include openssl compat shims in test. + + Fixes tests on platforms using older LibreSSL releases prior to 3.4. -commit 46d1fb16b20e971b9ac15e86a3d3e350b49c9ad6 -Author: Damien Miller -Date: Fri Sep 20 08:20:13 2024 +1000 +commit 1a9b1cfa4e8b807c7f82fdba8f730c2abdbba071 +Author: Darren Tucker +Date: Tue May 20 18:14:06 2025 +1000 - update version numbers + Add compat shims for EC_POINT affine_coordinates + + LibreSSL <3.4 does not have EC_POINT_[gs]et_affine_coordinates + but does have the now-deprecated _GFp variantes. We still support + LibreSSL back as far as 3.2.x so add a compat shim. -commit 0bdca1f218971b38728a0a129f482476baff0968 -Author: djm@openbsd.org -Date: Thu Sep 19 22:17:44 2024 +0000 +commit cff2175200b412a9207a4fe5c1bdcc54e8a73d07 +Author: tb@openbsd.org +Date: Mon May 12 05:42:02 2025 +0000 - upstream: openssh-9.9 + upstream: Use EC_POINT_[sg]et_affine_coordinates() - OpenBSD-Commit-ID: 303417285f1a73b9cb7a2ae78d3f493bbbe31f98 + It is available in all supported OpenSSL flavors/versions and the _GFp + variants will be removed from LibreSSL. + + ok hshoexer jsing + + OpenBSD-Regress-ID: 66cf1561e7b6c49002978f2d6720956f33a882f0 -commit ef2d7f2d3e1b4c9ae71bacf963e76a92ab8be543 -Author: Damien Miller -Date: Wed Sep 18 16:03:23 2024 +1000 +commit 2d35e24739b515394017b74465a0996c384cf28f +Author: tb@openbsd.org +Date: Mon May 12 05:41:20 2025 +0000 - include openbsd-compat/base64.c license in LICENSE + upstream: Use EC_POINT_[sg]et_affine_coordinates() + + It is available in all supported OpenSSL flavors/versions and the _GFp + variants will be removed from LibreSSL. + + ok hshoexer jsing + + OpenBSD-Commit-ID: ecedca0e1ffa80e0c9ef7c787bc6a972882c596b -commit 7ef362b989c8d1f7596f557f22e5924b9c08f0ea -Author: Damien Miller -Date: Wed Sep 18 09:01:23 2024 +1000 +commit 17003b9f1cd7b7bf1f52493cc4a1ab95727c3ed7 +Author: djm@openbsd.org +Date: Fri May 9 02:42:03 2025 +0000 - conditionally include mman.h in arc4random code + upstream: make the progress-meter code safe against being called + + when not initialised; spotted by tb@ feedback/ok tb@ deraadt@ + + OpenBSD-Commit-ID: a9fda1ee08a24c62e0981ff6d15ca93b63467038 -commit 5fb2b5ad0e748732a27fd8cc16a7ca3c21770806 -Author: Damien Miller -Date: Tue Sep 17 11:53:24 2024 +1000 +commit 2d023e7a95d673e93ccc1978bf8931f7335b2b53 +Author: tedu@openbsd.org +Date: Thu May 8 17:32:53 2025 +0000 - fix bug in recently-added sntrup761 fuzzer + upstream: convert a last quad_t to int64_t. ok deraadt djm - key values need to be static to persist across invocations; - spotted by the Qualys Security Advisory team. + OpenBSD-Commit-ID: 1c9e01ba1a9ccf442a9cdf10f222077f66885f1f -commit 0ca128c9ee894f1b0067abd473bfb33171df67f8 -Author: djm@openbsd.org -Date: Mon Sep 16 05:37:05 2024 +0000 +commit fc8c56ade809f66f7df4b5153a4d92593631c12a +Author: Darren Tucker +Date: Tue May 20 15:01:29 2025 +1000 - upstream: use 64 bit math to avoid signed underflow. upstream code + Set runner pasword to random string. - relies on using -fwrapv to provide defined over/underflow behaviour, but we - use -ftrapv to catch integer errors and abort the program. ok dtucker@ + The most recent version of the Github ubuntu-latest image sets the + password field to "!" which sshd considers to be a locked account, + breaking most of the tests. + +commit c404686c17daeda7e95ca6fc14c8a4a570cf975d +Author: Darren Tucker +Date: Sun May 11 22:54:13 2025 +1000 + + Debug log for why an account is considered locked. + +commit ee1d31781cf0d292a50b4df4cb8cb6ffcbfbe9af +Author: Darren Tucker +Date: Sun May 11 16:35:31 2025 +1000 + + Move debug log output into separate workflow step. - OpenBSD-Commit-ID: 8933369b33c17b5f02479503d0a92d87bc3a574b + Should reduce the need to scroll back to find out which test actually + failed. -commit f82e5e22cad88c81d8a117de74241328c7b101c3 -Author: jmc@openbsd.org -Date: Sun Sep 15 08:27:38 2024 +0000 +commit ddfb78a15f57a33427d462b9c401de5c8e6799da +Author: Darren Tucker +Date: Sat May 10 21:48:06 2025 +1000 - upstream: minor grammar/sort fixes for refuseconnection; ok djm + Skip sftp-perm on Cygwin too. + +commit 8846caccb86b3f5a4f1c10bfffcc9cf1adc17925 +Author: Darren Tucker +Date: Sat May 10 10:23:30 2025 +1000 + + Remove CYGWIN binmode as it's now obsolete. + +commit cf795d55437e6c1ffe85e90e0fae00e885e50036 +Author: Darren Tucker +Date: Sat May 10 09:25:18 2025 +1000 + + Also skip sftp-cmds test on Cygwin. - OpenBSD-Commit-ID: 1c81f37b138b8b66abba811fec836388a0f3e6da + Fails at the hardlink step. -commit 0c1165fc78e8fe69b5df71f81a8f944554a68b53 -Author: Damien Miller -Date: Sun Sep 15 13:30:13 2024 +1000 +commit d1b28639c1cb382943bd92c68992ea74af9b5773 +Author: Darren Tucker +Date: Sat May 10 08:52:11 2025 +1000 - avoid gcc warning in fuzz test + Tell Cygwin to use native symlinks. -commit ce171d0718104b643854b53443ff72f7283d33f2 -Author: djm@openbsd.org -Date: Sun Sep 15 03:09:44 2024 +0000 +commit 56782dad7d7f96b4943951227515bd7904ac3cf7 +Author: Darren Tucker +Date: Sat May 10 08:26:37 2025 +1000 - upstream: bad whitespace in config dump output + Skip keygen-knownhost test on Cygwin. - OpenBSD-Commit-ID: d899c13b0e8061d209298eaf58fe53e3643e967c + It fails but at this time it's not clear why. -commit 671c440786a5a66216922f15d0007b60f1e6733f -Author: Damien Miller -Date: Sun Sep 15 12:53:59 2024 +1000 +commit d5cbac2364b03e55b733a2422a07e78e16d2a118 +Author: Darren Tucker +Date: Sat May 10 07:59:44 2025 +1000 - use construct_utmp to construct btmp records + Pass Cygwin setup location to CI setup. - Simpler and removes some code with the old-style BSD license. + (instead of hard coding it, wrongly). -commit 930cb02b6113df72fbc732b9feb8e4f490952a81 -Author: djm@openbsd.org -Date: Sun Sep 15 02:20:51 2024 +0000 +commit 82f1f52c5582f005761e4e200c279ddd9c6781e4 +Author: Darren Tucker +Date: Sat May 10 06:37:24 2025 +1000 - upstream: update the Streamlined NTRU Prime code from the "ref" + Add RUN_ONLY_TEST to limit which tests are run. - implementation in SUPERCOP 20201130 to the "compact" implementation in - SUPERCOP 20240808. The new version is substantially faster. Thanks to Daniel - J Bernstein for pointing out the new implementation (and of course for - writing it). + For testing, you can set the repo variable RUN_ONLY_TEST in your repo + (Repo -> Settings -> Security -> Actions -> Variables) to run only that test. + +commit 140ba45895de8ebfb3e2517b0ddee58729979c29 +Author: Darren Tucker +Date: Fri May 9 19:32:06 2025 +1000 + + Move misc-agent.o to LIBSSH_OBJS. - tested in snaps/ok deraadt@ + It's needed by the fuzzer. + +commit 3357bf2fe2d11b6ed4465c1ed2871bd1099cbbc5 +Author: Darren Tucker +Date: Fri May 9 19:08:36 2025 +1000 + + Put PRIV_ECDSA back, it's still used. - OpenBSD-Commit-ID: bf1a77924c125ecdbf03e2f3df8ad13bd3dafdcb + Should fix oss-fuzz test. -commit 9306d6017e0ce5dea6824c29ca5ba5673c2923ad -Author: djm@openbsd.org -Date: Sun Sep 15 01:19:56 2024 +0000 +commit f5726215957bb34e18bb872d527845c2f64e2389 +Author: Darren Tucker +Date: Thu May 8 18:56:39 2025 +1000 - upstream: document Match invalid-user + Since it's unused, make dirfd() take void *. - OpenBSD-Commit-ID: 2c84a9b517283e9711e2812c1f268081dcb02081 + Some platforms (eg Old BSDs) in some configurations define DIR to "void + *", which causes compile errors in the no-op implementation. -commit 0118a4da21147a88a56dc8b90bbc2849fefd5c1e -Author: djm@openbsd.org -Date: Sun Sep 15 01:18:26 2024 +0000 +commit 1511f113a27d8aafe080aa6493cb3c0cf2b5abe0 +Author: Darren Tucker +Date: Thu May 8 11:38:24 2025 +1000 - upstream: add a "Match invalid-user" predicate to sshd_config Match + Add no-op implmentation of dirfd(). - options. + Fixes build on pre-POSIX.1 2008 systems. + +commit 086369736a9496b39af0d9f09443fa81b59b7f05 +Author: Daniel Kahn Gillmor +Date: Wed Apr 16 10:18:34 2025 +1000 + + ssh-agent: exit 0 from SIGTERM under systemd socket-activation - This allows writing Match conditions that trigger for invalid username. - E.g. + When the ssh-agent service is configured to be launched under systemd + socket-activation, the user can inspect the status of the agent with + something like: - PerSourcePenalties refuseconnection:90s - Match invalid-user - RefuseConnection yes + systemctl --user status ssh-agent.service - Will effectively penalise bots try to guess passwords for bogus accounts, - at the cost of implicitly revealing which accounts are invalid. + If the user does: - feedback markus@ + systemctl --user stop ssh-agent.service - OpenBSD-Commit-ID: 93d3a46ca04bbd9d84a94d1e1d9d3a21073fbb07 - -commit 7875975136f275619427604900cb0ffd7020e845 -Author: djm@openbsd.org -Date: Sun Sep 15 01:11:26 2024 +0000 - - upstream: Add a "refuseconnection" penalty class to sshd_config + it causes the `systemd --user` supervisor to send a SIGTERM to the + agent, which terminates while leaving the systemd-managed socket in + place. That's good, and as expected. (If the user wants to close the + socket, they can do "systemctl --user stop ssh-agent.socket" instead) - PerSourcePenalties + But because ssh-agent exits with code 2 in response to a SIGTERM, the + supervisor marks the service as "failed", even though the state of the + supervised service is exactly the same as during session startup (not + running, ready to launch when a client connects to the socket). - This allows penalising connection sources that have had connections - dropped by the RefuseConnection option. ok markus@ + This change makes ssh-agent exit cleanly (code 0) in response to a + SIGTERM when launched under socket activation. This aligns the systemd + supervisor's understanding of the state of supervised ssh-agent with + reality. - OpenBSD-Commit-ID: 3c8443c427470bb3eac1880aa075cb4864463cb6 + Signed-off-by: Daniel Kahn Gillmor -commit 8d21713b669b8516ca6d43424a356fccc37212bb -Author: djm@openbsd.org -Date: Sun Sep 15 01:09:40 2024 +0000 +commit 755c3d082e59e6884f28d30e6333a1444e9173d1 +Author: Darren Tucker +Date: Wed May 7 21:05:06 2025 +1000 - upstream: Add a sshd_config "RefuseConnection" option + Skip d_type check on platforms that don't have it. - If set, this will terminate the connection at the first authentication - request (this is the earliest we can evaluate sshd_config Match blocks) + On those, the subsequent stat() should catch the sockets. + +commit 207289a5663bdf49903e1aeb938dcc0924e2ac63 +Author: dtucker@openbsd.org +Date: Wed May 7 10:44:26 2025 +0000 + + upstream: Rename sockaddr_un sun -> sunaddr. - ok markus@ + This makes things easier in -portable, where on Solaris an derivatives + "sun" is defined to "1", causing compilation errors. ok deraadt@. - OpenBSD-Commit-ID: 43cc2533984074c44d0d2f92eb93f661e7a0b09c + OpenBSD-Commit-ID: 0669043afb49856b57b382f0489221bd98305d3b -commit acad117e66018fe1fa5caf41b36e6dfbd61f76a1 +commit 7cc8e150d51a4545b86d996692b541419b35d1a3 Author: djm@openbsd.org -Date: Sun Sep 15 00:58:01 2024 +0000 +Date: Tue May 6 06:05:48 2025 +0000 - upstream: switch sshd_config Match processing to the argv tokeniser - - too; ok markus@ + upstream: remove DSA from the regression/unit test suite too. - OpenBSD-Commit-ID: b74b5b0385f2e0379670e2b869318a65b0bc3923 + OpenBSD-Regress-ID: 4424d2eaf0bce3887318ef6d18de6c06f3617d6e -commit baec3f7f4c60cd5aa1bb9adbeb6dfa4a172502a8 +commit 0404fa799746c283325a463c363436eb152daefc Author: djm@openbsd.org -Date: Sun Sep 15 00:57:36 2024 +0000 +Date: Tue Apr 15 05:31:24 2025 +0000 - upstream: switch "Match" directive processing over to the argv - - string tokeniser, making it possible to use shell-like quoting in Match - directives, particularly "Match exec". ok markus@ + upstream: another missing ifdef - OpenBSD-Commit-ID: 0877309650b76f624b2194c35dbacaf065e769a5 + OpenBSD-Regress-ID: 4f71f8f122eac4cbf7f1d2088a9be45317dd3e4a -commit dd424d7c382c2074ab70f1b8ad4f169a10f60ee7 +commit c5dbbe8805caaee132545ab4cffd3b2221e80975 Author: djm@openbsd.org -Date: Sun Sep 15 00:47:01 2024 +0000 +Date: Tue Apr 15 05:00:13 2025 +0000 - upstream: include pathname in some of the ssh-keygen passphrase - - prompts. Helps the user know what's going on when ssh-keygen is invoked via - other tools. Requested in GHPR503 + upstream: missing ifdef - OpenBSD-Commit-ID: 613b0bb6cf845b7e787d69a5b314057ceda6a8b6 + OpenBSD-Regress-ID: 7260fb672de5738c17dec06c71a5be0186bb2b09 -commit 62bbf8f825cc390ecb0523752ddac1435006f206 +commit 93e904a673a632604525fdc98b940b7996f1ce54 Author: djm@openbsd.org -Date: Sun Sep 15 00:41:18 2024 +0000 +Date: Wed May 7 04:10:21 2025 +0000 - upstream: Do not apply authorized_keys options when signature + upstream: memory leak on error path; bz3821 - verification fails. Prevents restrictive key options being incorrectly - applied to subsequent keys in authorized_keys. bz3733, ok markus@ + OpenBSD-Commit-ID: 65577596a15ad6dd9a1ab3fc24c1c31303ee6e2b + +commit 55b38ff4d7286c8fac2a472da664462e0f2d75e0 +Author: deraadt@openbsd.org +Date: Tue May 6 15:15:05 2025 +0000 + + upstream: test ssh-agent with the -T flag to force the old /tmp - OpenBSD-Commit-ID: ba3776d9da4642443c19dbc015a1333622eb5a4e + location rather than inside the homedir. During relink operation, + /.ssh/agent was created which is surprising. This test sequence could use + some improvement so this is a temporary fix. observed by florian, change ok + semarie + + OpenBSD-Commit-ID: c7246a6b519ac390ca550719f91acfdaef1fa0f0 -commit 49f325fd47af4e53fcd7aafdbcc280e53f5aa5ce -Author: Wu Weixin -Date: Fri Aug 2 22:16:40 2024 +0800 +commit a32d28d792567253bb601362f36391f155f8f772 +Author: djm@openbsd.org +Date: Tue May 6 05:40:56 2025 +0000 - Fix without_openssl always being set to 1 + upstream: finally remove DSA signature support from OpenSSH. - In Fedora systems, %{?rhel} is empty. In RHEL systems, %{?fedora} is - empty. Therefore, the original code always sets without_openssl to 1. + feedback/ok tb@, ok deraadt@ + + OpenBSD-Commit-ID: bfe6ee73c1b676c81a2901030c791f8ec888228f -commit c21c3a2419bbc1c59cb1a16ea356e703e99a90d9 +commit 928f8dcc1bb622c25be409c34374b655d0149373 Author: djm@openbsd.org -Date: Thu Sep 12 00:36:27 2024 +0000 +Date: Mon May 5 05:51:11 2025 +0000 - upstream: Relax absolute path requirement back to what it was prior to + upstream: Now that there's an I-D for certificate keys, refer to - OpenSSH 9.8, which incorrectly required that sshd was started with an - absolute path in inetd mode. bz3717, patch from Colin Wilson + that instead of the much more basic format description we had previously. - OpenBSD-Commit-ID: 25c57f22764897242d942853f8cccc5e991ea058 + OpenBSD-Commit-ID: cf01e0727a813fee8626ad7b3aa240621cc92014 -commit 1bc426f51b0a5cfdcfbd205218f0b6839ffe91e9 -Author: naddy@openbsd.org -Date: Mon Sep 9 14:41:21 2024 +0000 +commit fe883543bece18c975fa53aa02104f0433645d99 +Author: jmc@openbsd.org +Date: Mon May 5 05:47:28 2025 +0000 - upstream: document the mlkem768x25519-sha256 key exchange algorithm + upstream: - add full stop to the text in -a - move the -U and -u - OpenBSD-Commit-ID: fa18dccdd9753dd287e62ecab189b3de45672521 + text to the correct place + + OpenBSD-Commit-ID: 2fb484337a0978c703f61983bb14bc5cbaf898c2 -commit 0a2db61a5ffc64d2e2961c52964f933879952fc7 +commit 5fd6ef297dec23e3574646b6334087131230d0a6 Author: Darren Tucker -Date: Tue Sep 10 21:11:14 2024 +1000 +Date: Tue May 6 19:01:00 2025 +1000 - Spell omnios test host correctly. + Add minimal implementations of fstatat and unlinkat. + + Fixes build on some pre-POSIX.1-2008 platforms. -commit 059ed698a47c9af541a49cf754fd09f984ac5a21 +commit d2480827b3ef6ec119965822afdff35d734b2dee Author: Darren Tucker -Date: Tue Sep 10 18:52:02 2024 +1000 +Date: Tue May 6 08:15:34 2025 +1000 - Add omnios test target. + New location of cygwin setup. -commit f4ff91575a448b19176ceaa8fd6843a25f39d572 +commit 57eb87b15bd0343372f99d661ce95efb25a16f1e Author: Darren Tucker -Date: Tue Sep 10 18:45:55 2024 +1000 +Date: Tue May 6 08:07:23 2025 +1000 - Wrap stdint.h in ifdef. + Boringssl now puts libcrypto in a different place. -commit ff714f001d20a9c843ee1fd9d92a16d40567d264 +commit 61525ba967ac1bb7394ea0792aa6030bcbbad049 Author: Darren Tucker -Date: Mon Sep 9 19:31:54 2024 +1000 +Date: Mon May 5 20:45:42 2025 +1000 - Also test PAM on dfly64. + Handle systems that don't have st_mtim. + + Ignores nanoseconds, but it's checking for >1h old so a few nanoseconds + shouldn't matter much. Fixes build on Mac OS X. -commit 509b757c052ea969b3a41fc36818b44801caf1cf -Author: Damien Miller -Date: Mon Sep 9 21:50:14 2024 +1000 +commit 27861e9b15151898841097c14ee974c026093131 +Author: Darren Tucker +Date: Mon May 5 19:09:25 2025 +1000 - stubs for ML-KEM KEX functions - - used for C89 compilers + Supply timespecsub if needed. -commit 273581210c99ce7275b8efdefbb9f89e1c22e341 -Author: Damien Miller -Date: Mon Sep 9 17:30:38 2024 +1000 +commit 7c0e6626e4be53efcfbb92f0c6382a76f1138e38 +Author: Darren Tucker +Date: Mon May 5 19:08:48 2025 +1000 - declare defeat trying to detect C89 compilers - - I can't find a reliable way to detect the features the ML-KEM code - requires in configure. Give up for now and use VLA support (that we - can detect) as a proxy for "old compiler" and turn off ML-KEM if - it isn't supported. + includes.h for compat, time.h for clock_gettime. -commit e8a0f19b56dfa20f98ea9876d7171ec315fb338a -Author: Damien Miller -Date: Mon Sep 9 16:46:40 2024 +1000 +commit 7a7cc3cf721fe7fe9f4925d92bb7c694b8550a7f +Author: Darren Tucker +Date: Mon May 5 18:51:34 2025 +1000 - fix previous; check for C99 compound literals - - The previous commit was incorrect (or at least insufficient), the - ML-KEM code is actually using compound literals, so test for them. + Cygwin install in back on D: -commit 7c07bec1446978bebe0780ed822c8fedfb377ae8 +commit 6ab8133c067a8e91ba69ce7ca04f95b50f2f2d7b Author: Damien Miller -Date: Mon Sep 9 16:06:21 2024 +1000 +Date: Mon May 5 14:59:30 2025 +1000 - test for compiler feature needed for ML-KEM - - The ML-KEM implementation we uses need the compiler to support - C99-style named struct initialisers (e.g foo = {.bar = 1}). We - still support (barely) building OpenSSH with older compilers, so - add a configure test for this. + depend -commit d469d5f348772058789d35332d1ccb0b109c28ef +commit 12912429cf39cfeca97dd18a8f875ad9824d1751 Author: djm@openbsd.org -Date: Mon Sep 9 03:13:39 2024 +0000 +Date: Mon May 5 03:35:06 2025 +0000 - upstream: test mlkem768x25519-sha256 + upstream: missing file in previous commit - OpenBSD-Regress-ID: 7baf6bc39ae55648db1a2bfdc55a624954847611 + OpenBSD-Commit-ID: e526c97fcb2fd9f0b7b229720972426ab437d7eb -commit 62fb2b51bb7f6863c3ab697f397b2068da1c993f +commit 80162f9d7e7eadca4ffd0bd1c015d38cb1821ab6 Author: djm@openbsd.org -Date: Mon Sep 9 02:39:57 2024 +0000 +Date: Mon May 5 02:48:06 2025 +0000 - upstream: pull post-quantum ML-KEM/x25519 key exchange out from + upstream: Move agent listener sockets from /tmp to under - compile-time flag now than an IANA codepoint has been assigned for the - algorithm. + ~/.ssh/agent for both ssh-agent(1) and forwarded sockets in sshd(8). - Add mlkem768x25519-sha256 in 2nd KexAlgorithms preference slot. + This ensures processes (such as Firefox) that have restricted + filesystem access that includes /tmp (via unveil(3)) do not have the + ability to use keys in an agent. - ok markus@ + Moving the default directory has the consequence that the OS will no + longer clean up stale agent sockets, so ssh-agent now gains this + ability. - OpenBSD-Commit-ID: 9f50a0fae7d7ae8b27fcca11f8dc6f979207451a + To support $HOME on NFS, the socket path includes a truncated hash of + the hostname. ssh-agent will by default only clean up sockets from + the same hostname. + + ssh-agent gains some new flags: -U suppresses the automatic cleanup + of stale sockets when it starts. -u forces a cleanup without + keeping a running agent, -uu forces a cleanup that ignores the + hostname. -T makes ssh-agent put the socket back in /tmp. + + feedback deraadt@ naddy@, doitdoitdoit deraadt@ + + OpenBSD-Commit-ID: 8383dabd98092fe5498d5f7f15c7d314b03a93e1 -commit a8ad7a2952111c6ce32949a775df94286550af6b +commit 566443b5f5d7bc4c5310313b4e46232760850c7a Author: djm@openbsd.org -Date: Fri Sep 6 02:30:44 2024 +0000 +Date: Mon May 5 02:40:30 2025 +0000 - upstream: make parsing user@host consistently look for the last '@' in + upstream: correct log messages; the reap function is used for more - the string rather than the first. This makes it possible to use usernames - that contain '@' characters. - MIME-Version: 1.0 - Content-Type: text/plain; charset=UTF-8 - Content-Transfer-Encoding: 8bit - - Prompted by Max Zettlmeißl; feedback/ok millert@ + than just the preauth process now - OpenBSD-Commit-ID: 0b16eec246cda15469ebdcf3b1e2479810e394c5 + OpenBSD-Commit-ID: 768c5b674bd77802bb197c31dba78559f1174c02 -commit 13cc78d016b67a74a67f1c97c7c348084cd9212c +commit e048230106fb3f5e7cc07abc311c6feb5f52fd05 Author: djm@openbsd.org -Date: Wed Sep 4 05:33:34 2024 +0000 +Date: Wed Apr 30 05:26:15 2025 +0000 - upstream: be more strict in parsing key type names. Only allow + upstream: make writing known_hosts lines more atomic, by writing - shortnames (e.g "rsa") in user-interface code and require full SSH protocol - names (e.g. "ssh-rsa") everywhere else. + the entire line in one operation and using unbuffered stdio. - Prompted by bz3725; ok markus@ + Usually writes to this file are serialised on the "Are you sure you + want to continue connecting?" prompt, but if host key checking is + disabled and connections were being made with high concurrency + then interleaved writes might have been possible. - OpenBSD-Commit-ID: b3d8de9dac37992eab78adbf84fab2fe0d84b187 + feedback/ok deraadt@ millert@ + + OpenBSD-Commit-ID: d11222b49dabe5cfe0937b49cb439ba3d4847b08 -commit ef8472309a68e319018def6f8ea47aeb40d806f5 +commit c991273c18afc490313a9f282383eaf59d9c13b9 Author: djm@openbsd.org -Date: Wed Sep 4 05:11:33 2024 +0000 +Date: Wed Apr 30 05:23:15 2025 +0000 - upstream: fix RCSID in output + upstream: fix a out-of-bounds read if the known_hosts file is - OpenBSD-Commit-ID: 889ae07f2d2193ddc4351711919134664951dd76 + truncated after the hostname. + + Reported by the OpenAI Security Research Team + + ok deraadt@ + + OpenBSD-Commit-ID: c0b516d7c80c4779a403826f73bcd8adbbc54ebd -commit ba2ef20c75c5268d4d1257adfc2ac11c930d31e1 -Author: jmc@openbsd.org -Date: Tue Sep 3 06:17:48 2024 +0000 +commit b5b405fee7f3e79d44e2d2971a4b6b4cc53f112e +Author: Darren Tucker +Date: Sun Apr 20 09:07:57 2025 +1000 - upstream: envrionment -> environment; + Set Windows permssions on regress dir. - OpenBSD-Commit-ID: b719f39c20e8c671ec6135c832d6cc67a595af9c + Prevents "unprotected private key file" error when running tests. -commit e66c0c5673a4304a3a9fbf8305c6a19f8653740f -Author: Damien Miller -Date: Wed Sep 4 15:35:29 2024 +1000 +commit 76631fdd04824c3e50ea6551d3611b1fe0216a41 +Author: Darren Tucker +Date: Fri Apr 18 08:18:52 2025 +1000 - add basic fuzzers for our import of sntrup761 + Add 10.0 branch to test status page. -commit d19dea6330ecd4eb403fef2423bd7e127f4c9828 -Author: djm@openbsd.org -Date: Tue Sep 3 05:58:56 2024 +0000 +commit c627b468d3b99e487e2b24c90958ae57e633d681 +Author: Darren Tucker +Date: Fri Apr 18 08:14:16 2025 +1000 - upstream: regression test for Include variable expansion - - OpenBSD-Regress-ID: 35477da3ba1abd9ca64bc49080c50a9c1350c6ca + cygwin-install-action now puts setup.exe on D: -commit 8c4d6a628051e318bae2f283e8dc38b896400862 -Author: djm@openbsd.org -Date: Tue Sep 3 05:29:55 2024 +0000 +commit 52bddbc1a7f53a1e5c871767913648eb639ac6d5 +Author: Darren Tucker +Date: Fri Apr 18 08:10:32 2025 +1000 - upstream: allow the "Include" directive to expand the same set of - - %-tokens that "Match Exec" and environment variables. + Include time.h for clock_gettime(). + +commit 9b50cb171b5c56184ce6fa3994ce62f9882d2daf +Author: Darren Tucker +Date: Thu Apr 17 16:51:14 2025 +1000 + + Add includes.h for new tests. - ok dtucker@ + Fixes builds on older platforms. + +commit 46e52fdae08b89264a0b23f94391c2bf637def34 +Author: Darren Tucker +Date: Wed Apr 16 22:29:17 2025 +1000 + + Provide INFINITY if it's not provided. - OpenBSD-Commit-ID: 12ef521eaa966a9241e684258564f52f1f3c5d37 + INFINITY is specified in c99, so define if not provided. -commit 51b82648b6827675fc0cde21175fd1ed8e89aab2 -Author: djm@openbsd.org -Date: Mon Sep 2 12:18:35 2024 +0000 +commit 849c2fd894aa87a7e40c71e8d5bda5392b1205be +Author: Darren Tucker +Date: Tue Apr 15 21:58:49 2025 +1000 - upstream: missing ifdef + Look for sqrt(), possibly in libm. - OpenBSD-Commit-ID: 85f09da957dd39fd0abe08fe5ee19393f25c2021 + The unit tests now use sqrt(), which in some platforms (notably + DragonFlyBSD and Solaris) is not in libc but rather libm. Since only + the unit tests use this, add TESTLIBS and if necessary put libm in it. -commit f68312eb593943127b39ba79a4d7fa438c34c153 -Author: djm@openbsd.org -Date: Mon Sep 2 12:13:56 2024 +0000 +commit 1ec5b39f1f673beac039bb42c98a11aa2b08a0b2 +Author: dtucker@openbsd.org +Date: Tue Apr 15 09:22:25 2025 +0000 - upstream: Add experimental support for hybrid post-quantum key exchange + upstream: Cast signalled_keydrop to int when logging to prevent warning - ML-KEM768 with ECDH/X25519 from the Internet-draft: - https://datatracker.ietf.org/doc/html/draft-kampanakis-curdle-ssh-pq-ke-03 + on platforms where sig_atomic_t is not the same as int. bz#3811, patch from + jlduran at gmail com. - This is based on previous patches from markus@ but adapted to use the - final FIPS203 standard ML-KEM using a formally-verified implementation - from libcrux. + OpenBSD-Commit-ID: b6bc9e9006e7f81ade57d41a48623a4323deca6c + +commit f3d465530e75cb6c02e2cde1d15e6c4bb51ebfd9 +Author: djm@openbsd.org +Date: Tue Apr 15 04:00:42 2025 +0000 + + upstream: basic benchmarking support for the unit test framework enable - Note this key exchange method is still a draft and thus subject to - change. It is therefore disabled by default; set MLKEM=yes to build it. - We're making it available now to make it easy for other SSH - implementations to test against it. + with "make UNITTEST_BENCHMARK=yes" - ok markus@ deraadt@ + ok dtucker@ - OpenBSD-Commit-ID: 02a8730a570b63fa8acd9913ec66353735dea42c + OpenBSD-Regress-ID: 7f16a2e247f860897ca46ff87bccbe6002a32564 -commit 05f2b141cfcc60c7cdedf9450d2b9d390c19eaad -Author: Antonio Larrosa -Date: Fri Aug 23 12:21:06 2024 +0200 +commit 609fe2cae2459d721ac11d23cd27b8a94397ef3c +Author: jmc@openbsd.org +Date: Mon Apr 14 05:41:42 2025 +0000 - Don't skip audit before exitting cleanup_exit + upstream: rework the text for -3 to make it clearer what default - This fixes an issue where the SSH_CONNECTION_ABANDON event is not - audited because cleanup_exit overrides the regular _exit too soon and - as a result, failed auth attempts are not logged correctly. + behaviour is, and adjust the text for -R to make them more consistent; - The problem was introduced in 81c1099d22b81ebfd20a334ce986c4f753b0db29 - where the code from upstream was merged before the audit_event call when - it should have been merged right before the _exit call in order to honor - the comment that just mentions an override of the exit value. - -commit 16eaf9d401e70996f89f3f417738a8db421aa959 -Author: djm@openbsd.org -Date: Wed Aug 28 12:08:26 2024 +0000 - - upstream: fix test: -F is the argument to specify a non-default + issue raised by mikhail mp39590; + behaviour explained by naddy - ssh_config, not -f (this is sadly not a new bug) + ok djm - OpenBSD-Regress-ID: 45a7bda4cf33f2cea218507d8b6a55cddbcfb322 + OpenBSD-Commit-ID: 15ff3bd1518d86c84fa8e91d7aa72cfdb41dccc8 -commit 10ccf611ab8ecba9ce6b0548c5ccd8c1220baf92 -Author: deraadt@openbsd.org -Date: Fri Aug 23 04:51:00 2024 +0000 +commit 8725dbc5b5fcc3e326fc71189ef8dba4333362cc +Author: Damien Miller +Date: Wed Apr 9 17:02:17 2025 +1000 - upstream: As defined in the RFC, the SSH protocol has negotiable - - compression support (which is requested as the name "zlib"). Compression - starts very early in the session. Relative early in OpenSSH lifetime, privsep - was added to sshd, and this required a shared-memory hack so the two - processes could see what was going on in the dataflow. This shared-memory - hack was soon recognized as a tremendous complexity risk, because it put libz - (which very much trusts it's memory) in a dangerous place, and a new option - ("zlib@openssh.com") was added begins compression after authentication (aka - delayed-compression). That change also permitted removal of the - shared-memory hack. Despite removal from the server, the old "zlib" support - remained in the client, to allow negotiation with non-OpenSSH daemons which - lack the delayed-compression option. This commit deletes support for the - older "zlib" option in the client. It reduces our featureset in a small way, - and encourages other servers to move to a better design. The SSH protocol is - different enough that compressed-key-material attacks like BEAST are - unlikely, but who wants to take the chance? We encourage other ssh servers - who care about optional compression support to add delayed-zlib support. - (Some already do "zlib@openssh.com") ok djm markus + update version numbers + +commit cc7feb9458ad3b893b53dc9c7500d1affd208bde +Author: djm@openbsd.org +Date: Wed Apr 9 07:00:21 2025 +0000 + + upstream: openssh-10.0 - OpenBSD-Commit-ID: 6df986f38e4ab389f795a6e39e7c6857a763ba72 + OpenBSD-Commit-ID: db5b4a1f1c9e988f8f166b56dc5643606294b403 -commit aee54878255d71bf93aa6e91bbd4eb1825c0d1b9 +commit fc86875e6acb36401dfc1dfb6b628a9d1460f367 Author: djm@openbsd.org -Date: Thu Aug 22 23:11:30 2024 +0000 +Date: Wed Apr 9 07:00:03 2025 +0000 - upstream: sntrup761x25519-sha512 now has an IANA codepoint assigned, so + upstream: Fix logic error in DisableForwarding option. This option - we can make the algorithm available without the @openssh.com suffix too. ok - markus@ deraadt@ + was documented as disabling X11 and agent forwarding but it failed to do so. + Spotted by Tim Rice. - OpenBSD-Commit-ID: eeed8fcde688143a737729d3d56d20ab4353770f + OpenBSD-Commit-ID: fffc89195968f7eedd2fc57f0b1f1ef3193f5ed1 -commit a76a6b85108e3032c8175611ecc5746e7131f876 -Author: Darren Tucker -Date: Thu Aug 22 20:36:12 2024 +1000 +commit dd73459e351b0a2908aed90910c8ff9b0b381c6d +Author: djm@openbsd.org +Date: Wed Apr 9 01:24:40 2025 +0000 - Move rekey test into valgrind-2. + upstream: oops, I accidentally backed out the typo fix - Now that the rekey test has been optimized it's fast enough to not be in - its own valgrind test, so move it into valgrind-2, which is currently - the quickest of the others, bringing all of them to roughly the same - runtime of ~1.1 hours. + OpenBSD-Commit-ID: f485f79bf3e9ebbe1de13ac96150cf458956cfd8 -commit 7e75e3f57c41b9a6e6401e7674d7c2ff5c33975b -Author: dtucker@openbsd.org -Date: Thu Aug 22 10:21:02 2024 +0000 +commit 0cb945891944bada5850e85d60afa3c807cf1af6 +Author: djm@openbsd.org +Date: Wed Apr 9 01:23:47 2025 +0000 - upstream: Use aes128-ctr for MAC tests since default has implicit MAC. - - Also verify that the Cipher or MAC we intended to use is actually the one - selected during the test. + upstream: typo - OpenBSD-Regress-ID: ff43fed30552afe23d1364526fe8cf88cbfafe1d + OpenBSD-Commit-ID: f912725c7d303720706b3ccfb2cb846d46296d13 -commit ebc890b8b4ba08c84cd1066b7b94b2b11f6c4cb4 +commit cd4a6bd50b658d707867caa1f5aa40b35c2b6c19 Author: Damien Miller -Date: Thu Aug 22 09:45:49 2024 +1000 +Date: Wed Apr 9 09:49:55 2025 +1000 - fix incorrect default for PasswordAuthentication - - merge botch spotted by gsgleason + initialise websafe_allowlist in agent fuzzer -commit 15ace435ea1c2fab2a1cc7d9c3157fe20c776b80 -Author: dtucker@openbsd.org -Date: Wed Aug 21 10:33:27 2024 +0000 +commit 55b7cb48af96c1102ef8ab5a73bb329cbed30945 +Author: djm@openbsd.org +Date: Tue Apr 8 23:10:46 2025 +0000 - upstream: Some awks won't match on the \r so delete it instead. Fixes - - regress in portable on, eg Solaris. + upstream: typo - OpenBSD-Regress-ID: 44a96d6d2f8341d89b7d5fff777502b92ac9e9ba + OpenBSD-Regress-ID: 08477b936d1d0c1e8a98aa1c0e1bdde8871894c9 -commit 51c96b6ed627779a04493a8fe25747996a37f3c2 -Author: dtucker@openbsd.org -Date: Wed Aug 21 07:06:27 2024 +0000 +commit 985d8cbcd3438cc36b4e709476f1783e358ddfb1 +Author: djm@openbsd.org +Date: Tue Apr 8 23:10:08 2025 +0000 - upstream: Import regenerated moduli. + upstream: typo - OpenBSD-Commit-ID: 5db7049ad5558dee5b2079d3422e8ddab187c1cc + OpenBSD-Commit-ID: 6e683e13e72bf1e43bbd3bbc6a8332d5a98bdc99 -commit 25c52f37a82c4da48ec537de37d7c168982b8d6d +commit 000c3d14e94d8f7597087c457260ea9417045b65 Author: dtucker@openbsd.org -Date: Wed Aug 21 06:59:08 2024 +0000 +Date: Mon Apr 7 08:12:22 2025 +0000 - upstream: Use curve25519-sha256 kex where possible. + upstream: Include time.h for time(). - Except where we're explicitly testing a different kex, use - curve25519-sha256 since it's faster than the default and supported even - when configured without OpenSSL. Add a check to ensure that the kex we - intended to test is the one we actually tested. Speeds test up by ~5%. + Fixes warning on some platforms when building without openssl. - OpenBSD-Regress-ID: 3b27fcc2ae953cb08fd82a0d3155c498b226d6e0 + OpenBSD-Commit-ID: 04ca29b8eaae1860c7adde3e770baa1866e30a54 -commit 3eb62b7ba49483c309b483eb9002a679014f3887 -Author: dtucker@openbsd.org -Date: Tue Aug 20 12:36:59 2024 +0000 +commit 49b8b9bf829e08af22366530614a5e59ac341ca9 +Author: tb@openbsd.org +Date: Wed Apr 2 04:28:03 2025 +0000 - upstream: Send only as much data as needed to trigger rekeying. Speeds + upstream: Wrap #include in #ifdef WITH_DSA - up tests by about 10% in the common case, hopefully more when instrumented - with something like valgrind. + ok djm - OpenBSD-Regress-ID: 7bf9292b4803357efcf0baf7cfbdc8521f212da1 + OpenBSD-Commit-ID: ed01a7c102243f84e4a317aefb431916d98aab15 -commit cbd3f034bbf7853618fac99d7d868a2250154ea7 +commit f80fb819e5521e13f167edbcc3eed66e22ad0c2a Author: Damien Miller -Date: Wed Aug 21 09:18:29 2024 +1000 +Date: Thu Apr 3 09:10:19 2025 +1100 - simplify sshkey_prekey_alloc(); always use mmap + remove all instances of -pie from LDFLAGS + + Previously only the first instance of this flag was removed. + Unbreaks build on OpenSUSE Tumbleweed. Patch from Antonio Larrosa -commit 4442bbc2fc661277a6dabfedb756a7e15ee8b8b8 -Author: dtucker@openbsd.org -Date: Tue Aug 20 09:15:49 2024 +0000 +commit 6c9872faa1c297a84c6d3e3b95a927be99eadbf6 +Author: djm@openbsd.org +Date: Tue Apr 1 23:23:20 2025 +0000 - upstream: Merge AEAD test into main test loop. + upstream: remove ability to enable DSA support. Actual code will be - Removes 3 duplicate tests and speeds overall test up by about 1%. + g/c'd separately. ok deraadt@ - OpenBSD-Regress-ID: 5e5c9ff3f7588091ed369e34ac28520490ad2619 + OpenBSD-Commit-ID: 2a032b75156c4d922e8343fa97ff6bc227f09819 -commit 829976a63fd1efae3a4c3e7c16fded59d92edb67 +commit 8460aaa4e1f8680f03cc5334556b9440b401f010 Author: dtucker@openbsd.org -Date: Tue Aug 20 09:02:45 2024 +0000 +Date: Fri Mar 28 21:45:55 2025 +0000 - upstream: Set a default RekeyLimit of 256k. - - Used unless overridden by a command-line flag, which simplifies some of - the ssh command lines. + upstream: Add TEST_SSH_SSHD_ENV to sshd lines here too. - OpenBSD-Regress-ID: e7cffa57027088e10336e412b34113969f88cb87 + OpenBSD-Regress-ID: 045f2c88b42d694b404db51c5de5eca20d748ff1 -commit 57d02c9ea36aebad4e7146d46e041b6b2e582f7f +commit 5e60f5937b9c33190b9d7614f72d85d4a9b38d3d Author: dtucker@openbsd.org -Date: Tue Aug 20 07:52:43 2024 +0000 +Date: Fri Mar 28 06:04:07 2025 +0000 - upstream: Add Compression=no to default ssh_config. + upstream: Pass "ControlMaster no" to ssh when invoked by scp & sftp. - All of the rekey tests use it (otherwise the encrypted byte counts would - not match) so this lets us simplify the command lines. + If you have ControlMaster auto (or yes) in your config, and the + first connection you make is via scp or sftp, then you may get a + few unexpected options applied to it (eg ForwardX11 no), since sftp + and sftp explicitly disable those for reasons. These effects will + persist beyond the initial scp or sftp command. - OpenBSD-Regress-ID: dab7ce10f4cf6c68827eb8658141272aab3ea262 + This explicitly disables persistent session *creation* by scp and sftp. + It will not prevent them from using an existing session if one has + already been created. + + From Github PR#557, ok djm@ kn@ + + OpenBSD-Commit-ID: 9dad7c737466837e0150c4318920f46d844770c4 -commit 7254eb26f7c0772c4b47c3b32f6d1b15855cdd8c +commit bbd36869dfb4b770cc9e6a345c04a585a0955aec Author: dtucker@openbsd.org -Date: Tue Aug 20 07:41:35 2024 +0000 +Date: Fri Mar 28 05:41:15 2025 +0000 + + upstream: Set sshd environment variables during sshd test run too. + + OpenBSD-Regress-ID: 50cb325d92c390a2909662c901f6ac5d80b6f74d + +commit 98f05b1484daddef2f56b79e24540523b5016143 +Author: dtucker@openbsd.org +Date: Fri Mar 28 05:36:24 2025 +0000 + + upstream: Add TEST_SSH_SSHD_ENV variable which is added to sshd's + + environment. Will be used in Portable to tweak behaviour of tcmalloc's + debugging. + + OpenBSD-Regress-ID: 67e38c3c4517ddb72c8a3549a3325a166d7bb6d6 + +commit 8cd9ed4df0eccc825eca0c45354a37332e125e38 +Author: dtucker@openbsd.org +Date: Fri Mar 28 05:33:30 2025 +0000 + + upstream: chown log directory in addition to log files. + + OpenBSD-Regress-ID: b520d54a0bbf2c6554413c798218bda26b385ad9 + +commit e32de6bf4f3229d4838beb127de45eed1377ccc5 +Author: Darren Tucker +Date: Fri Mar 28 16:47:58 2025 +1100 + + Be explicit about environment variables for tests. + + This will make it easier to reproduce a test failure by cut-and-paste of + the corresponding line from the github log. + +commit 77a3e6ba47381547b3fe4b29223256f276fbd07e +Author: Darren Tucker +Date: Fri Mar 28 16:46:40 2025 +1100 + + Add tcmalloc flags to TEST_SSH_SSHD_ENV. + + This will get passed to sshd via test-exec.sh. + +commit a73890e340fbd6121251854b658a72d738b86c84 +Author: Darren Tucker +Date: Thu Mar 27 23:04:44 2025 +1100 + + Add PuTTY 0.81, 0.82 and 0.83 to tests. + +commit 90a28de0d49570324d1695c0b4686354ef3bcae0 +Author: Darren Tucker +Date: Thu Mar 27 22:30:40 2025 +1100 + + Include TCMALLOC_STACKTRACE_METHOD in output. + + If TCMALLOC_STACKTRACE_METHOD happens to be set, include it in the debug + output to make reproducing test cases easier. + +commit fd5a6bb6dd7657c4bd8cd0ee11d5c8ddf0d927b2 +Author: Darren Tucker +Date: Thu Mar 27 20:15:11 2025 +1100 + + Test with-linux-memlock-onfault in kitchensink. + +commit 22330711e2459c23d9736ee16e0e2ee0fcc30b9a +Author: Collin Funk +Date: Wed Mar 26 18:24:59 2025 -0700 + + Include fcntl.h so AT_FDCWD does not get redefined. + +commit 6c49e5f7dcaf886b4a702a6c003cae9dca04d3ea +Author: Daniil Tatianin +Date: Thu Feb 27 11:37:13 2025 +0300 + + Add support for locking memory on Linux + + Linux wakes up kcompactd threads in order to make more contiguous memory + available on the system, it does this by migrating live movable pages + (actively modifying live processes' page tables and constantly flooding + them with page invalidation IPIs, which can be up to millions per + second), which causes the process to become unresponsive for up to + seconds or even minutes in some severe cases. In case of sshd, we want + to always be able to connect to the system, even if it's under heavy + kcompactd load. + + Introduce an option to protect sshd and its children sessions from being + compacted by kcompactd (this works in cojunction with + compact_unevictable_allowed = 0). Note that we depend on MCL_ONFAULT + being available, which was introduced in linux 4.4. MCL_ONFAULT allows + the system to lock pages lazily, thus drastically reducing memory usage + of a locked process (without MCL_ONFAULT, every existing mapping in the + process is instantly write-faulted). + +commit fdc4853c5b1567934d43ab13282f03033cc21325 +Author: Daniil Tatianin +Date: Thu Feb 27 11:46:25 2025 +0300 + + platform: introduce a way to hook new session start + + Previously this was possible via post_fork_child, but ever since sshd + was split into multiple binaries, this is now no longer possible becase + of execv. + +commit 1b311b6b17be81577514c38e8be4f5740d7df496 +Author: dtucker@openbsd.org +Date: Wed Mar 19 06:11:15 2025 +0000 + + upstream: Prevent theoretical NULL deref in throughlocal_sftp. + + Coverity CID 405019, although at the moment it's not reachable. ok djm@ + + OpenBSD-Commit-ID: 630d46c1021b69fbb470e349976c70e9a48b7644 + +commit 96493ebd6ff48bbb802576e208794a26928569b0 +Author: Darren Tucker +Date: Wed Mar 19 17:35:10 2025 +1100 + + Fix workflow syntax again. + +commit 575c43fd4c44d376b1771c0fdaf4941021ba88c9 +Author: Darren Tucker +Date: Tue Mar 18 20:54:48 2025 +1100 + + Differentiate logfiles better. + +commit 8a1294638f3a47d46263ea574fa85c8e115ea893 +Author: Darren Tucker +Date: Tue Mar 18 20:27:46 2025 +1100 + + Fix another typo in workflow. + +commit bd9e6bbcc864b3e10c4e11f5aec1b3a5e3a89b55 +Author: Darren Tucker +Date: Tue Mar 18 18:16:12 2025 +1100 + + Fix syntax error in workflow. + +commit ce88a1bb4a2e6425752094f7a2eb4adfb0ca7971 +Author: Darren Tucker +Date: Tue Mar 18 18:13:14 2025 +1100 + + Identify each logfile while printing them. + +commit b58e429960c4791fc4e30bb7c70d1f77d538b546 +Author: djm@openbsd.org +Date: Tue Mar 18 04:53:14 2025 +0000 + + upstream: fix NULL dereference for Match conditions missing + + arguments, e.g. "Match user". Spotted by Coverity (CID 477813) + + OpenBSD-Commit-ID: 13584281cfa23b8ebc41f9d128a6b9464ae960d4 + +commit 0ce5281f017c3ad7bdcc2bbd9745119a73e0cbb8 +Author: tb@openbsd.org +Date: Fri Mar 14 09:49:49 2025 +0000 + + upstream: Fix EVP_CIPHER_CTX_ctrl() return checks + + While this API tries to translate negative return values (i.e. -1) to 0 + in BoringSSL and LibreSSL, it is still possible for it to return negative + values in prinicple. We even incorrectly document that -1 can be returned + while Boring and OpenSSL plead the Fifth. + + In OpenSSL 3 there are now code paths that explicitly return -1 and they + started shifting their return checks to <= 0 - of course they do this in + inconsistent and sometimes incorrect manner. While these paths aren't + reachable from ssh right now, who can really tell what happens in the two + hundred lines of inscrutable bloated mess this has become. + + So error check with <= 0 to ensure that we don't accidentally translate an + error to success. + + ok markus schwarze + + OpenBSD-Commit-ID: a855c833cf4ecfce43bedc761f26ad924f70483c + +commit 2e81100763d5885e500f065b04c16ed87ce74318 +Author: Darren Tucker +Date: Mon Mar 17 21:35:55 2025 +1100 + + Fix debug log path. + +commit 442a44970179d70ebb62bba792699eaec978a1db +Author: Darren Tucker +Date: Fri Mar 14 16:24:06 2025 +1100 + + Also lazily unmount workspace in case of straggers. + +commit 20427f6735fe5ddab31911ce5315adc71acf47d8 +Author: Darren Tucker +Date: Fri Mar 14 16:17:39 2025 +1100 + + Make sure upstream tests run on correct hardware. + +commit 91a2f70a56827ae31649baf17227b0914ac5aa36 +Author: Darren Tucker +Date: Fri Mar 14 13:47:27 2025 +1100 + + Add OpenBSD upstream test on obsdsnap-arm64. + +commit c20f7413525602b0ea786d8974d03a81f7ca2a92 +Author: Damien Miller +Date: Thu Mar 13 10:45:53 2025 +1100 + + rebuild .depend + +commit d47ef958b89c6fa809302d654009d3dfabe11b75 +Author: djm@openbsd.org +Date: Wed Mar 12 22:43:44 2025 +0000 + + upstream: remove assumption that the sshd_config and any configs + + included from it can fit in a (possibly enlarged) socket buffer, by having + the sshd listener mainloop actively manage sending the configuration to the + sshd-session subprocess. + + work by markus@ w/ a little feedback from me; + ok me and committing on his behalf + + OpenBSD-Commit-ID: 8f54451483f64951853074adb76bc4f838eaf3ae + +commit 9c90b563943c16418d737433ac478974b8761ee5 +Author: dtucker@openbsd.org +Date: Tue Mar 11 11:46:44 2025 +0000 + + upstream: Prime caches for DNS names needed for tests. + + When running the SSHFP tests, particularly on an ephemeral VM, the first + query or two can fail for some reason, presumably because something isn't + fully initialized or something. To work around this, issue queries for the + names we'll need before we need them. + + OpenBSD-Regress-ID: 900841133540e7dead253407db5a874a6ed09eca + +commit 10124eefe875a3e4e1cfb84ebe6a613ed3213b78 +Author: dtucker@openbsd.org +Date: Tue Mar 11 09:06:50 2025 +0000 + + upstream: Some dd's don't understand "1m", so handle seperately. + + OpenBSD-Regress-ID: 1d983b27c96f28f69d3a288c19e8d8c58e1b2ee3 + +commit c21c8fc319376c2f5e0da166e9e89a97a245ae72 +Author: Darren Tucker +Date: Tue Mar 11 19:17:46 2025 +1100 + + Lazily unmount github workspace at end of workflow. + + Sometimes when a test times out the workspace is still busy when we try + to unmount it, which leaves the runner unusable until it's cleaned up + manually. We try to unmount this in the first step, but that usually + doesn't work since it fails during setup before it starts our workflow. + Move it to the end and make it a lazy unmount so it hopefully works + eventually. + +commit 4bcbac742968f5086cfd4c570a51de25ef77931f +Author: dtucker@openbsd.org +Date: Tue Mar 11 07:50:20 2025 +0000 + + upstream: Add regress test for sftp resume. + + OpenBSD-Regress-ID: 37f629b3014338fa23a85df1e1bb320ea12282e1 + +commit e2c4f070b43a4fd7d59a9350e2fe78df605830b5 +Author: dtucker@openbsd.org +Date: Tue Mar 11 07:46:02 2025 +0000 + + upstream: Use ssh binary instead of the (smaller) script when + + preparing test data files since it's faster. + + OpenBSD-Regress-ID: 4215e42682fdb73e131e10645d4a1a23a91d64f5 + +commit 62f02e95ba5cda4649c482d30f4370e2360eb94d +Author: dtucker@openbsd.org +Date: Tue Mar 11 07:43:45 2025 +0000 + + upstream: Set up dbclient's known_hosts as it expects. + + OpenBSD-Regress-ID: 9e0898e8423237ce5023be53787bb4062e0d0418 + +commit 395284bd52887dbaf7e78200c857d7f2d9ce398e +Author: dtucker@openbsd.org +Date: Tue Mar 11 07:43:03 2025 +0000 + + upstream: Use $DBCLIENT to access dbclient for consistency. + + OpenBSD-Regress-ID: 81e1b41e1ffc49aba1e6fcaeb6242f3b7875ea3c + +commit 97e10c0005a784622c61cb4e8bb7858b410bbcc6 +Author: dtucker@openbsd.org +Date: Tue Mar 11 07:42:08 2025 +0000 + + upstream: Check if dbclient supports SHA1 before trying SHA1-based + + KEX. + + Dropbear 2025.87 removed SHA1 support by default, which means + diffie-hellman-group14-sha1 is not available. Unfortunately there isn't a + flag to query supported KEX, so instead check MACs and if it doesn't have + SHA1 methods, assuming SHA1 based KEXes are likewise not available. Spotted + by anton@. + + OpenBSD-Regress-ID: acfa8e26c001cb18b9fb81a27271c3b51288d304 + +commit 29a5127f808d00aa539fd27d83a65c2c56179b0e +Author: dtucker@openbsd.org +Date: Tue Mar 11 07:48:51 2025 +0000 + + upstream: Set highwater when resuming a "put". Prevents bogus "server + + reordered acks" debug message. ok djm@ + + OpenBSD-Commit-ID: aa7f6d0fc2e893c8c278ea3e6e0974c2eca83f5d + +commit 6575859d7acb110acf408707f98ed9744ca7d692 +Author: dtucker@openbsd.org +Date: Mon Mar 3 06:54:37 2025 +0000 + + upstream: Test for %-token and env var expansion in SetEnv. + + OpenBSD-Regress-ID: bd6139a6177ac4afb29a0ce4afc23567b22ef9f9 + +commit fd7ad8d7bf7dbdeb8f11a8b51aa9d31df1a17e52 +Author: dtucker@openbsd.org +Date: Sun Mar 2 07:41:06 2025 +0000 + + upstream: Also test User expansions when supplied via -l option and + + user@host. + + OpenBSD-Regress-ID: 56415859260b53ef0dd20f71225ba5fdf6320f50 + +commit e6cfd783f1491b502db9322aa970822c63f1667d +Author: dtucker@openbsd.org +Date: Sat Mar 1 06:12:47 2025 +0000 + + upstream: Tests for User expansion of %-tokens and environment + + variables. + + OpenBSD-Regress-ID: 7ed21dd0e09fb1f3537b8b177f171018aa501628 + +commit 197e503b8e4b642ce0f405a5d65da4256fa96431 +Author: djm@openbsd.org +Date: Fri Dec 6 16:25:58 2024 +0000 + + upstream: use glob(3) wildcards in AuthorizedKeys/PrincipalsFile + + tests to exercise this feature; ok dtucker + + OpenBSD-Regress-ID: 7f7b19c0b05b1862cc6521ce61b2b301a3f9cc3b + +commit 396202180180a4ac16788d469508a348789dafa1 +Author: djm@openbsd.org +Date: Fri Dec 6 10:37:42 2024 +0000 + + upstream: implement attestation verification for ED25519 keys + + OpenBSD-Regress-ID: c44fa5cdb434375a8b5545fdb4fc651061afca1f + +commit b49875428cda9c16c5bd52552100da2b419cda5f +Author: dtucker@openbsd.org +Date: Mon Mar 3 06:53:09 2025 +0000 + + upstream: Add %-token and environment variable expansion to SetEnv. + + feedback deraadt@ jmc@, nits and ok djm@ + + OpenBSD-Commit-ID: 2f6e5070481cb73e6f35fd1c6608c1eeff88a5c1 + +commit b6bba67e6c31d268480773e4fed16d0a32b4218e +Author: djm@openbsd.org +Date: Sun Mar 2 22:44:00 2025 +0000 + + upstream: fix PerSourcePenalty incorrectly using "crash" penalty when + + LoginGraceTime was exceeded. Reported by irwin AT princeton.edu via bz3797 + + OpenBSD-Commit-ID: 1ba3e490a5a9451359618c550d995380af454d25 + +commit 38d69fee1b06948f160d94abd07b6b297630d30a +Author: Damien Miller +Date: Sun Mar 2 22:06:53 2025 +1100 + + include __builtin_popcount replacement function + + Some systems/compilers lack __builtin_popcount(), so replace it as + necessary. Reported by Dennis Clarke; ok dtucker@ + +commit c94138d02a45dda5015f38f5a60b0bdde29019c1 +Author: djm@openbsd.org +Date: Sun Mar 2 11:03:13 2025 +0000 + + upstream: whitespace + + OpenBSD-Commit-ID: 1bd8953a37451ef7e0991f9fceec5e8005fe986a + +commit 65d2c59628e68e166046efa69e76c1d395a8df6e +Author: dtucker@openbsd.org +Date: Sun Mar 2 07:02:49 2025 +0000 + + upstream: Make a copy of the user when handling ssh -l, so that + + later during User token expansion we don't end up freeing a member of argv. + Spotted by anton@'s regress tests. + + OpenBSD-Commit-ID: 2f671a4f5726b66d123b88b1fdd1a90581339955 + +commit bd30cf784d6e825ef71592fb723c41d4f2fd407b +Author: dtucker@openbsd.org +Date: Sat Mar 1 06:11:26 2025 +0000 + + upstream: Allow %-token and environment variable expansion in User, + + with the exception of %r and %C which are self-referential. Requested in + bz#3477, ok djm@, man page improvements jmc@ + + OpenBSD-Commit-ID: caeb46251ee073662f6f5864c6f7b92d8ac80fa8 + +commit 94f59dcfc57f95ae044f75c3ce544329c8956c35 +Author: Darren Tucker +Date: Sat Mar 1 10:28:59 2025 +1100 + + Rebuild config files if Makefile changes. + + This ensures paths are updated if they are changed by re-running configure. + Patch from rapier at psc.edu. + +commit dfd9880585db1570656022f9fe1519df673f7b8a +Author: Darren Tucker +Date: Wed Feb 26 18:16:03 2025 +1100 + + Check for le32toh, le64toh, htole64 individually. + + It appears that at least some versions of endian.h in glibc do not have + the latter two, so check for and replace each one individually. + bz#3794, ok djm@ + +commit cb99e8eb228df366af33f4fe88d7a9dd0dbf0756 +Author: djm@openbsd.org +Date: Tue Feb 25 06:25:30 2025 +0000 + + upstream: ressurect fix for "match invalid-user" that got clobbered + + by 1.423 + + OpenBSD-Commit-ID: d18bf0945976e0f3467d710d4bc8bdbe181c0567 + +commit 487cf4c18c123b66c1f3f733398cd37e6b2ab6ab +Author: deraadt@openbsd.org +Date: Fri Feb 21 18:22:41 2025 +0000 + + upstream: Also prohibit , (comma) in hostnames, proposed by David + + Leadbeater ok djm millert + + OpenBSD-Commit-ID: 2837fa31dc6e81976f510f0a259edaa559b20b07 + +commit 3bc6de98c830bd5207f6c371ba69c5874f06305b +Author: Damien Miller +Date: Mon Feb 24 17:27:50 2025 +1100 + + Try to fix github tcmalloc target failure + + tcmalloc may, depending on the stacktrace generator it uses, create + pipe(2) fds during shared library initialisation. These will later + get clobbered by ssh/sshd calling closefrom() and chaos will ensue. + Tell tcmalloc to use an unwinder that doesn't pull this stuff. + +commit 922e54bbfe8c8479453693ef52350338f0c19124 +Author: Damien Miller +Date: Fri Feb 21 13:44:35 2025 +1100 + + cleanup last mention of ubuntu-20.04 + +commit bc4b3f6dc1738d389e5c9dcca8c56d7e153fee49 +Author: Damien Miller +Date: Fri Feb 21 13:44:13 2025 +1100 + + prune gcc/clang versions to be tested + + Test only the oldest and latest versions of each + +commit 94b73755f931d592a612ef5cb998694643eab5ff +Author: Damien Miller +Date: Fri Feb 21 11:30:22 2025 +1100 + + Update AWS-LC version number + + Patch from Shubham Mittal bz bz3792 + +commit 6887099fae6d9f3482e1075d034e9343dc413200 +Author: Damien Miller +Date: Fri Feb 21 11:22:34 2025 +1100 + + adjust workflows for ubuntu version transition + + remove workflows for unsupported compilers, add a few for additional + supported compilers, move some workflows to run on ubuntu-latest + +commit 33bb47e6f74f2ca8093946e6f462d655a9ae46d3 +Author: Damien Miller +Date: Thu Feb 20 17:10:32 2025 +1100 + + Add ubuntu-*-arm test runners + +commit a0c95fbb215b2168fa51b15906e2d6990d7fef6b +Author: Damien Miller +Date: Thu Feb 20 17:03:28 2025 +1100 + + remove ubuntu-20.04 Github action runners + + ubuntu-20.04 is deprecated now, so migrate all its unique runners + to ubuntu-22.04. + + ok dtucker@ + +commit 0cbeedba81b57c56379e1d202b9ccd3b72af7ddc +Author: Damien Miller +Date: Tue Feb 18 19:03:42 2025 +1100 + + openssh-9.9p2 + +commit 0832aac79517611dd4de93ad0a83577994d9c907 +Author: djm@openbsd.org +Date: Tue Feb 18 08:02:48 2025 +0000 + + upstream: Fix cases where error codes were not correctly set + + Reported by the Qualys Security Advisory team. ok markus@ + + OpenBSD-Commit-ID: 7bcd4ffe0fa1e27ff98d451fb9c22f5fae6e610d + +commit 6ce00f0c2ecbb9f75023dbe627ee6460bcec78c2 +Author: djm@openbsd.org +Date: Tue Feb 18 08:02:12 2025 +0000 + + upstream: Don't reply to PING in preauth phase or during KEX + + Reported by the Qualys Security Advisory team. ok markus@ + + OpenBSD-Commit-ID: c656ac4abd1504389d1733d85152044b15830217 + +commit 9e5bd74a85192c00a842f63d7ab788713b4284c3 +Author: jmc@openbsd.org +Date: Sat Feb 15 06:48:56 2025 +0000 + + upstream: - use \& when contructs like "e.g." end a line, to avoid + + double spacing - macro is Qq not Oq + + OpenBSD-Commit-ID: 17e5d2d7f288cc7fc536e3af252224525f9fb43a + +commit f519e71fb7a46314ae16e2a75490649dc0bd01a2 +Author: Damien Miller +Date: Sat Feb 15 13:12:40 2025 +1100 + + depend + +commit 9131ac64b0ebe66dc1de9d44bf8d1bd64a24c350 +Author: djm@openbsd.org +Date: Sat Feb 15 01:52:07 2025 +0000 + + upstream: add "Match version" support to ssh_config. Allows + + matching on the local version of OpenSSH, e.g. "Match version OpenSSH_10.*" + + ok markus@ + + OpenBSD-Commit-ID: c0cb504d0b9e43ccf12e68a544a7cd625e89758d + +commit 192a20df00c8a56fe7d92ffa23d959c865d7fb9e +Author: djm@openbsd.org +Date: Sat Feb 15 01:50:47 2025 +0000 + + upstream: Add support for "Match sessiontype" to ssh_config. Allows + + matching on the type of session requested, either "shell" for interactive + sessions, "exec" for command execution sessions, "subsystem" for subsystem + requests, such as sftp, or "none" for transport/forwarding-only sessions. + + ok markus@ + + OpenBSD-Commit-ID: eff5c001aecb2283d36639cfb28c0935a8bfd468 + +commit caa3c0c77082888236b0b0c4feb3e6879731b3ba +Author: djm@openbsd.org +Date: Sat Feb 15 01:48:30 2025 +0000 + + upstream: "Match command ..." support for ssh_config to allow + + matching on the remote command specified on the commandline. + + Also relaxes matching rules for `Match tagged` to allow + `Match tagged ""` to match an empty tag value. This also works + for command. + + ok markus@ + + OpenBSD-Commit-ID: 00dcfea425bf58d824bf5e3464cfc2409121b60d + +commit 38f6000e9851a00e2e4b8e1eb4ea6a243ef7e6a3 +Author: Damien Miller +Date: Tue Feb 11 10:32:26 2025 +1100 + + depend + +commit aa1409e7a0a5605f0127651a3ba5a348666325bc +Author: djm@openbsd.org +Date: Mon Feb 10 23:19:26 2025 +0000 + + upstream: include arguments the command was invoked with, and + + operating system name, version and architecture in startup debugging output; + ok dtucker + + OpenBSD-Commit-ID: 2a509d319aaf31a6bf9998e1842832883fbc3edd + +commit 857ac20f5fe19f183defba5dbf4b7d9e6400230c +Author: djm@openbsd.org +Date: Mon Feb 10 23:16:51 2025 +0000 + + upstream: include line number in Match debug messages, makes it a + + little easier to see what's going on + + OpenBSD-Commit-ID: 1fcf4aa2ee667711b9497ded0fa52d757c69b1df + +commit af49d474e481d2d78b2f06b06a06b0b37629358e +Author: djm@openbsd.org +Date: Mon Feb 10 23:00:29 2025 +0000 + + upstream: fix "Match invalid-user" from incorrectly being activated + + in initial configuration pass when no other predicates were present on the + match line + + OpenBSD-Commit-ID: 02703b4bd207fafd03788bc4e7774bf80be6c9a8 + +commit 1c67bae3f5834e48ded71c406f2039dea6e536db +Author: schwarze@openbsd.org +Date: Sun Feb 9 18:24:08 2025 +0000 + + upstream: In a section 1 manual, use the plain English words + + "standard output" rather than the overly technical abbreviation "stdout" - we + are not talking about a device file or a FILE * object here. Issue reported + by on the groff mailing list. + + OpenBSD-Commit-ID: a0816999f970e6159523bed8484f62c42ec93109 + +commit 85b3d68dd931416ede657f371f1d60cdc3a66f34 +Author: dtucker@openbsd.org +Date: Fri Jan 17 00:09:41 2025 +0000 + + upstream: Fix debug logging of user specific delay. Patch from + + Achim Leitner (fjl5) via github PR#552. + + OpenBSD-Commit-ID: 834a869ed9b15058d3c1ef0cd75402ef989255d8 + +commit e4e5b06fdf4532705669c0ae944b364022d16b9d +Author: dtucker@openbsd.org +Date: Thu Jan 16 06:37:10 2025 +0000 + + upstream: Call log_init in sshd-auth and sshd-session immediately + + after parsing the config file so that any log settings set in the config file + take effect immediately. Move version banners to immediately after that, and + make them distinct per binary. ok djm@ + + OpenBSD-Commit-ID: acf3d090638edf9b6e6f78eed96b537fe671f0f5 + +commit 0643994b20f2cc54bca80842a984b3052ff1a6a9 +Author: dtucker@openbsd.org +Date: Wed Jan 15 22:23:13 2025 +0000 + + upstream: Use strprefix helper when processing sshd -C test args + + instead of counting bytes by hand. ok djm@ + + OpenBSD-Commit-ID: 2866d369d96fe04bf76112260ac37e489f98a9a9 + +commit 66efd0fbb6b8b95f8a520f2cdf8ede14e62b30b3 +Author: Damien Miller +Date: Thu Feb 6 09:38:09 2025 +1100 + + add support for AWS-LC (AWS libcrypto) + + Patch from Shubham Mittal via bz3784; ok dtucker + +commit 826483d51a9fee60703298bbf839d9ce37943474 +Author: Tim Rice +Date: Mon Dec 16 15:36:54 2024 -0800 + + fix old typo (s/SYSVINITSTOPT/SYSVINITSTOP/) + +commit 1a8ce460f1d0c3f7304edba0733783b57b430e21 +Author: dtucker@openbsd.org +Date: Thu Dec 12 09:09:09 2024 +0000 + + upstream: Plug leak on error path, spotted by Coverity. ok djm@ + + OpenBSD-Commit-ID: b1859959374b4709569760cae0866d22a16606d3 + +commit 924f996144fc0ae1a659fadcfc2237d1ae935fc4 +Author: Xavier Hsinyuan +Date: Mon Dec 9 11:21:05 2024 +0800 + + Add $(srcdir) for standalone sk-libfido2 make target. + + Fix out-of-tree build failure due to incorrect path for `sk-usbhid.c`. + +commit bbc9c18e84de29c83fa03e69290979fcca54a2b2 +Author: djm@openbsd.org +Date: Sat Dec 7 10:12:19 2024 +0000 + + upstream: replace bespoke logging of MaxSessions enforcement with + + new ratelimited logging infrastructure. + + Add ratelimits to logging of connections dropped by PerSourcePenalties + + ok dtucker + + OpenBSD-Commit-ID: f22fe7c39607e4361aadf95e33773ffd68c59489 + +commit 5a6ddf946cf105189c2c99a04f86ce95edc55fc5 +Author: djm@openbsd.org +Date: Sat Dec 7 10:05:36 2024 +0000 + + upstream: add infrastructure for ratelimited logging; feedback/ok + + dtucker + + OpenBSD-Commit-ID: 18a83e5ac09d59aaf1e834fd6b796db89dd842e7 + +commit 85f0c1e75e8f6c5d83b8070918ee2f6ab16d403e +Author: djm@openbsd.org +Date: Fri Dec 6 16:24:27 2024 +0000 + + upstream: allow glob(3) patterns for sshd_config AuthorizedKeysFile + + and AuthorizedPrincipalsFile directives; bz2755 ok dtucker + + OpenBSD-Commit-ID: 3e3e05a17fca39bba78b993a07b44664519adf7f + +commit 9a9ffee6e10bcd039f1f9385599577441ebe542a +Author: djm@openbsd.org +Date: Fri Dec 6 16:21:48 2024 +0000 + + upstream: support VersionAddendum in the client, mirroring the + + option of the same name in the server; bz2745 ok dtucker@ + + OpenBSD-Commit-ID: 6ff7905b3f9806649bde750515786553fb89cdf4 + +commit 41ab0ccecd68232e196efae5e224b31ca104c423 +Author: djm@openbsd.org +Date: Fri Dec 6 16:02:12 2024 +0000 + + upstream: clarify encoding of options/extensions; bz2389 + + OpenBSD-Commit-ID: c4e92356d44dfe6d0a4416deecb33d1d1eba016c + +commit 5488810359f0fd91e2f7b919c70a3798e46376cb +Author: djm@openbsd.org +Date: Fri Dec 6 15:17:15 2024 +0000 + + upstream: ignore SIGPIPE here; some downstreams have had this for + + years... + + OpenBSD-Commit-ID: 73674ee4f8ceb8fc9cb8de71d8ddea0c721eb035 + +commit 4389a792d9078212366eba124a3eed36e009d09e +Author: djm@openbsd.org +Date: Fri Dec 6 15:12:56 2024 +0000 + + upstream: sync -o option lists with ssh.1; requested jmc@ + + OpenBSD-Commit-ID: a7ac295b444da7b2ca7a33a52370594f6897f6bb + +commit 6b9cd095565ddc5402d5096dce248fa0521dbda3 +Author: Fabio Pedretti +Date: Mon Oct 16 17:12:24 2023 +0200 + + Remove ancient RHL 6.x config in RPM spec. + + It looks like build6x options were intended for RHL 6.x + (the Red Hat distro predating Fedora, not RHEL), but were + then applied to RHEL. + + Completely remove support for this ancient configuration. + + Successfully built, installed and run on RHEL 6. This also + remove a build warning about deprecation of PreReq. + +commit 5cacfa798f92b707491375fed748d1d1bcb33ec9 +Author: Darren Tucker +Date: Fri Dec 6 23:54:45 2024 +1100 + + Add new hardware-backed signing key for myself. + + Retire old non-hardware based signing key. + +commit f129b6ee1d4361799e65307216e3a4d5544356b7 +Author: Jonas 'Sortie' Termansen +Date: Sat Nov 2 22:05:45 2024 +0100 + + Fix configure implicit declaration and format warnings. + +commit 11a5e5179077f73c2d45bcdf3f60153ae3f17815 +Author: dtucker@openbsd.org +Date: Fri Dec 6 07:05:54 2024 +0000 + + upstream: Expand $SSH to absolute path if it's not already. + + Prevents problem later in increase_datafile_size if ssh is not in + the path. Patch from quaresmajose via GHPR#510. + + OpenBSD-Regress-ID: 2670a66af8b827410ca7139f0a89f4501cece77b + +commit dc2ef8f0944a4ff7ba19e52fd17b4654e6bd9b93 +Author: dtucker@openbsd.org +Date: Fri Dec 6 06:55:28 2024 +0000 + + upstream: Change "login again" to "log in again" + + in password change message. From ThinLinc-Zeijlon via github PR#532. + + OpenBSD-Commit-ID: fea5e9bc04caf613a118c419f16863733b340cf1 + +commit 8252f346eb21cd6b30816f905b7d94f10962373e +Author: naddy@openbsd.org +Date: Thu Dec 5 22:45:03 2024 +0000 + + upstream: catch up documentation: AES-GCM is preferred to AES-CTR + + OpenBSD-Commit-ID: 63360924b6834507fe70020edb936f5075043a9e + +commit 9a2f4c75081769bd45eba2bf3fab0a32b25f1879 +Author: Darren Tucker +Date: Fri Dec 6 17:56:17 2024 +1100 + + Change text from "login to" to "log in to". + + From ThinLinc-Zeijlon via GHPR#532. + +commit 24dcf368d816b06136a02845ebd0c7846bf18927 +Author: Xavier Hsinyuan +Date: Fri Dec 6 11:56:34 2024 +0800 + + Fix configure message typo in sk-libfido2 standalone. + +commit 1a0cac2f3411a22d69ae6918eff48456b805e73b +Author: Alexander Kanavin +Date: Thu Dec 5 16:26:46 2024 +0100 + + Skip 2038 key expiry test on 64 bit time_t systems. + + This allows testing Y2038 with system time set to after that (i.e. 2040), + so that actual Y2038 issues can be exposed, and not masked by key expiry + errors. + + Signed-off-by: Alexander Kanavin + +commit 6b4611dc1232c5d2c8e43201f580f19aab320c87 +Author: Darren Tucker +Date: Fri Dec 6 01:45:52 2024 +1100 + + Skip 64bit expiry time test on 32bit time_t. + +commit c9b7866a7dc5e6c30f5aa9d22dd0bbafda0d496f +Author: dtucker@openbsd.org +Date: Thu Dec 5 14:28:39 2024 +0000 + + upstream: Add key expiry test in the 64bit time_t range for additional + + coverage. From Alexander Kanavin via bz#3684. + + OpenBSD-Regress-ID: bdf6eb3c2421f2e1e11483d03b34c7931d1bccf7 + +commit 790c913b5fc6ee93ae14793443dc85a0f574b7eb +Author: Damien Miller +Date: Thu Dec 5 19:24:56 2024 +1100 + + typo + +commit d23a23aaeeabc228792e3fd7eb5f2fa6ae13c482 +Author: Damien Miller +Date: Thu Dec 5 08:47:02 2024 +1100 + + add a Makefile target for ssh-verify-attestation + + Not built by default, but easier than doing it by hand + +commit d0ac63d0f8b5f778d5fd326701ef4489bc27635e +Author: dtucker@openbsd.org +Date: Thu Dec 5 06:49:26 2024 +0000 + + upstream: De-magic the x11 base port number into a define. ok djm@ + + OpenBSD-Commit-ID: 23b85ca9d222cb739b9c33ee5e4d6ac9fdeecbfa + +commit 9998c93d57bf0f1df2bc93e0bc2d8112c6f8c720 +Author: dtucker@openbsd.org +Date: Thu Dec 5 06:47:00 2024 +0000 + + upstream: Prevent integer overflow in x11 port handling. These are + + theoretically possible if the admin misconfigures X11DisplayOffset or the + user misconfigures their own $DISPLAY, but don't happen in normal operation. + From Suhov Roman via bz#3730, ok djm@ + + OpenBSD-Commit-ID: e9e3860f1a19b862ccf07dc8ecbe8f1e1034f4ed + +commit 8c9ee046d40e4254c6c1711783ea11027b72c3e9 +Author: djm@openbsd.org +Date: Wed Dec 4 16:42:49 2024 +0000 + + upstream: add a work-in-progress tool to verify FIDO attestation + + blobs that ssh-keygen can write when enrolling FIDO keys. + + OpenBSD-Regress-ID: 6c97bf3f46e48866677ad69f54b77683eb92437f + +commit 50c640d874d0246dd0a0d949398c3d7f757c716a +Author: dtucker@openbsd.org +Date: Wed Dec 4 10:51:13 2024 +0000 + + upstream: Don't assume existence of SK provider in test. Patch from + + balu.gajjala at gmail via bz#3402. + + OpenBSD-Regress-ID: d571932016d07d135b54433d07520b9e1901db43 + +commit 73d782693144262570d3585b62f16b183170c014 +Author: djm@openbsd.org +Date: Wed Dec 4 14:37:55 2024 +0000 + + upstream: sync the list of options accepted by -o with ssh_config.5 + + prompted by bz3455 + + OpenBSD-Commit-ID: 0ecbfa70aea6c769bcc259defe07182edf461f57 + +commit 6993d9f0959534b0b7d52e17b95e9e79fb0b3d0a +Author: djm@openbsd.org +Date: Wed Dec 4 14:24:20 2024 +0000 + + upstream: don't screw up ssh-keygen -l output when the file + + contains CR characters; GHPR236 bz3385, fix from Dmitry Belyavskiy + + OpenBSD-Commit-ID: e458cf6b0adcea5b69ef4c7ba38e590841d02ef4 - upstream: Remove duplicate curve25519-sha256 kex. +commit c0b03c2534946fc114880092177aa4a3683ced2d +Author: jsg@openbsd.org +Date: Tue Dec 3 22:30:03 2024 +0000 + + upstream: spelling; ok djm@ - curve25519-sha256@libssh.org is the pre-standardization name for the same - thing, so remove it as a duplicate. Speeds up test by a tiny amount. + OpenBSD-Commit-ID: c8ff3f70020451eef214e598117b7ce1a29853ef + +commit 97eb247f40167f44324e88a537d5b4fe771a63b2 +Author: dtucker@openbsd.org +Date: Tue Dec 3 16:27:53 2024 +0000 + + upstream: Remove fallback to compiled-in gropup for dhgex when the - OpenBSD-Regress-ID: 5a5ee5fa1595a6e140b1cc16040bedf5996a5715 + moduli file exists, but does not contain moduli within the client-requested + range. The fallback behaviour remains for the case where the moduli file does + not exist (typically, running tests prior to installing). From bz#2793, based + in part on patch from Joe Testa, ok djm@ + + OpenBSD-Commit-ID: b1a8c5dbbedf249b42474679ebaf14db7332b1ab -commit 749896b874928c2785256cae4d75161dc3bfcc7d +commit 30c746265ebde29806dba77c92fb1fd3803cbf5c +Author: tb@openbsd.org +Date: Tue Dec 3 15:53:51 2024 +0000 + + upstream: Remove redundant field of definition check + + This will allow us to get rid of EC_GROUP_method_of() in the near future. + + ok djm + + OpenBSD-Commit-ID: b4a3d2e00990cf5c2ec6881c21ddca67327c2df8 + +commit eaa1744f34c30740328fd0a0d84b5f2f9e6918c1 +Author: Damien Miller +Date: Thu Dec 5 00:59:19 2024 +1100 + + don't ignore changes in regress Makefiles + + reported by Torben Hansen in bz2880 + +commit 66e986880b2472fefaad781f10113b138b65ff27 +Author: Damien Miller +Date: Thu Dec 5 00:01:33 2024 +1100 + + Support systemd-style socket activation in agent + + Adds support for systemd LISTEN_PID/LISTEN_FDS socket activation to + ssh-agent. Activated when these environment variables are set and + the agent is started with the -d or -D option and no socket path + is set. + + Based on GHPR502 by Daniel Kahn Gillmor, ok dtucker + +commit 9b57c099f57152e6c94f633c114f544087f4bdaa +Author: Darren Tucker +Date: Wed Dec 4 21:36:01 2024 +1100 + + Update readme files to better reflect reality. + + Prompted by bz#3738, ok djm@. + +commit ffa885db1b960451d426455045d2f51288e48ee8 Author: dtucker@openbsd.org -Date: Tue Aug 20 07:27:25 2024 +0000 +Date: Tue Dec 3 14:12:47 2024 +0000 - upstream: Unnest rekey param parsing test and use ssh not sshd. + upstream: Improve description of KbdInteractiveAuthentication. - ssh uses the same parsing code, now has "-G" to dump its config and is - slightly faster to start up. This speeds up the test slightly (~5%) in the - common case but should help more during instrumented tests, eg under - valgrind, where startup costs are magnified. + Based on bz#3658, fixes jmc@ ok markus@ djm@. - OpenBSD-Regress-ID: 07c3acaf4c728e641033071f4441afc88141b0d0 + OpenBSD-Commit-ID: 9fadb56b9afed554d501acbba911c685acd6ffc2 -commit 2b1762115481ff2b7a60fd4db2ae69b725437462 +commit b460f82a67795bba37c6cc6c78f788e5b435b4cb +Author: Jonas 'Sortie' Termansen +Date: Sat Nov 2 17:53:23 2024 +0100 + + Inherit DESTDIR from the environment. + + autoconf packages conventionally inherit the DESTDIR variable from the + environment. + +commit 9da7fa7c7464df241ae5d17da94e4ebed9013719 +Author: Jonas 'Sortie' Termansen +Date: Sat Nov 2 22:10:39 2024 +0100 + + Define u_short and u_long if needed. + +commit d3a7ff7cecbc23cc37044bdf02e7118d05bf3c35 Author: djm@openbsd.org -Date: Tue Aug 20 11:10:04 2024 +0000 +Date: Tue Dec 3 08:31:49 2024 +0000 - upstream: actually use the length parameter that was passed in rather + upstream: support FIDO tokens that return no attestation data, e.g. - than a constant (this makes no difference in practice because the length is - always the same); reported by martin AT nmkd.net + recent WinHello. From Michael Braun via GHPR542 - OpenBSD-Commit-ID: 4aecce232c2fe9b16e9217ff6bcb3c848d853e7e + OpenBSD-Commit-ID: a71b0542f2f7819ba0e33a88908e01b6fc49e4ce -commit d922762ca16a7381131b242f49d7376c41fabcb5 -Author: Damien Miller -Date: Tue Aug 20 13:55:30 2024 +1000 +commit 96b64056c812620014b65371a9e3ac86bfcd08d5 +Author: Thorsten Kukuk +Date: Tue Nov 19 10:53:28 2024 +0100 - private key coredump protection for Linux/FreeBSD + Add wtmpdb support as Y2038 safe wtmp replacement + +commit 1d9563a56f2ad5b0c0aeef20e19c1a03ad54f88a +Author: djm@openbsd.org +Date: Mon Dec 2 14:06:42 2024 +0000 + + upstream: unbreak - platforms not supporting coredump exclusion using mmap/madvise flags - fall back to plain old malloc(3). + OpenBSD-Commit-ID: 05b6c31f4a6e385338f43cc0e08776cea75802a1 -commit cc048ca536d6bed6f2285b07040b0d57cd559ba5 +commit d75837b9f6d0d6cc18ed5078789ea0f3dad08f00 Author: djm@openbsd.org -Date: Tue Aug 20 03:48:30 2024 +0000 +Date: Mon Dec 2 13:37:18 2024 +0000 - upstream: place shielded keys (i.e. keys at rest in RAM) into memory + upstream: prefer AES-GCM to AES-CTR; ok deraadt markus - allocated using mmap(3) with MAP_CONCEAL set. This prevents exposure of the - key material in coredumps, etc (this is in addition to other measures we take - in this area). + OpenBSD-Commit-ID: 8366a72e0f300ee31c5dab2c95025387ec15bbc9 + +commit e19cd494b567a73dc390e09b47c1e21545e6116b +Author: Shiva Kaul +Date: Mon Dec 2 02:04:20 2024 -0500 + + Fix compilation with DEBUG_SK enabled - ok deraadt@ + In `ssh_ecdsa_sk_verify`, the `datalen` variable was renamed to `dlen` -- but not in this debugging block. + +commit 67ace92be0718df7e0f52c0a76684fc2ebae4089 +Author: dtucker@openbsd.org +Date: Fri Nov 29 00:13:36 2024 +0000 + + upstream: Import regenerated moduli. - OpenBSD-Commit-ID: cbbae59f337a00c9858d6358bc65f74e62261369 + OpenBSD-Commit-ID: 311d271bf0fab8a119e84f4f696d8cd40731692f -commit a0b35c791cad1f85481b23ba46373060292e1c80 +commit ca0697a90e5720ba4d76cb0ae9d5572b5260a16c +Author: Jeremy Stott +Date: Sat Oct 19 12:10:52 2024 +1300 + + Add make target for standalone sk-libfido2 + + Add a Makefile target for sk-libfido2, the standalone fido2 security + key shared library, suitable for use with the SecurityKeyProvider + option. + + Add a new configure option `--with-security-key-standalone` that + optionally sets the shared library target sk-libfido2$(SHLIBEXT), and + adds it to $(TARGETS). + + misc.h is required when SK_STANDALONE is defined, because of the use + of `monotime_tv` in `sk_select_by_touch`. + + Sets the shared library extension for sk-libfido2 is by setting + `SHLIBEXT` depending on the platform in configure.ac. + + Add the shared library to the CI builds in the `sk` target config to + make sure it can compile under the same conditions as + `--with-security-key-builtin`. + + Add a libssh-pic.a static library that compiles with `-fPIC` reusing + .c.lo method in sk-dummy.so for use in the shared library sk-libfido2. + + Note, a separate static library libssh-pic.a is needed, since defining + -DSK_STANDALONE excludes some symbols needed in sshkey.lo. + +commit 74d70841efbf41b9fcc8e6f6f4777d2e9d7e2004 +Author: Arnout Engelen +Date: Fri Oct 18 13:42:38 2024 +0200 + + mdoc2man: balance nested square brackets + + I noticed the square brackets in `destination [command [argument...]` + in the synopsis for the `ssh.1` manpage were not balanced, + this balances them. + + Signed-off-by: Arnout Engelen + +commit 8eabd2ae2ca1d7756417a1ee5b41f09c5d997634 Author: djm@openbsd.org -Date: Sat Aug 17 08:35:04 2024 +0000 +Date: Wed Nov 27 16:07:08 2024 +0000 - upstream: mention that ed25519 is the default key type generated and + upstream: fix argument of "Compression" directive in ssh -G config - clarify that rsa-sha2-512 is the default signature scheme when RSA is in use. - Based on GHPR505 from SebastianRzk + dump, which used to work but broke in 9.8 - OpenBSD-Commit-ID: 1d90df71636a04601685d2a10a8233bcc8d4f4c5 + OpenBSD-Commit-ID: c79936242d29c70d01941b28d2d07fd0b85fe46f -commit 127a50f2c80572ed1a021feb11ecf941e92cbbef +commit 53c03961769d8879a81398074ea3cb36253d4f2e Author: djm@openbsd.org -Date: Sat Aug 17 08:23:04 2024 +0000 +Date: Wed Nov 27 13:27:34 2024 +0000 + + upstream: new name/link for agent I-D + + OpenBSD-Commit-ID: e3420f3925a297a1b2ab7dfe7c7d274cfc8e1193 + +commit 785e3c9110df8f2d30e42ce8b45969c49700f35b +Author: djm@openbsd.org +Date: Wed Nov 27 13:00:23 2024 +0000 + + upstream: mention that biometrics may be used for FIDO key user + + verification as well as PIN. Prompted by Zack Newman, ok jmc@ + + OpenBSD-Commit-ID: b774a4438c9be70012661ee278450790d21277b8 + +commit fd2e64c9ec9ea3e89e396be0db41aaf982ae1210 +Author: djm@openbsd.org +Date: Tue Nov 26 22:05:51 2024 +0000 + + upstream: g/c outdated XXX comments + + OpenBSD-Commit-ID: 74d0c0b74994d9a4343c4d7ea4948cb34f609a6c + +commit 0ad34a6193357d286042322ea7347262a6fb0778 +Author: djm@openbsd.org +Date: Tue Nov 26 22:02:28 2024 +0000 + + upstream: regression test for UpdateHostkeys with multiple keys backed + + by ssh-agent. Patch from Maxime Rey. + + OpenBSD-Regress-ID: 1777ab6e639e57c0e20cbcb6df60455b49fd8bb3 + +commit 84023656d91b78f1ef86c8321ec563f2e90f7227 +Author: djm@openbsd.org +Date: Tue Nov 26 22:01:37 2024 +0000 + + upstream: Explicitly specify the signature algorithm when signing + + hostkeys-prove requests. + + Fixes a corner-case triggered by UpdateHostKeys with one or more unknown + host keys stored in ssh-agent where sshd refuses to accept the signature + coming back from the agent. + + Report/fix from Maxime Rey + + OpenBSD-Commit-ID: 460c7d527a24f92b7e5f68ca1a2fa242ebf0d086 + +commit d1c1cfc5e4e9b43593d4642810ea8135e4c7db49 +Author: djm@openbsd.org +Date: Tue Nov 26 21:23:35 2024 +0000 - upstream: fix minor memory leak in Subsystem option parsing; from + upstream: when using RSA keys to sign messages, select the - Antonio Larrosa via GHPR515 + signature algorithm based on the requested hash algorithm ("-Ohashalg=xxx"). - OpenBSD-Commit-ID: fff3bbefd1b2c45c98cbe45c6b857b15d8a2d364 + This allows using something other than rsa-sha2-512, which may not + be supported on all signing backends, e.g. some smartcards only + support SHA256. + + Patch from Morten Linderud; ok markus@ + + OpenBSD-Commit-ID: 246353fac24e92629263996558c6788348363ad7 -commit 171427261d2079941eb1041079dbae875da37cbc +commit ac7544654441280071b90a4129a47467d40f2389 Author: djm@openbsd.org -Date: Sat Aug 17 08:09:50 2024 +0000 +Date: Sun Nov 24 23:47:50 2024 +0000 - upstream: fix swapping of source and destination addresses in some sshd + upstream: turn off CDIAGFLAGS and turn back on INSTALL_STRIP - log messages + accidentally changed in last commit - OpenBSD-Commit-ID: 24d4cbb86325275df1f037545aa3b91456e52d25 + OpenBSD-Commit-ID: 6d07e4606997e36b860621a14dd41975f2902f8f -commit 2a50a8f1fa57857a5e124a2280bcf61cc63c77f7 +commit 953fa5b59afb04c3c74ed82d7bace65c13cd8baa Author: Darren Tucker -Date: Sat Aug 17 11:10:19 2024 +1000 - - Add compat functions for EVP_Digest{Sign,Verify}. - - This should make LibreSSL 3.1.x through 3.3.x work again. Code from - tb@, ok djm@. Restore the test configs covering those. - -commit 1c3a7145260e03037cc18715b883880836fd122d -Author: Philip Hands -Date: Thu Aug 8 13:03:51 2024 +0200 +Date: Sat Nov 9 11:41:44 2024 +1100 - make sure that usage & man page match + Disable security key for bigendian interop. - SSH-Copy-ID-Upstream: da5b1abe55b72a16e0430e7598e1573da01779c0 + It doesn't currently work. It's not clear why, but I suspect + sk-dummy.so ends up being built for the wrong architecture. -commit cd0d681645b9adcf2467e7838bfd9d5142de4c4e -Author: Philip Hands -Date: Thu Aug 8 13:01:47 2024 +0200 +commit a80eb71c428c474098087c672398f200be8fabdf +Author: Darren Tucker +Date: Sat Nov 9 05:14:16 2024 +1100 - update copyright notices + Reshuffle OpenWRT test configs. - Bump the year to 2024, but also reflect the fact that hands.com Ltd. has - been wound up in the UK, and its assets (including this copyright) have - now reverted to its owner, Philip Hands. + Move the the flags used by the OpenWRT distro to mipsel target and + enable OpenSSL on all targets to improve coverage. - SSH-Copy-ID-Upstream: 0e4c4d072747a6568b11a790c29dd1b4ce663d7f + Explicitly disable security key and openssl on mips target so that host + end of the bigendian interop tests don't attempt them and fail (since + they're not enabled on the target side). -commit 7fc9ccdce18841ebd0a97e31e43258512ab32a32 -Author: Philip Hands -Date: Sun Aug 4 20:45:00 2024 +0200 +commit d2709c461359e4129311cdff81ee05242d6c53cd +Author: Darren Tucker +Date: Sat Nov 9 03:26:08 2024 +1100 - restore optionality of -i's argument - - SSH-Copy-ID-Upstream: f70e3abb510e4eeb040b47894e41828246c1b720 + Add keytype to bigendian interop test. -commit c37aa7012b1a3c2c322fd19e71310aadc90fc674 -Author: Philip Hands -Date: Fri Aug 2 15:52:07 2024 +0200 +commit 50ac0f0e0627d29fd9becf5e15e8ceca5ad18078 +Author: Darren Tucker +Date: Sat Nov 9 03:24:29 2024 +1100 - avoid exploring .ssh/id*.pub subdirectories - - SSH-Copy-ID-Upstream: 0b9e08b7707ad16de3c8e6a0410d9f42fbd56997 + Ignore chown failure, eg due to dangling symlinks. -commit 777dce9e2e0d12f7e81e162f77749f30899869fe -Author: Philip Hands -Date: Fri Aug 2 10:07:11 2024 +0200 +commit 9e528e65a03245cf28e814f09b88c701bec935d1 +Author: Darren Tucker +Date: Sat Nov 2 18:05:41 2024 +1100 - ensure that we're always told the source of keys + Test bigendian interop. - SSH-Copy-ID-Upstream: 1bee96f4793e8ec3fab9f9361204ae58f5cc7cae + Where our test target is a bigendian system, do an additional build on + the runner host (which is little endian) and test interop between the two. + Should hopefully catch obvious endianness bugs. -commit fb94fd2339848e40cad6c9bb42b822244cc1a7bc -Author: Philip Hands -Date: Wed Jul 31 23:19:51 2024 +0200 +commit dd416f5bfa96ac1ff44b27a93f7b55ee627c6baf +Author: Darren Tucker +Date: Fri Nov 1 19:44:29 2024 +1100 - add $HOME to ERROR if one cannot write to ~/.ssh + Allow overridding TEST_SSH_SSHD. - SSH-Copy-ID-Upstream: ebef3e9c06e0447bff06e9d84b33023cf592e0ba + This will allow tests to specify an alternative sshd, eg on a remote + machine with different endianness. -commit eb5aafa1ffaeee75799141ec5ded406a65ec7d18 -Author: Philip Hands -Date: Wed Jul 31 23:19:03 2024 +0200 +commit 82662d562cf54829df8a941cdfb2fd307e1d9a90 +Author: djm@openbsd.org +Date: Wed Nov 6 22:51:26 2024 +0000 - assert that SCRATCH_DIR is a writable directory + upstream: ssh-agent implemented an all-or-nothing allow-list of - SSH-Copy-ID-Upstream: ecb2b9d10883b9a16df56c83896c9bb47a80cde2 - -commit abcc460a2af46f0d812f8433d97a8eae1d80724c -Author: Philip Hands -Date: Wed Jul 31 23:17:54 2024 +0200 - - quote to avoid potential for word splitting + FIDO application IDs for security key-backed keys, to prevent web key handles + from being used remotely as this would likely lead to unpleasant surprises. + By default, only application IDs that start with "ssh:*" are allowed. - SSH-Copy-ID-Upstream: f379adbe06ac2ef1daf0f130752234c7f8b97e3c + This adds a -Owebsafe-allow=... argument that can override the default + list with a more or less restrictive one. The default remains unchanged. + + ok markus@ + + OpenBSD-Commit-ID: 957c1ed92a8d7c87453b9341f70cb3f4e6b23e8d -commit b3f91411fd1473605f74c40c1a91a024c7171e27 -Author: Philip Hands -Date: Wed Jul 31 23:15:11 2024 +0200 +commit 593a0b65c55c1e06a8c22b084aefc395aedb0127 +Author: jca@openbsd.org +Date: Mon Nov 4 21:59:15 2024 +0000 - ensure ERROR output goes to STDERR + upstream: Ignore extra groups that don't fit in the buffer passed - SSH-Copy-ID-Upstream: ac394b05eead3b91feb7c2ae4129a3e9b892f1e2 + to getgrouplist(3) + + Our kernel supports 16 groups (NGROUPS_MAX), but nothing prevents + an admin from adding a user to more groups. With that tweak we'll keep + on ignoring them instead of potentially reading past the buffer passed to + getgrouplist(3). That behavior is explicitely described in initgroups(3). + + ok millert@ gilles@ + + OpenBSD-Commit-ID: a959fc45ea3431b36f52eda04faefc58bcde00db -commit 674b8f30f0dbacd787eb1e4e7e1ece34b5543d8f -Author: Philip Hands -Date: Thu Aug 1 14:03:06 2024 +0200 +commit e7adebeff3a9d038d0eaeeb0fcefedf29acb7e90 +Author: Damien Miller +Date: Mon Nov 4 14:39:27 2024 +1100 - avoid extra space when no arg given to -i option - - SSH-Copy-ID-Upstream: feca9e67e6e37c5653445d1c733569d7abb1770e + Add git signing key for Tim Rice -commit 0efa0e1c41427c0c6ba839a18c72c1afcd7b7cc0 -Author: Philip Hands -Date: Wed Jul 31 23:28:36 2024 +0200 +commit da4b84845e874f12af7e0686170fa391c919d1df +Author: Darren Tucker +Date: Fri Nov 1 18:51:22 2024 +1100 - put the -i before -[pP] (matching man pages) - - The man pages (ssh, sftp & ssh-copy-id) all list -i before the port - setting, so make the output match that order, which also seems more - natural with the port being next to the server. - - SSH-Copy-ID-Upstream: 34d5d614172c78f9a42249466c4b81975b8883a1 + Correct path to c-cpp.yml file in workflow config. -commit 87831345e9745f2d13bd7a4a7972809f6788f331 -Author: Shreyas Mahangade -Date: Mon Jul 29 15:26:05 2024 +0000 +commit 28740aa2c75392a9c4191eb9523f9b20853e2932 +Author: Darren Tucker +Date: Fri Nov 1 18:44:42 2024 +1100 - Minor space issue fixed - - SSH-Copy-ID-Upstream: 335e44d7be78b03962a54c3a5c99a2ff45294a54 + Test new OpenSSL and LibreSSL releases.` -commit 2f3010f4736b4b3f5c10a4be97a24e90ff04c5e7 -Author: Shreyas Mahangade -Date: Mon Jul 29 16:55:28 2024 +0530 +commit a74809fe06540f16231b354ffe21fcbf39e81f73 +Author: Darren Tucker +Date: Fri Nov 1 18:44:00 2024 +1100 - Show identity file in 'ssh' command - - - Previously no identity file is shown in "ssh" command output on the line "Now try logging into the..." - - This commit makes sure whenever "ssh-copy-id" with "-i" is invoked, it also reflects in "ssh" command - - SSH-Copy-ID-Upstream: 58e022ec26cb2315eb3be581d01e0ba787082428 + Add nbsd10 default test config. -commit a13856374b894397a7682b32257ed0bf67cfede9 +commit 88b35cbdc1500efece65cd6a9a20a72cf7e46eaa Author: Damien Miller -Date: Fri Aug 16 08:30:20 2024 +1000 +Date: Wed Oct 30 14:25:14 2024 +1100 - more OPENSSL_HAS_ECC + fix uint64_t types; reported by Tom G. Christensen -commit 4da2a1a7f648979bea6eaf3b17f5f250faed4afc +commit ef7c26cd2f0f9a8222f851d1e551f6dfd3113f8b Author: Damien Miller -Date: Thu Aug 15 23:35:54 2024 +1000 +Date: Sun Oct 27 13:28:11 2024 +1100 - fix merge botch that broke !OPENSSL_HAS_ECC + htole64() etc for systems without endian.h -commit 2c53d2f32b8e3992b61682c909ae5bc5122b6e5d -Author: Damien Miller -Date: Thu Aug 15 15:09:45 2024 +1000 +commit 0c3927c45f8a57b511c874c4d51a8c89414f74ef +Author: djm@openbsd.org +Date: Sun Oct 27 02:06:59 2024 +0000 - missed OPENSSL_HAS_ECC case + upstream: explicitly include endian.h + + OpenBSD-Commit-ID: 13511fdef7535bdbc35b644c90090013da43a318 -commit 342dd7a219f39119b8b686b5aaa99c8e15ede368 -Author: Damien Miller -Date: Thu Aug 15 15:06:55 2024 +1000 +commit cf3e48ee8ba1beeccddd2f203b558fa102be67a2 +Author: djm@openbsd.org +Date: Sun Oct 27 02:06:01 2024 +0000 - retire testing aginst older LibreSSL versions + upstream: fix ML-KEM768x25519 KEX on big-endian systems; spotted by - libressl prior to 3.4.x lack support for the EVP_DigestSign and - EVP_DigestVerify APIs that we need now that sshkey is converted - to EVP_PKEY. + jsg@ feedback/ok deraadt@ - If someone makes a good case for why we should support these versions - then we could bring back support with wrappers. + OpenBSD-Commit-ID: 26d81a430811672bc762687166986cad40d28cc0 -commit a7c6ea8eebe0f179141ec5dbf0c9e5354417930f -Author: Damien Miller -Date: Thu Aug 15 12:44:17 2024 +1000 +commit ae566d51b64fa3dce7063e7745b9b35f8f47abde +Author: naddy@openbsd.org +Date: Fri Oct 25 21:53:24 2024 +0000 + + upstream: mlkem768x25519-sha256 has been promoted to default key + + exchange + + OpenBSD-Commit-ID: 5a3259a193fd42108a869ebf650b95b5f2d08dcf + +commit 3af1dba1384ca896df6e973c70398c41d36de1ea +Author: Darren Tucker +Date: Fri Oct 25 19:04:30 2024 +1100 + + Retire the minix3 test config. + + It got broken by the sshd-auth change, it's not obvious why, and the + platform lacks the debugging tools (eg gdb, strace) to figure it out. + The upstream project seems effectively dead (6 years since the last + commit, 10 since the last release). It was useful while it lasted + (we found a real bug because of it) but its time seems to have passed. + +commit 3b240cc44b8de9175280ddbe59331317d427b0e3 +Author: Preetish Amballi +Date: Mon Oct 21 14:07:02 2024 +0000 - sync TEST_MALLOC_OPTIONS for OpenBSD + Updated gitignore to ignore sshd-session and sshd-auth targets -commit 60c2cf22e8f64f35d8b1175e4671257313f2e4d3 -Author: Damien Miller -Date: Thu Aug 15 12:43:47 2024 +1000 +commit 326495744f06a0ab18ee0d16f87b3fe91cac92fb +Author: Darren Tucker +Date: Fri Oct 25 19:01:02 2024 +1100 - remove gratuitious difference from OpenBSD + Simplify pselect shim and remove side effects. + + Instead of maintaing state (pipe descriptors, signal handlers) across + pselect-on-select invocations, set up and restore them each call. + This prevents outside factors (eg a closefrom or signal handler + installation) from potentially causing problems. This does result in a + drop in throughput of a couple of percent on geriatric platforms without + a native pselect due to the extra overhead. Tweaks & ok djm@ -commit 339c4fc60a6250429d41fa8713f783d82aad4551 +commit e53b615f3934ffac1efb3c1e491d126b9b09fd24 Author: djm@openbsd.org -Date: Thu Aug 15 00:52:23 2024 +0000 +Date: Fri Oct 25 01:34:18 2024 +0000 - upstream: adapt to EVP_PKEY conversion + upstream: promote mlkem768x25519-sha256 to be the default key exchange; - OpenBSD-Regress-ID: 0e2d4efb0ed0e392e23cd8fda183fe56531ac446 + ok markus@ + + OpenBSD-Commit-ID: fc673065e6505bb06b2e2b9362f78ccb4200a828 -commit 63a94f99b9d7c8a48182a40192e45879d1ba8791 +commit de644b1831b970f6655f871c051774cc871e8e74 Author: djm@openbsd.org -Date: Fri Jul 19 04:33:36 2024 +0000 +Date: Thu Oct 24 03:28:34 2024 +0000 - upstream: test transfers in mux proxy mode too + upstream: test SIGUSR1 dropping all keys from ssh-agent - OpenBSD-Regress-ID: 2edfc980628cfef3550649cab8d69fa23b5cd6c4 + OpenBSD-Regress-ID: 8654b9aa8eb695b1499fffc408c25319592bf0e0 -commit 7bdfc20516e288b58c8c847958059c7b141eeff9 +commit e86d7a077ce9a2b9ee9d4138c358a17cbdb786f9 Author: djm@openbsd.org -Date: Thu Aug 15 00:51:51 2024 +0000 +Date: Thu Oct 24 03:15:47 2024 +0000 - upstream: Convert RSA and ECDSA key to the libcrypto EVP_PKEY API. - - DSA remains unconverted as it will be removed within six months. + upstream: amake ssh-agent drop all keys when it receives SIGUSR1; - Based on patches originally from Dmitry Belyavskiy, but significantly - reworked based on feedback from Bob Beck, Joel Sing and especially - Theo Buehler (apologies to anyone I've missed). + let's users zap keys without access to $SSH_AUTH_SOCK - ok tb@ + ok deraadt@ - OpenBSD-Commit-ID: d098744e89f1dc7e5952a6817bef234eced648b5 + OpenBSD-Commit-ID: dae9db0516b1011e5ba8c655ac702fce42e6c023 -commit 0af06e2c5b898992a18c74333e75a0136506acc6 -Author: tobias@openbsd.org -Date: Wed Aug 14 15:42:18 2024 +0000 +commit 94cdfebec852a2429c008cc2a55f8e4183f36972 +Author: djm@openbsd.org +Date: Thu Oct 24 03:14:37 2024 +0000 - upstream: Reorder calloc arguments - - The first argument should be the amount, the second argument should be the - element size. Fixing this also silences some gcc compiler warnings for - portable. - - Spotted with Benny Baumann (BenBE at geshi dot org). + upstream: relax valid_domain() checks to allow an underscore as the - ok djm@ + first character. ok deraadt@ - OpenBSD-Commit-ID: 711ad6f7bd7fb48bf52208f2cf9f108cddb6d41a + OpenBSD-Commit-ID: 3f8be6d32496e5596dd8b14e19cb067ddd7969ef -commit 56ce0aa3c6cf28d9fcbce3207457abeac91b5050 -Author: tobias@openbsd.org -Date: Wed Aug 14 15:40:30 2024 +0000 +commit 1b05d5437bf45bee5e3104772dea06ed51764f1b +Author: dtucker@openbsd.org +Date: Tue Oct 22 07:13:28 2024 +0000 - upstream: Extend sshbuf validation - - Multiple sshbuf structs can be linked through a parent/child relationship. - Make sure that a single sshbuf cannot be its own parent. If this would ever - happen, it would result in reference counting issues. - - This is a cheap way of testing this with very little overhead. It does not - detect A->B->A linkages though for performance reason and the fact that it - takes a programming error for this to occur anyway. - - Authored with Benny Baumann (BenBE at geshi dot org). + upstream: Remove sshd logfile in start_sshd - ok djm@ + ... and ssh and sshd log wrappers before recreating them. Prevents "can't + create" errors during tests when running tests without SUDO after having + run them with SUDO. - OpenBSD-Commit-ID: fb3fa9ee2cad3c7e842ebadfd7f5db220c4aaf16 + OpenBSD-Regress-ID: 2f0a83532e3dccd673a9bf0291090277268c69a6 -commit fc48ddf6998188517af42dce807e2088b6a0c0be -Author: tobias@openbsd.org -Date: Wed Aug 14 15:37:11 2024 +0000 +commit 307ab3c7720f8879b835614b02687358ee4df9b9 +Author: dtucker@openbsd.org +Date: Tue Oct 22 06:16:26 2024 +0000 - upstream: Use freezero for better readability - - It has the same meaning as the current pair of calling explicit_bzero - and free. Spotted with Benny Baumann (BenBE at geshi dot org). + upstream: Add a sshd debug wrapper - ok djm@ + ... to run all of the subprograms from the build directory while + developing and debugging. Should help prevent accidentally testing + against unchanged installed sshd-auth and sshd-session binaries. ok djm@ - OpenBSD-Commit-ID: 939fbe9ccf52d0d48c5fa53694d6f3bb9927970c + OpenBSD-Commit-ID: 61760cdc98c2bc8f1e9f83a6f97cca0f66b52e69 -commit 1ff6907ec26dac6ac59fe9fe232899a63b4c14d8 -Author: tobias@openbsd.org -Date: Wed Aug 14 15:35:23 2024 +0000 +commit 87bd1cb3ccba5e91d2650eb7f753c898ee43858e +Author: dtucker@openbsd.org +Date: Tue Oct 22 06:13:00 2024 +0000 - upstream: Fix typo in comment - - Spotted with Benny Baumann (BenBE at geshi dot org). + upstream: Make debug call printf("%s", NULL) safe. - ok djm@ + Prevents problems on platforms where this isn't safe (which it's not + required to be). ok djm@ - OpenBSD-Commit-ID: 829160ac8ef3ad3409695ce3a3ade835061cae57 + OpenBSD-Commit-ID: 8fa4ce3ad90915c925b81b99a79ab920b0523387 -commit 487faaed8f3bb9ffb19e8f807a3da72895b16421 -Author: dlg@openbsd.org -Date: Wed Jul 31 12:00:18 2024 +0000 +commit c44c349edd157b2c00c42bd5ef5f9dfb37de26f3 +Author: Darren Tucker +Date: Tue Oct 22 17:48:32 2024 +1100 - upstream: add a random amount of time (up to 4 seconds) to the - - grace login time. + Resync cvsid missed in commit 6072e4c9. + +commit fe4305c37ffe53540a67586854e25f05cf615849 +Author: djm@openbsd.org +Date: Fri Oct 18 05:53:26 2024 +0000 + + upstream: mention that LocalForward and RemoteForward can accept Unix - ok deraadt@ djm@ + domain socket paths; GHPR115 - OpenBSD-Commit-ID: abd3c57aaa5861517529b322df79b6be35ee67f4 + OpenBSD-Commit-ID: a8a34d0a0c51a9ddab3dfce615f9878fa76ef842 -commit 2865f5b7520bed3e74fbbb5f8d7a44193d7a4314 -Author: naddy@openbsd.org -Date: Fri Jul 26 15:24:49 2024 +0000 +commit 9c97b6af8e052ab5ffe0f9096fadc8f9a4d0ed0f +Author: djm@openbsd.org +Date: Fri Oct 18 05:45:40 2024 +0000 - upstream: document the reduced logingrace penalty + upstream: remove duplicate check; GHPR392 from Pedro Martelletto - OpenBSD-Commit-ID: 9b63e0e3599d524ddc10edc4f978081382c3548b + OpenBSD-Commit-ID: 597ab7dd3f0e78939d2659fc1904d0f39ee95487 -commit 1ec0a64c5dc57b8a2053a93b5ef0d02ff8598e5c -Author: Darren Tucker -Date: Sun Jul 28 21:26:51 2024 +1000 +commit d9cd208e89a471a3ff8adfcec68d6210af9e9fd5 +Author: djm@openbsd.org +Date: Fri Oct 18 05:37:24 2024 +0000 - Explicitly install libssl-devel cygwin. + upstream: allow "-" as output file for moduli screening - Should fix CI tests for cygwin default config. + based on GHPR393 + + OpenBSD-Commit-ID: 1517763764eb55d03a6092dd120d2909c6fef0e1 -commit 0bf6e5bb750b66b25c20a1c5a471f91850de3748 +commit 5eb5c4b2820d0636b1eccee646fb32ec946c4a95 Author: djm@openbsd.org -Date: Thu Jul 25 23:44:01 2024 +0000 +Date: Fri Oct 18 05:32:51 2024 +0000 - upstream: reduce logingrace penalty. + upstream: ssh-keyscan doesn't need it's own sshfatal() definition, it - A single forgotton login that times out should be below the penalty - threshold. + can use the shared one from fatal.c - ok deraadt/claudio + based on GHPR401 from lengyijun - OpenBSD-Commit-ID: cee1f7d17597c97bff8e5092af5d136fdb08f81d + OpenBSD-Commit-ID: 8ea75ea99f27f464c9223cbc89cb046ccf9cd5c4 -commit 29fb6f6d46b67770084b4f12bcf8a01bd535041b +commit 0a1e75499e2c6fc258ee903645c878480949f362 Author: djm@openbsd.org -Date: Thu Jul 25 22:40:08 2024 +0000 +Date: Fri Oct 18 05:14:51 2024 +0000 - upstream: Fix proxy multiplexing (-O proxy) bug - - If a mux started with ControlPersist then later has a forwarding added using - mux proxy connection and the forwarding was used, then when the mux proxy - session terminates, the mux master process will send a channel close to the - server with a bad channel ID and crash the connection. + upstream: in _ssh_order_hostkeyalgs() consider ECDSA curve type when - This was caused by my stupidly reusing c->remote_id for mux channel - associations when I should have just added another member to struct channel. + arranging the hostkey algorithms. AFAIK this code is unused in OpenSSH, but I + guess others are using it - ok markus@ + based on GHPR387 from Pawel Jakub Dawidek - OpenBSD-Commit-ID: c9f474e0124e3fe456c5e43749b97d75e65b82b2 + OpenBSD-Commit-ID: 4d462495ac0c40f7b7dd66178e0005b9b2128225 -commit 53d1d307438517805989c7d5616d752739a97e03 +commit d01ee7a88c5f4b1aa8c75a7c739f8f3bc1ad8bde Author: djm@openbsd.org -Date: Thu Jul 18 01:47:27 2024 +0000 +Date: Fri Oct 18 05:03:34 2024 +0000 - upstream: mention mux proxy mode + upstream: require control-escape character sequences passed via the '-e - OpenBSD-Commit-ID: fd77a77779f06d316a314e4540dc57c93fc3369a + ^x' commandline to be exactly two characters long. Avoids one by OOB read if + ssh is invoked as "ssh -e^ ..." + + Spotted by Maciej Domanski in GHPR368 + + OpenBSD-Commit-ID: baa72bc60898fc5639e6c62de7493a202c95823d -commit a9b90859d252c2f5a24142f985d38610ac74685f -Author: jsg@openbsd.org -Date: Sun Jul 14 10:19:23 2024 +0000 +commit 74ff6382f5743e09930e6cbd195dac65cd6062c9 +Author: djm@openbsd.org +Date: Fri Oct 18 04:30:09 2024 +0000 - upstream: fix double word; ok dtucker@ + upstream: remove addr.[ch] functions that are unused and - OpenBSD-Commit-ID: e6aff005914fa350b896d2be030be3d3b56ec0e8 + visbility-restrict ones that are unused outside the implementation itself; + based on GHPR#282 by tobias@ + + OpenBSD-Commit-ID: a0140f2418b4d46cfaa7b33febc0a0931f9b2744 -commit b05fda224bbcd2f641254534ed2175c42487f3c8 -Author: Darren Tucker -Date: Thu Jul 25 17:59:35 2024 +1000 +commit a9d6d7d93c533fa729f08b405e786d912553f33e +Author: djm@openbsd.org +Date: Fri Oct 18 04:14:59 2024 +0000 - Check for SA_RESTART before using it. + upstream: unreachable POLLERR case; from ya0guang via GHPR485 - ok djm@ + OpenBSD-Commit-ID: b3c82655190532b01eb817e532742cfaa4687eff -commit c276672fc0e99f0c4389988d54a84c203ce325b6 -Author: Yuichiro Naito -Date: Wed Sep 1 10:19:32 2021 +0900 +commit d76424bf279ff951383e21213eb3759ea4090674 +Author: djm@openbsd.org +Date: Fri Oct 18 04:11:54 2024 +0000 - Class-imposed login restrictions - - If the following functions are available, - add an additional check if users are allowed to login imposed by login class. + upstream: s/Sx/Cm/ for external references; from Domen Puncer - * auth_hostok(3) - * auth_timeok(3) + Kugler via GHPR501 - These functions are implemented on FreeBSD. + OpenBSD-Commit-ID: f864a34feb5d5ff17160cf7c42ad0f7744fe8a3f -commit 7717b9e9155209916cc6b4b4b54f4e8fa578e889 -Author: djm@openbsd.org -Date: Wed Jul 10 21:58:34 2024 +0000 +commit ca204b994e2981e7bf95627b3105408917105649 +Author: naddy@openbsd.org +Date: Mon Oct 14 23:53:34 2024 +0000 - upstream: correct keyword; from Yatao Su via GHPR509 + upstream: mention SshdAuthPath option; ok djm@ - OpenBSD-Commit-ID: 81c778c76dea7ef407603caa157eb0c381c52ad2 + OpenBSD-Commit-ID: 9a5d3add25e4e77bd3805bc5583a842ecf34d85c -commit f2b78bb8f149d6b4d1f62c21aa1f06995dccf4ce -Author: djm@openbsd.org -Date: Mon Jul 8 03:04:34 2024 +0000 +commit be27770e840c4dd9d9fcad1aa879400c727d7c2f +Author: Darren Tucker +Date: Fri Oct 18 13:37:55 2024 +1100 - upstream: don't need return at end of void function + Remove references to systrace and pledge sandboxes. - OpenBSD-Commit-ID: 42d322d37f13aa075ae7b1ad9eef591e20b89717 + ok djm@ -commit a395d37a813c0177cb5bfc4bebf5a52badb73cf0 -Author: djm@openbsd.org -Date: Thu Jul 4 22:53:59 2024 +0000 +commit 49e64bf63fbf2f14961062dafe8ef08cb816bb08 +Author: Pavel Miadzvedzeu +Date: Wed Apr 24 10:19:56 2024 +0300 - upstream: fix grammar: "a pattern lists" -> "one or more pattern - - lists" - - OpenBSD-Commit-ID: f3c844763398faa9800687e8ff6621225498202a + Fix "undeclared 'ut'" error by replacing it with 'utx' -commit 8b664df75966e5aed8dabea00b8838303d3488b8 +commit 67f684733f60f66479854a2867b953de731e71b2 Author: Darren Tucker -Date: Sun Jul 7 18:46:19 2024 +1000 +Date: Thu Oct 17 20:50:29 2024 +1100 - Cast to sockaddr * in systemd interface. + Seed RNG when starting up sshd-auth. - Fixes build with musl libx. bz#3707. + Makes builds configured --without-openssl work again since otherwise + the first use of the RNG comes after the sandbox init and it can't + open /dev/random. -commit 30c8c81da2169e78357d08dbb0ddd823b60e93bc +commit c06c681aeebbe8e84e7410095514e7ee91f7e6cb Author: Darren Tucker -Date: Thu Jul 4 20:12:26 2024 +1000 +Date: Thu Oct 17 19:18:23 2024 +1100 - Add 9.8 branch to ci-status page. + MacOS 12 runners are deprecated, replace with 15. -commit ee6b9e661633fcefd29dba0c811cecbc4d027f6f -Author: Samuel Thibault -Date: Tue Mar 26 22:15:08 2024 +0100 +commit 39db1f23bafb48a7c0cc9c65c716a0370f4cc677 +Author: Damien Miller +Date: Thu Oct 17 13:28:47 2024 +1100 - Fix detection of setres*id on GNU/Hurd - - Like Linux, proper _SOURCE macros need to be set to get declarations of - various standard functions, notably setres*id. Now that Debian is using - -Werror=implicit-function-declaration this is really required. While at - it, define other _SOURCE macros like on GNU/Linux, since GNU/Hurd uses - the same glibc. + Fix lookup path for sshd-auth; bz3745 -commit fa41f6592ff1b6ead4a652ac75af31eabb05b912 +commit c537eeb1ae5f069450053b0027e64efe5bdb37d2 Author: Damien Miller -Date: Mon Jul 1 14:33:26 2024 +1000 +Date: Wed Oct 16 08:28:21 2024 +1100 - version numbers + fix breakage; missing saved_argc symbol -commit bfebb8a5130a792c5356bd06e1ddef72a0a0449f -Author: djm@openbsd.org -Date: Mon Jul 1 04:31:59 2024 +0000 +commit 98a0883bdef28a06c7e017f27adf21ba57898bf4 +Author: Damien Miller +Date: Mon Oct 14 17:17:50 2024 +1100 - upstream: openssh-9.8 - - OpenBSD-Commit-ID: 5f8b89e38a4c5f7c6d52ffa19f796d49f36fab19 + fix capsicum sandbox -commit 146c420d29d055cc75c8606327a1cf8439fe3a08 +commit 164ea4380564a2a83713eacf71908e3946e5e4e4 +Author: Damien Miller +Date: Mon Oct 14 17:16:41 2024 +1100 + + put back some portable bits for sshd-auth.c + +commit f8edf08c258ee2918689872c4702302052729726 +Author: Damien Miller +Date: Mon Oct 14 14:49:25 2024 +1100 + + there's only one sandbox, move to a static global + +commit 4482f0042b41d3d63c3845d7ba9fcf47c9252a84 +Author: Damien Miller +Date: Mon Oct 14 14:49:20 2024 +1100 + + depend + +commit 74856204a353a187dc6e7706c6cf84b7f14d775d Author: djm@openbsd.org -Date: Mon Jul 1 04:31:17 2024 +0000 +Date: Mon Oct 14 03:02:08 2024 +0000 - upstream: when sending ObscureKeystrokeTiming chaff packets, we - - can't rely on channel_did_enqueue to tell that there is data to send. This - flag indicates that the channels code enqueued a packet on _this_ ppoll() - iteration, not that data was enqueued in _any_ ppoll() iteration in the - timeslice. ok markus@ + upstream: regress support for split sshd-auth binary - OpenBSD-Commit-ID: 009b74fd2769b36b5284a0188ade182f00564136 + OpenBSD-Regress-ID: df7d18a87b475f70004770f0f4e404adba5f6ab7 -commit 637e4dfea4ed81264e264b6200172ce319c64ead +commit 461741083d7254595fecea274e60fe3ebf3ce3f9 Author: djm@openbsd.org -Date: Mon Jul 1 03:10:19 2024 +0000 +Date: Fri Sep 27 01:05:54 2024 +0000 - upstream: use "lcd" to change directory before "lls" rather then "cd", + upstream: test some more Match syntax, including criteria=arg and - since the directory we're trying to list is local. Spotted by Corinna - Vinschen + negations - OpenBSD-Regress-ID: 821feca4a4bebe491944e624c8f7f2990b891415 + OpenBSD-Regress-ID: 67476baccc60bf1a255fd4e329ada950047b8b8d -commit c8cfe258cee0b8466ea84597bf15e1fcff3bc328 +commit 6072e4c9385713e9c166f32cfca6a7e603d4f0b8 Author: djm@openbsd.org -Date: Thu Jun 27 23:01:15 2024 +0000 +Date: Mon Oct 14 01:57:50 2024 +0000 - upstream: delete obsolete comment + upstream: Split per-connection sshd-session binary - OpenBSD-Commit-ID: 5fb04f298ed155053f3fbfdf0c6fe7cdf84bbfa2 + This splits the user authentication code from the sshd-session + binary into a separate sshd-auth binary. This will be executed by + sshd-session to complete the user authentication phase of the + protocol only. + + Splitting this code into a separate binary ensures that the crucial + pre-authentication attack surface has an entirely disjoint address + space from the code used for the rest of the connection. It also + yields a small runtime memory saving as the authentication code will + be unloaded after thhe authentication phase completes. + + Joint work with markus@ feedback deraadt@ + + Tested in snaps since last week + + OpenBSD-Commit-ID: 9c3b2087ae08626ec31b4177b023db600e986d9c -commit 94b9d37100f6fa536aaa1d1a0e4926fe44fbf04d +commit fe6c6330c1a94c7a537efe9069853ce7a275c50a Author: djm@openbsd.org -Date: Thu Jun 27 22:36:44 2024 +0000 +Date: Sun Oct 13 22:20:06 2024 +0000 - upstream: retire unused API + upstream: don't start the ObscureKeystrokeTiming mitigations if - OpenBSD-Commit-ID: 3e30d7b0615e2707f6bbe70f61b1c2f72f78161b + there has been traffic on a X11 forwarding channel recently. + + Should fix X11 forwarding performance problems when this setting is + enabled. Patch from Antonio Larrosa via bz3655 + + OpenBSD-Commit-ID: 820284a92eb4592fcd3d181a62c1b86b08a4a7ab -commit 268c3a7f5783e731ed60f4e28da66ee3743581d3 -Author: jmc@openbsd.org -Date: Thu Jun 27 21:02:16 2024 +0000 +commit 538cd28598ae942c94b99855b06fdd937e2e7381 +Author: jsg@openbsd.org +Date: Sat Oct 12 10:50:37 2024 +0000 - upstream: ssl(8) no longer contains a HISTORY section; + upstream: remove duplicate misc.h include ok dtucker@ - OpenBSD-Commit-ID: 83b7ff34433d79595e9c2a5d2a561a6660251245 + OpenBSD-Commit-ID: fdd056e7854294834d54632b4282b877cfe4c12e -commit 12b6cc09ce6c430681f03af2a8069e37a664690b +commit 0051381a8c33740a77a1eca6859efa1c78887d80 Author: djm@openbsd.org -Date: Wed Jun 26 23:47:46 2024 +0000 +Date: Sun Oct 6 23:37:17 2024 +0000 - upstream: move child process waitpid() loop out of SIGCHLD handler; + upstream: Turn off finite field (a.k.a modp) Diffie-Hellman key - ok deraadt + exchange in sshd by default. Specifically, this removes the + diffie-hellman-group* and diffie-hellman-group-exchange-* methods. The client + is unchanged and continues to support these methods by default. - OpenBSD-Commit-ID: 65815a39564e431414aed7c5ace8076f4e9ca741 + Finite field Diffie Hellman is slow and computationally expensive for + the same security level as Elliptic Curve DH or PQ key agreement while + offering no redeeming advantages. + + ECDH has been specified for the SSH protocol for 15 years and some + form of ECDH has been the default key exchange in OpenSSH for the last + 14 years. + + ok markus@ + + OpenBSD-Commit-ID: 4e238ad480a33312667cc10ae0eb6393abaec8da -commit d6bcd13297c2ab8b528df5a6898f994734849031 -Author: deraadt@openbsd.org -Date: Wed Jun 26 23:16:52 2024 +0000 +commit 67a115e7a56dbdc3f5a58c64b29231151f3670f5 +Author: djm@openbsd.org +Date: Thu Sep 26 23:55:08 2024 +0000 - upstream: Instead of using possibly complex ssh_signal(), write all + upstream: fix previous change to ssh_config Match, which broken on - the parts of the grace_alarm_handler() using the exact things allowed by the - signal-safe rules. This is a good rule of thumb: Handlers should be written - to either set a global volatile sig_atomic_t inspected from outside, and/or - directly perform only safe operations listed in our sigaction(2) manual page. - ok djm markus + negated Matches; spotted by phessler@ ok deraadt@ - OpenBSD-Commit-ID: 14168ae8368aab76e4ed79e17a667cb46f404ecd + OpenBSD-Commit-ID: b1c6acec66cd5bd1252feff1d02ad7129ced37c7 -commit b8793e2b0851f7d71b97554fa5260b23796d6277 -Author: deraadt@openbsd.org -Date: Wed Jun 26 23:14:14 2024 +0000 +commit 220b6c1290042acd5180d783dea01efe1365c265 +Author: jsg@openbsd.org +Date: Wed Sep 25 23:01:39 2024 +0000 - upstream: save_errno wrappers inside two small signal handlers that - - perform system calls, for systems with libc that do perform libc sigtramps. - ok djm markus + upstream: remove some unused defines; ok djm@ - OpenBSD-Commit-ID: 7749b56419a7c9dcfe4c6c04811e429813346c62 + OpenBSD-Commit-ID: 3a63e4e11d455704f684c28715d61b17f91e0996 -commit f23e9332c4c8df37465c4a4f38275ea98980ed7e +commit 3ef4f6e8a4d774f73852391fdccbb95f39fc71bf Author: jmc@openbsd.org -Date: Mon Jun 24 06:59:39 2024 +0000 +Date: Wed Sep 25 06:13:01 2024 +0000 - upstream: - uppercase start of sentence - correct sentence grammar + upstream: remove some unneeded Xo/Xc calls; from evan silberman the - ok djm + original diff had a couple of errors, which i've fixed - OpenBSD-Commit-ID: 1ec4b0fdb633a43667f2c8fff1d600bd647dde25 + OpenBSD-Commit-ID: f37ad5888adbc0d4e1cd6b6de237841f4b1e650d -commit 1839e3eb71a759aa795602c1e4196300f4ac2615 +commit 3f02368e8e9121847727c46b280efc280e5eb615 Author: djm@openbsd.org -Date: Mon Jun 24 04:05:11 2024 +0000 - - upstream: mention SshdSessionPath option - - OpenBSD-Commit-ID: c29734d36c21003973b15c1c9965c35f36cef30c - -commit 603193e32aef5db7d60c58066d5de89806e79312 -Author: Darren Tucker -Date: Thu Jun 20 18:45:14 2024 +1000 - - Rerun upstream tests on .sh file changes too. - -commit dbbf9337c19381786a8e5a8a49152fe6b80c780d -Author: dtucker@openbsd.org -Date: Thu Jun 20 08:23:18 2024 +0000 +Date: Wed Sep 25 01:24:04 2024 +0000 - upstream: Work around dbclient cipher/mac query bug. + upstream: fix regression introduced when I switched the "Match" - Unlike earlier versions, recent Dropbear (at least v2024.85) requires - a host arg when querying supported ciphers and macs via "-c/-m - help". Earlier versions accept but do not require it, so always - provide it. If these queries fail, skip the test with a warning. + criteria tokeniser to a more shell-like one. Apparently the old tokeniser + (accidentally?) allowed "Match criteria=argument" as well as the "Match + criteria argument" syntax that we tested for. - OpenBSD-Regress-ID: 98eb863a3f0363416922efb273885e6b3c7f68d4 - -commit 8de2c8cebc46bbdb94b7a2c120fcadfb66a3cccc -Author: dtucker@openbsd.org -Date: Thu Jun 20 08:18:34 2024 +0000 - - upstream: Remove dropbear key types not supported + People were using this syntax so this adds back support for + "Match criteria=argument" - by current OpenSSH. Allows subsequent test runs to work if OpenSSH is - rebuilt w/out OpenSSL. + bz3739 ok dtucker - OpenBSD-Regress-ID: e0129eb2b1d31771105903a8055216fbba20a770 + OpenBSD-Commit-ID: d1eebedb8c902002b75b75debfe1eeea1801f58a -commit e9b6471c59b21e5d9ef1b3832d4bf727338add85 +commit 9517cc58577f85a0ba5f8bb46778dff625f0688f Author: djm@openbsd.org -Date: Thu Jun 20 00:18:05 2024 +0000 +Date: Tue Sep 24 02:28:17 2024 +0000 - upstream: stricter check for overfull tables in penalty record path + upstream: some extra paranoia, reminded by jsg@ - OpenBSD-Commit-ID: 7df01e648a0723418c554e64a9f2b6d38db060a6 + OpenBSD-Commit-ID: 22072bfa1df1391858ae7768a6c627e08593a91e -commit d9336d344eb2a1e898c5e66147b3f108c7214694 -Author: djm@openbsd.org -Date: Wed Jun 19 23:24:47 2024 +0000 +commit 815a94e86a68c1000b8310cb47695cea9329516c +Author: Damien Miller +Date: Wed Sep 25 11:15:45 2024 +1000 - upstream: put back reaping of preauth child process when writes - - from the monitor fail. Not sure how this got lost in the avalanche of - patches. + gss-serv.c needs sys/param.h - OpenBSD-Commit-ID: eb7eb36371e1ac01050b32b70fb2b3e5d98e72f5 + From Void Linux -commit 579d9adb70ec0206a788eb5c63804c31a67e9310 -Author: naddy@openbsd.org -Date: Mon Jun 17 13:50:18 2024 +0000 +commit 76a618d2842c34c16cd21a4efc7230e2f459008d +Author: Damien Miller +Date: Wed Sep 25 11:13:05 2024 +1000 - upstream: remove one more mention of DSA + build construct_utmp() when USE_BTMP is set - OpenBSD-Commit-ID: 8515f55a15f02836ba657df341415f63c60526ca - -commit 7089b5f8436ef0b8d3d3ad9ce01045fb9e7aab15 -Author: Darren Tucker -Date: Wed Jun 19 23:09:05 2024 +1000 - - Move -f to the place needed to restart sshd. + Fixes compile error on Void Linux/Musl -commit d5f83cfd852b14a25f347f082ab539a9454702ad +commit d3aee17f6d395202eaa42a0c449b6da41f61527c Author: Darren Tucker -Date: Wed Jun 19 21:04:01 2024 +1000 - - Need to supply "-f" to restart sshd. - -commit fad34b4ca25c0ef31e5aa841d461b6f21da5b8c1 -Author: dtucker@openbsd.org -Date: Wed Jun 19 10:15:51 2024 +0000 +Date: Tue Sep 24 18:41:44 2024 +1000 - upstream: Provide defaults for ciphers and macs - - if querying for them fails since on some versions of Dropbear (at least - v2024.85) "-m help" doesn't seem to work. Enable all supported pubkey - algorithms in the server. - - OpenBSD-Regress-ID: 4f95556a49ee9f621789f25217c367a33d2745ca + Test the flags from OpenWRT's package. -commit 5521060e35ada9f957cecdddc06d0524e75409ef -Author: dtucker@openbsd.org -Date: Wed Jun 19 10:10:46 2024 +0000 +commit 0f5d19e6fe4b58a89e6dc8c71a2aae30365d193e +Author: Christoph Ostarek +Date: Wed Jul 3 12:46:59 2024 +0200 - upstream: Use ed25519 keys for kex tests - - since that's supported by OpenSSH even when built without OpenSSL. - Only test diffie-hellman kex if OpenSSH is compiled with support for it. + fix utmpx ifdef - OpenBSD-Regress-ID: a5d09ef9bbd171f9e4ec73ed0d9eeb49a8878e97 + 02e16ad95fb1f56ab004b01a10aab89f7103c55d did a copy-paste for + utmpx, but forgot to change the ifdef appropriately -commit dbd3b833f6e3815e58f2dc6e14f61a51bcd4d6bd -Author: dtucker@openbsd.org -Date: Wed Jun 19 10:08:34 2024 +0000 +commit e03239f999acf9dc3da0f2f72bde36abbe678911 +Author: jsg@openbsd.org +Date: Sun Sep 22 12:56:21 2024 +0000 - upstream: Rework dropbear key setup - - to always generate ed25519 keys, other types only if OpenSSH has support - for the corresponding key type. + upstream: remove some unused defines; ok djm@ - OpenBSD-Regress-ID: 8f91f12604cddb9f8d93aa34f3f93a3f6074395d + OpenBSD-Commit-ID: 81869ee6356fdbff19dae6ff757095e6b24de712 -commit d6218504e11ae9148adf410fc69b0710a052be36 -Author: Darren Tucker -Date: Wed Jun 19 20:20:24 2024 +1000 +commit a35f543d3a6275fef781e515c262d1c687c3bc28 +Author: jsg@openbsd.org +Date: Fri Sep 20 02:00:46 2024 +0000 - Restart sshd after installing it for testing. + upstream: remove unneeded semicolons; checked by millert@ - When installing an sshd built without OpenSSL the mismatch between - the running sshd and newly installed sshd-session will cause the - remainder of the test to fail. + OpenBSD-Commit-ID: 3fb621a58e04b759a875ad6a33f35bb57ca80231 -commit 786a4465b6bb702daf4fb17b7c3bcb42b52f0b46 +commit 1641f2d4d6e05d2147913442864cae546e64f08b Author: Darren Tucker -Date: Tue Jun 18 19:59:59 2024 +1000 +Date: Mon Sep 23 20:52:31 2024 +1000 - Remove macos-11 runner. - - Github is retiring them soon. + Add 9.9 branch to CI status console. -commit df1c72a55edbebac14363b57de66ac6a147ecc67 +commit 46d1fb16b20e971b9ac15e86a3d3e350b49c9ad6 Author: Damien Miller -Date: Wed Jun 19 09:34:34 2024 +1000 +Date: Fri Sep 20 08:20:13 2024 +1000 - PAMServiceName may appear in a Match block + update version numbers -commit de1c2e70e5a5dc3c8d2fe04b24cc93d8ef6930e7 -Author: dtucker@openbsd.org -Date: Tue Jun 18 08:11:48 2024 +0000 +commit 0bdca1f218971b38728a0a129f482476baff0968 +Author: djm@openbsd.org +Date: Thu Sep 19 22:17:44 2024 +0000 - upstream: Re-enable ssh-dss tests - - ... if ssh is compiled with DSA support + upstream: openssh-9.9 - OpenBSD-Regress-ID: bbfaf8c17f2b50a2d46ac35cb97af99b990c990d + OpenBSD-Commit-ID: 303417285f1a73b9cb7a2ae78d3f493bbbe31f98 -commit dabc2c7cf3c141e8e5d5a1a60d6c1d2d2422cf43 -Author: anton@openbsd.org -Date: Tue Jun 18 06:14:27 2024 +0000 +commit ef2d7f2d3e1b4c9ae71bacf963e76a92ab8be543 +Author: Damien Miller +Date: Wed Sep 18 16:03:23 2024 +1000 - upstream: Stop using DSA in dropbear interop tests. - - OpenBSD-Regress-ID: abfd4457d99d8cc1417fd22ca2c570270f74c1cf + include openbsd-compat/base64.c license in LICENSE -commit 761438012710169445acc179e3870c53c862bda0 +commit 7ef362b989c8d1f7596f557f22e5924b9c08f0ea Author: Damien Miller -Date: Tue Jun 18 12:29:45 2024 +1000 +Date: Wed Sep 18 09:01:23 2024 +1000 - missed a bit of DSA in the fuzzer + conditionally include mman.h in arc4random code -commit 3f9cc47da588e8de520720e59f98438043fdaf93 +commit 5fb2b5ad0e748732a27fd8cc16a7ca3c21770806 Author: Damien Miller -Date: Tue Jun 18 09:35:53 2024 +1000 +Date: Tue Sep 17 11:53:24 2024 +1000 - DSA support is disabled, so remove from fuzzers + fix bug in recently-added sntrup761 fuzzer + + key values need to be static to persist across invocations; + spotted by the Qualys Security Advisory team. -commit 00eb95957dea5484b2c7c043f7d2bbc87301bef2 +commit 0ca128c9ee894f1b0067abd473bfb33171df67f8 Author: djm@openbsd.org -Date: Mon Jun 17 08:30:29 2024 +0000 +Date: Mon Sep 16 05:37:05 2024 +0000 - upstream: disable the DSA signature algorithm by default; ok + upstream: use 64 bit math to avoid signed underflow. upstream code - markus@ + relies on using -fwrapv to provide defined over/underflow behaviour, but we + use -ftrapv to catch integer errors and abort the program. ok dtucker@ - (yes, I know this expands to "the Digitial Signature Algorithm - signature algorithm) + OpenBSD-Commit-ID: 8933369b33c17b5f02479503d0a92d87bc3a574b + +commit f82e5e22cad88c81d8a117de74241328c7b101c3 +Author: jmc@openbsd.org +Date: Sun Sep 15 08:27:38 2024 +0000 + + upstream: minor grammar/sort fixes for refuseconnection; ok djm - OpenBSD-Commit-ID: 961ef594e46dd2dcade8dd5721fa565cee79ffed + OpenBSD-Commit-ID: 1c81f37b138b8b66abba811fec836388a0f3e6da -commit 5603befe11c9464ea26fe77cbacc95a7cc0b1ea7 +commit 0c1165fc78e8fe69b5df71f81a8f944554a68b53 +Author: Damien Miller +Date: Sun Sep 15 13:30:13 2024 +1000 + + avoid gcc warning in fuzz test + +commit ce171d0718104b643854b53443ff72f7283d33f2 Author: djm@openbsd.org -Date: Mon Jun 17 08:28:31 2024 +0000 +Date: Sun Sep 15 03:09:44 2024 +0000 - upstream: promote connection-closed messages from verbose to info - - log level; they could be the only record of the connection terminating if the - client doesn't send a SSH2_MSG_DISCONNECT message. ok dtucker@ + upstream: bad whitespace in config dump output - OpenBSD-Commit-ID: 0c8bfaf5e9fdff945cee09ac21e641f6c5d65d3c + OpenBSD-Commit-ID: d899c13b0e8061d209298eaf58fe53e3643e967c -commit b00331402fe5c60d577f3ffcc35e49286cdc6b47 +commit 671c440786a5a66216922f15d0007b60f1e6733f Author: Damien Miller -Date: Mon Jun 17 17:02:18 2024 +1000 +Date: Sun Sep 15 12:53:59 2024 +1000 - propagate PAM crashes to PerSourcePenalties + use construct_utmp to construct btmp records - If the PAM subprocess crashes, exit with a crash status that will be - picked up by the sshd(8) listener process where it can be used by - PerSourcePenalties to block the client. This is similar handling to - the privsep preauth process. + Simpler and removes some code with the old-style BSD license. -commit 1c207f456ace38987deda047758d13fbf857f948 -Author: Damien Miller -Date: Mon Jun 17 15:06:01 2024 +1000 +commit 930cb02b6113df72fbc732b9feb8e4f490952a81 +Author: djm@openbsd.org +Date: Sun Sep 15 02:20:51 2024 +0000 - minix doesn't have loopback, so skip penalty tests + upstream: update the Streamlined NTRU Prime code from the "ref" - pointed out by dtucker@ + implementation in SUPERCOP 20201130 to the "compact" implementation in + SUPERCOP 20240808. The new version is substantially faster. Thanks to Daniel + J Bernstein for pointing out the new implementation (and of course for + writing it). + + tested in snaps/ok deraadt@ + + OpenBSD-Commit-ID: bf1a77924c125ecdbf03e2f3df8ad13bd3dafdcb -commit 48443d202eaec52d4d39defdd709a4499a7140c6 +commit 9306d6017e0ce5dea6824c29ca5ba5673c2923ad Author: djm@openbsd.org -Date: Sun Jun 16 11:54:49 2024 +0000 +Date: Sun Sep 15 01:19:56 2024 +0000 - upstream: same treatment for this test + upstream: document Match invalid-user - OpenBSD-Regress-ID: d0cc9efca7833e673ea7b0cb3a679a3acee8d4c7 + OpenBSD-Commit-ID: 2c84a9b517283e9711e2812c1f268081dcb02081 -commit 45562a95ea11d328c22d97bf39401cd29684fb1f +commit 0118a4da21147a88a56dc8b90bbc2849fefd5c1e Author: djm@openbsd.org -Date: Sun Jun 16 08:18:06 2024 +0000 +Date: Sun Sep 15 01:18:26 2024 +0000 - upstream: penalty test is still a bit racy + upstream: add a "Match invalid-user" predicate to sshd_config Match + + options. + + This allows writing Match conditions that trigger for invalid username. + E.g. + + PerSourcePenalties refuseconnection:90s + Match invalid-user + RefuseConnection yes + + Will effectively penalise bots try to guess passwords for bogus accounts, + at the cost of implicitly revealing which accounts are invalid. + + feedback markus@ + + OpenBSD-Commit-ID: 93d3a46ca04bbd9d84a94d1e1d9d3a21073fbb07 + +commit 7875975136f275619427604900cb0ffd7020e845 +Author: djm@openbsd.org +Date: Sun Sep 15 01:11:26 2024 +0000 + + upstream: Add a "refuseconnection" penalty class to sshd_config + + PerSourcePenalties + + This allows penalising connection sources that have had connections + dropped by the RefuseConnection option. ok markus@ - OpenBSD-Regress-ID: 90c9ac224db454637baf1ebee5857e007321e824 + OpenBSD-Commit-ID: 3c8443c427470bb3eac1880aa075cb4864463cb6 -commit 8d0f7eb147ef72d18acb16c0b18672d44941a8ca +commit 8d21713b669b8516ca6d43424a356fccc37212bb Author: djm@openbsd.org -Date: Sat Jun 15 03:59:10 2024 +0000 +Date: Sun Sep 15 01:09:40 2024 +0000 - upstream: crank up penalty timeouts so this should work on even the + upstream: Add a sshd_config "RefuseConnection" option - slowest of test builders + If set, this will terminate the connection at the first authentication + request (this is the earliest we can evaluate sshd_config Match blocks) - OpenBSD-Regress-ID: 70bda39c83e3fc9d0f3c1fad4542ed33e173d468 - -commit 93c75471a1202ab3e29db6938648d4e2602c0475 -Author: jmc@openbsd.org -Date: Fri Jun 14 05:20:34 2024 +0000 - - upstream: sort -q in the options list; + ok markus@ - OpenBSD-Commit-ID: 6839b38378f38f754de638a5e988c13b4164cc7c + OpenBSD-Commit-ID: 43cc2533984074c44d0d2f92eb93f661e7a0b09c -commit dd7807bbe80a93ffb4616f2bd5cf83ad5a5595fb +commit acad117e66018fe1fa5caf41b36e6dfbd61f76a1 Author: djm@openbsd.org -Date: Fri Jun 14 05:01:22 2024 +0000 +Date: Sun Sep 15 00:58:01 2024 +0000 - upstream: clarify KEXAlgorithms supported vs available. Inspired by + upstream: switch sshd_config Match processing to the argv tokeniser - bz3701 from Colin Watson. + too; ok markus@ - OpenBSD-Commit-ID: e698e69bea19bd52971d253f2b1094490c4701f7 + OpenBSD-Commit-ID: b74b5b0385f2e0379670e2b869318a65b0bc3923 -commit d172ad56df85b68316dbadbedad16761a1265874 +commit baec3f7f4c60cd5aa1bb9adbeb6dfa4a172502a8 Author: djm@openbsd.org -Date: Fri Jun 14 05:00:42 2024 +0000 +Date: Sun Sep 15 00:57:36 2024 +0000 - upstream: ssh-keyscan -q man bits + upstream: switch "Match" directive processing over to the argv - OpenBSD-Commit-ID: ba28d0e1ac609a4c99c453e57e86560c79079db1 - -commit 092e4ff9ccaacbe035f286feb1b56ed499604743 -Author: Damien Miller -Date: Fri Jun 14 14:46:35 2024 +1000 - - skip penalty-expire test in valgrind test env + string tokeniser, making it possible to use shell-like quoting in Match + directives, particularly "Match exec". ok markus@ + + OpenBSD-Commit-ID: 0877309650b76f624b2194c35dbacaf065e769a5 -commit 2866ad08a9c50d7b67ce9424ca990532b806a21a +commit dd424d7c382c2074ab70f1b8ad4f169a10f60ee7 Author: djm@openbsd.org -Date: Fri Jun 14 04:43:11 2024 +0000 +Date: Sun Sep 15 00:47:01 2024 +0000 - upstream: split the PerSourcePenalties test in two: one tests penalty - - enforcement but not penalty expiry, the other tests penalty expiry. + upstream: include pathname in some of the ssh-keygen passphrase - This lets us disable the expiry testing in certain CI test environments. + prompts. Helps the user know what's going on when ssh-keygen is invoked via + other tools. Requested in GHPR503 - OpenBSD-Regress-ID: f56811064f3e3cb52ee73a206b8c2a06af1c8791 + OpenBSD-Commit-ID: 613b0bb6cf845b7e787d69a5b314057ceda6a8b6 -commit b2c64bc170d75823622a37cab3ca1804ca87ad16 -Author: Damien Miller -Date: Fri Jun 14 14:19:23 2024 +1000 +commit 62bbf8f825cc390ecb0523752ddac1435006f206 +Author: djm@openbsd.org +Date: Sun Sep 15 00:41:18 2024 +0000 - add a sshd_config PamServiceName option + upstream: Do not apply authorized_keys options when signature - Allows selecting which PAM service name to use when UsePAM is - enabled. Defaults to "sshd" unless overridden at compile time - by defining SSHD_PAM_SERVICE. + verification fails. Prevents restrictive key options being incorrectly + applied to subsequent keys in authorized_keys. bz3733, ok markus@ - bz2102, ok dtucker@ + OpenBSD-Commit-ID: ba3776d9da4642443c19dbc015a1333622eb5a4e -commit 9f032a4dd17bf0ae6066223d82aa5e784285d987 -Author: djm@openbsd.org -Date: Fri Jun 14 00:26:12 2024 +0000 +commit 49f325fd47af4e53fcd7aafdbcc280e53f5aa5ce +Author: Wu Weixin +Date: Fri Aug 2 22:16:40 2024 +0800 - upstream: don't redirect stderr for ssh-keyscan we expect to succeed + Fix without_openssl always being set to 1 - OpenBSD-Regress-ID: 8878b8eb4e070ed2e343166d3eb86db4a08a216c + In Fedora systems, %{?rhel} is empty. In RHEL systems, %{?fedora} is + empty. Therefore, the original code always sets without_openssl to 1. -commit 1e84d0cf40e94ae3a77d6a7ca8c036d8e3d55a40 +commit c21c3a2419bbc1c59cb1a16ea356e703e99a90d9 Author: djm@openbsd.org -Date: Fri Jun 14 00:25:25 2024 +0000 +Date: Thu Sep 12 00:36:27 2024 +0000 - upstream: make host/banner comments go to stderr instead of stdout, - - so they are useful as comments without extra shell redirection and so they - don't clutter actual errors on stderr. - - Add a -q flag to shut them up. + upstream: Relax absolute path requirement back to what it was prior to - ok dtucker@ + OpenSSH 9.8, which incorrectly required that sshd was started with an + absolute path in inetd mode. bz3717, patch from Colin Wilson - OpenBSD-Commit-ID: bec813de56a71adb5c1a76adcf49621130d24264 + OpenBSD-Commit-ID: 25c57f22764897242d942853f8cccc5e991ea058 -commit 3e806d011855d6bd648ec95b9df630ebbd11c3bf +commit 1bc426f51b0a5cfdcfbd205218f0b6839ffe91e9 Author: naddy@openbsd.org -Date: Thu Jun 13 15:06:33 2024 +0000 +Date: Mon Sep 9 14:41:21 2024 +0000 - upstream: separate keywords with comma + upstream: document the mlkem768x25519-sha256 key exchange algorithm - OpenBSD-Commit-ID: d65a99666202a8188c4991c18d14374a229f7be5 + OpenBSD-Commit-ID: fa18dccdd9753dd287e62ecab189b3de45672521 -commit abfd1f7a3cbd0a92581a0febba254b2f6649c0d9 -Author: djm@openbsd.org -Date: Fri Jun 14 00:23:55 2024 +0000 +commit 0a2db61a5ffc64d2e2961c52964f933879952fc7 +Author: Darren Tucker +Date: Tue Sep 10 21:11:14 2024 +1000 - upstream: specify an algorithm for ssh-keyscan, otherwise it will make - - multiple attempts simultaneously and confuse the test - - OpenBSD-Regress-ID: 6e910f3315c4345053db1bf5cbf61826b194d0b9 + Spell omnios test host correctly. -commit a8fbe2f7d0d96d299ee8e69769e3b51067978748 -Author: Damien Miller -Date: Thu Jun 13 16:41:29 2024 +1000 +commit 059ed698a47c9af541a49cf754fd09f984ac5a21 +Author: Darren Tucker +Date: Tue Sep 10 18:52:02 2024 +1000 - sshd: don't use argv[0] as PAM service name - - sshd would implicitly use argv[0] as the PAM service name to - allow people to select different PAM service names by making - differently-named copies/links to the sshd binary. - - Splitting sshd into sshd/sshd-session broke this, as the process - that starts PAM is always sshd-session and the user has no control - over this. - - Hardcode "sshd" as the default PAM service name unless/until we - figure out a better way. Should unbreak OSX integration tests. + Add omnios test target. -commit bf204bd05c3ae650f87e2b96527688579f59774c -Author: Damien Miller -Date: Thu Jun 13 15:00:28 2024 +1000 +commit f4ff91575a448b19176ceaa8fd6843a25f39d572 +Author: Darren Tucker +Date: Tue Sep 10 18:45:55 2024 +1000 - prepare for checking in autogenerated files - - We plan to check in automatically generated files (config.h.in, etc) on - release branches. These files are normally ignored by .gitignore, but - this shuffles the contents of this file to make it easy to un-ignore - them. + Wrap stdint.h in ifdef. -commit 425f79a837489904c343b349ef00e09aeaa4e752 -Author: Damien Miller -Date: Thu Jun 13 14:41:33 2024 +1000 +commit ff714f001d20a9c843ee1fd9d92a16d40567d264 +Author: Darren Tucker +Date: Mon Sep 9 19:31:54 2024 +1000 - typo in comment + Also test PAM on dfly64. -commit afe10313c1fa8d478af399ee7d54c8f85503013b +commit 509b757c052ea969b3a41fc36818b44801caf1cf Author: Damien Miller -Date: Thu Jun 13 14:35:25 2024 +1000 +Date: Mon Sep 9 21:50:14 2024 +1000 - fix PTY allocation on Cygwin, broken by sshd split - - Cygwin doesn't support FD passing and so used to disable post-auth - privilege separation entirely because privsep requires PTY allocation - to happen in the privileged monitor process with the PTY file - descriptors being passed back to the unprivileged process. - - This brings back a minimal version of the previous special treatment - for Cygwin (and any other platform that sets DISABLE_FD_PASSING): - privilege separation remains enabled, but PTY allocation happens in - the post-auth user process rather than the monitor. + stubs for ML-KEM KEX functions - This either requires PTY allocation to not need privilege to begin - with (this appears to be the case on Cygwin), or the post-auth - privsep process retain privilege (other platforms that set the - DISABLE_FD_PASSING option). + used for C89 compilers + +commit 273581210c99ce7275b8efdefbb9f89e1c22e341 +Author: Damien Miller +Date: Mon Sep 9 17:30:38 2024 +1000 + + declare defeat trying to detect C89 compilers - Keeping privileges here is bad, but the non-Cygwin systems that set - DISABLE_FD_PASSING are so deeply legacy that this is likely to be the - least of their problems. + I can't find a reliable way to detect the features the ML-KEM code + requires in configure. Give up for now and use VLA support (that we + can detect) as a proxy for "old compiler" and turn off ML-KEM if + it isn't supported. -commit f66d4df5749551380a8c4ae642347675a0b6a2e9 +commit e8a0f19b56dfa20f98ea9876d7171ec315fb338a Author: Damien Miller -Date: Thu Jun 13 11:33:09 2024 +1000 +Date: Mon Sep 9 16:46:40 2024 +1000 - delay lookup of privsep user until config loaded + fix previous; check for C99 compound literals - sshd-session attempting to use options.kerberos_authentication to - decide whether it needed to lookup the privsep user before the - configuration was loaded. This caused it to get a placeholder value - that caused it always to try to lookup the privsep user, breaking at - least one test environment. + The previous commit was incorrect (or at least insufficient), the + ML-KEM code is actually using compound literals, so test for them. -commit f1c42858b94f5d9b58867b34dce3afb39c6b56a8 +commit 7c07bec1446978bebe0780ed822c8fedfb377ae8 Author: Damien Miller -Date: Thu Jun 13 11:16:57 2024 +1000 +Date: Mon Sep 9 16:06:21 2024 +1000 - missing file for PerSourcePenalties regress test + test for compiler feature needed for ML-KEM + + The ML-KEM implementation we uses need the compiler to support + C99-style named struct initialisers (e.g foo = {.bar = 1}). We + still support (barely) building OpenSSH with older compilers, so + add a configure test for this. -commit 4de80ff4e6fab5a6bb0028e7d57c6c23d1485adb +commit d469d5f348772058789d35332d1ccb0b109c28ef Author: djm@openbsd.org -Date: Wed Jun 12 22:36:00 2024 +0000 +Date: Mon Sep 9 03:13:39 2024 +0000 - upstream: split PerSourcePenalties address tracking. Previously it + upstream: test mlkem768x25519-sha256 - used one shared table and overflow policy for IPv4 and IPv6 addresses, now it - will use separate tables and optionally different overflow policies. + OpenBSD-Regress-ID: 7baf6bc39ae55648db1a2bfdc55a624954847611 + +commit 62fb2b51bb7f6863c3ab697f397b2068da1c993f +Author: djm@openbsd.org +Date: Mon Sep 9 02:39:57 2024 +0000 + + upstream: pull post-quantum ML-KEM/x25519 key exchange out from - This prevents misbehaviour from IPv6 addresses (which are vastly easier - to obtain many of) from affecting IPv4 connections and may allow for - stricter overflow policies. + compile-time flag now than an IANA codepoint has been assigned for the + algorithm. - ok deraadt@ + Add mlkem768x25519-sha256 in 2nd KexAlgorithms preference slot. - OpenBSD-Commit-ID: 12637ed0aa4d5f1f3e702da42ea967cbd8bfdfd9 - -commit 06ab4c6931b0aaa4334db2faaa7e1069e76d0df6 -Author: jmc@openbsd.org -Date: Tue Jun 11 05:24:39 2024 +0000 - - upstream: do not mark up "(default: 20ms)"; + ok markus@ - OpenBSD-Commit-ID: 54151ecdecfa1b67dcdda4fd24826ef6e2148ad4 + OpenBSD-Commit-ID: 9f50a0fae7d7ae8b27fcca11f8dc6f979207451a -commit cfe243cd9fde148ed060637876e27bb55ac78be9 +commit a8ad7a2952111c6ce32949a775df94286550af6b Author: djm@openbsd.org -Date: Tue Jun 11 02:54:51 2024 +0000 +Date: Fri Sep 6 02:30:44 2024 +0000 - upstream: reap preauth net child if it hangs up during privsep message + upstream: make parsing user@host consistently look for the last '@' in - send, not just message receive + the string rather than the first. This makes it possible to use usernames + that contain '@' characters. + MIME-Version: 1.0 + Content-Type: text/plain; charset=UTF-8 + Content-Transfer-Encoding: 8bit - OpenBSD-Commit-ID: 02a093f4ab4f8f83f0cd1ea2bb35b9ca420448f0 + Prompted by Max Zettlmeißl; feedback/ok millert@ + + OpenBSD-Commit-ID: 0b16eec246cda15469ebdcf3b1e2479810e394c5 -commit b0a711c00b9c64afd1c9d6fb538275c6604a2676 +commit 13cc78d016b67a74a67f1c97c7c348084cd9212c Author: djm@openbsd.org -Date: Tue Jun 11 01:58:27 2024 +0000 +Date: Wed Sep 4 05:33:34 2024 +0000 - upstream: fix PIDFILE handling, broken for SUDO=doas in last commit + upstream: be more strict in parsing key type names. Only allow - here + shortnames (e.g "rsa") in user-interface code and require full SSH protocol + names (e.g. "ssh-rsa") everywhere else. - OpenBSD-Regress-ID: 96fec579af228f87a036e94801eb294af9074625 + Prompted by bz3725; ok markus@ + + OpenBSD-Commit-ID: b3d8de9dac37992eab78adbf84fab2fe0d84b187 -commit 90fb801e2d9241be50a2a7ff79428386442a041f +commit ef8472309a68e319018def6f8ea47aeb40d806f5 Author: djm@openbsd.org -Date: Tue Jun 11 02:00:30 2024 +0000 +Date: Wed Sep 4 05:11:33 2024 +0000 - upstream: reap the pre-auth [net] child if it hangs up during privsep - - message sending, not just receiving + upstream: fix RCSID in output - OpenBSD-Commit-ID: f7341605bf08c4c15830910446e6775323f2f8cb + OpenBSD-Commit-ID: 889ae07f2d2193ddc4351711919134664951dd76 -commit ef878d58798f6688c7f4d4e417dc0c29023ea831 -Author: djm@openbsd.org -Date: Tue Jun 11 01:23:25 2024 +0000 +commit ba2ef20c75c5268d4d1257adfc2ac11c930d31e1 +Author: jmc@openbsd.org +Date: Tue Sep 3 06:17:48 2024 +0000 - upstream: a little more RB_TREE paranoia + upstream: envrionment -> environment; - OpenBSD-Commit-ID: 8dc2fd21eebd8830c4a4d25461ac4fe228e11156 + OpenBSD-Commit-ID: b719f39c20e8c671ec6135c832d6cc67a595af9c -commit fc4e96b2174d6a894d2033421699d091679baced +commit e66c0c5673a4304a3a9fbf8305c6a19f8653740f +Author: Damien Miller +Date: Wed Sep 4 15:35:29 2024 +1000 + + add basic fuzzers for our import of sntrup761 + +commit d19dea6330ecd4eb403fef2423bd7e127f4c9828 Author: djm@openbsd.org -Date: Tue Jun 11 01:22:25 2024 +0000 +Date: Tue Sep 3 05:58:56 2024 +0000 - upstream: fix off-by-one comparison for PerSourcePenalty + upstream: regression test for Include variable expansion - OpenBSD-Commit-ID: af4f5d01c41ef870b23e55655bfbf73474a6c02b + OpenBSD-Regress-ID: 35477da3ba1abd9ca64bc49080c50a9c1350c6ca -commit 82c836df4ff41145553cd7adb11c5b985aeaa06f +commit 8c4d6a628051e318bae2f283e8dc38b896400862 Author: djm@openbsd.org -Date: Tue Jun 11 01:21:41 2024 +0000 +Date: Tue Sep 3 05:29:55 2024 +0000 - upstream: move tree init before possible early return + upstream: allow the "Include" directive to expand the same set of - OpenBSD-Commit-ID: 72e2c5b69f151c08a7c5bf5ad929b97a92c273df + %-tokens that "Match Exec" and environment variables. + + ok dtucker@ + + OpenBSD-Commit-ID: 12ef521eaa966a9241e684258564f52f1f3c5d37 -commit a2300f015cc4939c4d9c564b58b74e71202dc978 +commit 51b82648b6827675fc0cde21175fd1ed8e89aab2 Author: djm@openbsd.org -Date: Tue Jun 11 01:07:35 2024 +0000 +Date: Mon Sep 2 12:18:35 2024 +0000 - upstream: update to mention that PerSourcePenalties default to - - being enabled and document the default values for each parameter. + upstream: missing ifdef - OpenBSD-Commit-ID: b981288bddfb097aad269f62df4081c688ce0034 + OpenBSD-Commit-ID: 85f09da957dd39fd0abe08fe5ee19393f25c2021 -commit 41987efd356d3fc30139aeab4b09374acf8f91a0 +commit f68312eb593943127b39ba79a4d7fa438c34c153 Author: djm@openbsd.org -Date: Tue Jun 11 00:44:52 2024 +0000 +Date: Mon Sep 2 12:13:56 2024 +0000 - upstream: reap the [net] child if it hangs up while writing privsep + upstream: Add experimental support for hybrid post-quantum key exchange - message payloads, not just the message header + ML-KEM768 with ECDH/X25519 from the Internet-draft: + https://datatracker.ietf.org/doc/html/draft-kampanakis-curdle-ssh-pq-ke-03 - OpenBSD-Commit-ID: 24dbd400aa381ac96be7ed2dd49018487dfef6ce + This is based on previous patches from markus@ but adapted to use the + final FIPS203 standard ML-KEM using a formally-verified implementation + from libcrux. + + Note this key exchange method is still a draft and thus subject to + change. It is therefore disabled by default; set MLKEM=yes to build it. + We're making it available now to make it easy for other SSH + implementations to test against it. + + ok markus@ deraadt@ + + OpenBSD-Commit-ID: 02a8730a570b63fa8acd9913ec66353735dea42c -commit 6211aa085fa91155a24922e5329576ac9a8f3175 -Author: djm@openbsd.org -Date: Tue Jun 11 00:40:21 2024 +0000 +commit 05f2b141cfcc60c7cdedf9450d2b9d390c19eaad +Author: Antonio Larrosa +Date: Fri Aug 23 12:21:06 2024 +0200 - upstream: log waitpid() status for abnormal exits + Don't skip audit before exitting cleanup_exit - OpenBSD-Commit-ID: b317930e06b51819c1a2bc6a4359764fecfb1c2d + This fixes an issue where the SSH_CONNECTION_ABANDON event is not + audited because cleanup_exit overrides the regular _exit too soon and + as a result, failed auth attempts are not logged correctly. + + The problem was introduced in 81c1099d22b81ebfd20a334ce986c4f753b0db29 + where the code from upstream was merged before the audit_event call when + it should have been merged right before the _exit call in order to honor + the comment that just mentions an override of the exit value. -commit a59634c7adb9ae988748d99963dfafb3070d8d41 +commit 16eaf9d401e70996f89f3f417738a8db421aa959 Author: djm@openbsd.org -Date: Tue Jun 11 00:36:20 2024 +0000 +Date: Wed Aug 28 12:08:26 2024 +0000 - upstream: correct error message + upstream: fix test: -F is the argument to specify a non-default - OpenBSD-Commit-ID: 581f60f73099083392887206860229ab104620ed + ssh_config, not -f (this is sadly not a new bug) + + OpenBSD-Regress-ID: 45a7bda4cf33f2cea218507d8b6a55cddbcfb322 -commit fa7d7a667f2ee031e72873e36de2d2a36bca973b +commit 10ccf611ab8ecba9ce6b0548c5ccd8c1220baf92 Author: deraadt@openbsd.org -Date: Fri Jun 7 13:23:30 2024 +0000 +Date: Fri Aug 23 04:51:00 2024 +0000 - upstream: avoid shadowing issues which some compilers won't accept + upstream: As defined in the RFC, the SSH protocol has negotiable - ok djm + compression support (which is requested as the name "zlib"). Compression + starts very early in the session. Relative early in OpenSSH lifetime, privsep + was added to sshd, and this required a shared-memory hack so the two + processes could see what was going on in the dataflow. This shared-memory + hack was soon recognized as a tremendous complexity risk, because it put libz + (which very much trusts it's memory) in a dangerous place, and a new option + ("zlib@openssh.com") was added begins compression after authentication (aka + delayed-compression). That change also permitted removal of the + shared-memory hack. Despite removal from the server, the old "zlib" support + remained in the client, to allow negotiation with non-OpenSSH daemons which + lack the delayed-compression option. This commit deletes support for the + older "zlib" option in the client. It reduces our featureset in a small way, + and encourages other servers to move to a better design. The SSH protocol is + different enough that compressed-key-material attacks like BEAST are + unlikely, but who wants to take the chance? We encourage other ssh servers + who care about optional compression support to add delayed-zlib support. + (Some already do "zlib@openssh.com") ok djm markus - OpenBSD-Commit-ID: 1e89572397dda83433d58c4fa6333a08f51170d4 + OpenBSD-Commit-ID: 6df986f38e4ab389f795a6e39e7c6857a763ba72 -commit 3ad4cd9eeca5c9bc6706db44b6de88e2e4513fd6 -Author: jmc@openbsd.org -Date: Thu Jun 6 21:14:49 2024 +0000 +commit aee54878255d71bf93aa6e91bbd4eb1825c0d1b9 +Author: djm@openbsd.org +Date: Thu Aug 22 23:11:30 2024 +0000 - upstream: escape the final dot at eol in "e.g." to avoid double + upstream: sntrup761x25519-sha512 now has an IANA codepoint assigned, so - spacing; + we can make the algorithm available without the @openssh.com suffix too. ok + markus@ deraadt@ - OpenBSD-Commit-ID: 0a9fb10bc9f7d577afe2da3f498a08bc431115b9 + OpenBSD-Commit-ID: eeed8fcde688143a737729d3d56d20ab4353770f -commit 0e0c69761a4c33ccd4a256560f522784a753d1a8 -Author: djm@openbsd.org -Date: Thu Jun 6 20:25:48 2024 +0000 +commit a76a6b85108e3032c8175611ecc5746e7131f876 +Author: Darren Tucker +Date: Thu Aug 22 20:36:12 2024 +1000 - upstream: enable PerSourcePenalties by default. - - ok markus + Move rekey test into valgrind-2. - NB. if you run a sshd that accepts connections from behind large NAT - blocks, proxies or anything else that aggregates many possible users - behind few IP addresses, then this change may cause legitimate traffic - to be denied. + Now that the rekey test has been optimized it's fast enough to not be in + its own valgrind test, so move it into valgrind-2, which is currently + the quickest of the others, bringing all of them to roughly the same + runtime of ~1.1 hours. + +commit 7e75e3f57c41b9a6e6401e7674d7c2ff5c33975b +Author: dtucker@openbsd.org +Date: Thu Aug 22 10:21:02 2024 +0000 + + upstream: Use aes128-ctr for MAC tests since default has implicit MAC. - Please read the PerSourcePenalties, PerSourcePenaltyExemptList and - PerSourceNetBlockSize options in sshd_config(5) for how to tune your - sshd(8) for your specific circumstances. + Also verify that the Cipher or MAC we intended to use is actually the one + selected during the test. - OpenBSD-Commit-ID: 24a0e5c23d37e5a63e16d2c6da3920a51078f6ce + OpenBSD-Regress-ID: ff43fed30552afe23d1364526fe8cf88cbfafe1d -commit bd1f74741daabeaf20939a85cd8cec08c76d0bec -Author: djm@openbsd.org -Date: Thu Jun 6 20:20:42 2024 +0000 +commit ebc890b8b4ba08c84cd1066b7b94b2b11f6c4cb4 +Author: Damien Miller +Date: Thu Aug 22 09:45:49 2024 +1000 - upstream: mention that PerSourcePenalties don't affect concurrent - - in-progress connections. + fix incorrect default for PasswordAuthentication - OpenBSD-Commit-ID: 20389da6264f2c97ac3463edfaa1182c212d420c + merge botch spotted by gsgleason -commit 9774b938578327d88a651f4c63c504809717590a -Author: djm@openbsd.org -Date: Thu Jun 6 19:49:25 2024 +0000 +commit 15ace435ea1c2fab2a1cc7d9c3157fe20c776b80 +Author: dtucker@openbsd.org +Date: Wed Aug 21 10:33:27 2024 +0000 - upstream: regress test for PerSourcePenalties + upstream: Some awks won't match on the \r so delete it instead. Fixes - OpenBSD-Regress-ID: a1af13d411b25a727742644459d26480b9a1b0f1 + regress in portable on, eg Solaris. + + OpenBSD-Regress-ID: 44a96d6d2f8341d89b7d5fff777502b92ac9e9ba -commit b8ebd86cefe9812204a10c028dc90de29918667d -Author: djm@openbsd.org -Date: Thu Jun 6 19:48:40 2024 +0000 +commit 51c96b6ed627779a04493a8fe25747996a37f3c2 +Author: dtucker@openbsd.org +Date: Wed Aug 21 07:06:27 2024 +0000 - upstream: make sure logs are saved from sshd run via start_sshd + upstream: Import regenerated moduli. - OpenBSD-Regress-ID: de4ef0e32e3ab85ff3a6c36eb08d1909c0dd1b4a + OpenBSD-Commit-ID: 5db7049ad5558dee5b2079d3422e8ddab187c1cc -commit d7b2070bdaa4ebbfafb9975c1d5a62b73289d31f -Author: djm@openbsd.org -Date: Thu Jun 6 19:47:48 2024 +0000 +commit 25c52f37a82c4da48ec537de37d7c168982b8d6d +Author: dtucker@openbsd.org +Date: Wed Aug 21 06:59:08 2024 +0000 - upstream: simplify + upstream: Use curve25519-sha256 kex where possible. - OpenBSD-Regress-ID: 50316e0d1ae0c0a057a45af042253e54ce23d11c + Except where we're explicitly testing a different kex, use + curve25519-sha256 since it's faster than the default and supported even + when configured without OpenSSL. Add a check to ensure that the kex we + intended to test is the one we actually tested. Speeds test up by ~5%. + + OpenBSD-Regress-ID: 3b27fcc2ae953cb08fd82a0d3155c498b226d6e0 -commit e6ea3d224513b6bfb93818809d4c7397f5995ba2 -Author: djm@openbsd.org -Date: Thu Jun 6 18:48:13 2024 +0000 +commit 3eb62b7ba49483c309b483eb9002a679014f3887 +Author: dtucker@openbsd.org +Date: Tue Aug 20 12:36:59 2024 +0000 - upstream: prepare for PerSourcePenalties being enabled by default + upstream: Send only as much data as needed to trigger rekeying. Speeds - in future + up tests by about 10% in the common case, hopefully more when instrumented + with something like valgrind. - OpenBSD-Regress-ID: 5236c6d1c823997aac5a35e2915da30f1903bec7 + OpenBSD-Regress-ID: 7bf9292b4803357efcf0baf7cfbdc8521f212da1 -commit c0cb3b8c837761816a60a3cdb54062668df09652 -Author: djm@openbsd.org -Date: Thu Jun 6 19:50:01 2024 +0000 +commit cbd3f034bbf7853618fac99d7d868a2250154ea7 +Author: Damien Miller +Date: Wed Aug 21 09:18:29 2024 +1000 - upstream: disable stderr redirection before closing fds - - OpenBSD-Commit-ID: d42cb895ee4542098050367fc35321c9303f003a + simplify sshkey_prekey_alloc(); always use mmap -commit 81c1099d22b81ebfd20a334ce986c4f753b0db29 -Author: djm@openbsd.org -Date: Thu Jun 6 17:15:25 2024 +0000 +commit 4442bbc2fc661277a6dabfedb756a7e15ee8b8b8 +Author: dtucker@openbsd.org +Date: Tue Aug 20 09:15:49 2024 +0000 - upstream: Add a facility to sshd(8) to penalise particular + upstream: Merge AEAD test into main test loop. - problematic client behaviours, controlled by two new sshd_config(5) options: - PerSourcePenalties and PerSourcePenaltyExemptList. + Removes 3 duplicate tests and speeds overall test up by about 1%. - When PerSourcePenalties are enabled, sshd(8) will monitor the exit - status of its child pre-auth session processes. Through the exit - status, it can observe situations where the session did not - authenticate as expected. These conditions include when the client - repeatedly attempted authentication unsucessfully (possibly indicating - an attack against one or more accounts, e.g. password guessing), or - when client behaviour caused sshd to crash (possibly indicating - attempts to exploit sshd). + OpenBSD-Regress-ID: 5e5c9ff3f7588091ed369e34ac28520490ad2619 + +commit 829976a63fd1efae3a4c3e7c16fded59d92edb67 +Author: dtucker@openbsd.org +Date: Tue Aug 20 09:02:45 2024 +0000 + + upstream: Set a default RekeyLimit of 256k. - When such a condition is observed, sshd will record a penalty of some - duration (e.g. 30 seconds) against the client's address. If this time - is above a minimum threshold specified by the PerSourcePenalties, then - connections from the client address will be refused (along with any - others in the same PerSourceNetBlockSize CIDR range). + Used unless overridden by a command-line flag, which simplifies some of + the ssh command lines. - Repeated offenses by the same client address will accrue greater - penalties, up to a configurable maximum. A PerSourcePenaltyExemptList - option allows certain address ranges to be exempt from all penalties. + OpenBSD-Regress-ID: e7cffa57027088e10336e412b34113969f88cb87 + +commit 57d02c9ea36aebad4e7146d46e041b6b2e582f7f +Author: dtucker@openbsd.org +Date: Tue Aug 20 07:52:43 2024 +0000 + + upstream: Add Compression=no to default ssh_config. - We hope these options will make it significantly more difficult for - attackers to find accounts with weak/guessable passwords or exploit - bugs in sshd(8) itself. + All of the rekey tests use it (otherwise the encrypted byte counts would + not match) so this lets us simplify the command lines. - PerSourcePenalties is off by default, but we expect to enable it - automatically in the near future. + OpenBSD-Regress-ID: dab7ce10f4cf6c68827eb8658141272aab3ea262 + +commit 7254eb26f7c0772c4b47c3b32f6d1b15855cdd8c +Author: dtucker@openbsd.org +Date: Tue Aug 20 07:41:35 2024 +0000 + + upstream: Remove duplicate curve25519-sha256 kex. - much feedback markus@ and others, ok markus@ + curve25519-sha256@libssh.org is the pre-standardization name for the same + thing, so remove it as a duplicate. Speeds up test by a tiny amount. - OpenBSD-Commit-ID: 89ded70eccb2b4926ef0366a4d58a693de366cca + OpenBSD-Regress-ID: 5a5ee5fa1595a6e140b1cc16040bedf5996a5715 -commit 916b0b6174e203cf2c5ec9bcf409472eb7ffbf43 -Author: Damien Miller -Date: Fri Jun 7 03:31:02 2024 +1000 +commit 749896b874928c2785256cae4d75161dc3bfcc7d +Author: dtucker@openbsd.org +Date: Tue Aug 20 07:27:25 2024 +0000 - whitespace + upstream: Unnest rekey param parsing test and use ssh not sshd. + + ssh uses the same parsing code, now has "-G" to dump its config and is + slightly faster to start up. This speeds up the test slightly (~5%) in the + common case but should help more during instrumented tests, eg under + valgrind, where startup costs are magnified. + + OpenBSD-Regress-ID: 07c3acaf4c728e641033071f4441afc88141b0d0 -commit 49b55e44182b8294419aa580cbf043d5b9e3d953 -Author: deraadt@openbsd.org -Date: Tue Jun 4 15:14:45 2024 +0000 +commit 2b1762115481ff2b7a60fd4db2ae69b725437462 +Author: djm@openbsd.org +Date: Tue Aug 20 11:10:04 2024 +0000 - upstream: enable -fret-clean on amd64, for libc libcrypto ld.so + upstream: actually use the length parameter that was passed in rather - kernel, and all the ssh tools. The dynamic objects are entirely ret-clean, - static binaries will contain a blend of cleaning and non-cleaning callers. + than a constant (this makes no difference in practice because the length is + always the same); reported by martin AT nmkd.net - OpenBSD-Commit-ID: 112aacedd3b61cc5c34b1fa6d9fb759214179172 + OpenBSD-Commit-ID: 4aecce232c2fe9b16e9217ff6bcb3c848d853e7e -commit cc80d51d034bcb24fd0f2564a4bdf1612000a2a2 +commit d922762ca16a7381131b242f49d7376c41fabcb5 Author: Damien Miller -Date: Wed Jun 5 02:21:30 2024 +1000 +Date: Tue Aug 20 13:55:30 2024 +1000 - remove PRIVSEP macros for osx + private key coredump protection for Linux/FreeBSD + + platforms not supporting coredump exclusion using mmap/madvise flags + fall back to plain old malloc(3). -commit 8785491123d4d722b310c20f383570be758f8263 +commit cc048ca536d6bed6f2285b07040b0d57cd559ba5 Author: djm@openbsd.org -Date: Sat Jun 1 07:03:37 2024 +0000 +Date: Tue Aug 20 03:48:30 2024 +0000 - upstream: be really strict with fds reserved for communication with the + upstream: place shielded keys (i.e. keys at rest in RAM) into memory - separate sshd-session process - reserve them early and fatal if we can't - dup2(2) them later. The pre-split fallback to re-reading the configuration - files is not possible, so sshd-session absolutely requires the fd the - configuration is passed over to be in order. + allocated using mmap(3) with MAP_CONCEAL set. This prevents exposure of the + key material in coredumps, etc (this is in addition to other measures we take + in this area). ok deraadt@ - OpenBSD-Commit-ID: 308a98ef3c8a6665ebf92c7c9a0fc9600ccd7065 - -commit f1c8918cb98459910fb159373baea053ba4108c0 -Author: Damien Miller -Date: Fri May 31 19:12:26 2024 +1000 - - depend + OpenBSD-Commit-ID: cbbae59f337a00c9858d6358bc65f74e62261369 -commit 94b4866cb1f4b0ed29a9f367047b30f81002316f -Author: Damien Miller -Date: Fri May 31 19:11:14 2024 +1000 +commit a0b35c791cad1f85481b23ba46373060292e1c80 +Author: djm@openbsd.org +Date: Sat Aug 17 08:35:04 2024 +0000 - rename need_privsep to need_chroot + upstream: mention that ed25519 is the default key type generated and - privsep is mandatory, chroot is optional (disabled when running - sshd as non-root) - -commit e68a95142e5024b144f8eeccd5ffdee42c34f44c -Author: Damien Miller -Date: Fri May 31 19:05:34 2024 +1000 - - remove remaining use_privsep mention + clarify that rsa-sha2-512 is the default signature scheme when RSA is in use. + Based on GHPR505 from SebastianRzk + + OpenBSD-Commit-ID: 1d90df71636a04601685d2a10a8233bcc8d4f4c5 -commit b21d271f651d2536dca819cc6d74032fe98634db +commit 127a50f2c80572ed1a021feb11ecf941e92cbbef Author: djm@openbsd.org -Date: Fri May 31 09:01:08 2024 +0000 +Date: Sat Aug 17 08:23:04 2024 +0000 - upstream: warn when -r (deprecated option to disable re-exec) is + upstream: fix minor memory leak in Subsystem option parsing; from - passed + Antonio Larrosa via GHPR515 - OpenBSD-Commit-ID: 73145ef5150edbe3ce7889f0844ed8fa6155f551 + OpenBSD-Commit-ID: fff3bbefd1b2c45c98cbe45c6b857b15d8a2d364 -commit a4b5bc246cbca476deeeb4462aa31746a56e3021 +commit 171427261d2079941eb1041079dbae875da37cbc Author: djm@openbsd.org -Date: Fri May 31 08:49:35 2024 +0000 +Date: Sat Aug 17 08:09:50 2024 +0000 - upstream: typos + upstream: fix swapping of source and destination addresses in some sshd - OpenBSD-Commit-ID: edfa72eb06bfa65da30fabf7d2fe76d2d33f77bf + log messages + + OpenBSD-Commit-ID: 24d4cbb86325275df1f037545aa3b91456e52d25 -commit 8054b906983ceaed01fabd8188d3dac24c05ba39 -Author: djm@openbsd.org -Date: Mon May 27 01:52:26 2024 +0000 +commit 2a50a8f1fa57857a5e124a2280bcf61cc63c77f7 +Author: Darren Tucker +Date: Sat Aug 17 11:10:19 2024 +1000 - upstream: don't need sys/queue.h here + Add compat functions for EVP_Digest{Sign,Verify}. - OpenBSD-Commit-ID: dd137396828171eb19e4911581812ca58de6c578 + This should make LibreSSL 3.1.x through 3.3.x work again. Code from + tb@, ok djm@. Restore the test configs covering those. -commit 210d4239733da6180ce853538aeb9413d5c62ad5 -Author: naddy@openbsd.org -Date: Sun May 26 20:35:12 2024 +0000 +commit 1c3a7145260e03037cc18715b883880836fd122d +Author: Philip Hands +Date: Thu Aug 8 13:03:51 2024 +0200 - upstream: remove references to SSH1 and DSA server keys + make sure that usage & man page match - OpenBSD-Commit-ID: 57cc1c98d4f998981473734f144b904af7d178a2 + SSH-Copy-ID-Upstream: da5b1abe55b72a16e0430e7598e1573da01779c0 -commit f0b9261d7fdd0ef86806b49fe76344bd16770cd0 -Author: jsg@openbsd.org -Date: Thu May 23 23:47:16 2024 +0000 +commit cd0d681645b9adcf2467e7838bfd9d5142de4c4e +Author: Philip Hands +Date: Thu Aug 8 13:01:47 2024 +0200 - upstream: remove unused struct fwd_perm_list, no decl with complete + update copyright notices - type ok djm@ + Bump the year to 2024, but also reflect the fact that hands.com Ltd. has + been wound up in the UK, and its assets (including this copyright) have + now reverted to its owner, Philip Hands. - OpenBSD-Commit-ID: 416fb3970b7e73c76d2963c4f00cf96f2b2ee2fb + SSH-Copy-ID-Upstream: 0e4c4d072747a6568b11a790c29dd1b4ce663d7f -commit 2477a98c3ef78e63b11a1393656e00288f52ae97 -Author: naddy@openbsd.org -Date: Wed May 22 15:24:55 2024 +0000 +commit 7fc9ccdce18841ebd0a97e31e43258512ab32a32 +Author: Philip Hands +Date: Sun Aug 4 20:45:00 2024 +0200 - upstream: Do not pass -Werror twice when building with clang. + restore optionality of -i's argument - OpenBSD-Commit-ID: 5f378c38ad8976d507786dc4db9283a879ec8cd0 + SSH-Copy-ID-Upstream: f70e3abb510e4eeb040b47894e41828246c1b720 -commit 435844f5675245b4271f8581f15e6d1f34fde3bc -Author: miod@openbsd.org -Date: Wed May 22 11:49:36 2024 +0000 +commit c37aa7012b1a3c2c322fd19e71310aadc90fc674 +Author: Philip Hands +Date: Fri Aug 2 15:52:07 2024 +0200 - upstream: Do not pass -Werror if building with gcc 3, for asn1.h - - and bio.h cause (admittedly bogus) warnings with gcc 3. + avoid exploring .ssh/id*.pub subdirectories - OpenBSD-Commit-ID: fb39324748824cb0387e9d67c41d1bef945c54ea + SSH-Copy-ID-Upstream: 0b9e08b7707ad16de3c8e6a0410d9f42fbd56997 -commit fc5dc092830de23767c6ef67baa18310a64ee533 -Author: djm@openbsd.org -Date: Wed May 22 04:20:00 2024 +0000 +commit 777dce9e2e0d12f7e81e162f77749f30899869fe +Author: Philip Hands +Date: Fri Aug 2 10:07:11 2024 +0200 - upstream: this test has been broken since 2014, and has been - - testing the same key exchange algorithm repeatedly instead of testing all of - them. Spotted by nreilly AT blackberry.com in bz3692 + ensure that we're always told the source of keys - Who broke the test? me. + SSH-Copy-ID-Upstream: 1bee96f4793e8ec3fab9f9361204ae58f5cc7cae + +commit fb94fd2339848e40cad6c9bb42b822244cc1a7bc +Author: Philip Hands +Date: Wed Jul 31 23:19:51 2024 +0200 + + add $HOME to ERROR if one cannot write to ~/.ssh - OpenBSD-Regress-ID: 48f4f5946276f975667141957d25441b3c9a50e2 + SSH-Copy-ID-Upstream: ebef3e9c06e0447bff06e9d84b33023cf592e0ba -commit fd4816791beaed2fdae7eea3e1494d1972b2a39d -Author: anton@openbsd.org -Date: Sun May 19 19:10:01 2024 +0000 +commit eb5aafa1ffaeee75799141ec5ded406a65ec7d18 +Author: Philip Hands +Date: Wed Jul 31 23:19:03 2024 +0200 - upstream: Add missing kex-names.c source file required since the - - ssh split. + assert that SCRATCH_DIR is a writable directory - OpenBSD-Regress-ID: ca666223f828fc4b069cb9016bff1eb50faf9fbb + SSH-Copy-ID-Upstream: ecb2b9d10883b9a16df56c83896c9bb47a80cde2 -commit beccb7319c5449f6454889013403c336446d622e -Author: naddy@openbsd.org -Date: Fri May 17 14:42:00 2024 +0000 +commit abcc460a2af46f0d812f8433d97a8eae1d80724c +Author: Philip Hands +Date: Wed Jul 31 23:17:54 2024 +0200 - upstream: remove duplicate copy of relink kit for sshd-session + quote to avoid potential for word splitting - OpenBSD-Commit-ID: 6d2ded4cd91d4d727c2b26e099b91ea935bed504 + SSH-Copy-ID-Upstream: f379adbe06ac2ef1daf0f130752234c7f8b97e3c -commit dcd79fa141311c287e0595ede684b7116122fae0 -Author: jsg@openbsd.org -Date: Fri May 17 06:42:04 2024 +0000 +commit b3f91411fd1473605f74c40c1a91a024c7171e27 +Author: Philip Hands +Date: Wed Jul 31 23:15:11 2024 +0200 - upstream: remove prototypes with no matching function; ok djm@ + ensure ERROR output goes to STDERR - OpenBSD-Commit-ID: 6d9065dadea5f14a01bece0dbfe2fba1be31c693 + SSH-Copy-ID-Upstream: ac394b05eead3b91feb7c2ae4129a3e9b892f1e2 -commit 6454a05e7c6574d70adf17efe505a8581a86ca4f -Author: jsg@openbsd.org -Date: Fri May 17 06:38:00 2024 +0000 +commit 674b8f30f0dbacd787eb1e4e7e1ece34b5543d8f +Author: Philip Hands +Date: Thu Aug 1 14:03:06 2024 +0200 - upstream: remove externs for removed vars; ok djm@ + avoid extra space when no arg given to -i option - OpenBSD-Commit-ID: f51ea791d45c15d4927eb4ae7d877ccc1e5a2aab + SSH-Copy-ID-Upstream: feca9e67e6e37c5653445d1c733569d7abb1770e -commit f3e4db4601ef7d2feb1d6f7447e432aaf353a616 -Author: deraadt@openbsd.org -Date: Fri May 17 06:11:17 2024 +0000 +commit 0efa0e1c41427c0c6ba839a18c72c1afcd7b7cc0 +Author: Philip Hands +Date: Wed Jul 31 23:28:36 2024 +0200 - upstream: -Werror was turned on (probably just for development), + put the -i before -[pP] (matching man pages) - and this is a simple way to satisfy older gcc. + The man pages (ssh, sftp & ssh-copy-id) all list -i before the port + setting, so make the output match that order, which also seems more + natural with the port being next to the server. - OpenBSD-Commit-ID: 7f698df54384b437ce33ab7405f0b86c87019e86 + SSH-Copy-ID-Upstream: 34d5d614172c78f9a42249466c4b81975b8883a1 -commit 24a1f3e5ad6f4a49377d4c74c36637e9a239efd0 -Author: Damien Miller -Date: Fri May 17 14:50:43 2024 +1000 +commit 87831345e9745f2d13bd7a4a7972809f6788f331 +Author: Shreyas Mahangade +Date: Mon Jul 29 15:26:05 2024 +0000 - attempt at updating RPM specs for sshd-session + Minor space issue fixed + + SSH-Copy-ID-Upstream: 335e44d7be78b03962a54c3a5c99a2ff45294a54 -commit 17b566eeb7a0c6acc9c48b35c08885901186f861 -Author: djm@openbsd.org -Date: Fri May 17 04:42:13 2024 +0000 +commit 2f3010f4736b4b3f5c10a4be97a24e90ff04c5e7 +Author: Shreyas Mahangade +Date: Mon Jul 29 16:55:28 2024 +0530 - upstream: g/c unused variable + Show identity file in 'ssh' command - OpenBSD-Commit-ID: aa6ef0778a1f1bde0d73efba72a777c48d2bd010 + - Previously no identity file is shown in "ssh" command output on the line "Now try logging into the..." + - This commit makes sure whenever "ssh-copy-id" with "-i" is invoked, it also reflects in "ssh" command + + SSH-Copy-ID-Upstream: 58e022ec26cb2315eb3be581d01e0ba787082428 -commit 01fb82eb2aa0a4eaf5c394ea8bb37ea4c26f8a3f -Author: jsg@openbsd.org -Date: Fri May 17 02:39:11 2024 +0000 +commit a13856374b894397a7682b32257ed0bf67cfede9 +Author: Damien Miller +Date: Fri Aug 16 08:30:20 2024 +1000 - upstream: spelling; ok djm@ - - OpenBSD-Commit-ID: bdea29bb3ed2a5a7782999c4c663b219d2270483 + more OPENSSL_HAS_ECC -commit b88b690e99145a021fc1a1a116a11e0bce0594e7 -Author: djm@openbsd.org -Date: Fri May 17 01:45:22 2024 +0000 +commit 4da2a1a7f648979bea6eaf3b17f5f250faed4afc +Author: Damien Miller +Date: Thu Aug 15 23:35:54 2024 +1000 - upstream: allow overriding the sshd-session binary path - - OpenBSD-Regress-ID: 5058cd1c4b6ca1a15474e33546142931d9f964da + fix merge botch that broke !OPENSSL_HAS_ECC -commit a68f80f2511f0e0c5cef737a8284cc2dfabad818 -Author: anton@openbsd.org -Date: Wed Apr 3 06:01:11 2024 +0000 +commit 2c53d2f32b8e3992b61682c909ae5bc5122b6e5d +Author: Damien Miller +Date: Thu Aug 15 15:09:45 2024 +1000 - upstream: Since ssh-agent(1) is only readable by root by now, use - - ssh(1) while generating data in tests. - - OpenBSD-Regress-ID: 24eb40de2e6b0ace185caaba35e2d470331ffe68 + missed OPENSSL_HAS_ECC case -commit 92e55890314ce2b0be21a43ebcbc043b4abc232f -Author: djm@openbsd.org -Date: Fri May 17 01:17:40 2024 +0000 +commit 342dd7a219f39119b8b686b5aaa99c8e15ede368 +Author: Damien Miller +Date: Thu Aug 15 15:06:55 2024 +1000 - upstream: fix incorrect debug option name introduce in previous + retire testing aginst older LibreSSL versions - commit + libressl prior to 3.4.x lack support for the EVP_DigestSign and + EVP_DigestVerify APIs that we need now that sshkey is converted + to EVP_PKEY. - OpenBSD-Commit-ID: 66d69e22b1c072c694a7267c847f212284614ed3 + If someone makes a good case for why we should support these versions + then we could bring back support with wrappers. -commit 4ad72878af7b6ec28da6e230e36a91650ebe84c1 -Author: deraadt@openbsd.org -Date: Fri May 17 00:33:25 2024 +0000 +commit a7c6ea8eebe0f179141ec5dbf0c9e5354417930f +Author: Damien Miller +Date: Thu Aug 15 12:44:17 2024 +1000 - upstream: construct and install a relink-kit for sshd-session ok - - djm - - OpenBSD-Commit-ID: 8b3820adb4da4e139c4b3cffbcc0bde9f08bf0c6 + sync TEST_MALLOC_OPTIONS for OpenBSD -commit 02e679a2cb3f6df8e9dbb1519ed578226485157f +commit 60c2cf22e8f64f35d8b1175e4671257313f2e4d3 Author: Damien Miller -Date: Fri May 17 12:21:27 2024 +1000 +Date: Thu Aug 15 12:43:47 2024 +1000 - Makefile support for sshd-session + remove gratuitious difference from OpenBSD -commit c0416035c5eaf70a8450d11c8833c5f7068ee7ad +commit 339c4fc60a6250429d41fa8713f783d82aad4551 Author: djm@openbsd.org -Date: Fri May 17 00:32:32 2024 +0000 +Date: Thu Aug 15 00:52:23 2024 +0000 - upstream: missing files from previous + upstream: adapt to EVP_PKEY conversion - OpenBSD-Commit-ID: 4b7be4434d8799f02365552b641a7a70a7ebeb2f + OpenBSD-Regress-ID: 0e2d4efb0ed0e392e23cd8fda183fe56531ac446 -commit 03e3de416ed7c34faeb692967737be4a7bbe2eb5 +commit 63a94f99b9d7c8a48182a40192e45879d1ba8791 Author: djm@openbsd.org -Date: Fri May 17 00:30:23 2024 +0000 +Date: Fri Jul 19 04:33:36 2024 +0000 - upstream: Start the process of splitting sshd into separate - - binaries. This step splits sshd into a listener and a session binary. More - splits are planned. - - After this changes, the listener binary will validate the configuration, - load the hostkeys, listen on port 22 and manage MaxStartups only. All - session handling will be performed by a new sshd-session binary that the - listener fork+execs. - - This reduces the listener process to the minimum necessary and sets us - up for future work on the sshd-session binary. - - feedback/ok markus@ deraadt@ - - NB. if you're updating via source, please restart sshd after installing, - otherwise you run the risk of locking yourself out. + upstream: test transfers in mux proxy mode too - OpenBSD-Commit-ID: 43c04a1ab96cdbdeb53d2df0125a6d42c5f19934 + OpenBSD-Regress-ID: 2edfc980628cfef3550649cab8d69fa23b5cd6c4 -commit 1c0d81357921f8d3bab06841df649edac515ae5b +commit 7bdfc20516e288b58c8c847958059c7b141eeff9 Author: djm@openbsd.org -Date: Thu May 9 09:46:47 2024 +0000 +Date: Thu Aug 15 00:51:51 2024 +0000 - upstream: simplify exit message handling, which was more complicated + upstream: Convert RSA and ECDSA key to the libcrypto EVP_PKEY API. - than it needed to be because of unexpunged ssh1 remnants. ok markus@ + DSA remains unconverted as it will be removed within six months. - OpenBSD-Commit-ID: 8b0cd2c0dee75fb053718f442aa89510b684610b + Based on patches originally from Dmitry Belyavskiy, but significantly + reworked based on feedback from Bob Beck, Joel Sing and especially + Theo Buehler (apologies to anyone I've missed). + + ok tb@ + + OpenBSD-Commit-ID: d098744e89f1dc7e5952a6817bef234eced648b5 -commit cbbbf76aa6cd54fce32eacce1300e7abcf9461d4 +commit 0af06e2c5b898992a18c74333e75a0136506acc6 Author: tobias@openbsd.org -Date: Mon May 6 19:26:17 2024 +0000 +Date: Wed Aug 14 15:42:18 2024 +0000 - upstream: remove SSH1 leftovers + upstream: Reorder calloc arguments - Authored with Space Meyer + The first argument should be the amount, the second argument should be the + element size. Fixing this also silences some gcc compiler warnings for + portable. - ok djm + Spotted with Benny Baumann (BenBE at geshi dot org). - OpenBSD-Commit-ID: 81db602e4cb407baae472689db1c222ed7b2afa3 + ok djm@ + + OpenBSD-Commit-ID: 711ad6f7bd7fb48bf52208f2cf9f108cddb6d41a -commit bc5dcb8ab9a4e8af54a724883732af378f42ea78 +commit 56ce0aa3c6cf28d9fcbce3207457abeac91b5050 Author: tobias@openbsd.org -Date: Tue Apr 30 15:40:43 2024 +0000 +Date: Wed Aug 14 15:40:30 2024 +0000 - upstream: never close stdin - - The sanitise_stdfd call makes sure that standard file descriptors are - open (if they were closed, they are connected with /dev/null). - - Do not close stdin in any case to prevent error messages when stdin is - read multiple times and to prevent later usage of fd 0 for connections, - e.g. + upstream: Extend sshbuf validation - echo localhost | ssh-keyscan -f - -f - + Multiple sshbuf structs can be linked through a parent/child relationship. + Make sure that a single sshbuf cannot be its own parent. If this would ever + happen, it would result in reference counting issues. - While at it, make stdin-related error messages nicer. + This is a cheap way of testing this with very little overhead. It does not + detect A->B->A linkages though for performance reason and the fact that it + takes a programming error for this to occur anyway. - Authored with Max Kunzelmann + Authored with Benny Baumann (BenBE at geshi dot org). - ok djm + ok djm@ - OpenBSD-Commit-ID: 48e9b7938e2fa2f9bd47e6de6df66a31e0b375d3 + OpenBSD-Commit-ID: fb3fa9ee2cad3c7e842ebadfd7f5db220c4aaf16 -commit 6a42b70e56bef1aacdcdf06352396e837883e84f -Author: Damien Miller -Date: Wed May 8 09:43:59 2024 +1000 +commit fc48ddf6998188517af42dce807e2088b6a0c0be +Author: tobias@openbsd.org +Date: Wed Aug 14 15:37:11 2024 +0000 - sync getrrsetbyname.c with recent upstream changes + upstream: Use freezero for better readability + + It has the same meaning as the current pair of calling explicit_bzero + and free. Spotted with Benny Baumann (BenBE at geshi dot org). + + ok djm@ + + OpenBSD-Commit-ID: 939fbe9ccf52d0d48c5fa53694d6f3bb9927970c -commit 385ecb31e147dfea59c1c488a1d2011d3867e60e -Author: djm@openbsd.org -Date: Tue Apr 30 06:23:51 2024 +0000 +commit 1ff6907ec26dac6ac59fe9fe232899a63b4c14d8 +Author: tobias@openbsd.org +Date: Wed Aug 14 15:35:23 2024 +0000 - upstream: fix home-directory extension implementation, it always + upstream: Fix typo in comment - returned the current user's home directory contrary to the spec. + Spotted with Benny Baumann (BenBE at geshi dot org). - Patch from Jakub Jelen via GHPR477 + ok djm@ - OpenBSD-Commit-ID: 5afd775eab7f9cbe222d7fbae4c793de6c3b3d28 + OpenBSD-Commit-ID: 829160ac8ef3ad3409695ce3a3ade835061cae57 -commit 14e2b16bc67ffcc188906f65008667e22f73d103 -Author: djm@openbsd.org -Date: Tue Apr 30 06:16:55 2024 +0000 +commit 487faaed8f3bb9ffb19e8f807a3da72895b16421 +Author: dlg@openbsd.org +Date: Wed Jul 31 12:00:18 2024 +0000 - upstream: flush stdout after writing "sftp>" prompt when not using + upstream: add a random amount of time (up to 4 seconds) to the - editline. + grace login time. - From Alpine Linux via GHPR480 + ok deraadt@ djm@ - OpenBSD-Commit-ID: 80bdc7ffe0358dc090eb9b93e6dedb2b087b24cd + OpenBSD-Commit-ID: abd3c57aaa5861517529b322df79b6be35ee67f4 -commit 2e69a724051488e3fb3cd11531c4b5bc1764945b -Author: djm@openbsd.org -Date: Tue Apr 30 05:53:03 2024 +0000 +commit 2865f5b7520bed3e74fbbb5f8d7a44193d7a4314 +Author: naddy@openbsd.org +Date: Fri Jul 26 15:24:49 2024 +0000 - upstream: stricter validation of messaging socket fd number; disallow + upstream: document the reduced logingrace penalty - usage of stderr. Based on GHPR492 by RealHurrison + OpenBSD-Commit-ID: 9b63e0e3599d524ddc10edc4f978081382c3548b + +commit 1ec0a64c5dc57b8a2053a93b5ef0d02ff8598e5c +Author: Darren Tucker +Date: Sun Jul 28 21:26:51 2024 +1000 + + Explicitly install libssl-devel cygwin. - OpenBSD-Commit-ID: 73dbbe82ea16f73ce1d044d3232bc869ae2f2ce8 + Should fix CI tests for cygwin default config. -commit da757b022bf18c6f7d04e685a10cd96ed00f83da +commit 0bf6e5bb750b66b25c20a1c5a471f91850de3748 Author: djm@openbsd.org -Date: Tue Apr 30 05:45:56 2024 +0000 +Date: Thu Jul 25 23:44:01 2024 +0000 - upstream: add missing reserved fields to key constraint protocol + upstream: reduce logingrace penalty. - documentation. + A single forgotton login that times out should be below the penalty + threshold. - from Wiktor Kwapisiewicz via GHPR487 + ok deraadt/claudio - OpenBSD-Commit-ID: 0dfb69998cfdb3fa00cbb0e7809e7d2f6126e3df - -commit 16d0b82fa08038f35f1b3630c70116979f49784f -Author: Damien Miller -Date: Tue Apr 30 12:39:34 2024 +1000 - - depend + OpenBSD-Commit-ID: cee1f7d17597c97bff8e5092af5d136fdb08f81d -commit 66aaa678dbe59aa21d0d9d89a3596ecedde0254b +commit 29fb6f6d46b67770084b4f12bcf8a01bd535041b Author: djm@openbsd.org -Date: Tue Apr 30 02:14:10 2024 +0000 +Date: Thu Jul 25 22:40:08 2024 +0000 - upstream: correctly restore sigprocmask around ppoll() reported + upstream: Fix proxy multiplexing (-O proxy) bug - by Tõivo Leedjärv; ok deraadt@ + If a mux started with ControlPersist then later has a forwarding added using + mux proxy connection and the forwarding was used, then when the mux proxy + session terminates, the mux master process will send a channel close to the + server with a bad channel ID and crash the connection. - OpenBSD-Commit-ID: c0c0f89de5294a166578f071eade2501929c4686 + This was caused by my stupidly reusing c->remote_id for mux channel + associations when I should have just added another member to struct channel. + + ok markus@ + + OpenBSD-Commit-ID: c9f474e0124e3fe456c5e43749b97d75e65b82b2 -commit 80fb0eb21551aed3aebb009ab20aeffeb01e44e0 +commit 53d1d307438517805989c7d5616d752739a97e03 Author: djm@openbsd.org -Date: Tue Apr 30 02:10:49 2024 +0000 +Date: Thu Jul 18 01:47:27 2024 +0000 - upstream: add explict check for server hostkey type against - - HostkeyAlgorithms. Allows HostkeyAlgorithms to disable implicit fallback from - certificate keys to plain keys. ok markus@ + upstream: mention mux proxy mode - OpenBSD-Commit-ID: 364087e4a395ff9b2f42bf3aefdb2090bb23643a + OpenBSD-Commit-ID: fd77a77779f06d316a314e4540dc57c93fc3369a -commit 5b28096d31ff7d80748fc845553a4aef5bb05d86 +commit a9b90859d252c2f5a24142f985d38610ac74685f Author: jsg@openbsd.org -Date: Tue Apr 23 13:34:50 2024 +0000 +Date: Sun Jul 14 10:19:23 2024 +0000 - upstream: correct indentation; no functional change ok tb@ + upstream: fix double word; ok dtucker@ - OpenBSD-Commit-ID: dd9702fd43de546bc6a3f4f025c74d6f3692a0d4 + OpenBSD-Commit-ID: e6aff005914fa350b896d2be030be3d3b56ec0e8 -commit fd3cb8a82784e05f621dea5b56ac6f89bc53c067 -Author: semarie@openbsd.org -Date: Thu Apr 4 16:00:51 2024 +0000 +commit b05fda224bbcd2f641254534ed2175c42487f3c8 +Author: Darren Tucker +Date: Thu Jul 25 17:59:35 2024 +1000 - upstream: set right mode on ssh-agent at boot-time - - which sthen@ - ok deraadt@ + Check for SA_RESTART before using it. - OpenBSD-Commit-ID: 662b5056a2c6171563e1626f9c69f27862b5e7af + ok djm@ -commit 54343a260e3aa4bceca1852dde31cd08e2abd82b -Author: deraadt@openbsd.org -Date: Tue Apr 2 12:22:38 2024 +0000 +commit c276672fc0e99f0c4389988d54a84c203ce325b6 +Author: Yuichiro Naito +Date: Wed Sep 1 10:19:32 2021 +0900 - upstream: Oops, incorrect hex conversion spotted by claudio. + Class-imposed login restrictions - While here try to improve how it reads a bit better. Surprising the - regression tests didn't spot this error, maybe it fails to roundtrip the - values. + If the following functions are available, + add an additional check if users are allowed to login imposed by login class. - OpenBSD-Commit-ID: 866cfcc1955aef8f3fc32da0b70c353a1b859f2e + * auth_hostok(3) + * auth_timeok(3) + + These functions are implemented on FreeBSD. -commit ec78c31409590ad74efc194f886273ed080a545a -Author: deraadt@openbsd.org -Date: Tue Apr 2 10:02:08 2024 +0000 +commit 7717b9e9155209916cc6b4b4b54f4e8fa578e889 +Author: djm@openbsd.org +Date: Wed Jul 10 21:58:34 2024 +0000 - upstream: for parse_ipqos(), use strtonum() instead of mostly - - idiomatic strtoul(), but wow it's so gross. ok djm + upstream: correct keyword; from Yatao Su via GHPR509 - OpenBSD-Commit-ID: cec14a76af2eb7b225300c80fc0e21052be67b05 + OpenBSD-Commit-ID: 81c778c76dea7ef407603caa157eb0c381c52ad2 -commit 8176e1a6c2e6da9361a7abb6fbf6c23c299f495b -Author: deraadt@openbsd.org -Date: Tue Apr 2 09:56:58 2024 +0000 +commit f2b78bb8f149d6b4d1f62c21aa1f06995dccf4ce +Author: djm@openbsd.org +Date: Mon Jul 8 03:04:34 2024 +0000 - upstream: can shortcut by returning strtonum() value directly; ok - - djm + upstream: don't need return at end of void function - OpenBSD-Commit-ID: 7bb2dd3d6d1f288dac14247d1de446e3d7ba8b8e + OpenBSD-Commit-ID: 42d322d37f13aa075ae7b1ad9eef591e20b89717 -commit 9f543d7022a781f80bb696f9d73f1d1c6f9e31d6 -Author: deraadt@openbsd.org -Date: Tue Apr 2 09:52:14 2024 +0000 +commit a395d37a813c0177cb5bfc4bebf5a52badb73cf0 +Author: djm@openbsd.org +Date: Thu Jul 4 22:53:59 2024 +0000 - upstream: rewrite convtime() to use a isdigit-scanner and + upstream: fix grammar: "a pattern lists" -> "one or more pattern - strtonum() instead of strange strtoul can might be fooled by garage - characters. passes regress/usr.bin/ssh/unittests/misc ok djm + lists" - OpenBSD-Commit-ID: 4b1ef826bb16047aea3f3bdcb385b72ffd450abc + OpenBSD-Commit-ID: f3c844763398faa9800687e8ff6621225498202a -commit 8673137f780d8d9e4cda3c4605cb5d88d5cea271 -Author: claudio@openbsd.org -Date: Tue Apr 2 09:48:24 2024 +0000 +commit 8b664df75966e5aed8dabea00b8838303d3488b8 +Author: Darren Tucker +Date: Sun Jul 7 18:46:19 2024 +1000 - upstream: Remove unused ptr[3] char array in pkcs11_decode_hex. - - OK deraadt@ + Cast to sockaddr * in systemd interface. - OpenBSD-Commit-ID: 3d14433e39fd558f662d3b0431c4c555ef920481 + Fixes build with musl libx. bz#3707. -commit c7fec708f331f108343d69e4d74c9a5d86d6cfe7 -Author: deraadt@openbsd.org -Date: Tue Apr 2 09:32:28 2024 +0000 +commit 30c8c81da2169e78357d08dbb0ddd823b60e93bc +Author: Darren Tucker +Date: Thu Jul 4 20:12:26 2024 +1000 - upstream: Replace non-idiomatic strtoul(, 16) to parse a region - - of 2-character hex sequences with a low-level replacement designed just for - the task. ok djm - - OpenBSD-Commit-ID: 67bab8b8a4329a19a0add5085eacd6f4cc215e85 + Add 9.8 branch to ci-status page. -commit 019a5f483b0f588da6270ec401d0b4bb35032f3f -Author: deraadt@openbsd.org -Date: Tue Apr 2 09:29:31 2024 +0000 +commit ee6b9e661633fcefd29dba0c811cecbc4d027f6f +Author: Samuel Thibault +Date: Tue Mar 26 22:15:08 2024 +0100 - upstream: Use strtonum() instead of severely non-idomatic - - strtoul() In particular this will now reject trailing garbage, ie. - '12garbage'. ok djm + Fix detection of setres*id on GNU/Hurd - OpenBSD-Commit-ID: c82d95e3ccbfedfc91a8041c2f8bf0cf987d1501 + Like Linux, proper _SOURCE macros need to be set to get declarations of + various standard functions, notably setres*id. Now that Debian is using + -Werror=implicit-function-declaration this is really required. While at + it, define other _SOURCE macros like on GNU/Linux, since GNU/Hurd uses + the same glibc. -commit 8231ca046fa39ea4eb99b79e0a6e09dec50ac952 -Author: deraadt@openbsd.org -Date: Mon Apr 1 15:50:17 2024 +0000 +commit fa41f6592ff1b6ead4a652ac75af31eabb05b912 +Author: Damien Miller +Date: Mon Jul 1 14:33:26 2024 +1000 - upstream: also create a relink kit for ssh-agent, since it is a - - long-running setgid program carrying keys with some (not very powerful) - communication channels. solution for testing the binary from dtucker. - agreement from djm. Will add it into /etc/rc in a few days. - - OpenBSD-Commit-ID: 2fe8d707ae35ba23c7916adcb818bb5b66837ba0 + version numbers -commit bf7bf50bd6a14e49c9c243cb8f4de31e555a5a2e -Author: deraadt@openbsd.org -Date: Mon Apr 1 15:48:16 2024 +0000 +commit bfebb8a5130a792c5356bd06e1ddef72a0a0449f +Author: djm@openbsd.org +Date: Mon Jul 1 04:31:59 2024 +0000 - upstream: new-style relink kit for sshd. The old scheme created - - a Makefile by concatenating two Makefiles and was incredibly fragile. In the - new way a narrow-purposed install.sh script is created and shipped with the - objects. A recently commited /etc/rc script understands these files. + upstream: openssh-9.8 - OpenBSD-Commit-ID: ef9341d5a50f0d33e3a6fbe995e92964bc7ef2d3 + OpenBSD-Commit-ID: 5f8b89e38a4c5f7c6d52ffa19f796d49f36fab19 -commit 00e63688920905e326d8667cb47f17a156b6dc8f -Author: renmingshuai -Date: Fri Apr 12 10:20:49 2024 +0800 +commit 146c420d29d055cc75c8606327a1cf8439fe3a08 +Author: djm@openbsd.org +Date: Mon Jul 1 04:31:17 2024 +0000 - Shell syntax fix (leftover from a sync). + upstream: when sending ObscureKeystrokeTiming chaff packets, we - Signed-off-by: renmingshuai + can't rely on channel_did_enqueue to tell that there is data to send. This + flag indicates that the channels code enqueued a packet on _this_ ppoll() + iteration, not that data was enqueued in _any_ ppoll() iteration in the + timeslice. ok markus@ + + OpenBSD-Commit-ID: 009b74fd2769b36b5284a0188ade182f00564136 -commit 2eded551ba96e66bc3afbbcc883812c2eac02bd7 -Author: Darren Tucker -Date: Thu Apr 25 13:20:19 2024 +1000 +commit 637e4dfea4ed81264e264b6200172ce319c64ead +Author: djm@openbsd.org +Date: Mon Jul 1 03:10:19 2024 +0000 - Merge flags for OpenSSL 3.x versions. + upstream: use "lcd" to change directory before "lls" rather then "cd", - OpenSSL has moved to 3.4 which we don't currently accept. Based on - the OpenSSL versioning policy[0] it looks like all of the 3.x versions - should work with OpenSSH, so remove the distinction in configure and - accept all of them. + since the directory we're trying to list is local. Spotted by Corinna + Vinschen - [0] https://openssl.org/policies/general/versioning-policy.html + OpenBSD-Regress-ID: 821feca4a4bebe491944e624c8f7f2990b891415 -commit 8673245918081c6d1dc7fb3733c8eb2c5a902c5e -Author: Darren Tucker -Date: Thu Apr 25 13:19:03 2024 +1000 +commit c8cfe258cee0b8466ea84597bf15e1fcff3bc328 +Author: djm@openbsd.org +Date: Thu Jun 27 23:01:15 2024 +0000 - Remove 9.6 branch from status page. + upstream: delete obsolete comment + + OpenBSD-Commit-ID: 5fb04f298ed155053f3fbfdf0c6fe7cdf84bbfa2 -commit 70d43049747fa3c66cf876d52271859407cec2fa -Author: Darren Tucker -Date: Thu Apr 25 13:16:58 2024 +1000 +commit 94b9d37100f6fa536aaa1d1a0e4926fe44fbf04d +Author: djm@openbsd.org +Date: Thu Jun 27 22:36:44 2024 +0000 - Update LibreSSL and OpenSSL versions tested. + upstream: retire unused API - Update LibreSSL versions to current releases (3.8.4 & 3.9.1). - Add newly-released OpenSSL 3.3.0, and add tests against the 3.1 and - 3.3 branches. + OpenBSD-Commit-ID: 3e30d7b0615e2707f6bbe70f61b1c2f72f78161b -commit 88351eca17dcc55189991ba60e50819b6d4193c1 -Author: 90 -Date: Fri Apr 5 19:36:06 2024 +0100 +commit 268c3a7f5783e731ed60f4e28da66ee3743581d3 +Author: jmc@openbsd.org +Date: Thu Jun 27 21:02:16 2024 +0000 - Fix missing header for systemd notification + upstream: ssl(8) no longer contains a HISTORY section; + + OpenBSD-Commit-ID: 83b7ff34433d79595e9c2a5d2a561a6660251245 -commit 08f579231cd38a1c657aaa6ddeb8ab57a1fd4f5c -Author: Damien Miller -Date: Wed Apr 3 14:40:32 2024 +1100 +commit 12b6cc09ce6c430681f03af2a8069e37a664690b +Author: djm@openbsd.org +Date: Wed Jun 26 23:47:46 2024 +0000 - notify systemd on listen and reload + upstream: move child process waitpid() loop out of SIGCHLD handler; - Standalone implementation that does not depend on libsystemd. - With assistance from Luca Boccassi, and feedback/testing from Colin - Watson. bz2641 + ok deraadt + + OpenBSD-Commit-ID: 65815a39564e431414aed7c5ace8076f4e9ca741 -commit 43e7c1c07cf6aae7f4394ca8ae91a3efc46514e2 -Author: Darren Tucker -Date: Sun Mar 31 21:51:57 2024 +1100 +commit d6bcd13297c2ab8b528df5a6898f994734849031 +Author: deraadt@openbsd.org +Date: Wed Jun 26 23:16:52 2024 +0000 - Port changes from selfhosted to upstream tests. + upstream: Instead of using possibly complex ssh_signal(), write all - Should get them working again. + the parts of the grace_alarm_handler() using the exact things allowed by the + signal-safe rules. This is a good rule of thumb: Handlers should be written + to either set a global volatile sig_atomic_t inspected from outside, and/or + directly perform only safe operations listed in our sigaction(2) manual page. + ok djm markus + + OpenBSD-Commit-ID: 14168ae8368aab76e4ed79e17a667cb46f404ecd -commit 281ea25a44bff53eefb4af7bab7aa670b1f8b6b2 -Author: Darren Tucker -Date: Sat Mar 30 18:20:16 2024 +1100 +commit b8793e2b0851f7d71b97554fa5260b23796d6277 +Author: deraadt@openbsd.org +Date: Wed Jun 26 23:14:14 2024 +0000 - Check if OpenSSL implementation supports DSA. + upstream: save_errno wrappers inside two small signal handlers that - If --enable/disable-dsa-keys is not specified, set based on what OpenSSL - supports. If specified as enabled, but not supported by OpenSSL error - out. ok djm@ + perform system calls, for systems with libc that do perform libc sigtramps. + ok djm markus + + OpenBSD-Commit-ID: 7749b56419a7c9dcfe4c6c04811e429813346c62 -commit 2d2c068de8d696fe3246f390b146197f51ea1e83 -Author: djm@openbsd.org -Date: Sat Mar 30 05:56:22 2024 +0000 +commit f23e9332c4c8df37465c4a4f38275ea98980ed7e +Author: jmc@openbsd.org +Date: Mon Jun 24 06:59:39 2024 +0000 - upstream: in OpenSSH private key format, correct type for subsequent + upstream: - uppercase start of sentence - correct sentence grammar - private keys in blob. From Jakub Jelen via GHPR430 + ok djm - OpenBSD-Commit-ID: d17dbf47554de2d752061592f95b5d772baab50b + OpenBSD-Commit-ID: 1ec4b0fdb633a43667f2c8fff1d600bd647dde25 -commit c2c0bdd3e96b3ef66d77fccb85ff4962dc76caf0 -Author: Eero Häkkinen -Date: Sat Sep 16 00:55:08 2023 +0300 +commit 1839e3eb71a759aa795602c1e4196300f4ac2615 +Author: djm@openbsd.org +Date: Mon Jun 24 04:05:11 2024 +0000 - Expose SSH_AUTH_INFO_0 always to PAM auth modules. + upstream: mention SshdSessionPath option - This changes SSH_AUTH_INFO_0 to be exposed to PAM auth modules also - when a password authentication method is in use and not only - when a keyboard-interactive authentication method is in use. + OpenBSD-Commit-ID: c29734d36c21003973b15c1c9965c35f36cef30c -commit 02c5ad23124ae801cf248d99ea5068fc4331ca01 +commit 603193e32aef5db7d60c58066d5de89806e79312 Author: Darren Tucker -Date: Wed Mar 27 17:42:58 2024 +1100 +Date: Thu Jun 20 18:45:14 2024 +1000 - Rearrange selfhosted VM scheduling. - - Instead of trying to infer the type of the self hosted tests in each of - the driver scripts (inconsistently...), set one of the following - variables to "true" in the workflow: - - VM: tests run in a virtual machine. - EPHEMERAL: tests run on an ephemeral virtual machine. - PERSISTENT: tests run on a persistent virtual machine - REMOTE: tests run on a physical remote host. - - EPHEMERAL VMs can have multiple instances of any given VM can exist - simultaneously and are run by a runner pool. The other types have a - dedicated runner instance and can only run a single test at a time. - - Other settings: - SSHFS: We need to sshfs mount over the repo so the workflow can collect - build artifacts. This also implies the tests must be run over ssh. - DEBUG_ACTIONS: enable "set -x" in scripts for debugging. + Rerun upstream tests on .sh file changes too. -commit cd8a72707c02615365d0851ac51063ab6bfe258f -Author: Damien Miller -Date: Sat Mar 30 16:05:59 2024 +1100 +commit dbbf9337c19381786a8e5a8a49152fe6b80c780d +Author: dtucker@openbsd.org +Date: Thu Jun 20 08:23:18 2024 +0000 - add new token-based signing key for dtucker@ + upstream: Work around dbclient cipher/mac query bug. - Verified in person and via signature with old key. - Will remove old key in a bit. + Unlike earlier versions, recent Dropbear (at least v2024.85) requires + a host arg when querying supported ciphers and macs via "-c/-m + help". Earlier versions accept but do not require it, so always + provide it. If these queries fail, skip the test with a warning. + + OpenBSD-Regress-ID: 98eb863a3f0363416922efb273885e6b3c7f68d4 -commit 8d0e46c1ddb5b7f0992591b0dc5d8aaa77cc9dba -Author: Alkaid -Date: Tue Mar 12 03:59:12 2024 -0700 +commit 8de2c8cebc46bbdb94b7a2c120fcadfb66a3cccc +Author: dtucker@openbsd.org +Date: Thu Jun 20 08:18:34 2024 +0000 - Fix OpenSSL ED25519 support detection + upstream: Remove dropbear key types not supported - Wrong function signature in configure.ac prevents openssh from enabling - the recently new support for ED25519 priv keys in PEM PKCS8 format. + by current OpenSSH. Allows subsequent test runs to work if OpenSSH is + rebuilt w/out OpenSSL. + + OpenBSD-Regress-ID: e0129eb2b1d31771105903a8055216fbba20a770 -commit 697359be9c23ee43618243cdbcc9c7981e766752 +commit e9b6471c59b21e5d9ef1b3832d4bf727338add85 Author: djm@openbsd.org -Date: Sat Mar 30 04:27:44 2024 +0000 +Date: Thu Jun 20 00:18:05 2024 +0000 - upstream: allow WAYLAND_DISPLAY to enable SSH_ASKPASS - - From dkg via GHPR479; ok dtucker@ + upstream: stricter check for overfull tables in penalty record path - OpenBSD-Commit-ID: 1ac1f9c45da44eabbae89375393c662349239257 + OpenBSD-Commit-ID: 7df01e648a0723418c554e64a9f2b6d38db060a6 -commit 7844705b0364574cc70b941be72036c2c2966363 -Author: dtucker@openbsd.org -Date: Fri Mar 29 10:40:07 2024 +0000 +commit d9336d344eb2a1e898c5e66147b3f108c7214694 +Author: djm@openbsd.org +Date: Wed Jun 19 23:24:47 2024 +0000 - upstream: Use egrep instead of grep -E. + upstream: put back reaping of preauth child process when writes - Some plaforms don't have the latter so this makes things easier - in -portable. + from the monitor fail. Not sure how this got lost in the avalanche of + patches. - OpenBSD-Regress-ID: ff82260eb0db1f11130200b25d820cf73753bbe3 + OpenBSD-Commit-ID: eb7eb36371e1ac01050b32b70fb2b3e5d98e72f5 -commit 22b2b6c555334bffdf357a2e4aa74308b03b83c3 -Author: dtucker@openbsd.org -Date: Tue Mar 26 08:09:16 2024 +0000 +commit 579d9adb70ec0206a788eb5c63804c31a67e9310 +Author: naddy@openbsd.org +Date: Mon Jun 17 13:50:18 2024 +0000 - upstream: test -h is the POSIXly way of testing for a symlink. Reduces - - diff vs Portable. + upstream: remove one more mention of DSA - OpenBSD-Regress-ID: 6f31cd6e231e3b8c5c2ca0307573ccb7484bff7d + OpenBSD-Commit-ID: 8515f55a15f02836ba657df341415f63c60526ca -commit edcff77f82c2bb2b5653b36f1e47274c5ef3e8be +commit 7089b5f8436ef0b8d3d3ad9ce01045fb9e7aab15 Author: Darren Tucker -Date: Tue Mar 26 18:58:58 2024 +1100 +Date: Wed Jun 19 23:09:05 2024 +1000 - Fix name of OpenBSD upstream CI jobs. + Move -f to the place needed to restart sshd. -commit 861b084429940e024f1b6e9c2779eac95d7a45db +commit d5f83cfd852b14a25f347f082ab539a9454702ad Author: Darren Tucker -Date: Tue Mar 26 18:55:33 2024 +1100 +Date: Wed Jun 19 21:04:01 2024 +1000 - Resync with upstream: ${} around DATAFILE. + Need to supply "-f" to restart sshd. -commit 63f248c7693e7f0a3b9a13d2980ac9a7e37f2aea -Author: djm@openbsd.org -Date: Mon Mar 25 19:28:09 2024 +0000 +commit fad34b4ca25c0ef31e5aa841d461b6f21da5b8c1 +Author: dtucker@openbsd.org +Date: Wed Jun 19 10:15:51 2024 +0000 - upstream: optional debugging + upstream: Provide defaults for ciphers and macs - OpenBSD-Regress-ID: b4852bf97ac8fb2e3530f2d5f999edd66058d7bc + if querying for them fails since on some versions of Dropbear (at least + v2024.85) "-m help" doesn't seem to work. Enable all supported pubkey + algorithms in the server. + + OpenBSD-Regress-ID: 4f95556a49ee9f621789f25217c367a33d2745ca -commit 16e2ebe06a62f09d4877b769876d92d6008a896f +commit 5521060e35ada9f957cecdddc06d0524e75409ef Author: dtucker@openbsd.org -Date: Mon Mar 25 06:05:42 2024 +0000 +Date: Wed Jun 19 10:10:46 2024 +0000 - upstream: Verify string returned from local shell command. + upstream: Use ed25519 keys for kex tests - OpenBSD-Regress-ID: 5039bde24d33d809aebfa8d3ad7fe9053224e6f8 + since that's supported by OpenSSH even when built without OpenSSL. + Only test diffie-hellman kex if OpenSSH is compiled with support for it. + + OpenBSD-Regress-ID: a5d09ef9bbd171f9e4ec73ed0d9eeb49a8878e97 -commit b326f7a1f39ff31324cc3fe2735178fb474c04a4 +commit dbd3b833f6e3815e58f2dc6e14f61a51bcd4d6bd Author: dtucker@openbsd.org -Date: Mon Mar 25 03:30:31 2024 +0000 +Date: Wed Jun 19 10:08:34 2024 +0000 - upstream: Improve shell portability: grep -q is not portable so + upstream: Rework dropbear key setup - redirect stdout, and use printf instead of relying on echo to do \n - substitution. Reduces diff vs Portable. + to always generate ed25519 keys, other types only if OpenSSH has support + for the corresponding key type. - Also resync somewhat with upstream. + OpenBSD-Regress-ID: 8f91f12604cddb9f8d93aa34f3f93a3f6074395d + +commit d6218504e11ae9148adf410fc69b0710a052be36 +Author: Darren Tucker +Date: Wed Jun 19 20:20:24 2024 +1000 + + Restart sshd after installing it for testing. - OpenBSD-Regress-ID: 9ae876a8ec4c4725f1e9820a0667360ee2398337 + When installing an sshd built without OpenSSL the mismatch between + the running sshd and newly installed sshd-session will cause the + remainder of the test to fail. -commit dbf2e319f0c582613fa45a735ea3c242ce56946b -Author: dtucker@openbsd.org -Date: Mon Mar 25 02:07:08 2024 +0000 +commit 786a4465b6bb702daf4fb17b7c3bcb42b52f0b46 +Author: Darren Tucker +Date: Tue Jun 18 19:59:59 2024 +1000 - upstream: Save error code from SSH for use inside case statement, - - from portable. In some shells, "case" will reset the value of $?, so save it - first. + Remove macos-11 runner. - OpenBSD-Regress-ID: da32e5be19299cb4f0f7de7f29c11257a62d6949 + Github is retiring them soon. -commit d2c8c4fa7def4fb057ed05b3db57b62c810a26f6 -Author: dtucker@openbsd.org -Date: Mon Mar 25 01:40:47 2024 +0000 +commit df1c72a55edbebac14363b57de66ac6a147ecc67 +Author: Damien Miller +Date: Wed Jun 19 09:34:34 2024 +1000 - upstream: Increase timeout. Resyncs with portable where some of - - the test VMs are slow enough for this to matter. - - OpenBSD-Regress-ID: 6a83a693602eb0312f06a4ad2cd6f40d99d24b26 + PAMServiceName may appear in a Match block -commit 83621b63514a84791623db3efb59d38bc4bf9563 +commit de1c2e70e5a5dc3c8d2fe04b24cc93d8ef6930e7 Author: dtucker@openbsd.org -Date: Mon Mar 25 01:28:29 2024 +0000 +Date: Tue Jun 18 08:11:48 2024 +0000 - upstream: In PuTTY interop test, don't assume the PuTTY major + upstream: Re-enable ssh-dss tests - version is 0. Patch from cjwatson at debian.org via bz#3671. + ... if ssh is compiled with DSA support - OpenBSD-Regress-ID: 835ed03c1b04ad46be82e674495521f11b840191 + OpenBSD-Regress-ID: bbfaf8c17f2b50a2d46ac35cb97af99b990c990d -commit 8a421b927700f3834b4d985778e252b8e3299f83 -Author: Darren Tucker -Date: Tue Mar 26 18:38:14 2024 +1100 +commit dabc2c7cf3c141e8e5d5a1a60d6c1d2d2422cf43 +Author: anton@openbsd.org +Date: Tue Jun 18 06:14:27 2024 +0000 - Really mkdir /usr/local/etc in CI tests. + upstream: Stop using DSA in dropbear interop tests. + + OpenBSD-Regress-ID: abfd4457d99d8cc1417fd22ca2c570270f74c1cf -commit 2946ed522c47ce045314533d426b4e379f745e59 -Author: Darren Tucker -Date: Tue Mar 26 17:19:09 2024 +1100 +commit 761438012710169445acc179e3870c53c862bda0 +Author: Damien Miller +Date: Tue Jun 18 12:29:45 2024 +1000 - Better short name for OpenBSD upstream CI jobs too. + missed a bit of DSA in the fuzzer -commit 18dbe8eff647aacb82d7e86b4ce63d5beee11f25 -Author: Darren Tucker -Date: Tue Mar 26 17:13:52 2024 +1100 +commit 3f9cc47da588e8de520720e59f98438043fdaf93 +Author: Damien Miller +Date: Tue Jun 18 09:35:53 2024 +1000 - Ensure /usr/local/etc exists before using in tests. + DSA support is disabled, so remove from fuzzers -commit 5fc1085128e3348bb1b5ee4d955cc767b019b3ad -Author: Darren Tucker -Date: Tue Mar 26 16:50:46 2024 +1100 +commit 00eb95957dea5484b2c7c043f7d2bbc87301bef2 +Author: djm@openbsd.org +Date: Mon Jun 17 08:30:29 2024 +0000 - Be more specific about when to rerun workflows. + upstream: disable the DSA signature algorithm by default; ok + + markus@ + + (yes, I know this expands to "the Digitial Signature Algorithm + signature algorithm) + + OpenBSD-Commit-ID: 961ef594e46dd2dcade8dd5721fa565cee79ffed -commit 5516923e8ae3da0823fea0d7d28aa813627142c0 -Author: Darren Tucker -Date: Tue Mar 26 16:35:27 2024 +1100 +commit 5603befe11c9464ea26fe77cbacc95a7cc0b1ea7 +Author: djm@openbsd.org +Date: Mon Jun 17 08:28:31 2024 +0000 - Add short names for test jobs on github CI. + upstream: promote connection-closed messages from verbose to info + + log level; they could be the only record of the connection terminating if the + client doesn't send a SSH2_MSG_DISCONNECT message. ok dtucker@ + + OpenBSD-Commit-ID: 0c8bfaf5e9fdff945cee09ac21e641f6c5d65d3c -commit dc37d2d2470b4a9cedcee9ac926b7362214e3305 -Author: Darren Tucker -Date: Tue Mar 26 16:26:14 2024 +1100 +commit b00331402fe5c60d577f3ffcc35e49286cdc6b47 +Author: Damien Miller +Date: Mon Jun 17 17:02:18 2024 +1000 - If we're using xpg4's id, remember to pass args. + propagate PAM crashes to PerSourcePenalties + + If the PAM subprocess crashes, exit with a crash status that will be + picked up by the sshd(8) listener process where it can be used by + PerSourcePenalties to block the client. This is similar handling to + the privsep preauth process. -commit fe169487937780392b23d3ff3c00e5898c10f784 -Author: dtucker@openbsd.org -Date: Tue Mar 26 01:23:11 2024 +0000 +commit 1c207f456ace38987deda047758d13fbf857f948 +Author: Damien Miller +Date: Mon Jun 17 15:06:01 2024 +1000 - upstream: Import regenerated moduli. + minix doesn't have loopback, so skip penalty tests - OpenBSD-Commit-ID: ad3d1486d105b008c93e952d158e5af4d9d4c531 + pointed out by dtucker@ -commit 151146f03b490d19145cd421763aa7d42f5c50e2 -Author: job@openbsd.org -Date: Thu Mar 14 06:23:14 2024 +0000 +commit 48443d202eaec52d4d39defdd709a4499a7140c6 +Author: djm@openbsd.org +Date: Sun Jun 16 11:54:49 2024 +0000 - upstream: Clarify how literal IPv6 addresses can be used in -J mode - - OK djm@ + upstream: same treatment for this test - OpenBSD-Commit-ID: 524ddae97746b3563ad4a887dfd0a6e6ba114c50 + OpenBSD-Regress-ID: d0cc9efca7833e673ea7b0cb3a679a3acee8d4c7 -commit 0d5bdc87a675271862b67eb6a9fb13a202fb4894 -Author: Darren Tucker -Date: Mon Mar 25 16:14:21 2024 +1100 +commit 45562a95ea11d328c22d97bf39401cd29684fb1f +Author: djm@openbsd.org +Date: Sun Jun 16 08:18:06 2024 +0000 - Add Mac OS X 14 test targets. + upstream: penalty test is still a bit racy + + OpenBSD-Regress-ID: 90c9ac224db454637baf1ebee5857e007321e824 -commit 2d7964a03e1f50a48040ec6912c0a956df909d21 -Author: Darren Tucker -Date: Mon Mar 25 14:05:40 2024 +1100 +commit 8d0f7eb147ef72d18acb16c0b18672d44941a8ca +Author: djm@openbsd.org +Date: Sat Jun 15 03:59:10 2024 +0000 - Move xpg4 'id' handling into test-exec.sh. + upstream: crank up penalty timeouts so this should work on even the - Handle replacement of 'id' the same way as we do other Portable specific - replacements in test-exec.sh. This brings percent.sh back into sync - with upstream. + slowest of test builders + + OpenBSD-Regress-ID: 70bda39c83e3fc9d0f3c1fad4542ed33e173d468 -commit 75d1d49ed10d978171cdafad28bdbffdbd48f41e -Author: Darren Tucker -Date: Mon Mar 25 10:38:03 2024 +1100 +commit 93c75471a1202ab3e29db6938648d4e2602c0475 +Author: jmc@openbsd.org +Date: Fri Jun 14 05:20:34 2024 +0000 - Update branches shown on ci-status to 9.7 and 9.6. + upstream: sort -q in the options list; + + OpenBSD-Commit-ID: 6839b38378f38f754de638a5e988c13b4164cc7c -commit f9193f03db0029fc9c31fbdb5c66a2737446bd8f -Author: Darren Tucker -Date: Mon Mar 25 09:28:02 2024 +1100 +commit dd7807bbe80a93ffb4616f2bd5cf83ad5a5595fb +Author: djm@openbsd.org +Date: Fri Jun 14 05:01:22 2024 +0000 - Improve detection of -fzero-call-used-regs=used. + upstream: clarify KEXAlgorithms supported vs available. Inspired by - Should better detect problems with gcc 13 on m68k. bz#3673 from Colin - Watson via bz#3673 and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110934 + bz3701 from Colin Watson. - Signed-off-by: Darren Tucker + OpenBSD-Commit-ID: e698e69bea19bd52971d253f2b1094490c4701f7 -commit 86bdd3853f4d32c85e295e6216a2fe0953ad93f0 -Author: Damien Miller -Date: Mon Mar 11 16:20:49 2024 +1100 +commit d172ad56df85b68316dbadbedad16761a1265874 +Author: djm@openbsd.org +Date: Fri Jun 14 05:00:42 2024 +0000 - version number in README + upstream: ssh-keyscan -q man bits + + OpenBSD-Commit-ID: ba28d0e1ac609a4c99c453e57e86560c79079db1 -commit 282721418e6465bc39ccfd39bb0133e670ee4423 +commit 092e4ff9ccaacbe035f286feb1b56ed499604743 Author: Damien Miller -Date: Mon Mar 11 16:20:08 2024 +1100 +Date: Fri Jun 14 14:46:35 2024 +1000 - crank RPM spec versions + skip penalty-expire test in valgrind test env -commit 3876a3bbd2ca84d23ba20f8b69ba83270c04ce3a +commit 2866ad08a9c50d7b67ce9424ca990532b806a21a Author: djm@openbsd.org -Date: Mon Mar 11 04:59:47 2024 +0000 +Date: Fri Jun 14 04:43:11 2024 +0000 - upstream: openssh-9.7 + upstream: split the PerSourcePenalties test in two: one tests penalty - OpenBSD-Commit-ID: 618ececf58b8cdae016b149787af06240f7b0cbc + enforcement but not penalty expiry, the other tests penalty expiry. + + This lets us disable the expiry testing in certain CI test environments. + + OpenBSD-Regress-ID: f56811064f3e3cb52ee73a206b8c2a06af1c8791 -commit 8fc109cc614954a8eb2738c48c0db36a62af9a06 -Author: Darren Tucker -Date: Mon Mar 11 12:59:26 2024 +1100 +commit b2c64bc170d75823622a37cab3ca1804ca87ad16 +Author: Damien Miller +Date: Fri Jun 14 14:19:23 2024 +1000 - Test against current OpenSSL and LibreSSL releases. + add a sshd_config PamServiceName option - Add LibreSSL 3.9.0, bump older branches to their respective current - releases. + Allows selecting which PAM service name to use when UsePAM is + enabled. Defaults to "sshd" unless overridden at compile time + by defining SSHD_PAM_SERVICE. + + bz2102, ok dtucker@ -commit 26b09b45fec7b88ba09042c09be4157e58e231e2 -Author: Damien Miller -Date: Sun Mar 10 16:24:57 2024 +1100 +commit 9f032a4dd17bf0ae6066223d82aa5e784285d987 +Author: djm@openbsd.org +Date: Fri Jun 14 00:26:12 2024 +0000 - quote regexes used to test for algorithm support + upstream: don't redirect stderr for ssh-keyscan we expect to succeed - Fixes test failures on Solaris 8 reported by Tom G. Christensen + OpenBSD-Regress-ID: 8878b8eb4e070ed2e343166d3eb86db4a08a216c -commit a6a740a4948d10a622b505135bb485c10f21db5e +commit 1e84d0cf40e94ae3a77d6a7ca8c036d8e3d55a40 Author: djm@openbsd.org -Date: Sat Mar 9 05:12:13 2024 +0000 +Date: Fri Jun 14 00:25:25 2024 +0000 - upstream: avoid logging in signal handler by converting mainloop to + upstream: make host/banner comments go to stderr instead of stdout, - ppoll() bz3670, reported by Ben Hamilton; ok dtucker@ + so they are useful as comments without extra shell redirection and so they + don't clutter actual errors on stderr. - OpenBSD-Commit-ID: e58f18042b86425405ca09e6e9d7dfa1df9f5f7f + Add a -q flag to shut them up. + + ok dtucker@ + + OpenBSD-Commit-ID: bec813de56a71adb5c1a76adcf49621130d24264 -commit cd82f7526e0481720567ae41db7849ab1c27e27b +commit 3e806d011855d6bd648ec95b9df630ebbd11c3bf +Author: naddy@openbsd.org +Date: Thu Jun 13 15:06:33 2024 +0000 + + upstream: separate keywords with comma + + OpenBSD-Commit-ID: d65a99666202a8188c4991c18d14374a229f7be5 + +commit abfd1f7a3cbd0a92581a0febba254b2f6649c0d9 Author: djm@openbsd.org -Date: Fri Mar 8 22:16:32 2024 +0000 +Date: Fri Jun 14 00:23:55 2024 +0000 - upstream: skip more whitespace, fixes find-principals on + upstream: specify an algorithm for ssh-keyscan, otherwise it will make - allowed_signers files with blank lines; reported by Wiktor Kwapisiewicz + multiple attempts simultaneously and confuse the test - OpenBSD-Commit-ID: b3a22a2afd753d70766f34bc7f309c03706b5298 + OpenBSD-Regress-ID: 6e910f3315c4345053db1bf5cbf61826b194d0b9 -commit 2f9d2af5cb19905d87f37d1e11c9f035ac5daf3b -Author: dtucker@openbsd.org -Date: Fri Mar 8 11:34:10 2024 +0000 +commit a8fbe2f7d0d96d299ee8e69769e3b51067978748 +Author: Damien Miller +Date: Thu Jun 13 16:41:29 2024 +1000 - upstream: Invoke ProxyCommand that uses stderr redirection via + sshd: don't use argv[0] as PAM service name - $TEST_SHELL. Fixes test when run by a user whose login shell is tcsh. - Found by vinschen at redhat.com. + sshd would implicitly use argv[0] as the PAM service name to + allow people to select different PAM service names by making + differently-named copies/links to the sshd binary. - OpenBSD-Regress-ID: f68d79e7f00caa8d216ebe00ee5f0adbb944062a - -commit 9b3f0beb4007a7e01dfedabb429097fb593deae6 -Author: Darren Tucker -Date: Thu Mar 7 17:18:14 2024 +1100 - - Prefer openssl binary from --with-ssl-dir directory. + Splitting sshd into sshd/sshd-session broke this, as the process + that starts PAM is always sshd-session and the user has no control + over this. - Use openssl in the directory specified by --with-ssl-dir as long - as it's functional. Reported by The Doctor. + Hardcode "sshd" as the default PAM service name unless/until we + figure out a better way. Should unbreak OSX integration tests. -commit c47e1c9c7911f38b2fc2fb01b1f6ae3a3121a838 -Author: djm@openbsd.org -Date: Wed Mar 6 02:59:59 2024 +0000 +commit bf204bd05c3ae650f87e2b96527688579f59774c +Author: Damien Miller +Date: Thu Jun 13 15:00:28 2024 +1000 - upstream: fix memory leak in mux proxy mode when requesting forwarding. - - found by RASU JSC, reported by Maks Mishin in GHPR#467 + prepare for checking in autogenerated files - OpenBSD-Commit-ID: 97d96a166b1ad4b8d229864a553e3e56d3116860 + We plan to check in automatically generated files (config.h.in, etc) on + release branches. These files are normally ignored by .gitignore, but + this shuffles the contents of this file to make it easy to un-ignore + them. -commit 242742827fea4508e68097c128e802edc79addb5 -Author: djm@openbsd.org -Date: Wed Mar 6 00:31:04 2024 +0000 +commit 425f79a837489904c343b349ef00e09aeaa4e752 +Author: Damien Miller +Date: Thu Jun 13 14:41:33 2024 +1000 - upstream: wrap a few PKCS#11-specific bits in ENABLE_PKCS11 - - OpenBSD-Commit-ID: 463e4a69eef3426a43a2b922c4e7b2011885d923 + typo in comment -commit d52b6509210e2043f33e5a1de58dd4a0d5d48c2a +commit afe10313c1fa8d478af399ee7d54c8f85503013b Author: Damien Miller -Date: Wed Mar 6 11:31:36 2024 +1100 +Date: Thu Jun 13 14:35:25 2024 +1000 - disable RSA tests when algorithm is not supported + fix PTY allocation on Cygwin, broken by sshd split - Unbreaks "make test" when compiled --without-openssl. + Cygwin doesn't support FD passing and so used to disable post-auth + privilege separation entirely because privsep requires PTY allocation + to happen in the privileged monitor process with the PTY file + descriptors being passed back to the unprivileged process. - Similar treatment to how we do DSA and ECDSA. + This brings back a minimal version of the previous special treatment + for Cygwin (and any other platform that sets DISABLE_FD_PASSING): + privilege separation remains enabled, but PTY allocation happens in + the post-auth user process rather than the monitor. + + This either requires PTY allocation to not need privilege to begin + with (this appears to be the case on Cygwin), or the post-auth + privsep process retain privilege (other platforms that set the + DISABLE_FD_PASSING option). + + Keeping privileges here is bad, but the non-Cygwin systems that set + DISABLE_FD_PASSING are so deeply legacy that this is likely to be the + least of their problems. -commit 668d270a6c77e8b5a1da26ecad2e6de9f62c8fe4 +commit f66d4df5749551380a8c4ae642347675a0b6a2e9 Author: Damien Miller -Date: Wed Mar 6 10:33:20 2024 +1100 +Date: Thu Jun 13 11:33:09 2024 +1000 - add a --without-retpoline configure option + delay lookup of privsep user until config loaded - discussed with deraadt and dtucker a while ago + sshd-session attempting to use options.kerberos_authentication to + decide whether it needed to lookup the privsep user before the + configuration was loaded. This caused it to get a placeholder value + that caused it always to try to lookup the privsep user, breaking at + least one test environment. -commit 3deb501f86fc47e175ef6a3eaba9b9846a80d444 -Author: djm@openbsd.org -Date: Mon Mar 4 04:13:18 2024 +0000 +commit f1c42858b94f5d9b58867b34dce3afb39c6b56a8 +Author: Damien Miller +Date: Thu Jun 13 11:16:57 2024 +1000 - upstream: fix leak of CanonicalizePermittedCNAMEs on error path; - - spotted by Coverity (CID 438039) - - OpenBSD-Commit-ID: 208839699939721f452a4418afc028a9f9d3d8af + missing file for PerSourcePenalties regress test -commit 65a44a8a4f7d902a64d4e60eda84384b2e2a24a2 +commit 4de80ff4e6fab5a6bb0028e7d57c6c23d1485adb Author: djm@openbsd.org -Date: Mon Mar 4 02:16:11 2024 +0000 +Date: Wed Jun 12 22:36:00 2024 +0000 - upstream: Separate parsing of string array options from applying them + upstream: split PerSourcePenalties address tracking. Previously it - to the active configuration. This fixes the config parser from erroneously - rejecting cases like: + used one shared table and overflow policy for IPv4 and IPv6 addresses, now it + will use separate tables and optionally different overflow policies. - AuthenticationMethods password - Match User ivy - AuthenticationMethods any + This prevents misbehaviour from IPv6 addresses (which are vastly easier + to obtain many of) from affecting IPv4 connections and may allow for + stricter overflow policies. - bz3657 ok markus@ + ok deraadt@ - OpenBSD-Commit-ID: 7f196cba634c2a3dba115f3fac3c4635a2199491 + OpenBSD-Commit-ID: 12637ed0aa4d5f1f3e702da42ea967cbd8bfdfd9 -commit 6886e1b1f55c90942e4e6deed930f8ac32e0f938 -Author: Darren Tucker -Date: Thu Feb 22 17:59:35 2024 +1100 +commit 06ab4c6931b0aaa4334db2faaa7e1069e76d0df6 +Author: jmc@openbsd.org +Date: Tue Jun 11 05:24:39 2024 +0000 - Add nbsd10 test target. + upstream: do not mark up "(default: 20ms)"; + + OpenBSD-Commit-ID: 54151ecdecfa1b67dcdda4fd24826ef6e2148ad4 -commit d86bf8a3f6ea4fa7887406c2aa9959db71fa41be -Author: Damien Miller -Date: Thu Feb 22 12:06:10 2024 +1100 +commit cfe243cd9fde148ed060637876e27bb55ac78be9 +Author: djm@openbsd.org +Date: Tue Jun 11 02:54:51 2024 +0000 - more descriptive configure test name + upstream: reap preauth net child if it hangs up during privsep message + + send, not just message receive + + OpenBSD-Commit-ID: 02a093f4ab4f8f83f0cd1ea2bb35b9ca420448f0 -commit 9ee335aacc9f5bdc4cc2c19fafb45e27be7d234e +commit b0a711c00b9c64afd1c9d6fb538275c6604a2676 Author: djm@openbsd.org -Date: Wed Feb 21 06:17:29 2024 +0000 +Date: Tue Jun 11 01:58:27 2024 +0000 - upstream: explain arguments of internal-sftp GHPR#454 from Niklas + upstream: fix PIDFILE handling, broken for SUDO=doas in last commit - Hambüchen - MIME-Version: 1.0 - Content-Type: text/plain; charset=UTF-8 - Content-Transfer-Encoding: 8bit + here - OpenBSD-Commit-ID: 0335d641ae6b5b6201b9ffd5dd06345ebbd0a3f3 + OpenBSD-Regress-ID: 96fec579af228f87a036e94801eb294af9074625 -commit d1164cb1001dd208fee88aaa9b43d5e6fd917274 +commit 90fb801e2d9241be50a2a7ff79428386442a041f Author: djm@openbsd.org -Date: Wed Feb 21 06:06:43 2024 +0000 +Date: Tue Jun 11 02:00:30 2024 +0000 - upstream: clarify permissions requirements for ChrootDirectory Part + upstream: reap the pre-auth [net] child if it hangs up during privsep - of GHPR#454 from Niklas Hambüchen - MIME-Version: 1.0 - Content-Type: text/plain; charset=UTF-8 - Content-Transfer-Encoding: 8bit + message sending, not just receiving - OpenBSD-Commit-ID: d37bc8786317a11649c62ff5e2936441186ef7a0 + OpenBSD-Commit-ID: f7341605bf08c4c15830910446e6775323f2f8cb -commit d410e17d186552d0717f18217d0d049486754365 +commit ef878d58798f6688c7f4d4e417dc0c29023ea831 Author: djm@openbsd.org -Date: Wed Feb 21 06:05:06 2024 +0000 +Date: Tue Jun 11 01:23:25 2024 +0000 - upstream: .Cm for a keyword. Part of GHPR#454 from Niklas Hambüchen + upstream: a little more RB_TREE paranoia - OpenBSD-Commit-ID: d59c52559f926fa82859035d79749fbb4a3ce18a + OpenBSD-Commit-ID: 8dc2fd21eebd8830c4a4d25461ac4fe228e11156 -commit ab73f9678ebf06b32d6361b88b50b42775e0565b +commit fc4e96b2174d6a894d2033421699d091679baced Author: djm@openbsd.org -Date: Wed Feb 21 06:01:13 2024 +0000 +Date: Tue Jun 11 01:22:25 2024 +0000 - upstream: fix typo in match directive predicate (s/tagged/tag) GHPR#462 + upstream: fix off-by-one comparison for PerSourcePenalty - from Tobias Manske + OpenBSD-Commit-ID: af4f5d01c41ef870b23e55655bfbf73474a6c02b + +commit 82c836df4ff41145553cd7adb11c5b985aeaa06f +Author: djm@openbsd.org +Date: Tue Jun 11 01:21:41 2024 +0000 + + upstream: move tree init before possible early return - OpenBSD-Commit-ID: 05b23b772677d48aa82eefd7ebebd369ae758908 + OpenBSD-Commit-ID: 72e2c5b69f151c08a7c5bf5ad929b97a92c273df -commit 9844aa2521ccfb1a2d73745680327b79e0574445 +commit a2300f015cc4939c4d9c564b58b74e71202dc978 Author: djm@openbsd.org -Date: Wed Feb 21 05:57:34 2024 +0000 +Date: Tue Jun 11 01:07:35 2024 +0000 - upstream: fix proxy multiplexing mode, broken when keystroke timing + upstream: update to mention that PerSourcePenalties default to - obfuscation was added. GHPR#463 from montag451 + being enabled and document the default values for each parameter. - OpenBSD-Commit-ID: 4e412d59b3f557d431f1d81c715a3bc0491cc677 + OpenBSD-Commit-ID: b981288bddfb097aad269f62df4081c688ce0034 -commit ee6d932acb532f80b11bb7cf161668c70ec8a117 +commit 41987efd356d3fc30139aeab4b09374acf8f91a0 Author: djm@openbsd.org -Date: Tue Feb 20 04:10:03 2024 +0000 +Date: Tue Jun 11 00:44:52 2024 +0000 - upstream: don't append a gratuitous space to the end of subsystem + upstream: reap the [net] child if it hangs up while writing privsep - arguments; bz3667 + message payloads, not just the message header - OpenBSD-Commit-ID: e11023aeb3f30b77a674e37b8292c862926d5dc6 + OpenBSD-Commit-ID: 24dbd400aa381ac96be7ed2dd49018487dfef6ce -commit e27f032aa8fcbae9b2e7c451baaf4b8ac6fa3d45 -Author: dtucker@openbsd.org -Date: Mon Feb 19 09:25:52 2024 +0000 +commit 6211aa085fa91155a24922e5329576ac9a8f3175 +Author: djm@openbsd.org +Date: Tue Jun 11 00:40:21 2024 +0000 - upstream: Always define puttysetup function. + upstream: log waitpid() status for abnormal exits - OpenBSD-Regress-ID: b4c0ccfa4006a1bc5dfd99ccf21c854d3ce2aee0 + OpenBSD-Commit-ID: b317930e06b51819c1a2bc6a4359764fecfb1c2d -commit 84046f9991abef5f46b040b10cf3d494f933a17b -Author: dtucker@openbsd.org -Date: Fri Feb 9 08:56:59 2024 +0000 +commit a59634c7adb9ae988748d99963dfafb3070d8d41 +Author: djm@openbsd.org +Date: Tue Jun 11 00:36:20 2024 +0000 - upstream: Exapnd PuTTY test coverage. + upstream: correct error message - Expand the set of ciphers, MACs and KEX methods in the PuTTY interop - tests. + OpenBSD-Commit-ID: 581f60f73099083392887206860229ab104620ed + +commit fa7d7a667f2ee031e72873e36de2d2a36bca973b +Author: deraadt@openbsd.org +Date: Fri Jun 7 13:23:30 2024 +0000 + + upstream: avoid shadowing issues which some compilers won't accept + + ok djm + + OpenBSD-Commit-ID: 1e89572397dda83433d58c4fa6333a08f51170d4 + +commit 3ad4cd9eeca5c9bc6706db44b6de88e2e4513fd6 +Author: jmc@openbsd.org +Date: Thu Jun 6 21:14:49 2024 +0000 + + upstream: escape the final dot at eol in "e.g." to avoid double - OpenBSD-Regress-ID: dd28d97d48efe7329a396d0d505ee2907bf7fc57 + spacing; + + OpenBSD-Commit-ID: 0a9fb10bc9f7d577afe2da3f498a08bc431115b9 -commit bbf541ee2afe07b08a8b56fa0dc6f38fcfceef2a -Author: dtucker@openbsd.org -Date: Fri Feb 9 08:47:42 2024 +0000 +commit 0e0c69761a4c33ccd4a256560f522784a753d1a8 +Author: djm@openbsd.org +Date: Thu Jun 6 20:25:48 2024 +0000 - upstream: Factor out PuTTY setup. + upstream: enable PerSourcePenalties by default. - Factor out PuTTY and call only when needed. + ok markus - This allows us to avoid PuTTY key setup when it's not needed, which - speeds up the overall test run by a couple of percent. + NB. if you run a sshd that accepts connections from behind large NAT + blocks, proxies or anything else that aggregates many possible users + behind few IP addresses, then this change may cause legitimate traffic + to be denied. - OpenBSD-Regress-ID: c25eaccc3c91bc874400f7c85ce40e9032358c1c + Please read the PerSourcePenalties, PerSourcePenaltyExemptList and + PerSourceNetBlockSize options in sshd_config(5) for how to tune your + sshd(8) for your specific circumstances. + + OpenBSD-Commit-ID: 24a0e5c23d37e5a63e16d2c6da3920a51078f6ce -commit d31c21c57fb4245271680a1e5043cf6470a96766 -Author: naddy@openbsd.org -Date: Sat Feb 10 11:28:52 2024 +0000 +commit bd1f74741daabeaf20939a85cd8cec08c76d0bec +Author: djm@openbsd.org +Date: Thu Jun 6 20:20:42 2024 +0000 - upstream: clean sshd random relinking kit; ok miod@ + upstream: mention that PerSourcePenalties don't affect concurrent - OpenBSD-Commit-ID: 509bb19bb9762a4b3b589af98bac2e730541b6d4 + in-progress connections. + + OpenBSD-Commit-ID: 20389da6264f2c97ac3463edfaa1182c212d420c -commit 4dbc5a363ff53a2fcecf6bc3bcc038badc12f118 +commit 9774b938578327d88a651f4c63c504809717590a Author: djm@openbsd.org -Date: Fri Feb 2 00:13:34 2024 +0000 +Date: Thu Jun 6 19:49:25 2024 +0000 - upstream: whitespace + upstream: regress test for PerSourcePenalties - OpenBSD-Commit-ID: b24680bc755b621ea801ff8edf6f0f02b68edae1 + OpenBSD-Regress-ID: a1af13d411b25a727742644459d26480b9a1b0f1 -commit efde85dda2130272af24cc346f6c3cd326182ff1 -Author: Darren Tucker -Date: Mon Feb 19 17:29:31 2024 +1100 +commit b8ebd86cefe9812204a10c028dc90de29918667d +Author: djm@openbsd.org +Date: Thu Jun 6 19:48:40 2024 +0000 - Improve error message for OpenSSL header check. + upstream: make sure logs are saved from sshd run via start_sshd - bz#3668, ok djm@ + OpenBSD-Regress-ID: de4ef0e32e3ab85ff3a6c36eb08d1909c0dd1b4a -commit cbbdf868bce431a59e2fa36ca244d5739429408d -Author: Darren Tucker -Date: Wed Feb 7 13:45:02 2024 +1100 +commit d7b2070bdaa4ebbfafb9975c1d5a62b73289d31f +Author: djm@openbsd.org +Date: Thu Jun 6 19:47:48 2024 +0000 - Interop test against PuTTY snapshot and releases. + upstream: simplify + + OpenBSD-Regress-ID: 50316e0d1ae0c0a057a45af042253e54ce23d11c -commit 91898bf786b0f149f962c4c96c08a46f29888c10 -Author: Darren Tucker -Date: Tue Feb 6 16:21:05 2024 +1100 +commit e6ea3d224513b6bfb93818809d4c7397f5995ba2 +Author: djm@openbsd.org +Date: Thu Jun 6 18:48:13 2024 +0000 - Put privsep dir on OS X on /usr/local. + upstream: prepare for PerSourcePenalties being enabled by default - On some runners we can't create /var/empty, so put it some place we can - write. Should fix test breakage on Max OS X 11. + in future + + OpenBSD-Regress-ID: 5236c6d1c823997aac5a35e2915da30f1903bec7 -commit be5ed8ebed8388c5056bfde4688308cc873c18b9 -Author: Darren Tucker -Date: Tue Feb 6 11:19:42 2024 +1100 +commit c0cb3b8c837761816a60a3cdb54062668df09652 +Author: djm@openbsd.org +Date: Thu Jun 6 19:50:01 2024 +0000 - Add --disable-fd-passing option. + upstream: disable stderr redirection before closing fds - .. and enable for the minix3 test VM. This will cause it to more reliably - skip tests that need FD passing and should fix the current test breakage. + OpenBSD-Commit-ID: d42cb895ee4542098050367fc35321c9303f003a -commit 0f6a8a0d0a518fd78c4cbebfdac990a57a1c4e41 -Author: Darren Tucker -Date: Tue Feb 6 11:18:44 2024 +1100 +commit 81c1099d22b81ebfd20a334ce986c4f753b0db29 +Author: djm@openbsd.org +Date: Thu Jun 6 17:15:25 2024 +0000 - Use "skip" function instead doing it ourselves. + upstream: Add a facility to sshd(8) to penalise particular + + problematic client behaviours, controlled by two new sshd_config(5) options: + PerSourcePenalties and PerSourcePenaltyExemptList. + + When PerSourcePenalties are enabled, sshd(8) will monitor the exit + status of its child pre-auth session processes. Through the exit + status, it can observe situations where the session did not + authenticate as expected. These conditions include when the client + repeatedly attempted authentication unsucessfully (possibly indicating + an attack against one or more accounts, e.g. password guessing), or + when client behaviour caused sshd to crash (possibly indicating + attempts to exploit sshd). + + When such a condition is observed, sshd will record a penalty of some + duration (e.g. 30 seconds) against the client's address. If this time + is above a minimum threshold specified by the PerSourcePenalties, then + connections from the client address will be refused (along with any + others in the same PerSourceNetBlockSize CIDR range). + + Repeated offenses by the same client address will accrue greater + penalties, up to a configurable maximum. A PerSourcePenaltyExemptList + option allows certain address ranges to be exempt from all penalties. + + We hope these options will make it significantly more difficult for + attackers to find accounts with weak/guessable passwords or exploit + bugs in sshd(8) itself. + + PerSourcePenalties is off by default, but we expect to enable it + automatically in the near future. + + much feedback markus@ and others, ok markus@ + + OpenBSD-Commit-ID: 89ded70eccb2b4926ef0366a4d58a693de366cca -commit 3ad669f81aabbd2ba9fbd472903f680f598e1e99 +commit 916b0b6174e203cf2c5ec9bcf409472eb7ffbf43 Author: Damien Miller -Date: Thu Feb 1 14:01:18 2024 +1100 +Date: Fri Jun 7 03:31:02 2024 +1000 - ignore some vim droppings + whitespace -commit c283f29d23611a06bbee06bcf458f2fffad721d9 -Author: djm@openbsd.org -Date: Thu Feb 1 02:37:33 2024 +0000 +commit 49b55e44182b8294419aa580cbf043d5b9e3d953 +Author: deraadt@openbsd.org +Date: Tue Jun 4 15:14:45 2024 +0000 - upstream: whitespace + upstream: enable -fret-clean on amd64, for libc libcrypto ld.so - OpenBSD-Commit-ID: bf9e4a1049562ee4322684fbdce07142f04fdbb7 + kernel, and all the ssh tools. The dynamic objects are entirely ret-clean, + static binaries will contain a blend of cleaning and non-cleaning callers. + + OpenBSD-Commit-ID: 112aacedd3b61cc5c34b1fa6d9fb759214179172 -commit 0d96b1506b2f4757fefa5d1f884d49e96a6fd4c3 +commit cc80d51d034bcb24fd0f2564a4bdf1612000a2a2 Author: Damien Miller -Date: Tue Jan 16 14:40:18 2024 +1100 +Date: Wed Jun 5 02:21:30 2024 +1000 - skip tests that use multiplexing on Windows - - Some tests here use multiplexing, skip these if DISABLE_FD_PASSING - is set. Should unbreak tests on Windows. + remove PRIVSEP macros for osx -commit 50080fa42f5f744b798ee29400c0710f1b59f50e +commit 8785491123d4d722b310c20f383570be758f8263 Author: djm@openbsd.org -Date: Thu Jan 11 04:50:28 2024 +0000 +Date: Sat Jun 1 07:03:37 2024 +0000 - upstream: don't disable RSA test when DSA is disabled; bug introduced - - in last commit + upstream: be really strict with fds reserved for communication with the - OpenBSD-Regress-ID: 8780a7250bf742b33010e9336359a1c516f2d7b5 - -commit 415c94ce17288e0cdcb9e58cc91fba78d33c8457 -Author: djm@openbsd.org -Date: Thu Jan 11 01:45:58 2024 +0000 - - upstream: make DSA testing optional, defaulting to on + separate sshd-session process - reserve them early and fatal if we can't + dup2(2) them later. The pre-split fallback to re-reading the configuration + files is not possible, so sshd-session absolutely requires the fd the + configuration is passed over to be in order. - ok markus + ok deraadt@ - OpenBSD-Regress-ID: dfc27b5574e3f19dc4043395594cea5f90b8572a + OpenBSD-Commit-ID: 308a98ef3c8a6665ebf92c7c9a0fc9600ccd7065 -commit f9311e8921d92c5efca767227a497ab63280ac39 -Author: djm@openbsd.org -Date: Thu Jan 11 01:51:16 2024 +0000 +commit f1c8918cb98459910fb159373baea053ba4108c0 +Author: Damien Miller +Date: Fri May 31 19:12:26 2024 +1000 - upstream: ensure key_fd is filled when DSA is disabled; spotted by - - tb@ - - OpenBSD-Commit-ID: 9dd417b6eec3cf67e870f147464a8d93f076dce7 + depend -commit 4e838120a759d187b036036610402cbda33f3203 -Author: djm@openbsd.org -Date: Thu Jan 11 01:45:36 2024 +0000 +commit 94b4866cb1f4b0ed29a9f367047b30f81002316f +Author: Damien Miller +Date: Fri May 31 19:11:14 2024 +1000 - upstream: make DSA key support compile-time optional, defaulting to - - on - - ok markus@ + rename need_privsep to need_chroot - OpenBSD-Commit-ID: 4f8e98fc1fd6de399d0921d5b31b3127a03f581d + privsep is mandatory, chroot is optional (disabled when running + sshd as non-root) -commit afcc9028bfc411bc26d20bba803b83f90cb84e26 -Author: jmc@openbsd.org -Date: Wed Jan 10 06:33:13 2024 +0000 +commit e68a95142e5024b144f8eeccd5ffdee42c34f44c +Author: Damien Miller +Date: Fri May 31 19:05:34 2024 +1000 - upstream: fix incorrect capitalisation; - - OpenBSD-Commit-ID: cb07eb06e15fa2334660ac73e98f29b6a1931984 + remove remaining use_privsep mention -commit 9707c8170c0c1baeb1e06e5a53f604498193885f +commit b21d271f651d2536dca819cc6d74032fe98634db Author: djm@openbsd.org -Date: Tue Jan 9 22:19:36 2024 +0000 +Date: Fri May 31 09:01:08 2024 +0000 - upstream: extend ChannelTimeout regression test to exercise multiplexed + upstream: warn when -r (deprecated option to disable re-exec) is - connections and the new "global" timeout type. ok dtucker@ + passed - OpenBSD-Regress-ID: f10d19f697024e9941acad7c2057f73d6eacb8a2 + OpenBSD-Commit-ID: 73145ef5150edbe3ce7889f0844ed8fa6155f551 -commit b31b12d28de96e1d43581d32f34da8db27e11c03 +commit a4b5bc246cbca476deeeb4462aa31746a56e3021 Author: djm@openbsd.org -Date: Tue Jan 9 22:19:00 2024 +0000 +Date: Fri May 31 08:49:35 2024 +0000 - upstream: add a "global" ChannelTimeout type to ssh(1) and sshd(8) - - that watches all open channels and will close all open channels if there is - no traffic on any of them for the specified interval. This is in addition to - the existing per-channel timeouts added a few releases ago. - - This supports use-cases like having a session + x11 forwarding channel - open where one may be idle for an extended period but the other is - actively used. The global timeout would allow closing both channels when - both have been idle for too long. - - ok dtucker@ + upstream: typos - OpenBSD-Commit-ID: 0054157d24d2eaa5dc1a9a9859afefc13d1d7eb3 + OpenBSD-Commit-ID: edfa72eb06bfa65da30fabf7d2fe76d2d33f77bf -commit 602f4beeeda5bb0eca181f8753d923a2997d0a51 +commit 8054b906983ceaed01fabd8188d3dac24c05ba39 Author: djm@openbsd.org -Date: Tue Jan 9 21:39:14 2024 +0000 +Date: Mon May 27 01:52:26 2024 +0000 - upstream: adapt ssh_api.c code for kex-strict - - from markus@ ok me + upstream: don't need sys/queue.h here - OpenBSD-Commit-ID: 4d9f256852af2a5b882b12cae9447f8f00f933ac + OpenBSD-Commit-ID: dd137396828171eb19e4911581812ca58de6c578 -commit 42ba34aba8708cf96583ff52975d95a8b47d990d -Author: Damien Miller -Date: Mon Jan 8 16:26:37 2024 +1100 +commit 210d4239733da6180ce853538aeb9413d5c62ad5 +Author: naddy@openbsd.org +Date: Sun May 26 20:35:12 2024 +0000 - nite that recent OSX tun/tap is unsupported + upstream: remove references to SSH1 and DSA server keys + + OpenBSD-Commit-ID: 57cc1c98d4f998981473734f144b904af7d178a2 -commit 690bc125f9a3b20e47745fa8f5b5e1fd5820247f -Author: Sevan Janiyan -Date: Wed Dec 27 04:57:49 2023 +0000 +commit f0b9261d7fdd0ef86806b49fe76344bd16770cd0 +Author: jsg@openbsd.org +Date: Thu May 23 23:47:16 2024 +0000 - README.platform: update tuntap url + upstream: remove unused struct fwd_perm_list, no decl with complete + + type ok djm@ + + OpenBSD-Commit-ID: 416fb3970b7e73c76d2963c4f00cf96f2b2ee2fb -commit 6b8be2ccd7dd091808f86af52066b0c2ec30483a -Author: Rose <83477269+AtariDreams@users.noreply.github.com> -Date: Tue Dec 19 11:48:20 2023 -0500 +commit 2477a98c3ef78e63b11a1393656e00288f52ae97 +Author: naddy@openbsd.org +Date: Wed May 22 15:24:55 2024 +0000 - Fix compilation error in ssh-pcks11-client.c + upstream: Do not pass -Werror twice when building with clang. - Compilation fails becaus of an undefined reference to helper_by_ec, - because we forgot the preprocessor conditional that excludes that function - from being called in unsupported configurations. + OpenBSD-Commit-ID: 5f378c38ad8976d507786dc4db9283a879ec8cd0 -commit 219c8134157744886ee6ac5b8c1650abcd981f4c -Author: djm@openbsd.org -Date: Mon Jan 8 05:11:18 2024 +0000 +commit 435844f5675245b4271f8581f15e6d1f34fde3bc +Author: miod@openbsd.org +Date: Wed May 22 11:49:36 2024 +0000 - upstream: Remove outdated note from PROTOCOL.mux - - Port forward close by control master is already implemented - by `mux_master_process_close_fwd` in `mux.c` + upstream: Do not pass -Werror if building with gcc 3, for asn1.h - GHPR442 from bigb4ng + and bio.h cause (admittedly bogus) warnings with gcc 3. - OpenBSD-Commit-ID: ad0734fe5916d2dc7dd02b588906cea4df0482fb + OpenBSD-Commit-ID: fb39324748824cb0387e9d67c41d1bef945c54ea -commit 4c3cf362631ccc4ffd422e572f075d5d594feace +commit fc5dc092830de23767c6ef67baa18310a64ee533 Author: djm@openbsd.org -Date: Mon Jan 8 05:05:15 2024 +0000 +Date: Wed May 22 04:20:00 2024 +0000 - upstream: fix missing field in users-groups-by-id@openssh.com reply + upstream: this test has been broken since 2014, and has been - documentation + testing the same key exchange algorithm repeatedly instead of testing all of + them. Spotted by nreilly AT blackberry.com in bz3692 - GHPR441 from TJ Saunders + Who broke the test? me. - OpenBSD-Commit-ID: ff5733ff6ef4cd24e0758ebeed557aa91184c674 + OpenBSD-Regress-ID: 48f4f5946276f975667141957d25441b3c9a50e2 -commit f64cede2a3c298b50a2659a8b53eb3ab2c0b8d23 -Author: djm@openbsd.org -Date: Mon Jan 8 04:10:03 2024 +0000 +commit fd4816791beaed2fdae7eea3e1494d1972b2a39d +Author: anton@openbsd.org +Date: Sun May 19 19:10:01 2024 +0000 - upstream: make kex-strict section more explicit about its intent: + upstream: Add missing kex-names.c source file required since the - banning all messages not strictly required in KEX + ssh split. - OpenBSD-Commit-ID: fc33a2d7f3b7013a7fb7500bdbaa8254ebc88116 + OpenBSD-Regress-ID: ca666223f828fc4b069cb9016bff1eb50faf9fbb -commit 698fe6fd61cbcb8e3e0e874a561d4335a49fbde5 -Author: Damien Miller -Date: Mon Jan 8 14:46:19 2024 +1100 +commit beccb7319c5449f6454889013403c336446d622e +Author: naddy@openbsd.org +Date: Fri May 17 14:42:00 2024 +0000 - update fuzzer example makefile to clang16 + upstream: remove duplicate copy of relink kit for sshd-session + + OpenBSD-Commit-ID: 6d2ded4cd91d4d727c2b26e099b91ea935bed504 -commit fc332cb2d602c60983a8ec9f89412754ace06425 -Author: Damien Miller -Date: Mon Jan 8 14:45:49 2024 +1100 +commit dcd79fa141311c287e0595ede684b7116122fae0 +Author: jsg@openbsd.org +Date: Fri May 17 06:42:04 2024 +0000 - unbreak fuzzers - missing pkcs11_make_cert() + upstream: remove prototypes with no matching function; ok djm@ - provide stub for use in fuzzer harness + OpenBSD-Commit-ID: 6d9065dadea5f14a01bece0dbfe2fba1be31c693 -commit 9ea0a4524ae3276546248a926b6641b2fbc8421b -Author: Damien Miller -Date: Mon Jan 8 14:45:14 2024 +1100 +commit 6454a05e7c6574d70adf17efe505a8581a86ca4f +Author: jsg@openbsd.org +Date: Fri May 17 06:38:00 2024 +0000 - unbreak fuzzers for clang16 + upstream: remove externs for removed vars; ok djm@ - getopt() needs a throw() attribute to compile, so supply one when compiling - things with C++ + OpenBSD-Commit-ID: f51ea791d45c15d4927eb4ae7d877ccc1e5a2aab -commit a72833d00788ef91100c643536ac08ada46440e1 -Author: djm@openbsd.org -Date: Mon Jan 8 00:34:33 2024 +0000 +commit f3e4db4601ef7d2feb1d6f7447e432aaf353a616 +Author: deraadt@openbsd.org +Date: Fri May 17 06:11:17 2024 +0000 - upstream: remove ext-info-* in the kex.c code, not in callers; + upstream: -Werror was turned on (probably just for development), - with/ok markus@ + and this is a simple way to satisfy older gcc. - OpenBSD-Commit-ID: c06fe2d3a0605c517ff7d65e38ec7b2d1b0b2799 + OpenBSD-Commit-ID: 7f698df54384b437ce33ab7405f0b86c87019e86 -commit 86f9e96d9bcfd1f5cd4bf8fb57a9b4c242df67df -Author: djm@openbsd.org -Date: Mon Jan 8 00:30:39 2024 +0000 +commit 24a1f3e5ad6f4a49377d4c74c36637e9a239efd0 +Author: Damien Miller +Date: Fri May 17 14:50:43 2024 +1000 - upstream: fix typo; spotted by Albert Chin - - OpenBSD-Commit-ID: 77140b520a43375b886e535eb8bd842a268f9368 + attempt at updating RPM specs for sshd-session -commit f0cbd26ec91bd49719fb3eea7ca44d2380318b9a -Author: dtucker@openbsd.org -Date: Thu Jan 4 09:51:49 2024 +0000 +commit 17b566eeb7a0c6acc9c48b35c08885901186f861 +Author: djm@openbsd.org +Date: Fri May 17 04:42:13 2024 +0000 - upstream: Import regenerated moduli. + upstream: g/c unused variable - OpenBSD-Commit-ID: 5a636f6ca7f25bfe775df4952f7aac90a7fcbbee + OpenBSD-Commit-ID: aa6ef0778a1f1bde0d73efba72a777c48d2bd010 -commit 64ddf776531ca4933832beecc8b7ebe1b937e081 +commit 01fb82eb2aa0a4eaf5c394ea8bb37ea4c26f8a3f Author: jsg@openbsd.org -Date: Wed Dec 20 00:06:25 2023 +0000 +Date: Fri May 17 02:39:11 2024 +0000 - upstream: spelling; ok markus@ + upstream: spelling; ok djm@ - OpenBSD-Commit-ID: 9d01f2e9d59a999d5d42fc3b3efcf8dfb892e31b + OpenBSD-Commit-ID: bdea29bb3ed2a5a7782999c4c663b219d2270483 -commit 503fbe9ea238a4637e8778208bde8c09bcf78475 -Author: jmc@openbsd.org -Date: Tue Dec 19 06:57:34 2023 +0000 +commit b88b690e99145a021fc1a1a116a11e0bce0594e7 +Author: djm@openbsd.org +Date: Fri May 17 01:45:22 2024 +0000 - upstream: sort -C, and add to usage(); ok djm + upstream: allow overriding the sshd-session binary path - OpenBSD-Commit-ID: 80141b2a5d60c8593e3c65ca3c53c431262c812f + OpenBSD-Regress-ID: 5058cd1c4b6ca1a15474e33546142931d9f964da -commit 5413b1c7ff5a19c6a7d44bd98c5a83eb47819ba6 -Author: djm@openbsd.org -Date: Tue Dec 19 06:41:14 2023 +0000 +commit a68f80f2511f0e0c5cef737a8284cc2dfabad818 +Author: anton@openbsd.org +Date: Wed Apr 3 06:01:11 2024 +0000 - upstream: correct section numbers; from Ed Maste + upstream: Since ssh-agent(1) is only readable by root by now, use - OpenBSD-Commit-ID: e289576ee5651528404cb2fb68945556052cf83f + ssh(1) while generating data in tests. + + OpenBSD-Regress-ID: 24eb40de2e6b0ace185caaba35e2d470331ffe68 -commit 430ef864645cff83a4022f5b050174c840e275da +commit 92e55890314ce2b0be21a43ebcbc043b4abc232f Author: djm@openbsd.org -Date: Mon Dec 18 15:58:56 2023 +0000 +Date: Fri May 17 01:17:40 2024 +0000 - upstream: match flag type (s/int/u_int) + upstream: fix incorrect debug option name introduce in previous - OpenBSD-Commit-ID: 9422289747c35ccb7b31d0e1888ccd5e74ad566a + commit + + OpenBSD-Commit-ID: 66d69e22b1c072c694a7267c847f212284614ed3 -commit 1036d77b34a5fa15e56f516b81b9928006848cbd -Author: Damien Miller -Date: Fri Dec 22 17:56:26 2023 +1100 +commit 4ad72878af7b6ec28da6e230e36a91650ebe84c1 +Author: deraadt@openbsd.org +Date: Fri May 17 00:33:25 2024 +0000 - better detection of broken -fzero-call-used-regs - - gcc 13.2.0 on ppc64le refuses to compile some function, including - cipher.c:compression_alg_list() with an error: - - > sorry, unimplemented: argument ‘used’ is not supportedcw - > for ‘-fzero-call-used-regs’ on this target + upstream: construct and install a relink-kit for sshd-session ok - This extends the autoconf will-it-work test with a similarly- - structured function that seems to catch this. + djm - Spotted/tested by Colin Watson; bz3645 - -commit 8241b9c0529228b4b86d88b1a6076fb9f97e4a99 -Author: Damien Miller -Date: Tue Dec 19 01:59:50 2023 +1100 - - crank versions + OpenBSD-Commit-ID: 8b3820adb4da4e139c4b3cffbcc0bde9f08bf0c6 -commit 2f2c65cb5f1518a9c556d3e8efa27ea0ca305c6b +commit 02e679a2cb3f6df8e9dbb1519ed578226485157f Author: Damien Miller -Date: Tue Dec 19 01:59:06 2023 +1100 +Date: Fri May 17 12:21:27 2024 +1000 - depend + Makefile support for sshd-session -commit e48cdee8e19059203b1aeeabec2350b8375fa61f +commit c0416035c5eaf70a8450d11c8833c5f7068ee7ad Author: djm@openbsd.org -Date: Mon Dec 18 14:50:08 2023 +0000 +Date: Fri May 17 00:32:32 2024 +0000 - upstream: regress test for agent PKCS#11-backed certificates + upstream: missing files from previous - OpenBSD-Regress-ID: 38f681777cb944a8cc3bf9d0ad62959a16764df9 + OpenBSD-Commit-ID: 4b7be4434d8799f02365552b641a7a70a7ebeb2f -commit 2f512f862df1d5f456f82a0334c9e8cc7208a2a1 +commit 03e3de416ed7c34faeb692967737be4a7bbe2eb5 Author: djm@openbsd.org -Date: Mon Dec 18 14:49:39 2023 +0000 +Date: Fri May 17 00:30:23 2024 +0000 - upstream: regress test for constrained PKCS#11 keys + upstream: Start the process of splitting sshd into separate - OpenBSD-Regress-ID: b2f26ae95d609d12257b43aef7cd7714c82618ff + binaries. This step splits sshd into a listener and a session binary. More + splits are planned. + + After this changes, the listener binary will validate the configuration, + load the hostkeys, listen on port 22 and manage MaxStartups only. All + session handling will be performed by a new sshd-session binary that the + listener fork+execs. + + This reduces the listener process to the minimum necessary and sets us + up for future work on the sshd-session binary. + + feedback/ok markus@ deraadt@ + + NB. if you're updating via source, please restart sshd after installing, + otherwise you run the risk of locking yourself out. + + OpenBSD-Commit-ID: 43c04a1ab96cdbdeb53d2df0125a6d42c5f19934 -commit cdddd66412ca5920ed4d3ebbfa6ace12dbd9b82f +commit 1c0d81357921f8d3bab06841df649edac515ae5b Author: djm@openbsd.org -Date: Mon Dec 18 14:48:44 2023 +0000 +Date: Thu May 9 09:46:47 2024 +0000 - upstream: openssh-9.6 + upstream: simplify exit message handling, which was more complicated - OpenBSD-Commit-ID: 21759837cf0e0092d9a2079f8fb562071c11016b + than it needed to be because of unexpunged ssh1 remnants. ok markus@ + + OpenBSD-Commit-ID: 8b0cd2c0dee75fb053718f442aa89510b684610b -commit 6d51feab157cedf1e7ef5b3f8781ca8ff9c4ab1b -Author: djm@openbsd.org -Date: Mon Dec 18 14:48:08 2023 +0000 +commit cbbbf76aa6cd54fce32eacce1300e7abcf9461d4 +Author: tobias@openbsd.org +Date: Mon May 6 19:26:17 2024 +0000 - upstream: ssh-agent: record failed session-bind attempts - - Record failed attempts to session-bind a connection and refuse signing - operations on that connection henceforth. + upstream: remove SSH1 leftovers - 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. + Authored with Space Meyer - Spotted by Jann Horn + ok djm - OpenBSD-Commit-ID: b0fdd023e920aa4831413f640de4c5307b53552e + OpenBSD-Commit-ID: 81db602e4cb407baae472689db1c222ed7b2afa3 -commit 7ef3787c84b6b524501211b11a26c742f829af1a -Author: djm@openbsd.org -Date: Mon Dec 18 14:47:44 2023 +0000 +commit bc5dcb8ab9a4e8af54a724883732af378f42ea78 +Author: tobias@openbsd.org +Date: Tue Apr 30 15:40:43 2024 +0000 - upstream: ban user/hostnames with most shell metacharacters + upstream: never close stdin - This makes ssh(1) refuse user or host names provided on the - commandline that contain most shell metacharacters. + The sanitise_stdfd call makes sure that standard file descriptors are + open (if they were closed, they are connected with /dev/null). - 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. + Do not close stdin in any case to prevent error messages when stdin is + read multiple times and to prevent later usage of fd 0 for connections, + e.g. - 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. + echo localhost | ssh-keyscan -f - -f - - 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. + While at it, make stdin-related error messages nicer. - feedback/ok millert@ markus@ dtucker@ deraadt@ + Authored with Max Kunzelmann - OpenBSD-Commit-ID: 3b487348b5964f3e77b6b4d3da4c3b439e94b2d9 + ok djm + + OpenBSD-Commit-ID: 48e9b7938e2fa2f9bd47e6de6df66a31e0b375d3 -commit 0cb50eefdd29f0fec31d0e71cc4b004a5f704e67 +commit 6a42b70e56bef1aacdcdf06352396e837883e84f +Author: Damien Miller +Date: Wed May 8 09:43:59 2024 +1000 + + sync getrrsetbyname.c with recent upstream changes + +commit 385ecb31e147dfea59c1c488a1d2011d3867e60e Author: djm@openbsd.org -Date: Mon Dec 18 14:47:20 2023 +0000 +Date: Tue Apr 30 06:23:51 2024 +0000 - upstream: stricter handling of channel window limits + upstream: fix home-directory extension implementation, it always - 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. + returned the current user's home directory contrary to the spec. - ok markus@ + Patch from Jakub Jelen via GHPR477 - OpenBSD-Commit-ID: 811e21b41831eba3dd7f67b3d409a438f20d3037 + OpenBSD-Commit-ID: 5afd775eab7f9cbe222d7fbae4c793de6c3b3d28 -commit 4448a2938abc76e6bd33ba09b2ec17a216dfb491 +commit 14e2b16bc67ffcc188906f65008667e22f73d103 Author: djm@openbsd.org -Date: Mon Dec 18 14:46:56 2023 +0000 +Date: Tue Apr 30 06:16:55 2024 +0000 - upstream: Make it possible to load certs from PKCS#11 tokens + upstream: flush stdout after writing "sftp>" prompt when not using - Adds a protocol extension to allow grafting certificates supplied by - ssh-add to keys loaded from PKCS#11 tokens in the agent. + editline. - feedback/ok markus@ + From Alpine Linux via GHPR480 - OpenBSD-Commit-ID: bb5433cd28ede2bc910996eb3c0b53e20f86037f + OpenBSD-Commit-ID: 80bdc7ffe0358dc090eb9b93e6dedb2b087b24cd -commit 881d9c6af9da4257c69c327c4e2f1508b2fa754b +commit 2e69a724051488e3fb3cd11531c4b5bc1764945b Author: djm@openbsd.org -Date: Mon Dec 18 14:46:12 2023 +0000 +Date: Tue Apr 30 05:53:03 2024 +0000 - upstream: apply destination constraints to all p11 keys - - Previously applied only to the first key returned from each token. + upstream: stricter validation of messaging socket fd number; disallow - ok markus@ + usage of stderr. Based on GHPR492 by RealHurrison - OpenBSD-Commit-ID: 36df3afb8eb94eec6b2541f063d0d164ef8b488d + OpenBSD-Commit-ID: 73dbbe82ea16f73ce1d044d3232bc869ae2f2ce8 -commit a7ed931caeb68947d30af8a795f4108b6efad761 +commit da757b022bf18c6f7d04e685a10cd96ed00f83da Author: djm@openbsd.org -Date: Mon Dec 18 14:45:49 2023 +0000 +Date: Tue Apr 30 05:45:56 2024 +0000 - upstream: add "ext-info-in-auth@openssh.com" extension - - 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. + upstream: add missing reserved fields to key constraint protocol - 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. + documentation. - Full details in the PROTOCOL file + from Wiktor Kwapisiewicz via GHPR487 - OpenBSD-Commit-ID: 1de7da7f2b6c32a46043d75fcd49b0cbb7db7779 + OpenBSD-Commit-ID: 0dfb69998cfdb3fa00cbb0e7809e7d2f6126e3df -commit 1edb00c58f8a6875fad6a497aa2bacf37f9e6cd5 +commit 16d0b82fa08038f35f1b3630c70116979f49784f +Author: Damien Miller +Date: Tue Apr 30 12:39:34 2024 +1000 + + depend + +commit 66aaa678dbe59aa21d0d9d89a3596ecedde0254b Author: djm@openbsd.org -Date: Mon Dec 18 14:45:17 2023 +0000 +Date: Tue Apr 30 02:14:10 2024 +0000 - upstream: implement "strict key exchange" in ssh and sshd + upstream: correctly restore sigprocmask around ppoll() reported - This adds a protocol extension to improve the integrity of the SSH - transport protocol, particular in and around the initial key exchange - (KEX) phase. + by Tõivo Leedjärv; ok deraadt@ - Full details of the extension are in the PROTOCOL file. + OpenBSD-Commit-ID: c0c0f89de5294a166578f071eade2501929c4686 + +commit 80fb0eb21551aed3aebb009ab20aeffeb01e44e0 +Author: djm@openbsd.org +Date: Tue Apr 30 02:10:49 2024 +0000 + + upstream: add explict check for server hostkey type against - with markus@ + HostkeyAlgorithms. Allows HostkeyAlgorithms to disable implicit fallback from + certificate keys to plain keys. ok markus@ - OpenBSD-Commit-ID: 2a66ac962f0a630d7945fee54004ed9e9c439f14 + OpenBSD-Commit-ID: 364087e4a395ff9b2f42bf3aefdb2090bb23643a -commit 59d691b886c79e70b1d1c4ab744e81fd176222fd -Author: Damien Miller -Date: Mon Dec 18 14:49:11 2023 +1100 +commit 5b28096d31ff7d80748fc845553a4aef5bb05d86 +Author: jsg@openbsd.org +Date: Tue Apr 23 13:34:50 2024 +0000 - better detection of broken -fzero-call-used-regs + upstream: correct indentation; no functional change ok tb@ - Use OSSH_CHECK_CFLAG_LINK() for detection of these flags and extend - test program to exercise varargs, which seems to catch more stuff. + OpenBSD-Commit-ID: dd9702fd43de546bc6a3f4f025c74d6f3692a0d4 + +commit fd3cb8a82784e05f621dea5b56ac6f89bc53c067 +Author: semarie@openbsd.org +Date: Thu Apr 4 16:00:51 2024 +0000 + + upstream: set right mode on ssh-agent at boot-time - ok dtucker@ + which sthen@ + ok deraadt@ + + OpenBSD-Commit-ID: 662b5056a2c6171563e1626f9c69f27862b5e7af -commit aa7b21708511a6d4aed3839fc9f6e82e849dd4a1 -Author: djm@openbsd.org -Date: Wed Dec 13 03:28:19 2023 +0000 +commit 54343a260e3aa4bceca1852dde31cd08e2abd82b +Author: deraadt@openbsd.org +Date: Tue Apr 2 12:22:38 2024 +0000 - upstream: when invoking KnownHostsCommand to determine the order of + upstream: Oops, incorrect hex conversion spotted by claudio. - host key algorithms to request, ensure that the hostname passed to the - command is decorated with the port number for ports other than 22. + While here try to improve how it reads a bit better. Surprising the + regression tests didn't spot this error, maybe it fails to roundtrip the + values. - This matches the behaviour of KnownHostsCommand when invoked to look - up the actual host key. + OpenBSD-Commit-ID: 866cfcc1955aef8f3fc32da0b70c353a1b859f2e + +commit ec78c31409590ad74efc194f886273ed080a545a +Author: deraadt@openbsd.org +Date: Tue Apr 2 10:02:08 2024 +0000 + + upstream: for parse_ipqos(), use strtonum() instead of mostly - bz3643, ok dtucker@ + idiomatic strtoul(), but wow it's so gross. ok djm - OpenBSD-Commit-ID: 5cfabc0b7c6c7ab473666df314f377b1f15420b1 + OpenBSD-Commit-ID: cec14a76af2eb7b225300c80fc0e21052be67b05 -commit 4086bd6652c0badccc020218a62190a7798fb72c -Author: markus@openbsd.org -Date: Fri Dec 8 09:18:39 2023 +0000 +commit 8176e1a6c2e6da9361a7abb6fbf6c23c299f495b +Author: deraadt@openbsd.org +Date: Tue Apr 2 09:56:58 2024 +0000 - upstream: prevent leak in sshsig_match_principals; ok djm@ + upstream: can shortcut by returning strtonum() value directly; ok - OpenBSD-Commit-ID: 594f61ad4819ff5c72dfe99ba666a17f0e1030ae + djm + + OpenBSD-Commit-ID: 7bb2dd3d6d1f288dac14247d1de446e3d7ba8b8e -commit 19d3ee2f3adf7d9a606ff015c1e153744702c4c9 -Author: djm@openbsd.org -Date: Wed Dec 6 21:06:48 2023 +0000 +commit 9f543d7022a781f80bb696f9d73f1d1c6f9e31d6 +Author: deraadt@openbsd.org +Date: Tue Apr 2 09:52:14 2024 +0000 - upstream: short circuit debug log processing early if we're not going + upstream: rewrite convtime() to use a isdigit-scanner and - to log anything. From Kobe Housen + strtonum() instead of strange strtoul can might be fooled by garage + characters. passes regress/usr.bin/ssh/unittests/misc ok djm - OpenBSD-Commit-ID: 2bcddd695872a1bef137cfff7823044dcded90ea + OpenBSD-Commit-ID: 4b1ef826bb16047aea3f3bdcb385b72ffd450abc -commit 947affad4831df015c498c00c6351ea6f13895d5 -Author: Darren Tucker -Date: Mon Nov 27 09:37:28 2023 +1100 +commit 8673137f780d8d9e4cda3c4605cb5d88d5cea271 +Author: claudio@openbsd.org +Date: Tue Apr 2 09:48:24 2024 +0000 - Add tests for OpenSSL 3.2.0 and 3.2 stable branch. + upstream: Remove unused ptr[3] char array in pkcs11_decode_hex. + + OK deraadt@ + + OpenBSD-Commit-ID: 3d14433e39fd558f662d3b0431c4c555ef920481 -commit 747dce36206675ca6b885010a835733df469351b -Author: Darren Tucker -Date: Sat Nov 25 09:03:38 2023 +1100 +commit c7fec708f331f108343d69e4d74c9a5d86d6cfe7 +Author: deraadt@openbsd.org +Date: Tue Apr 2 09:32:28 2024 +0000 - Use non-zero arg in compiler test program. + upstream: Replace non-idiomatic strtoul(, 16) to parse a region - 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. + of 2-character hex sequences with a low-level replacement designed just for + the task. ok djm + + OpenBSD-Commit-ID: 67bab8b8a4329a19a0add5085eacd6f4cc215e85 -commit 3d44a5c56585d1c351dbc006240a591b6da502b1 -Author: dtucker@openbsd.org -Date: Fri Nov 24 00:31:30 2023 +0000 +commit 019a5f483b0f588da6270ec401d0b4bb35032f3f +Author: deraadt@openbsd.org +Date: Tue Apr 2 09:29:31 2024 +0000 - upstream: Plug mem leak of msg when processing a quit message. + upstream: Use strtonum() instead of severely non-idomatic - Coverity CID#427852, ok djm@ + strtoul() In particular this will now reject trailing garbage, ie. + '12garbage'. ok djm - OpenBSD-Commit-ID: bf85362addbe2134c3d8c4b80f16601fbff823b7 + OpenBSD-Commit-ID: c82d95e3ccbfedfc91a8041c2f8bf0cf987d1501 -commit 1d7f9b6e297877bd00973e6dc5c0642dbefc3b5f -Author: dtucker@openbsd.org -Date: Thu Nov 23 03:37:05 2023 +0000 +commit 8231ca046fa39ea4eb99b79e0a6e09dec50ac952 +Author: deraadt@openbsd.org +Date: Mon Apr 1 15:50:17 2024 +0000 - upstream: Include existing mux path in debug message. + upstream: also create a relink kit for ssh-agent, since it is a - OpenBSD-Commit-ID: 1c3641be10c2f4fbad2a1b088a441d072e18bf16 + long-running setgid program carrying keys with some (not very powerful) + communication channels. solution for testing the binary from dtucker. + agreement from djm. Will add it into /etc/rc in a few days. + + OpenBSD-Commit-ID: 2fe8d707ae35ba23c7916adcb818bb5b66837ba0 -commit f29934066bd0e561a2e516b7e584fb92d2eedee0 -Author: Darren Tucker -Date: Thu Nov 23 19:41:27 2023 +1100 +commit bf7bf50bd6a14e49c9c243cb8f4de31e555a5a2e +Author: deraadt@openbsd.org +Date: Mon Apr 1 15:48:16 2024 +0000 - Add an Ubuntu 22.04 test VM. + upstream: new-style relink kit for sshd. The old scheme created - 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. + a Makefile by concatenating two Makefiles and was incredibly fragile. In the + new way a narrow-purposed install.sh script is created and shipped with the + objects. A recently commited /etc/rc script understands these files. + + OpenBSD-Commit-ID: ef9341d5a50f0d33e3a6fbe995e92964bc7ef2d3 -commit a93284a780cd3972afe5f89086b75d564ba157f3 -Author: Darren Tucker -Date: Thu Nov 23 19:36:22 2023 +1100 +commit 00e63688920905e326d8667cb47f17a156b6dc8f +Author: renmingshuai +Date: Fri Apr 12 10:20:49 2024 +0800 - Add gcc-12 -Werror test on Ubuntu 22.04. + Shell syntax fix (leftover from a sync). - Explictly specify gcc-11 on Ubuntu 22.04 (it's the system compiler). + Signed-off-by: renmingshuai -commit 670f5a647e98b6fd95ad64f789f87ee3274b481b +commit 2eded551ba96e66bc3afbbcc883812c2eac02bd7 Author: Darren Tucker -Date: Thu Nov 23 19:34:57 2023 +1100 +Date: Thu Apr 25 13:20:19 2024 +1000 - Check return value from write to prevent warning. + Merge flags for OpenSSL 3.x versions. - ... and since we're testing for flags with -Werror, this caused - configure to mis-detect compiler flags. + OpenSSL has moved to 3.4 which we don't currently accept. Based on + the OpenSSL versioning policy[0] it looks like all of the 3.x versions + should work with OpenSSH, so remove the distinction in configure and + accept all of them. + + [0] https://openssl.org/policies/general/versioning-policy.html -commit cea007d691cfedfa07a5b8599f97ce0511f53fc9 +commit 8673245918081c6d1dc7fb3733c8eb2c5a902c5e Author: Darren Tucker -Date: Wed Nov 22 21:18:55 2023 +1100 +Date: Thu Apr 25 13:19:03 2024 +1000 - Run compiler test program when compiling natively. - - ok djm@ + Remove 9.6 branch from status page. -commit ee0d305828f13536c0a416bbf9c3e81039d9ea55 +commit 70d43049747fa3c66cf876d52271859407cec2fa Author: Darren Tucker -Date: Wed Nov 22 21:18:07 2023 +1100 +Date: Thu Apr 25 13:16:58 2024 +1000 - Factor out compiler test program into a macro. + Update LibreSSL and OpenSSL versions tested. - ok djm@ + Update LibreSSL versions to current releases (3.8.4 & 3.9.1). + Add newly-released OpenSSL 3.3.0, and add tests against the 3.1 and + 3.3 branches. -commit de304c76316b029df460673725a9104224b9959b -Author: Darren Tucker -Date: Wed Nov 22 08:55:36 2023 +1100 +commit 88351eca17dcc55189991ba60e50819b6d4193c1 +Author: 90 +Date: Fri Apr 5 19:36:06 2024 +0100 - Add fbsd14 VM to test pool. + Fix missing header for systemd notification -commit 99a2df5e1994cdcb44ba2187b5f34d0e9190be91 -Author: Darren Tucker -Date: Tue Nov 21 16:19:29 2023 +1100 +commit 08f579231cd38a1c657aaa6ddeb8ab57a1fd4f5c +Author: Damien Miller +Date: Wed Apr 3 14:40:32 2024 +1100 - Expand -fzero-call-used-regs test to cover gcc 11. + notify systemd on listen and reload - 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@. + Standalone implementation that does not depend on libsystemd. + With assistance from Luca Boccassi, and feedback/testing from Colin + Watson. bz2641 -commit ff220d4010717f7bfbbc02a2400666fb9d24f250 +commit 43e7c1c07cf6aae7f4394ca8ae91a3efc46514e2 Author: Darren Tucker -Date: Tue Nov 21 14:04:34 2023 +1100 +Date: Sun Mar 31 21:51:57 2024 +1100 - Stop using -fzero-call-used-regs=all + Port changes from selfhosted to upstream tests. - ... 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@ + Should get them working again. -commit 2a19e02f36b16f0f6cc915f7d1e60ead5e36303b +commit 281ea25a44bff53eefb4af7bab7aa670b1f8b6b2 Author: Darren Tucker -Date: Tue Nov 21 14:02:18 2023 +1100 +Date: Sat Mar 30 18:20:16 2024 +1100 - Allow for vendor prefix on clang version numbers. + Check if OpenSSL implementation supports DSA. - Correctly detects the version of OpenBSD's native clang, as well as - Apple's. Spotted tb@, ok djm@. + If --enable/disable-dsa-keys is not specified, set based on what OpenSSL + supports. If specified as enabled, but not supported by OpenSSL error + out. ok djm@ -commit c52db0114826d73eff6cdbf205e9c1fa4f7ca6c6 +commit 2d2c068de8d696fe3246f390b146197f51ea1e83 Author: djm@openbsd.org -Date: Mon Nov 20 02:50:00 2023 +0000 +Date: Sat Mar 30 05:56:22 2024 +0000 - upstream: set errno=EAFNOSUPPORT when filtering addresses that don't + upstream: in OpenSSH private key format, correct type for subsequent - match AddressFamily; yields slightly better error message if no address - matches. bz#3526 + private keys in blob. From Jakub Jelen via GHPR430 - OpenBSD-Commit-ID: 29cea900ddd8b04a4d1968da5c4a893be2ebd9e6 + OpenBSD-Commit-ID: d17dbf47554de2d752061592f95b5d772baab50b -commit 26f3f3bbc69196d908cad6558c8c7dc5beb8d74a -Author: djm@openbsd.org -Date: Wed Nov 15 23:03:38 2023 +0000 +commit c2c0bdd3e96b3ef66d77fccb85ff4962dc76caf0 +Author: Eero Häkkinen +Date: Sat Sep 16 00:55:08 2023 +0300 - upstream: when connecting via socket (the default case), filter - - addresses by AddressFamily if one was specified. Fixes the case where, if - CanonicalizeHostname is enabled, ssh may ignore AddressFamily. bz5326; ok - dtucker + Expose SSH_AUTH_INFO_0 always to PAM auth modules. - OpenBSD-Commit-ID: 6c7d7751f6cd055126b2b268a7b64dcafa447439 + This changes SSH_AUTH_INFO_0 to be exposed to PAM auth modules also + when a password authentication method is in use and not only + when a keyboard-interactive authentication method is in use. -commit 050c335c8da43741ed0df2570ebfbd5d1dfd0a31 -Author: djm@openbsd.org -Date: Wed Nov 15 22:51:49 2023 +0000 +commit 02c5ad23124ae801cf248d99ea5068fc4331ca01 +Author: Darren Tucker +Date: Wed Mar 27 17:42:58 2024 +1100 - upstream: when deciding whether to enable keystroke timing + Rearrange selfhosted VM scheduling. - obfuscation, only consider enabling it when a channel with a tty is open. + Instead of trying to infer the type of the self hosted tests in each of + the driver scripts (inconsistently...), set one of the following + variables to "true" in the workflow: - Avoids turning on the obfucation when X11 forwarding only is in use, - which slows it right down. Reported by Roger Marsh + VM: tests run in a virtual machine. + EPHEMERAL: tests run on an ephemeral virtual machine. + PERSISTENT: tests run on a persistent virtual machine + REMOTE: tests run on a physical remote host. - OpenBSD-Commit-ID: c292f738db410f729190f92de100c39ec931a4f1 + EPHEMERAL VMs can have multiple instances of any given VM can exist + simultaneously and are run by a runner pool. The other types have a + dedicated runner instance and can only run a single test at a time. + + Other settings: + SSHFS: We need to sshfs mount over the repo so the workflow can collect + build artifacts. This also implies the tests must be run over ssh. + DEBUG_ACTIONS: enable "set -x" in scripts for debugging. -commit 676377ce67807a24e08a54cd60ec832946cc6cae -Author: tobhe@openbsd.org -Date: Mon Nov 13 09:18:19 2023 +0000 +commit cd8a72707c02615365d0851ac51063ab6bfe258f +Author: Damien Miller +Date: Sat Mar 30 16:05:59 2024 +1100 - upstream: Make sure sftp_get_limits() only returns 0 if 'limits' + add new token-based signing key for dtucker@ - 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. + Verified in person and via signature with old key. + Will remove old key in a bit. + +commit 8d0e46c1ddb5b7f0992591b0dc5d8aaa77cc9dba +Author: Alkaid +Date: Tue Mar 12 03:59:12 2024 -0700 + + Fix OpenSSL ED25519 support detection - ok djm@ + Wrong function signature in configure.ac prevents openssh from enabling + the recently new support for ED25519 priv keys in PEM PKCS8 format. + +commit 697359be9c23ee43618243cdbcc9c7981e766752 +Author: djm@openbsd.org +Date: Sat Mar 30 04:27:44 2024 +0000 + + upstream: allow WAYLAND_DISPLAY to enable SSH_ASKPASS - OpenBSD-Commit-ID: 1c177d7c3becc1d71bc8763eecf61873a1d3884c + From dkg via GHPR479; ok dtucker@ + + OpenBSD-Commit-ID: 1ac1f9c45da44eabbae89375393c662349239257 -commit 64e0600f23c6dec36c3875392ac95b8a9100c2d6 -Author: Darren Tucker -Date: Mon Nov 13 20:03:31 2023 +1100 +commit 7844705b0364574cc70b941be72036c2c2966363 +Author: dtucker@openbsd.org +Date: Fri Mar 29 10:40:07 2024 +0000 - Test current releases of LibreSSL and OpenSSL. + upstream: Use egrep instead of grep -E. - Retire some of the older releases. + Some plaforms don't have the latter so this makes things easier + in -portable. + + OpenBSD-Regress-ID: ff82260eb0db1f11130200b25d820cf73753bbe3 -commit c8ed7cc545879ac15f6ce428be4b29c35598bb2a +commit 22b2b6c555334bffdf357a2e4aa74308b03b83c3 Author: dtucker@openbsd.org -Date: Wed Nov 1 02:08:38 2023 +0000 +Date: Tue Mar 26 08:09:16 2024 +0000 - upstream: Specify ssh binary to use + upstream: test -h is the POSIXly way of testing for a symlink. Reduces - ... instead of relying on installed one. Fixes test failures in -portable - when running tests prior to installation. + diff vs Portable. - OpenBSD-Regress-ID: b6d6ba71c23209c616efc805a60d9a445d53a685 + OpenBSD-Regress-ID: 6f31cd6e231e3b8c5c2ca0307573ccb7484bff7d -commit e9fc2c48121cada1b4dcc5dadea5d447fe0093c3 +commit edcff77f82c2bb2b5653b36f1e47274c5ef3e8be Author: Darren Tucker -Date: Wed Nov 1 13:11:31 2023 +1100 +Date: Tue Mar 26 18:58:58 2024 +1100 - Put long-running test targets on hipri runners. - - 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. + Fix name of OpenBSD upstream CI jobs. -commit 7ddf27668f0e21233f08c0ab2fe9ee3fdd6ab1e2 +commit 861b084429940e024f1b6e9c2779eac95d7a45db +Author: Darren Tucker +Date: Tue Mar 26 18:55:33 2024 +1100 + + Resync with upstream: ${} around DATAFILE. + +commit 63f248c7693e7f0a3b9a13d2980ac9a7e37f2aea Author: djm@openbsd.org -Date: Wed Nov 1 00:29:46 2023 +0000 +Date: Mon Mar 25 19:28:09 2024 +0000 - upstream: add some tests of forced commands overriding Subsystem - - directives + upstream: optional debugging - OpenBSD-Regress-ID: eb48610282f6371672bdf2a8b5d2aa33cfbd322b + OpenBSD-Regress-ID: b4852bf97ac8fb2e3530f2d5f999edd66058d7bc -commit fb06f9b5a065dfbbef5916fc4accc03c0bf026dd +commit 16e2ebe06a62f09d4877b769876d92d6008a896f Author: dtucker@openbsd.org -Date: Tue Oct 31 04:15:40 2023 +0000 +Date: Mon Mar 25 06:05:42 2024 +0000 - upstream: Don't try to use sudo inside sshd log wrapper. - - 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. + upstream: Verify string returned from local shell command. - OpenBSD-Regress-ID: 70d58df7503db699de579a9479300e5f3735f4ee + OpenBSD-Regress-ID: 5039bde24d33d809aebfa8d3ad7fe9053224e6f8 -commit fc3cc33e88c242c704781c6c48087838f1dcfa2a +commit b326f7a1f39ff31324cc3fe2735178fb474c04a4 Author: dtucker@openbsd.org -Date: Tue Oct 31 02:58:45 2023 +0000 +Date: Mon Mar 25 03:30:31 2024 +0000 - upstream: Only try to chmod logfile if we have sudo. If we don't have + upstream: Improve shell portability: grep -q is not portable so - sudo then we won't need to chmod. + redirect stdout, and use printf instead of relying on echo to do \n + substitution. Reduces diff vs Portable. - OpenBSD-Regress-ID: dbad2f5ece839658ef8af3376cb1fb1cabe2e324 + Also resync somewhat with upstream. + + OpenBSD-Regress-ID: 9ae876a8ec4c4725f1e9820a0667360ee2398337 -commit 3a506598fddd3f18f9095af3fe917f24cbdd32e0 -Author: djm@openbsd.org -Date: Mon Oct 30 23:00:25 2023 +0000 +commit dbf2e319f0c582613fa45a735ea3c242ce56946b +Author: dtucker@openbsd.org +Date: Mon Mar 25 02:07:08 2024 +0000 - upstream: move PKCS#11 setup code to test-exec.sh so it can be reused + upstream: Save error code from SSH for use inside case statement, - elsewhere + from portable. In some shells, "case" will reset the value of $?, so save it + first. - OpenBSD-Regress-ID: 1d29e6be40f994419795d9e660a8d07f538f0acb + OpenBSD-Regress-ID: da32e5be19299cb4f0f7de7f29c11257a62d6949 -commit f82fa227a52661c37404a6d33bbabf14fed05db0 -Author: djm@openbsd.org -Date: Mon Oct 30 17:32:00 2023 +0000 +commit d2c8c4fa7def4fb057ed05b3db57b62c810a26f6 +Author: dtucker@openbsd.org +Date: Mon Mar 25 01:40:47 2024 +0000 - upstream: tidy and refactor PKCS#11 setup code + upstream: Increase timeout. Resyncs with portable where some of - Replace the use of a perl script to delete the controlling TTY with a - SSH_ASKPASS script to directly load the PIN. + the test VMs are slow enough for this to matter. - Move PKCS#11 setup code to functions in anticipation of it being used - elsewhere in additional tests. + OpenBSD-Regress-ID: 6a83a693602eb0312f06a4ad2cd6f40d99d24b26 + +commit 83621b63514a84791623db3efb59d38bc4bf9563 +Author: dtucker@openbsd.org +Date: Mon Mar 25 01:28:29 2024 +0000 + + upstream: In PuTTY interop test, don't assume the PuTTY major - Reduce stdout spam + version is 0. Patch from cjwatson at debian.org via bz#3671. - OpenBSD-Regress-ID: 07705c31de30bab9601a95daf1ee6bef821dd262 + OpenBSD-Regress-ID: 835ed03c1b04ad46be82e674495521f11b840191 -commit 3cf698c6d4ffa9be1da55672a3519e2135a6366a +commit 8a421b927700f3834b4d985778e252b8e3299f83 Author: Darren Tucker -Date: Mon Oct 30 21:35:03 2023 +1100 +Date: Tue Mar 26 18:38:14 2024 +1100 - Add obsd74 test VM and retire obsd69 and obsd70. + Really mkdir /usr/local/etc in CI tests. -commit 3e21d58a09894acb38dc69ed615d101131f473d0 +commit 2946ed522c47ce045314533d426b4e379f745e59 Author: Darren Tucker -Date: Mon Oct 30 18:34:12 2023 +1100 +Date: Tue Mar 26 17:19:09 2024 +1100 - Add OpenSSL 3.3.0 as a known dev version. + Better short name for OpenBSD upstream CI jobs too. -commit 917ba181c2cbdb250a443589ec732aa36fd51ffa +commit 18dbe8eff647aacb82d7e86b4ce63d5beee11f25 Author: Darren Tucker -Date: Mon Oct 30 13:32:03 2023 +1100 +Date: Tue Mar 26 17:13:52 2024 +1100 - Restore nopasswd sudo rule on Mac OS X. - - This seems to be missing from some (but not all) github runners, so - restore it if it seems to be missing. + Ensure /usr/local/etc exists before using in tests. -commit c5698abad6d4ec98ca20bcaaabaeacd5e1ec3f4f +commit 5fc1085128e3348bb1b5ee4d955cc767b019b3ad Author: Darren Tucker -Date: Mon Oct 30 13:26:52 2023 +1100 +Date: Tue Mar 26 16:50:46 2024 +1100 - 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. + Be more specific about when to rerun workflows. -commit 1d6a878ceba60b9dc14037dddc8f036070c0065f +commit 5516923e8ae3da0823fea0d7d28aa813627142c0 +Author: Darren Tucker +Date: Tue Mar 26 16:35:27 2024 +1100 + + Add short names for test jobs on github CI. + +commit dc37d2d2470b4a9cedcee9ac926b7362214e3305 +Author: Darren Tucker +Date: Tue Mar 26 16:26:14 2024 +1100 + + If we're using xpg4's id, remember to pass args. + +commit fe169487937780392b23d3ff3c00e5898c10f784 Author: dtucker@openbsd.org -Date: Sun Oct 29 06:22:07 2023 +0000 +Date: Tue Mar 26 01:23:11 2024 +0000 - upstream: Only try to chown logfiles that exist to prevent spurious - - errors. + upstream: Import regenerated moduli. - OpenBSD-Regress-ID: f1b20a476734e885078c481f1324c9ea03af991e + OpenBSD-Commit-ID: ad3d1486d105b008c93e952d158e5af4d9d4c531 -commit e612376427a66f835e284f6b426d16d7c85301bc -Author: anton@openbsd.org -Date: Thu Oct 26 18:52:45 2023 +0000 +commit 151146f03b490d19145cd421763aa7d42f5c50e2 +Author: job@openbsd.org +Date: Thu Mar 14 06:23:14 2024 +0000 - upstream: make use of bsd.regress.mk in extra and interop targets; ok + upstream: Clarify how literal IPv6 addresses can be used in -J mode - dtucker@ + OK djm@ - OpenBSD-Regress-ID: 7ea21b5f6fc4506165093b2123d88d20ff13a4f0 + OpenBSD-Commit-ID: 524ddae97746b3563ad4a887dfd0a6e6ba114c50 -commit ea0039173957d0edcd6469b9614dcedb44dcb4f9 -Author: dtucker@openbsd.org -Date: Thu Oct 26 12:44:07 2023 +0000 +commit 0d5bdc87a675271862b67eb6a9fb13a202fb4894 +Author: Darren Tucker +Date: Mon Mar 25 16:14:21 2024 +1100 - upstream: Skip conch interop tests when not enabled instead of fatal. + Add Mac OS X 14 test targets. + +commit 2d7964a03e1f50a48040ec6912c0a956df909d21 +Author: Darren Tucker +Date: Mon Mar 25 14:05:40 2024 +1100 + + Move xpg4 'id' handling into test-exec.sh. - OpenBSD-Regress-ID: b0abf81c24ac6c21f367233663228ba16fa96a46 + Handle replacement of 'id' the same way as we do other Portable specific + replacements in test-exec.sh. This brings percent.sh back into sync + with upstream. -commit d220b9ed5494252b26b95f05be118472bc3ab5c0 -Author: dtucker@openbsd.org -Date: Wed Oct 25 05:38:08 2023 +0000 +commit 75d1d49ed10d978171cdafad28bdbffdbd48f41e +Author: Darren Tucker +Date: Mon Mar 25 10:38:03 2024 +1100 - upstream: Import regenerated moduli. + Update branches shown on ci-status to 9.7 and 9.6. + +commit f9193f03db0029fc9c31fbdb5c66a2737446bd8f +Author: Darren Tucker +Date: Mon Mar 25 09:28:02 2024 +1100 + + Improve detection of -fzero-call-used-regs=used. - OpenBSD-Commit-ID: 95f5dd6107e8902b87dc5b005ef2b53f1ff378b8 + Should better detect problems with gcc 13 on m68k. bz#3673 from Colin + Watson via bz#3673 and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110934 + + Signed-off-by: Darren Tucker -commit a611e4db4009447a0151f31a44e235ca32ed4429 -Author: anton@openbsd.org -Date: Wed Oct 25 08:01:59 2023 +0000 +commit 86bdd3853f4d32c85e295e6216a2fe0953ad93f0 +Author: Damien Miller +Date: Mon Mar 11 16:20:49 2024 +1100 - upstream: ssh conch interop tests requires a controlling terminal; + version number in README + +commit 282721418e6465bc39ccfd39bb0133e670ee4423 +Author: Damien Miller +Date: Mon Mar 11 16:20:08 2024 +1100 + + crank RPM spec versions + +commit 3876a3bbd2ca84d23ba20f8b69ba83270c04ce3a +Author: djm@openbsd.org +Date: Mon Mar 11 04:59:47 2024 +0000 + + upstream: openssh-9.7 - ok dtucker@ + OpenBSD-Commit-ID: 618ececf58b8cdae016b149787af06240f7b0cbc + +commit 8fc109cc614954a8eb2738c48c0db36a62af9a06 +Author: Darren Tucker +Date: Mon Mar 11 12:59:26 2024 +1100 + + Test against current OpenSSL and LibreSSL releases. - OpenBSD-Regress-ID: cbf2701bc347c2f19d907f113779c666f1ecae4a + Add LibreSSL 3.9.0, bump older branches to their respective current + releases. -commit da951b5e08c167acb5d6e2eec6f146502f5d6ed8 -Author: anton@openbsd.org -Date: Mon Oct 23 11:30:49 2023 +0000 +commit 26b09b45fec7b88ba09042c09be4157e58e231e2 +Author: Damien Miller +Date: Sun Mar 10 16:24:57 2024 +1100 - upstream: Use private key that is allowed by sshd defaults in conch + quote regexes used to test for algorithm support - interop tests. + Fixes test failures on Solaris 8 reported by Tom G. Christensen + +commit a6a740a4948d10a622b505135bb485c10f21db5e +Author: djm@openbsd.org +Date: Sat Mar 9 05:12:13 2024 +0000 + + upstream: avoid logging in signal handler by converting mainloop to - ok dtucker@ + ppoll() bz3670, reported by Ben Hamilton; ok dtucker@ - OpenBSD-Regress-ID: 3b7f65c8f409c328bcd4b704f60cb3d31746f045 + OpenBSD-Commit-ID: e58f18042b86425405ca09e6e9d7dfa1df9f5f7f -commit 1ca166dbb3c0ce632b98869cd955f69320aa6fe8 -Author: Darren Tucker -Date: Fri Oct 20 20:43:00 2023 +1100 +commit cd82f7526e0481720567ae41db7849ab1c27e27b +Author: djm@openbsd.org +Date: Fri Mar 8 22:16:32 2024 +0000 - Install Dropbear for interop testing. + upstream: skip more whitespace, fixes find-principals on + + allowed_signers files with blank lines; reported by Wiktor Kwapisiewicz + + OpenBSD-Commit-ID: b3a22a2afd753d70766f34bc7f309c03706b5298 -commit f993bb58351c5cb71e61aede63805a34a6d4daea -Author: Darren Tucker -Date: Fri Oct 20 20:39:03 2023 +1100 +commit 2f9d2af5cb19905d87f37d1e11c9f035ac5daf3b +Author: dtucker@openbsd.org +Date: Fri Mar 8 11:34:10 2024 +0000 - Resync PuTTY and Conch path handling with upstream. + upstream: Invoke ProxyCommand that uses stderr redirection via - Now that configure finds these for us we can remove these -portable - specific changes. + $TEST_SHELL. Fixes test when run by a user whose login shell is tcsh. + Found by vinschen at redhat.com. + + OpenBSD-Regress-ID: f68d79e7f00caa8d216ebe00ee5f0adbb944062a -commit ff85becd5f5f06a76efa45d30fb204a3c5e5215c +commit 9b3f0beb4007a7e01dfedabb429097fb593deae6 Author: Darren Tucker -Date: Fri Oct 20 20:35:46 2023 +1100 +Date: Thu Mar 7 17:18:14 2024 +1100 - Have configure find PuTTY and Conch binaries. + Prefer openssl binary from --with-ssl-dir directory. - This will let us remove some -portable specific changes from - test-exec.sh. + Use openssl in the directory specified by --with-ssl-dir as long + as it's functional. Reported by The Doctor. -commit c54a50359b9cecddbf3ffcdc26efcb3cd6071ec1 -Author: dtucker@openbsd.org -Date: Fri Oct 20 07:37:07 2023 +0000 +commit c47e1c9c7911f38b2fc2fb01b1f6ae3a3121a838 +Author: djm@openbsd.org +Date: Wed Mar 6 02:59:59 2024 +0000 - upstream: Allow overriding the locations of the Dropbear binaries + upstream: fix memory leak in mux proxy mode when requesting forwarding. - similar to what we do for the PuTTY ones. + found by RASU JSC, reported by Maks Mishin in GHPR#467 - OpenBSD-Regress-ID: 7de0e00518fb0c8fdc5f243b7f82f523c936049c + OpenBSD-Commit-ID: 97d96a166b1ad4b8d229864a553e3e56d3116860 -commit fbaa707d455a61d0aef8ae65e02a25bac5351e5c -Author: dtucker@openbsd.org -Date: Fri Oct 20 06:56:45 2023 +0000 +commit 242742827fea4508e68097c128e802edc79addb5 +Author: djm@openbsd.org +Date: Wed Mar 6 00:31:04 2024 +0000 - 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. + upstream: wrap a few PKCS#11-specific bits in ENABLE_PKCS11 - OpenBSD-Regress-ID: 8cb898c414fcdb252ca6328896b0687acdaee496 + OpenBSD-Commit-ID: 463e4a69eef3426a43a2b922c4e7b2011885d923 -commit c2003d0dbdcdb61ca336c3f90c5c2b4a09c8e73f -Author: Fabio Pedretti -Date: Mon Oct 16 11:59:53 2023 +0200 +commit d52b6509210e2043f33e5a1de58dd4a0d5d48c2a +Author: Damien Miller +Date: Wed Mar 6 11:31:36 2024 +1100 - Update openssl-devel dependency in RPM spec. + disable RSA tests when algorithm is not supported - 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 + Unbreaks "make test" when compiled --without-openssl. + + Similar treatment to how we do DSA and ECDSA. -commit 064e09cd632721c7e6889904e07767443ee23821 -Author: Fabio Pedretti -Date: Mon Oct 16 10:13:06 2023 +0200 +commit 668d270a6c77e8b5a1da26ecad2e6de9f62c8fe4 +Author: Damien Miller +Date: Wed Mar 6 10:33:20 2024 +1100 - Remove reference of dropped sshd.pam.old file + add a --without-retpoline configure option - The file was removed in openssh 8.8 + discussed with deraadt and dtucker a while ago -commit 62db354b696b378a164b6e478cb6b0171dcb0c3d -Author: dtucker@openbsd.org -Date: Mon Oct 16 08:40:00 2023 +0000 +commit 3deb501f86fc47e175ef6a3eaba9b9846a80d444 +Author: djm@openbsd.org +Date: Mon Mar 4 04:13:18 2024 +0000 - upstream: Move declaration of "len" into the block where it's used. + upstream: fix leak of CanonicalizePermittedCNAMEs on error path; - This lets us compile Portable with -Werror with when OpenSSL doesn't have - Ed25519 support. + spotted by Coverity (CID 438039) - OpenBSD-Commit-ID: e02e4b4af351946562a7caee905da60eff16ba29 + OpenBSD-Commit-ID: 208839699939721f452a4418afc028a9f9d3d8af -commit 6eee8c972d5901d10e80634a006b4e346b2c8c19 -Author: Damien Miller -Date: Fri Oct 13 15:15:05 2023 +1100 +commit 65a44a8a4f7d902a64d4e60eda84384b2e2a24a2 +Author: djm@openbsd.org +Date: Mon Mar 4 02:16:11 2024 +0000 - run t-extra regress tests + upstream: Separate parsing of string array options from applying them - 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 637624dbbac13f2bc3c8ec5b15c9d627d07f2935 -Author: Darren Tucker -Date: Thu Oct 12 22:01:23 2023 +1100 - - Don't use make -j2. + to the active configuration. This fixes the config parser from erroneously + rejecting cases like: - 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. + AuthenticationMethods password + Match User ivy + AuthenticationMethods any + + bz3657 ok markus@ + + OpenBSD-Commit-ID: 7f196cba634c2a3dba115f3fac3c4635a2199491 -commit 971e0cfcfd52ef1d73cf5244074c306a60006e89 +commit 6886e1b1f55c90942e4e6deed930f8ac32e0f938 Author: Darren Tucker -Date: Thu Oct 12 16:23:05 2023 +1100 +Date: Thu Feb 22 17:59:35 2024 +1100 - Correct arg order for ED255519 AC_LINK_IFELSE test. + Add nbsd10 test target. -commit c616e64688b2a0c1b4daad69b056099be998d121 -Author: djm@openbsd.org -Date: Thu Oct 12 03:51:08 2023 +0000 +commit d86bf8a3f6ea4fa7887406c2aa9959db71fa41be +Author: Damien Miller +Date: Thu Feb 22 12:06:10 2024 +1100 - upstream: typos and extra debug trace calls - - OpenBSD-Regress-ID: 98a2a6b9333743274359e3c0f0e65cf919a591d1 + more descriptive configure test name -commit c49a3fbf10162128c67c59562348de2041188974 +commit 9ee335aacc9f5bdc4cc2c19fafb45e27be7d234e Author: djm@openbsd.org -Date: Thu Oct 12 03:48:53 2023 +0000 +Date: Wed Feb 21 06:17:29 2024 +0000 - upstream: ensure logs are owned by correct user; feedback/ok + upstream: explain arguments of internal-sftp GHPR#454 from Niklas - dtucker@ + Hambüchen + MIME-Version: 1.0 + Content-Type: text/plain; charset=UTF-8 + Content-Transfer-Encoding: 8bit - OpenBSD-Regress-ID: c3297af8f07717f1d400a5d34529962f1a76b5a3 + OpenBSD-Commit-ID: 0335d641ae6b5b6201b9ffd5dd06345ebbd0a3f3 -commit 5ec0ed79ac074c3437b25f6cba8b8cf21c8d4587 +commit d1164cb1001dd208fee88aaa9b43d5e6fd917274 Author: djm@openbsd.org -Date: Thu Oct 12 03:36:32 2023 +0000 +Date: Wed Feb 21 06:06:43 2024 +0000 - upstream: 64 %-expansion keys ought to be enough for anybody; ok + upstream: clarify permissions requirements for ChrootDirectory Part - dtucker (we just hit the previous limit in some cases) + of GHPR#454 from Niklas Hambüchen + MIME-Version: 1.0 + Content-Type: text/plain; charset=UTF-8 + Content-Transfer-Encoding: 8bit - OpenBSD-Commit-ID: 84070f8001ec22ff5d669f836b62f206e08c5787 + OpenBSD-Commit-ID: d37bc8786317a11649c62ff5e2936441186ef7a0 -commit f59a94e22e46db2c23eddeb871aa9e8d93ab0016 +commit d410e17d186552d0717f18217d0d049486754365 Author: djm@openbsd.org -Date: Thu Oct 12 02:48:43 2023 +0000 - - upstream: don't dereference NULL pointer when hashing jumphost - - OpenBSD-Commit-ID: 251c0263e1759a921341c7efe7f1d4c73e1c70f4 - -commit 281c79168edcc303abfd5bca983616eaa24c5f32 -Author: Damien Miller -Date: Thu Oct 12 13:20:01 2023 +1100 +Date: Wed Feb 21 06:05:06 2024 +0000 - Solaris: prefer PRIV_XPOLICY to PRIV_LIMIT + upstream: .Cm for a keyword. Part of GHPR#454 from Niklas Hambüchen - If the system support PRIV_XPOLICY and one is set, then don't - modify PRIV_LIMIT. bz2833, patch from Ron Jordan, ok dtucker@ + OpenBSD-Commit-ID: d59c52559f926fa82859035d79749fbb4a3ce18a -commit 98fc34df837f3a3b79d2a111b96fe8a39adcab55 +commit ab73f9678ebf06b32d6361b88b50b42775e0565b Author: djm@openbsd.org -Date: Thu Oct 12 02:18:18 2023 +0000 +Date: Wed Feb 21 06:01:13 2024 +0000 - upstream: add %j token that expands to the configured ProxyJump + upstream: fix typo in match directive predicate (s/tagged/tag) GHPR#462 - hostname (or the empty string if this option is not being used). bz3610, ok - dtucker + from Tobias Manske - OpenBSD-Commit-ID: ce9983f7efe6a178db90dc5c1698df025df5e339 + OpenBSD-Commit-ID: 05b23b772677d48aa82eefd7ebebd369ae758908 -commit 7f3180be8a85320b5d3221714b40c16e66881249 +commit 9844aa2521ccfb1a2d73745680327b79e0574445 Author: djm@openbsd.org -Date: Thu Oct 12 02:15:53 2023 +0000 +Date: Wed Feb 21 05:57:34 2024 +0000 - upstream: release GSS OIDs only at end of authentication; bz2982, + upstream: fix proxy multiplexing mode, broken when keystroke timing - ok dtucker@ + obfuscation was added. GHPR#463 from montag451 - OpenBSD-Commit-ID: 0daa41e0525ae63cae4483519ecaa37ac485d94c + OpenBSD-Commit-ID: 4e412d59b3f557d431f1d81c715a3bc0491cc677 -commit a612b93de5d86e955bfb6e24278f621118eea500 +commit ee6d932acb532f80b11bb7cf161668c70ec8a117 Author: djm@openbsd.org -Date: Thu Oct 12 02:12:53 2023 +0000 +Date: Tue Feb 20 04:10:03 2024 +0000 - upstream: mask SIGINT/TERM/QUIT/HUP before checking quit_pending + upstream: don't append a gratuitous space to the end of subsystem - and use ppoll() to unmask them in the mainloop. Avoids race condition between - signaling ssh to exit and polling. bz3531; ok dtucker + arguments; bz3667 - OpenBSD-Commit-ID: 5c14e1aabcddedb95cdf972283d9c0d5083229e7 + OpenBSD-Commit-ID: e11023aeb3f30b77a674e37b8292c862926d5dc6 -commit 531b27a006116fe7aff325510aaa576f24844452 -Author: djm@openbsd.org -Date: Wed Oct 11 23:23:58 2023 +0000 +commit e27f032aa8fcbae9b2e7c451baaf4b8ac6fa3d45 +Author: dtucker@openbsd.org +Date: Mon Feb 19 09:25:52 2024 +0000 - upstream: sync usage() with ssh.1; spotted by kn@ + upstream: Always define puttysetup function. - OpenBSD-Commit-ID: 191a85639477dcb5fa1616d270d93b7c8d5c1dfd + OpenBSD-Regress-ID: b4c0ccfa4006a1bc5dfd99ccf21c854d3ce2aee0 -commit 64f7ca881b19be754425dca60d1590d306c9d1d0 -Author: djm@openbsd.org -Date: Wed Oct 11 23:14:33 2023 +0000 +commit 84046f9991abef5f46b040b10cf3d494f933a17b +Author: dtucker@openbsd.org +Date: Fri Feb 9 08:56:59 2024 +0000 - upstream: ssh -Q does not make sense with other command-line options, + upstream: Exapnd PuTTY test coverage. - so give it its own line in the manpage + Expand the set of ciphers, MACs and KEX methods in the PuTTY interop + tests. - OpenBSD-Commit-ID: 00a747f0655c12122bbb77c2796be0013c105361 + OpenBSD-Regress-ID: dd28d97d48efe7329a396d0d505ee2907bf7fc57 -commit a752a6c0e1001f93696d7025f0c867f0376e2ecf -Author: djm@openbsd.org -Date: Wed Oct 11 22:42:26 2023 +0000 +commit bbf541ee2afe07b08a8b56fa0dc6f38fcfceef2a +Author: dtucker@openbsd.org +Date: Fri Feb 9 08:47:42 2024 +0000 - upstream: add ChannelTimeout support to the client, mirroring the + upstream: Factor out PuTTY setup. - same option in the server. ok markus@ + Factor out PuTTY and call only when needed. - OpenBSD-Commit-ID: 55630b26f390ac063980cfe7ad8c54b03284ef02 + This allows us to avoid PuTTY key setup when it's not needed, which + speeds up the overall test run by a couple of percent. + + OpenBSD-Regress-ID: c25eaccc3c91bc874400f7c85ce40e9032358c1c -commit 76e91e7238cdc5662bc818e2a48d466283840d23 +commit d31c21c57fb4245271680a1e5043cf6470a96766 +Author: naddy@openbsd.org +Date: Sat Feb 10 11:28:52 2024 +0000 + + upstream: clean sshd random relinking kit; ok miod@ + + OpenBSD-Commit-ID: 509bb19bb9762a4b3b589af98bac2e730541b6d4 + +commit 4dbc5a363ff53a2fcecf6bc3bcc038badc12f118 Author: djm@openbsd.org -Date: Wed Oct 11 22:41:05 2023 +0000 +Date: Fri Feb 2 00:13:34 2024 +0000 - upstream: add support for reading ED25519 private keys in PEM PKCS8 + upstream: whitespace - format; ok markus@ tb@ + OpenBSD-Commit-ID: b24680bc755b621ea801ff8edf6f0f02b68edae1 + +commit efde85dda2130272af24cc346f6c3cd326182ff1 +Author: Darren Tucker +Date: Mon Feb 19 17:29:31 2024 +1100 + + Improve error message for OpenSSL header check. + + bz#3668, ok djm@ + +commit cbbdf868bce431a59e2fa36ca244d5739429408d +Author: Darren Tucker +Date: Wed Feb 7 13:45:02 2024 +1100 + + Interop test against PuTTY snapshot and releases. + +commit 91898bf786b0f149f962c4c96c08a46f29888c10 +Author: Darren Tucker +Date: Tue Feb 6 16:21:05 2024 +1100 + + Put privsep dir on OS X on /usr/local. - OpenBSD-Commit-ID: 01b85c91757e6b057e9b23b8a23f96415c3c7174 + On some runners we can't create /var/empty, so put it some place we can + write. Should fix test breakage on Max OS X 11. -commit fc77c8e352c0f44125425c05265e3a00c183d78a -Author: djm@openbsd.org -Date: Wed Oct 11 06:40:54 2023 +0000 +commit be5ed8ebed8388c5056bfde4688308cc873c18b9 +Author: Darren Tucker +Date: Tue Feb 6 11:19:42 2024 +1100 - upstream: mention "none" is a valid argument to IdentityFile; bz3080 + Add --disable-fd-passing option. - OpenBSD-Commit-ID: 1b4fb590ef731099349a7d468b77f02b240ac926 + .. and enable for the minix3 test VM. This will cause it to more reliably + skip tests that need FD passing and should fix the current test breakage. -commit c97520d23d1fe53d30725a2af25d2dddd6f2faff -Author: djm@openbsd.org -Date: Wed Oct 11 05:42:08 2023 +0000 +commit 0f6a8a0d0a518fd78c4cbebfdac990a57a1c4e41 +Author: Darren Tucker +Date: Tue Feb 6 11:18:44 2024 +1100 - upstream: in olde rcp/scp protocol mode, when rejecting a path from the - - 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 - - OpenBSD-Commit-ID: 0bd8db8a595334ca86bca8f36e23fc0395315765 + Use "skip" function instead doing it ourselves. -commit 208c2b719879805983398160791d6a1ef9c2c3fc +commit 3ad669f81aabbd2ba9fbd472903f680f598e1e99 +Author: Damien Miller +Date: Thu Feb 1 14:01:18 2024 +1100 + + ignore some vim droppings + +commit c283f29d23611a06bbee06bcf458f2fffad721d9 Author: djm@openbsd.org -Date: Wed Oct 11 04:46:29 2023 +0000 +Date: Thu Feb 1 02:37:33 2024 +0000 - upstream: s/%.100s/%s/ in SSH- banner construction as there's no - - reason to limit its size: the version string bring included is a compile time - constant going into an allocated banner string. + upstream: whitespace - OpenBSD-Commit-ID: 0ef73304b9bf3e534c60900cd84ab699f859ebcd + OpenBSD-Commit-ID: bf9e4a1049562ee4322684fbdce07142f04fdbb7 -commit 0354790826b97c41bbd171a965574e159b58d83e -Author: tb@openbsd.org -Date: Tue Oct 10 06:49:54 2023 +0000 +commit 0d96b1506b2f4757fefa5d1f884d49e96a6fd4c3 +Author: Damien Miller +Date: Tue Jan 16 14:40:18 2024 +1100 - upstream: Garbage collect cipher_get_keyiv_len() - - This is a compat20 leftover, unused since 2017. - - ok djm + skip tests that use multiplexing on Windows - OpenBSD-Commit-ID: 91fa5497c9dc6883064624ac27813a567883fdce + Some tests here use multiplexing, skip these if DISABLE_FD_PASSING + is set. Should unbreak tests on Windows. -commit 8d29ee4115001a02641386ae394992c65ed279e0 +commit 50080fa42f5f744b798ee29400c0710f1b59f50e Author: djm@openbsd.org -Date: Tue Oct 10 03:57:45 2023 +0000 +Date: Thu Jan 11 04:50:28 2024 +0000 - upstream: Reserve a range of "local extension" message numbers that + upstream: don't disable RSA test when DSA is disabled; bug introduced - OpenSSH promises not to use (comment change only) + in last commit - OpenBSD-Commit-ID: e61795b453d4892d2c99ce1039112c4a00250e03 + OpenBSD-Regress-ID: 8780a7250bf742b33010e9336359a1c516f2d7b5 -commit 90b0d73d63a706e85f6431f05a62d2ce1b476472 +commit 415c94ce17288e0cdcb9e58cc91fba78d33c8457 Author: djm@openbsd.org -Date: Fri Oct 6 03:32:15 2023 +0000 +Date: Thu Jan 11 01:45:58 2024 +0000 - upstream: typo in error message + upstream: make DSA testing optional, defaulting to on - OpenBSD-Regress-ID: 6a8edf0dc39941298e3780b147b10c0a600b4fee + ok markus + + OpenBSD-Regress-ID: dfc27b5574e3f19dc4043395594cea5f90b8572a -commit e84517f51532ec913d8fb01a8aab7307134774bb +commit f9311e8921d92c5efca767227a497ab63280ac39 Author: djm@openbsd.org -Date: Fri Oct 6 03:25:14 2023 +0000 +Date: Thu Jan 11 01:51:16 2024 +0000 - upstream: Perform the softhsm2 setup as discrete steps rather than + upstream: ensure key_fd is filled when DSA is disabled; spotted by - as a long shell pipeline. Makes it easier to figure out what has happened - when it breaks. + tb@ - OpenBSD-Regress-ID: b3f1292115fed65765d0a95414df16e27772d81c + OpenBSD-Commit-ID: 9dd417b6eec3cf67e870f147464a8d93f076dce7 -commit cb54becff4d776238e0e9072943ba0872260535d -Author: claudio@openbsd.org -Date: Sun Sep 24 08:14:13 2023 +0000 +commit 4e838120a759d187b036036610402cbda33f3203 +Author: djm@openbsd.org +Date: Thu Jan 11 01:45:36 2024 +0000 - upstream: REGRESS_FAIL_EARLY defaults to yes now. So no need to + upstream: make DSA key support compile-time optional, defaulting to - overload the value here anymore. OK tb@ bluhm@ + on - OpenBSD-Regress-ID: f063330f1bebbcd373100afccebc91a965b14496 + ok markus@ + + OpenBSD-Commit-ID: 4f8e98fc1fd6de399d0921d5b31b3127a03f581d -commit f01f5137ceba65baf34ceac5a298c12ac01b1fef +commit afcc9028bfc411bc26d20bba803b83f90cb84e26 Author: jmc@openbsd.org -Date: Wed Oct 4 05:42:10 2023 +0000 +Date: Wed Jan 10 06:33:13 2024 +0000 - upstream: spelling fix; + upstream: fix incorrect capitalisation; - OpenBSD-Commit-ID: 493f95121567e5ab0d9dd1150f873b5535ca0195 - -commit 80a2f64b8c1d27383cc83d182b73920d1e6a91f1 -Author: Damien Miller -Date: Wed Oct 4 15:34:10 2023 +1100 - - crank version numbers + OpenBSD-Commit-ID: cb07eb06e15fa2334660ac73e98f29b6a1931984 -commit f65f187b105d9b5c12fd750a211397d08c17c6d4 +commit 9707c8170c0c1baeb1e06e5a53f604498193885f Author: djm@openbsd.org -Date: Wed Oct 4 04:04:09 2023 +0000 +Date: Tue Jan 9 22:19:36 2024 +0000 - upstream: openssh-9.5 + upstream: extend ChannelTimeout regression test to exercise multiplexed + + connections and the new "global" timeout type. ok dtucker@ - OpenBSD-Commit-ID: 5e0af680480bd3b6f5560cf840ad032d48fd6b16 + OpenBSD-Regress-ID: f10d19f697024e9941acad7c2057f73d6eacb8a2 -commit ffe27e54a4bb18d5d3bbd3f4cc93a41b8d94dfd2 +commit b31b12d28de96e1d43581d32f34da8db27e11c03 Author: djm@openbsd.org -Date: Wed Oct 4 04:03:50 2023 +0000 +Date: Tue Jan 9 22:19:00 2024 +0000 - upstream: add some cautionary text about % token expansion and + upstream: add a "global" ChannelTimeout type to ssh(1) and sshd(8) + + that watches all open channels and will close all open channels if there is + no traffic on any of them for the specified interval. This is in addition to + the existing per-channel timeouts added a few releases ago. + + This supports use-cases like having a session + x11 forwarding channel + open where one may be idle for an extended period but the other is + actively used. The global timeout would allow closing both channels when + both have been idle for too long. - shell metacharacters; based on report from vinci AT protonmail.ch + ok dtucker@ - OpenBSD-Commit-ID: aa1450a54fcee2f153ef70368d90edb1e7019113 + OpenBSD-Commit-ID: 0054157d24d2eaa5dc1a9a9859afefc13d1d7eb3 -commit 60ec3d54fd1ebfe2dda75893fa1e870b8dffbb0d +commit 602f4beeeda5bb0eca181f8753d923a2997d0a51 Author: djm@openbsd.org -Date: Tue Oct 3 23:56:10 2023 +0000 +Date: Tue Jan 9 21:39:14 2024 +0000 - upstream: fix link to agent draft; spotted by Jann Horn + upstream: adapt ssh_api.c code for kex-strict + + from markus@ ok me - OpenBSD-Commit-ID: ff5bda21a83ec013db683e282256a85201d2dc4b + OpenBSD-Commit-ID: 4d9f256852af2a5b882b12cae9447f8f00f933ac -commit 12e2d4b13f6f63ce2de13cbfcc9e4d0d4b4ab231 +commit 42ba34aba8708cf96583ff52975d95a8b47d990d Author: Damien Miller -Date: Wed Oct 4 10:54:04 2023 +1100 +Date: Mon Jan 8 16:26:37 2024 +1100 - use portable provider allowlist path in manpage - - spotted by Jann Horn + nite that recent OSX tun/tap is unsupported -commit 6c2c6ffde75df95fd838039850d3dd3d84956d87 -Author: deraadt@openbsd.org -Date: Tue Sep 19 20:37:07 2023 +0000 +commit 690bc125f9a3b20e47745fa8f5b5e1fd5820247f +Author: Sevan Janiyan +Date: Wed Dec 27 04:57:49 2023 +0000 - upstream: typo; from Jim Spath - - OpenBSD-Commit-ID: 2f5fba917b5d4fcf93d9e0b0756c7f63189e228e + README.platform: update tuntap url -commit b6b49130a0089b297245ee39e769231d7c763014 -Author: djm@openbsd.org -Date: Sun Sep 10 23:12:32 2023 +0000 +commit 6b8be2ccd7dd091808f86af52066b0c2ec30483a +Author: Rose <83477269+AtariDreams@users.noreply.github.com> +Date: Tue Dec 19 11:48:20 2023 -0500 - upstream: rename remote_glob() -> sftp_glob() to match other API + Fix compilation error in ssh-pcks11-client.c - OpenBSD-Commit-ID: d9dfb3708d824ec02970a84d96cf5937e0887229 + Compilation fails becaus of an undefined reference to helper_by_ec, + because we forgot the preprocessor conditional that excludes that function + from being called in unsupported configurations. -commit 21b79af6c8d2357c822c84cef3fbdb8001ed263b +commit 219c8134157744886ee6ac5b8c1650abcd981f4c Author: djm@openbsd.org -Date: Sun Sep 10 03:51:55 2023 +0000 +Date: Mon Jan 8 05:11:18 2024 +0000 - upstream: typo in comment + upstream: Remove outdated note from PROTOCOL.mux - 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. + Port forward close by control master is already implemented + by `mux_master_process_close_fwd` in `mux.c` + + GHPR442 from bigb4ng - 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). + OpenBSD-Commit-ID: ad0734fe5916d2dc7dd02b588906cea4df0482fb -commit 90ccc5918ea505bf156c31148b6b59a1bf5d6dc6 +commit 4c3cf362631ccc4ffd422e572f075d5d594feace Author: djm@openbsd.org -Date: Sun Sep 10 03:25:53 2023 +0000 +Date: Mon Jan 8 05:05:15 2024 +0000 - upstream: randomise keystroke obfuscation intervals and average + upstream: fix missing field in users-groups-by-id@openssh.com reply - interval rate. ok dtucker@ + documentation + + GHPR441 from TJ Saunders - OpenBSD-Commit-ID: 05f61d051ab418fcfc4857ff306e420037502382 + OpenBSD-Commit-ID: ff5733ff6ef4cd24e0758ebeed557aa91184c674 -commit bd1b9e52f5fa94d87223c90905c5fdc1a7c32aa6 +commit f64cede2a3c298b50a2659a8b53eb3ab2c0b8d23 Author: djm@openbsd.org -Date: Fri Sep 8 06:34:24 2023 +0000 +Date: Mon Jan 8 04:10:03 2024 +0000 - upstream: fix sizeof(*ptr) instead sizeof(ptr) in realloc (pointer here + upstream: make kex-strict section more explicit about its intent: - is char**, so harmless); spotted in CID 416964 + banning all messages not strictly required in KEX - OpenBSD-Commit-ID: c61caa4a5a667ee20bb1042098861e6c72c69002 + OpenBSD-Commit-ID: fc33a2d7f3b7013a7fb7500bdbaa8254ebc88116 -commit c4f966482983e18601eec70a1563115de836616f -Author: djm@openbsd.org -Date: Fri Sep 8 06:10:57 2023 +0000 +commit 698fe6fd61cbcb8e3e0e874a561d4335a49fbde5 +Author: Damien Miller +Date: Mon Jan 8 14:46:19 2024 +1100 - upstream: regress test recursive remote-remote directories copies where - - the directory contains a symlink to another directory. - - also remove errant `set -x` that snuck in at some point - - OpenBSD-Regress-ID: 1c94a48bdbd633ef2285954ee257725cd7bc456f + update fuzzer example makefile to clang16 -commit 5e1dfe5014ebc194641678303e22ab3bba15f4e5 -Author: djm@openbsd.org -Date: Fri Sep 8 06:10:02 2023 +0000 +commit fc332cb2d602c60983a8ec9f89412754ace06425 +Author: Damien Miller +Date: Mon Jan 8 14:45:49 2024 +1100 - upstream: fix recursive remote-remote copies of directories that - - contain symlinks to other directories (similar to bz3611) + unbreak fuzzers - missing pkcs11_make_cert() - OpenBSD-Commit-ID: 7e19d2ae09b4f941bf8eecc3955c9120171da37f + provide stub for use in fuzzer harness -commit 7c0ce2bf98b303b6ad91493ee3247d96c18ba1f6 -Author: djm@openbsd.org -Date: Fri Sep 8 05:50:57 2023 +0000 +commit 9ea0a4524ae3276546248a926b6641b2fbc8421b +Author: Damien Miller +Date: Mon Jan 8 14:45:14 2024 +1100 - upstream: regress test for recursive copies of directories containing - - symlinks to other directories. bz3611, ok dtucker@ + unbreak fuzzers for clang16 - OpenBSD-Regress-ID: eaa4c29cc5cddff4e72a16bcce14aeb1ecfc94b9 + getopt() needs a throw() attribute to compile, so supply one when compiling + things with C++ -commit 2de990142a83bf60ef694378b8598706bc654b08 +commit a72833d00788ef91100c643536ac08ada46440e1 Author: djm@openbsd.org -Date: Fri Sep 8 05:56:13 2023 +0000 +Date: Mon Jan 8 00:34:33 2024 +0000 - upstream: the sftp code was one of my first contributions to - - OpenSSH and it shows - the function names are terrible. - - Rename do_blah() to sftp_blah() to make them less so. + upstream: remove ext-info-* in the kex.c code, not in callers; - 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. + with/ok markus@ - OpenBSD-Commit-ID: eb54d6a72d0bbba4d623e2175cf5cc4c75dc2ba4 + OpenBSD-Commit-ID: c06fe2d3a0605c517ff7d65e38ec7b2d1b0b2799 -commit 249d8bd0472b53e3a2a0e138b4c030a31e83346a +commit 86f9e96d9bcfd1f5cd4bf8fb57a9b4c242df67df Author: djm@openbsd.org -Date: Fri Sep 8 05:50:12 2023 +0000 +Date: Mon Jan 8 00:30:39 2024 +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: fix typo; spotted by Albert Chin - OpenBSD-Commit-ID: 9760fda668eaa94a992250d7670dfbc62a45197c + OpenBSD-Commit-ID: 77140b520a43375b886e535eb8bd842a268f9368 -commit 0e1f4401c466fa4fdaea81b6dadc8dd1fc4cf0af -Author: djm@openbsd.org -Date: Wed Sep 6 23:36:09 2023 +0000 +commit f0cbd26ec91bd49719fb3eea7ca44d2380318b9a +Author: dtucker@openbsd.org +Date: Thu Jan 4 09:51:49 2024 +0000 - upstream: regression test for override of subsystem in match blocks + upstream: Import regenerated moduli. - OpenBSD-Regress-ID: 5f8135da3bfda71067084c048d717b0e8793e87c + OpenBSD-Commit-ID: 5a636f6ca7f25bfe775df4952f7aac90a7fcbbee -commit 8a1450c62035e834d8a79a5d0d1c904236f9dcfe -Author: djm@openbsd.org -Date: Wed Sep 6 23:35:35 2023 +0000 +commit 64ddf776531ca4933832beecc8b7ebe1b937e081 +Author: jsg@openbsd.org +Date: Wed Dec 20 00:06:25 2023 +0000 - upstream: allow override of Sybsystem directives in sshd Match + upstream: spelling; ok markus@ - blocks + OpenBSD-Commit-ID: 9d01f2e9d59a999d5d42fc3b3efcf8dfb892e31b + +commit 503fbe9ea238a4637e8778208bde8c09bcf78475 +Author: jmc@openbsd.org +Date: Tue Dec 19 06:57:34 2023 +0000 + + upstream: sort -C, and add to usage(); ok djm - OpenBSD-Commit-ID: 3911d18a826a2d2fe7e4519075cf3e57af439722 + OpenBSD-Commit-ID: 80141b2a5d60c8593e3c65ca3c53c431262c812f -commit 6e52826e2a74d077147a82ead8d4fbd5b54f4e3b +commit 5413b1c7ff5a19c6a7d44bd98c5a83eb47819ba6 Author: djm@openbsd.org -Date: Wed Sep 6 23:26:37 2023 +0000 +Date: Tue Dec 19 06:41:14 2023 +0000 - upstream: allocate the subsystems array as necessary and remove the - - fixed limit of subsystems. Saves a few kb of memory in the server and makes - it more like the other options. + upstream: correct section numbers; from Ed Maste - OpenBSD-Commit-ID: e683dfca6bdcbc3cc339bb6c6517c0c4736a547f + OpenBSD-Commit-ID: e289576ee5651528404cb2fb68945556052cf83f -commit e19069c9fac4c111d6496b19c7f7db43b4f07b4f +commit 430ef864645cff83a4022f5b050174c840e275da Author: djm@openbsd.org -Date: Wed Sep 6 23:23:53 2023 +0000 +Date: Mon Dec 18 15:58:56 2023 +0000 - upstream: preserve quoting of Subsystem commands and arguments. - - This may change behaviour of exotic configurations, but the most common - subsystem configuration (sftp-server) is unlikely to be affected. + upstream: match flag type (s/int/u_int) - OpenBSD-Commit-ID: 8ffa296aeca981de5b0945242ce75aa6dee479bf + OpenBSD-Commit-ID: 9422289747c35ccb7b31d0e1888ccd5e74ad566a -commit 52dfe3c72d98503d8b7c6f64fc7e19d685636c0b -Author: djm@openbsd.org -Date: Wed Sep 6 23:21:36 2023 +0000 +commit 1036d77b34a5fa15e56f516b81b9928006848cbd +Author: Damien Miller +Date: Fri Dec 22 17:56:26 2023 +1100 - upstream: downgrade duplicate Subsystem directives from being a + better detection of broken -fzero-call-used-regs + + gcc 13.2.0 on ppc64le refuses to compile some function, including + cipher.c:compression_alg_list() with an error: + + > sorry, unimplemented: argument ‘used’ is not supportedcw + > for ‘-fzero-call-used-regs’ on this target - fatal error to being a debug message to match behaviour with just about all - other directives. + This extends the autoconf will-it-work test with a similarly- + structured function that seems to catch this. - OpenBSD-Commit-ID: fc90ed2cc0c18d4eb8e33d2c5e98d25f282588ce + Spotted/tested by Colin Watson; bz3645 -commit 1ee0a16e07b6f0847ff463d7b5221c4bf1876e25 -Author: djm@openbsd.org -Date: Wed Sep 6 23:18:15 2023 +0000 +commit 8241b9c0529228b4b86d88b1a6076fb9f97e4a99 +Author: Damien Miller +Date: Tue Dec 19 01:59:50 2023 +1100 - upstream: handle cr+lf (instead of just cr) in sshsig signature - - files - - OpenBSD-Commit-ID: 647460a212b916540016d066568816507375fd7f + crank versions -commit e1c284d60a928bcdd60bc575c6f9604663502770 -Author: job@openbsd.org -Date: Mon Sep 4 10:29:58 2023 +0000 +commit 2f2c65cb5f1518a9c556d3e8efa27ea0ca305c6b +Author: Damien Miller +Date: Tue Dec 19 01:59:06 2023 +1100 - upstream: Generate Ed25519 keys when invoked without arguments - - Ed25519 public keys are very convenient due to their small size. - OpenSSH has supported Ed25519 since version 6.5 (January 2014). - - OK djm@ markus@ sthen@ deraadt@ - - OpenBSD-Commit-ID: f498beaad19c8cdcc357381a60df4a9c69858b3f + depend -commit 694150ad92765574ff82a18f4e86322bd3231e68 +commit e48cdee8e19059203b1aeeabec2350b8375fa61f Author: djm@openbsd.org -Date: Mon Sep 4 00:08:14 2023 +0000 +Date: Mon Dec 18 14:50:08 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. - - Based on / tested by naddy@ + upstream: regress test for agent PKCS#11-backed certificates - OpenBSD-Commit-ID: d98f32dc62d7663ff4660e4556e184032a0db123 + OpenBSD-Regress-ID: 38f681777cb944a8cc3bf9d0ad62959a16764df9 -commit b5fd97896b59a3a46245cf438cc8b16c795d9f74 +commit 2f512f862df1d5f456f82a0334c9e8cc7208a2a1 Author: djm@openbsd.org -Date: Mon Sep 4 00:04:02 2023 +0000 +Date: Mon Dec 18 14:49:39 2023 +0000 - upstream: avoid bogus "obfuscate_keystroke_timing: stopping ..." - - debug messages when keystroke timing obfuscation was never started; spotted - by naddy@ + upstream: regress test for constrained PKCS#11 keys - OpenBSD-Commit-ID: 5c270d35f7d2974db5c1646e9c64188f9393be31 + OpenBSD-Regress-ID: b2f26ae95d609d12257b43aef7cd7714c82618ff -commit ccf7d913db34e49b7a6db1b8331bd402004c840d +commit cdddd66412ca5920ed4d3ebbfa6ace12dbd9b82f Author: djm@openbsd.org -Date: Mon Sep 4 00:01:46 2023 +0000 +Date: Mon Dec 18 14:48:44 2023 +0000 - upstream: make channel_output_poll() return a flag indicating - - whether channel data was enqueued. Will be used to improve keystroke timing - obfuscation. Problem spotted by / tested by naddy@ + upstream: openssh-9.6 - OpenBSD-Commit-ID: f9776c7b0065ba7c3bbe50431fd3b629f44314d0 + OpenBSD-Commit-ID: 21759837cf0e0092d9a2079f8fb562071c11016b -commit 43254b326ac6e2131dbd750f9464dc62c14bd5a7 +commit 6d51feab157cedf1e7ef5b3f8781ca8ff9c4ab1b Author: djm@openbsd.org -Date: Sun Sep 3 23:59:32 2023 +0000 +Date: Mon Dec 18 14:48:08 2023 +0000 - upstream: set interactive mode for ControlPersist sessions if they + upstream: ssh-agent: record failed session-bind attempts - originally requested a tty; enables keystroke timing obfuscation for most - ControlPersist sessions. Spotted by naddy@ + Record failed attempts to session-bind a connection and refuse signing + operations on that connection henceforth. - OpenBSD-Commit-ID: 72783a26254202e2f3f41a2818a19956fe49a772 - -commit ff3eda68ceb2e2bb8f48e3faceb96076c3e85c20 -Author: Darren Tucker -Date: Thu Aug 31 23:02:35 2023 +1000 - - Set LLONG_MAX for C89 test. + 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. - 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 f98031773db361424d59e3301aa92aacf423d920 -Author: djm@openbsd.org -Date: Tue Aug 29 02:50:10 2023 +0000 - - upstream: make PerSourceMaxStartups first-match-wins; ok dtucker@ + Spotted by Jann Horn - OpenBSD-Commit-ID: dac0c24cb709e3c595b8b4f422a0355dc5a3b4e7 + OpenBSD-Commit-ID: b0fdd023e920aa4831413f640de4c5307b53552e -commit cfa66857db90cd908de131e0041a50ffc17c7df8 +commit 7ef3787c84b6b524501211b11a26c742f829af1a Author: djm@openbsd.org -Date: Mon Aug 28 09:52:09 2023 +0000 +Date: Mon Dec 18 14:47:44 2023 +0000 - upstream: descriptive text shouldn't be under .Cm + upstream: ban user/hostnames with most shell metacharacters - OpenBSD-Commit-ID: b1afaeb456a52bc8a58f4f9f8b2f9fa8f6bf651b - -commit 01dbf3d46651b7d6ddf5e45d233839bbfffaeaec -Author: djm@openbsd.org -Date: Mon Aug 28 09:48:11 2023 +0000 - - upstream: limit artificial login delay to a reasonable maximum (5s) + This makes ssh(1) refuse user or host names provided on the + commandline that contain most shell metacharacters. - and don't delay at all for the "none" authentication mechanism. Patch by - Dmitry Belyavskiy in bz3602 with polish/ok dtucker@ + 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. - OpenBSD-Commit-ID: 85b364676dd84cf1de0e98fc2fbdcb1a844ce515 - -commit 528da5b9d7c5da01ed7a73ff21c722e1b5326006 -Author: jmc@openbsd.org -Date: Mon Aug 28 05:32:28 2023 +0000 - - upstream: add spacing for punctuation when macro args; + 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: e80343c16ce0420b2aec98701527cf90371bd0db + OpenBSD-Commit-ID: 3b487348b5964f3e77b6b4d3da4c3b439e94b2d9 -commit 3867361ca691d0956ef7d5fb8181cf554a91d84a +commit 0cb50eefdd29f0fec31d0e71cc4b004a5f704e67 Author: djm@openbsd.org -Date: Mon Aug 28 04:06:52 2023 +0000 +Date: Mon Dec 18 14:47:20 2023 +0000 - upstream: explicit long long type in timing calculations (doesn't + upstream: stricter handling of channel window limits + + 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. - matter, since the range is pre-clamped) + ok markus@ - OpenBSD-Commit-ID: f786ed902d04a5b8ecc581d068fea1a79aa772de + OpenBSD-Commit-ID: 811e21b41831eba3dd7f67b3d409a438f20d3037 -commit 7603ba71264e7fa938325c37eca993e2fa61272f +commit 4448a2938abc76e6bd33ba09b2ec17a216dfb491 Author: djm@openbsd.org -Date: Mon Aug 28 03:31:16 2023 +0000 +Date: Mon Dec 18 14:46:56 2023 +0000 - upstream: Add keystroke timing obfuscation to the client. + upstream: Make it possible to load certs from PKCS#11 tokens - 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/ + Adds a protocol extension to allow grafting certificates supplied by + ssh-add to keys loaded from PKCS#11 tokens in the agent. feedback/ok markus@ - OpenBSD-Commit-ID: 02231ddd4f442212820976068c34a36e3c1b15be + OpenBSD-Commit-ID: bb5433cd28ede2bc910996eb3c0b53e20f86037f -commit dce6d80d2ed3cad2c516082682d5f6ca877ef714 +commit 881d9c6af9da4257c69c327c4e2f1508b2fa754b Author: djm@openbsd.org -Date: Mon Aug 28 03:28:43 2023 +0000 +Date: Mon Dec 18 14:46:12 2023 +0000 - upstream: Introduce a transport-level ping facility + upstream: apply destination constraints to all p11 keys - 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". + Previously applied only to the first key returned from each token. ok markus@ - OpenBSD-Commit-ID: b6b3c4cb2084c62f85a8dc67cf74954015eb547f + OpenBSD-Commit-ID: 36df3afb8eb94eec6b2541f063d0d164ef8b488d -commit d2d247938b38b928f8a6e1a47a330c5584d3a358 -Author: tobhe@openbsd.org -Date: Mon Aug 21 21:16:18 2023 +0000 +commit a7ed931caeb68947d30af8a795f4108b6efad761 +Author: djm@openbsd.org +Date: Mon Dec 18 14:45:49 2023 +0000 - upstream: Log errors in kex_exchange_identification() with level + upstream: add "ext-info-in-auth@openssh.com" extension - verbose instead of error to reduce preauth log spam. All of those get logged - with a more generic error message by sshpkt_fatal(). + 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. - feedback from sthen@ - ok djm@ + 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. + + Full details in the PROTOCOL file - OpenBSD-Commit-ID: bd47dab4695b134a44c379f0e9a39eed33047809 + OpenBSD-Commit-ID: 1de7da7f2b6c32a46043d75fcd49b0cbb7db7779 -commit 9d7193a8359639801193ad661a59d1ae4dc3d302 +commit 1edb00c58f8a6875fad6a497aa2bacf37f9e6cd5 Author: djm@openbsd.org -Date: Mon Aug 21 04:59:54 2023 +0000 +Date: Mon Dec 18 14:45:17 2023 +0000 - upstream: correct math for ClientAliveInterval that caused the + upstream: implement "strict key exchange" in ssh and sshd + + This adds a protocol extension to improve the integrity of the SSH + transport protocol, particular in and around the initial key exchange + (KEX) phase. - probes to be sent less frequently than configured; from Dawid Majchrzak + Full details of the extension are in the PROTOCOL file. - OpenBSD-Commit-ID: 641153e7c05117436ddfc58267aa267ca8b80038 - -commit 3c6ab63b383b0b7630da175941e01de9db32a256 -Author: Darren Tucker -Date: Fri Aug 25 14:48:02 2023 +1000 - - Include Portable version in sshd version string. + with markus@ - bz#3608, ok djm@ + OpenBSD-Commit-ID: 2a66ac962f0a630d7945fee54004ed9e9c439f14 -commit 17fa6cd10a26e193bb6f65d21264d2fe553bcd87 -Author: Darren Tucker -Date: Mon Aug 21 19:47:58 2023 +1000 +commit 59d691b886c79e70b1d1c4ab744e81fd176222fd +Author: Damien Miller +Date: Mon Dec 18 14:49:11 2023 +1100 - obsd-arm64 host is real hardware... + better detection of broken -fzero-call-used-regs - so put in the correct config location. - -commit 598ca75c85acaaacee5ef954251e489cc20d7be9 -Author: Darren Tucker -Date: Mon Aug 21 18:38:36 2023 +1000 - - Add OpenBSD ARM64 test host. - -commit 1acac79bfbe207e8db639e8043524962037c8feb -Author: Darren Tucker -Date: Mon Aug 21 18:05:26 2023 +1000 - - Add test for zlib development branch. + Use OSSH_CHECK_CFLAG_LINK() for detection of these flags and extend + test program to exercise varargs, which seems to catch more stuff. + + ok dtucker@ -commit 84efebf352fc700e9040c8065707c63caedd36a3 +commit aa7b21708511a6d4aed3839fc9f6e82e849dd4a1 Author: djm@openbsd.org -Date: Mon Aug 21 04:36:46 2023 +0000 +Date: Wed Dec 13 03:28:19 2023 +0000 - upstream: want stdlib.h for free(3) + upstream: when invoking KnownHostsCommand to determine the order of - OpenBSD-Commit-ID: 743af3c6e3ce5e6cecd051668f0327a01f44af29 - -commit cb4ed12ffc332d1f72d054ed92655b5f1c38f621 -Author: Darren Tucker -Date: Sat Aug 19 07:39:08 2023 +1000 - - Fix zlib version check for 1.3 and future version. + host key algorithms to request, ensure that the hostname passed to the + command is decorated with the port number for ports other than 22. - bz#3604. - -commit 25b75e21f16bccdaa472ea1889b293c9bd51a87b -Author: Darren Tucker -Date: Mon Aug 14 11:10:08 2023 +1000 - - Add 9.4 branch to CI status page. - -commit 803e22eabd3ba75485eedd8b7b44d6ace79f2052 -Author: djm@openbsd.org -Date: Fri Aug 18 01:37:41 2023 +0000 - - upstream: fix regression in OpenSSH 9.4 (mux.c r1.99) that caused + This matches the behaviour of KnownHostsCommand when invoked to look + up the actual host key. - multiplexed sessions to ignore SIGINT under some circumstances. Reported by / - feedback naddy@, ok dtucker@ + bz3643, ok dtucker@ - OpenBSD-Commit-ID: 4d5c6c894664f50149153fd4764f21f43e7d7e5a + OpenBSD-Commit-ID: 5cfabc0b7c6c7ab473666df314f377b1f15420b1 -commit e706bca324a70f68dadfd0ec69edfdd486eed23a -Author: djm@openbsd.org -Date: Wed Aug 16 16:14:11 2023 +0000 +commit 4086bd6652c0badccc020218a62190a7798fb72c +Author: markus@openbsd.org +Date: Fri Dec 8 09:18:39 2023 +0000 - upstream: defence-in-depth MaxAuthTries check in monitor; ok markus + upstream: prevent leak in sshsig_match_principals; ok djm@ - OpenBSD-Commit-ID: 65a4225dc708e2dae71315adf93677edace46c21 + OpenBSD-Commit-ID: 594f61ad4819ff5c72dfe99ba666a17f0e1030ae -commit d1ab7eb90474df656d5e9935bae6df0bd000d343 +commit 19d3ee2f3adf7d9a606ff015c1e153744702c4c9 Author: djm@openbsd.org -Date: Mon Aug 14 03:37:00 2023 +0000 +Date: Wed Dec 6 21:06:48 2023 +0000 - upstream: add message number of SSH2_MSG_NEWCOMPRESS defined in RFC8308 + upstream: short circuit debug log processing early if we're not going + + to log anything. From Kobe Housen - OpenBSD-Commit-ID: 6c984171c96ed67effd7b5092f3d3975d55d6028 + OpenBSD-Commit-ID: 2bcddd695872a1bef137cfff7823044dcded90ea -commit fa8da52934cb7dff6f660a143276bdb28bb9bbe1 +commit 947affad4831df015c498c00c6351ea6f13895d5 Author: Darren Tucker -Date: Sun Aug 13 15:01:27 2023 +1000 +Date: Mon Nov 27 09:37:28 2023 +1100 - Add obsd72 and obsd73 test targets. + Add tests for OpenSSL 3.2.0 and 3.2 stable branch. -commit f9f18006678d2eac8b0c5a5dddf17ab7c50d1e9f -Author: djm@openbsd.org -Date: Thu Aug 10 23:05:48 2023 +0000 +commit 747dce36206675ca6b885010a835733df469351b +Author: Darren Tucker +Date: Sat Nov 25 09:03:38 2023 +1100 - upstream: better debug logging of sessions' exit status + Use non-zero arg in compiler test program. - OpenBSD-Commit-ID: 82237567fcd4098797cbdd17efa6ade08e1a36b0 + 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 a8c57bcb077f0cfdffcf9f23866bf73bb93e185c -Author: naddy@openbsd.org -Date: Thu Aug 10 14:37:32 2023 +0000 +commit 3d44a5c56585d1c351dbc006240a591b6da502b1 +Author: dtucker@openbsd.org +Date: Fri Nov 24 00:31:30 2023 +0000 - upstream: drop a wayward comma, ok jmc@ + upstream: Plug mem leak of msg when processing a quit message. - OpenBSD-Commit-ID: 5c11fbb9592a29b37bbf36f66df50db9d38182c6 - -commit e962f9b318a238db1becc53c2bf79dd3a49095b4 -Author: Damien Miller -Date: Thu Aug 10 11:10:22 2023 +1000 - - depend - -commit 0fcb60bf83130dfa428bc4422b3a3ac20fb528af -Author: Damien Miller -Date: Thu Aug 10 11:05:42 2023 +1000 - - update versions in RPM specs - -commit d0cee4298491314f09afa1c4383a66d913150b26 -Author: Damien Miller -Date: Thu Aug 10 11:05:14 2023 +1000 - - update version in README + Coverity CID#427852, ok djm@ + + OpenBSD-Commit-ID: bf85362addbe2134c3d8c4b80f16601fbff823b7 -commit 78b4dc6684f4d35943b46b24ee645edfdb9974f5 -Author: djm@openbsd.org -Date: Thu Aug 10 01:01:07 2023 +0000 +commit 1d7f9b6e297877bd00973e6dc5c0642dbefc3b5f +Author: dtucker@openbsd.org +Date: Thu Nov 23 03:37:05 2023 +0000 - upstream: openssh-9.4 + upstream: Include existing mux path in debug message. - OpenBSD-Commit-ID: 71fc1e01a4c4ea061b252bd399cda7be757e6e35 + OpenBSD-Commit-ID: 1c3641be10c2f4fbad2a1b088a441d072e18bf16 -commit 58ca4f0aa8c4306ac0a629c9a85fb1efaf4ff092 +commit f29934066bd0e561a2e516b7e584fb92d2eedee0 Author: Darren Tucker -Date: Thu Aug 10 11:30:24 2023 +1000 - - Only include unistd.h once. - -commit 3961ed02dc578517a9d2535128cff5c3a5460d28 -Author: Damien Miller -Date: Thu Aug 10 09:08:49 2023 +1000 - - wrap poll.h include in HAVE_POLL_H - -commit e535fbe2af893046c28adfcd787c1fdbae36a24a -Author: dtucker@openbsd.org -Date: Fri Aug 4 06:32:40 2023 +0000 +Date: Thu Nov 23 19:41:27 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@ + Add an Ubuntu 22.04 test VM. - OpenBSD-Commit-ID: 2fbe1a36d4a24b98531b2d298a6557c8285dc1b4 + 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 9d92e7b24848fcc605945f7c2e3460c7c31832ce +commit a93284a780cd3972afe5f89086b75d564ba157f3 Author: Darren Tucker -Date: Thu Aug 3 19:35:33 2023 +1000 +Date: Thu Nov 23 19:36:22 2023 +1100 - Fix RNG seeding for OpenSSL w/out self seeding. + Add gcc-12 -Werror test on Ubuntu 22.04. - 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@ + Explictly specify gcc-11 on Ubuntu 22.04 (it's the system compiler). -commit f70010d9b0b3e7e95de8aa0b961e1d74362cfb5d -Author: djm@openbsd.org -Date: Wed Aug 2 23:04:38 2023 +0000 +commit 670f5a647e98b6fd95ad64f789f87ee3274b481b +Author: Darren Tucker +Date: Thu Nov 23 19:34:57 2023 +1100 - upstream: CheckHostIP has defaulted to 'no' for a while; make the - - commented- out config option match. From Ed Maste + Check return value from write to prevent warning. - OpenBSD-Commit-ID: e66e934c45a9077cb1d51fc4f8d3df4505db58d9 + ... and since we're testing for flags with -Werror, this caused + configure to mis-detect compiler flags. -commit c88a8788f9865d02b986d00405b9f0be65ad0b5a -Author: dtucker@openbsd.org -Date: Tue Aug 1 08:15:04 2023 +0000 +commit cea007d691cfedfa07a5b8599f97ce0511f53fc9 +Author: Darren Tucker +Date: Wed Nov 22 21:18:55 2023 +1100 - upstream: remove unnecessary if statement. - - github PR#422 from eyalasulin999, ok djm@ + Run compiler test program when compiling natively. - OpenBSD-Commit-ID: 2b6b0dde4407e039f58f86c8d2ff584a8205ea55 + ok djm@ -commit 77b8b865cd5a8c79a47605c0c5b2bacf4692c4d5 -Author: jmc@openbsd.org -Date: Fri Jul 28 05:42:36 2023 +0000 +commit ee0d305828f13536c0a416bbf9c3e81039d9ea55 +Author: Darren Tucker +Date: Wed Nov 22 21:18:07 2023 +1100 - upstream: %C is a callable macro in mdoc(7) - - so, as we do for %D, escape it; + Factor out compiler test program into a macro. - OpenBSD-Commit-ID: 538cfcddbbb59dc3a8739604319491dcb8e0c0c9 + ok djm@ -commit e0f91aa9c2fbfc951e9ced7e1305455fc614d3f2 -Author: djm@openbsd.org -Date: Fri Jul 28 05:33:15 2023 +0000 +commit de304c76316b029df460673725a9104224b9959b +Author: Darren Tucker +Date: Wed Nov 22 08:55:36 2023 +1100 - upstream: don't need to start a command here; use ssh -N instead. - - Fixes failure on cygwin spotted by Darren - - OpenBSD-Regress-ID: ff678a8cc69160a3b862733d935ec4a383f93cfb + Add fbsd14 VM to test pool. -commit f446a44f30bc680e0d026a4204844b02646c1c2d -Author: djm@openbsd.org -Date: Wed May 17 05:52:01 2023 +0000 +commit 99a2df5e1994cdcb44ba2187b5f34d0e9190be91 +Author: Darren Tucker +Date: Tue Nov 21 16:19:29 2023 +1100 - upstream: add LTESTS_FROM variable to allow skipping of tests up to - - a specific point. e.g. "make LTESTS_FROM=t-sftp" will only run the sftp.sh - test and subsequent ones. ok dtucker@ + Expand -fzero-call-used-regs test to cover gcc 11. - OpenBSD-Regress-ID: 07f653de731def074b29293db946042706fcead3 + 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 8eb8899d612440a9b608bee7f916081d3d0b7812 -Author: djm@openbsd.org -Date: Fri May 12 06:37:42 2023 +0000 +commit ff220d4010717f7bfbbc02a2400666fb9d24f250 +Author: Darren Tucker +Date: Tue Nov 21 14:04:34 2023 +1100 - upstream: test ChrootDirectory in Match block + Stop using -fzero-call-used-regs=all - OpenBSD-Regress-ID: a6150262f39065939f025e546af2a346ffe674c1 + ... 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 e43f43d3f19516222e9a143468ea0dc1b3ab67b6 -Author: djm@openbsd.org -Date: Fri May 12 06:36:27 2023 +0000 +commit 2a19e02f36b16f0f6cc915f7d1e60ead5e36303b +Author: Darren Tucker +Date: Tue Nov 21 14:02:18 2023 +1100 - upstream: better error messages + Allow for vendor prefix on clang version numbers. - OpenBSD-Regress-ID: 55e4186604e80259496d841e690ea2090981bc7a + Correctly detects the version of OpenBSD's native clang, as well as + Apple's. Spotted tb@, ok djm@. -commit 6958f00acf3b9e0b3730f7287e69996bcf3ceda4 +commit c52db0114826d73eff6cdbf205e9c1fa4f7ca6c6 Author: djm@openbsd.org -Date: Thu Jul 27 22:26:49 2023 +0000 +Date: Mon Nov 20 02:50:00 2023 +0000 - upstream: don't incorrectly truncate logged strings retrieved from + upstream: set errno=EAFNOSUPPORT when filtering addresses that don't - PKCS#11 modules; based on GHPR406 by Jakub Jelen; ok markus + match AddressFamily; yields slightly better error message if no address + matches. bz#3526 - OpenBSD-Commit-ID: 7ed1082f23a13b38c373008f856fd301d50012f9 + OpenBSD-Commit-ID: 29cea900ddd8b04a4d1968da5c4a893be2ebd9e6 -commit d1ffde6b55170cd4b9a72bfd9a3f17508e6cf714 +commit 26f3f3bbc69196d908cad6558c8c7dc5beb8d74a Author: djm@openbsd.org -Date: Thu Jul 27 22:25:17 2023 +0000 +Date: Wed Nov 15 23:03:38 2023 +0000 - upstream: make sshd_config AuthorizedPrincipalsCommand and + upstream: when connecting via socket (the default case), filter - AuthorizedKeysCommand accept the %D (routing domain) and a new %C (connection - address/port 4-tuple) as expansion sequences; ok markus + 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: ee9a48bf1a74c4ace71b69de69cfdaa2a7388565 + OpenBSD-Commit-ID: 6c7d7751f6cd055126b2b268a7b64dcafa447439 -commit 999a2886ca1844a7a74b905e5f2c8c701f9838cd +commit 050c335c8da43741ed0df2570ebfbd5d1dfd0a31 Author: djm@openbsd.org -Date: Thu Jul 27 22:23:05 2023 +0000 +Date: Wed Nov 15 22:51:49 2023 +0000 - upstream: increase default KDF work-factor for OpenSSH format + upstream: when deciding whether to enable keystroke timing - private keys from 16 to 24; { feedback ok } x { deraadt markus } + obfuscation, only consider enabling it when a channel with a tty is open. + + Avoids turning on the obfucation when X11 forwarding only is in use, + which slows it right down. Reported by Roger Marsh - OpenBSD-Commit-ID: a3afb1383f8ff0a49613d449f02395d9e8d4a9ec + OpenBSD-Commit-ID: c292f738db410f729190f92de100c39ec931a4f1 -commit 0fa803a1dd1c7b546c166000e23a869cf6c4ec10 -Author: Darren Tucker -Date: Thu Jul 27 02:25:09 2023 +1000 +commit 676377ce67807a24e08a54cd60ec832946cc6cae +Author: tobhe@openbsd.org +Date: Mon Nov 13 09:18:19 2023 +0000 - Prefer OpenSSL's SHA256 in sk-dummy.so + upstream: Make sure sftp_get_limits() only returns 0 if 'limits' - 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. + 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. - 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. + ok djm@ - Admit defeat and use OpenSSL's SHA256 unless we aren't using OpenSSL at - all. ok djm@ + OpenBSD-Commit-ID: 1c177d7c3becc1d71bc8763eecf61873a1d3884c -commit 36cdb5dbf55c99c0faad06066f56a7c341258c1f +commit 64e0600f23c6dec36c3875392ac95b8a9100c2d6 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: Wed Jul 26 23:06:00 2023 +0000 +Date: Mon Nov 13 20:03:31 2023 +1100 - upstream: make ssh -f (fork after authentication) work properly in - - multiplexed cases (inc. ControlPersist). bz3589 bz3589 Based on patches by - Peter Chubb; ok dtucker@ + Test current releases of LibreSSL and OpenSSL. - OpenBSD-Commit-ID: a7a2976a54b93e6767dc846b85647e6ec26969ac + Retire some of the older releases. -commit 076aeda86a7ee9be8fd2f0181ec7b9729a6ceb37 -Author: naddy@openbsd.org -Date: Sun Jul 23 20:04:45 2023 +0000 +commit c8ed7cc545879ac15f6ce428be4b29c35598bb2a +Author: dtucker@openbsd.org +Date: Wed Nov 1 02:08:38 2023 +0000 - upstream: man page typos; ok jmc@ + upstream: Specify ssh binary to use - 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; + ... instead of relying on installed one. Fixes test failures in -portable + when running tests prior to installation. - OpenBSD-Commit-ID: bc965460a89edf76865b7279b45cf9cbdebd558a + OpenBSD-Regress-ID: b6d6ba71c23209c616efc805a60d9a445d53a685 -commit 5f83342b61d1f76c141de608ed2bd293990416bd +commit e9fc2c48121cada1b4dcc5dadea5d447fe0093c3 Author: Darren Tucker -Date: Tue Jul 25 13:00:22 2023 +1000 +Date: Wed Nov 1 13:11:31 2023 +1100 - Handle a couple more OpenSSL no-ecc cases. + Put long-running test targets on hipri runners. - 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 + 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 099cdf59ce1e72f55d421c8445bf6321b3004755 +commit 7ddf27668f0e21233f08c0ab2fe9ee3fdd6ab1e2 Author: djm@openbsd.org -Date: Wed Jul 19 14:03:45 2023 +0000 +Date: Wed Nov 1 00:29:46 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: add some tests of forced commands overriding Subsystem - ok markus@ + directives - OpenBSD-Commit-ID: 0ce188b14fe271ab0568f4500070d96c5657244e + OpenBSD-Regress-ID: eb48610282f6371672bdf2a8b5d2aa33cfbd322b -commit 29ef8a04866ca14688d5b7fed7b8b9deab851f77 -Author: djm@openbsd.org -Date: Wed Jul 19 14:02:27 2023 +0000 +commit fb06f9b5a065dfbbef5916fc4accc03c0bf026dd +Author: dtucker@openbsd.org +Date: Tue Oct 31 04:15:40 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. + upstream: Don't try to use sudo inside sshd log wrapper. - Feedback deraadt; ok markus + 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-Commit-ID: 1508a5fbd74e329e69a55b56c453c292029aefbe + OpenBSD-Regress-ID: 70d58df7503db699de579a9479300e5f3735f4ee -commit 1f2731f5d7a8f8a8385c6031667ed29072c0d92a -Author: djm@openbsd.org -Date: Wed Jul 19 13:56:33 2023 +0000 +commit fc3cc33e88c242c704781c6c48087838f1dcfa2a +Author: dtucker@openbsd.org +Date: Tue Oct 31 02:58:45 2023 +0000 - upstream: Disallow remote addition of FIDO/PKCS11 provider - - 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`. - - 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. + upstream: Only try to chmod logfile if we have sudo. If we don't have - ok markus@ + sudo then we won't need to chmod. - OpenBSD-Commit-ID: 4c2bdf79b214ae7e60cc8c39a45501344fa7bd7c + OpenBSD-Regress-ID: dbad2f5ece839658ef8af3376cb1fb1cabe2e324 -commit 892506b13654301f69f9545f48213fc210e5c5cc +commit 3a506598fddd3f18f9095af3fe917f24cbdd32e0 Author: djm@openbsd.org -Date: Wed Jul 19 13:55:53 2023 +0000 +Date: Mon Oct 30 23:00:25 2023 +0000 - upstream: terminate process if requested to load a PKCS#11 provider + upstream: move PKCS#11 setup code to test-exec.sh so it can be reused - that isn't a PKCS#11 provider; from / ok markus@ + elsewhere - OpenBSD-Commit-ID: 39532cf18b115881bb4cfaee32084497aadfa05c - -commit f3f56df8ec476b2de6cbdbdfdb77a2a61087829d -Author: Damien Miller -Date: Wed Jul 19 12:07:18 2023 +1000 - - agent_fuzz doesn't want stdint.h conditionalised + OpenBSD-Regress-ID: 1d29e6be40f994419795d9e660a8d07f538f0acb -commit 750911fd31d307a767cc86e3bfa90bbbb77b1a25 -Author: Damien Miller -Date: Tue Jul 18 15:41:12 2023 +1000 +commit f82fa227a52661c37404a6d33bbabf14fed05db0 +Author: djm@openbsd.org +Date: Mon Oct 30 17:32:00 2023 +0000 - conditionalise stdint.h inclusion on HAVE_STDINT_H + upstream: tidy and refactor PKCS#11 setup code - fixes build on AIX5 at least - -commit ff047504fa6e008c4092f8929881816b8993bea0 -Author: Damien Miller -Date: Tue Jul 18 15:30:45 2023 +1000 - - conditionalise match localnetwork on ifaddrs.h + Replace the use of a perl script to delete the controlling TTY with a + SSH_ASKPASS script to directly load the PIN. - Fixes build breakage on platforms that lack getifaddrs() - -commit b87b03282e466ca2927954ce93f5dbf0bfdc68f6 -Author: djm@openbsd.org -Date: Mon Jul 17 06:16:33 2023 +0000 - - upstream: missing match localnetwork negation check + Move PKCS#11 setup code to functions in anticipation of it being used + elsewhere in additional tests. + + Reduce stdout spam - OpenBSD-Commit-ID: 9a08ed8dae27d3f38cf280f1b28d4e0ff41a737a + OpenBSD-Regress-ID: 07705c31de30bab9601a95daf1ee6bef821dd262 -commit 6d6e185ba29ef4274164b77eab4dc763907f8821 -Author: jmc@openbsd.org -Date: Mon Jul 17 05:41:53 2023 +0000 +commit 3cf698c6d4ffa9be1da55672a3519e2135a6366a +Author: Darren Tucker +Date: Mon Oct 30 21:35:03 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 - - OpenBSD-Commit-ID: 5235dd7aa42e5bf90ae54579d519f92fc107036e + Add obsd74 test VM and retire obsd69 and obsd70. -commit f1a9898283a0638667b587ee4a950afd61ab51b0 -Author: jmc@openbsd.org -Date: Mon Jul 17 05:38:10 2023 +0000 +commit 3e21d58a09894acb38dc69ed615d101131f473d0 +Author: Darren Tucker +Date: Mon Oct 30 18:34:12 2023 +1100 - upstream: -P before -p in SYNOPSIS; - - OpenBSD-Commit-ID: 535f5257c779e26c6a662a038d241b017f8cab7c + Add OpenSSL 3.3.0 as a known dev version. -commit eef4d7e873568e1c84c36bb4034e2c3378250a61 -Author: jsg@openbsd.org -Date: Mon Jul 17 05:36:14 2023 +0000 +commit 917ba181c2cbdb250a443589ec732aa36fd51ffa +Author: Darren Tucker +Date: Mon Oct 30 13:32:03 2023 +1100 - upstream: configuation -> configuration + Restore nopasswd sudo rule on Mac OS X. - OpenBSD-Commit-ID: 4776ced33b780f1db0b2902faec99312f26a726b + This seems to be missing from some (but not all) github runners, so + restore it if it seems to be missing. -commit dc1dbe94cf6532bd546a3373ad436404f8850e5f -Author: djm@openbsd.org -Date: Mon Jul 17 05:26:38 2023 +0000 +commit c5698abad6d4ec98ca20bcaaabaeacd5e1ec3f4f +Author: Darren Tucker +Date: Mon Oct 30 13:26:52 2023 +1100 - upstream: move other RCSIDs to before their respective license blocks - - too no code change + Don't exit early when setting up on Mac OS X. - OpenBSD-Commit-ID: ef5bf46b57726e4260a63b032b0b5ac3b4fe9cd4 + 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 ebe11044681caff78834ca6b78311ad19c1860b8 -Author: djm@openbsd.org -Date: Mon Jul 17 05:22:30 2023 +0000 +commit 1d6a878ceba60b9dc14037dddc8f036070c0065f +Author: dtucker@openbsd.org +Date: Sun Oct 29 06:22:07 2023 +0000 - upstream: Move RCSID to before license block and away from #includes, + upstream: Only try to chown logfiles that exist to prevent spurious - where it caused merge conflict in -portable for each commit :( + errors. - OpenBSD-Commit-ID: 756ebac963df3245258b962e88150ebab9d5fc20 + OpenBSD-Regress-ID: f1b20a476734e885078c481f1324c9ea03af991e -commit 05c08e5f628de3ecf6f7ea20947735bcfa3201e0 -Author: djm@openbsd.org -Date: Mon Jul 17 05:20:15 2023 +0000 +commit e612376427a66f835e284f6b426d16d7c85301bc +Author: anton@openbsd.org +Date: Thu Oct 26 18:52:45 2023 +0000 - upstream: return SSH_ERR_KRL_BAD_MAGIC when a KRL doesn't contain a + upstream: make use of bsd.regress.mk in extra and interop targets; ok - 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. + dtucker@ - 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-Regress-ID: 7ea21b5f6fc4506165093b2123d88d20ff13a4f0 -commit 919bc3d3b712c920de1ae6be5ac6561c98886d7e -Author: djm@openbsd.org -Date: Mon Jul 17 04:08:31 2023 +0000 +commit ea0039173957d0edcd6469b9614dcedb44dcb4f9 +Author: dtucker@openbsd.org +Date: Thu Oct 26 12:44:07 2023 +0000 - upstream: Add support for configuration tags to ssh(1). - - 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. - - ok markus + upstream: Skip conch interop tests when not enabled instead of fatal. - OpenBSD-Commit-ID: dc08358e70e702b59ac3e591827e5a96141b06a3 + OpenBSD-Regress-ID: b0abf81c24ac6c21f367233663228ba16fa96a46 -commit 3071d85a47061c1bdaf11a0ac233b501ecba862c -Author: djm@openbsd.org -Date: Mon Jul 17 04:04:36 2023 +0000 +commit d220b9ed5494252b26b95f05be118472bc3ab5c0 +Author: dtucker@openbsd.org +Date: Wed Oct 25 05:38:08 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). - - ok markus@ + upstream: Import regenerated moduli. - OpenBSD-Commit-ID: cffb6ff9a3803abfc52b5cad0aa190c5e424c139 + OpenBSD-Commit-ID: 95f5dd6107e8902b87dc5b005ef2b53f1ff378b8 -commit beec17bb311365b75a0a5941418d4b96df7d7888 -Author: djm@openbsd.org -Date: Mon Jul 17 04:01:10 2023 +0000 +commit a611e4db4009447a0151f31a44e235ca32ed4429 +Author: anton@openbsd.org +Date: Wed Oct 25 08:01:59 2023 +0000 - upstream: remove vestigal support for KRL signatures - - 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. + upstream: ssh conch interop tests requires a controlling terminal; - ok markus@ + ok dtucker@ - OpenBSD-Commit-ID: 517437bab3d8180f695c775410c052340e038804 + OpenBSD-Regress-ID: cbf2701bc347c2f19d907f113779c666f1ecae4a -commit 449566f64c21b4578d5c0c431badd0328adc53ed -Author: djm@openbsd.org -Date: Mon Jul 17 03:57:21 2023 +0000 +commit da951b5e08c167acb5d6e2eec6f146502f5d6ed8 +Author: anton@openbsd.org +Date: Mon Oct 23 11:30:49 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: Use private key that is allowed by sshd defaults in conch - ok markus + interop tests. - 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. + ok dtucker@ - OpenBSD-Commit-ID: e7c31034a5434f2ead3579b13a7892960651e6b0 + OpenBSD-Regress-ID: 3b7f65c8f409c328bcd4b704f60cb3d31746f045 -commit 20b768fcd13effe0f2d3619661b6c8592c773553 +commit 1ca166dbb3c0ce632b98869cd955f69320aa6fe8 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 +Date: Fri Oct 20 20:43:00 2023 +1100 - 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 + Install Dropbear for interop testing. -commit 2ee48adb9fc8692e8d6ac679dcc9f35e89ad68f0 -Author: djm@openbsd.org -Date: Fri Jul 14 05:31:44 2023 +0000 +commit f993bb58351c5cb71e61aede63805a34a6d4daea +Author: Darren Tucker +Date: Fri Oct 20 20:39:03 2023 +1100 - upstream: add defence-in-depth checks for some unreachable integer - - overflows reported by Yair Mizrahi @ JFrog; feedback/ok millert@ + Resync PuTTY and Conch path handling with upstream. - OpenBSD-Commit-ID: 52af085f4e7ef9f9d8423d8c1840a6a88bda90bd + Now that configure finds these for us we can remove these -portable + specific changes. -commit 4b43bc358ae6f6b19a973679246dc5172f6ac41b -Author: djm@openbsd.org -Date: Mon Jul 10 04:51:26 2023 +0000 +commit ff85becd5f5f06a76efa45d30fb204a3c5e5215c +Author: Darren Tucker +Date: Fri Oct 20 20:35:46 2023 +1100 - upstream: misplaced debug message + Have configure find PuTTY and Conch binaries. - OpenBSD-Commit-ID: d0f12af0a5067a756aa707bc39a83fa6f58bf7e5 + This will let us remove some -portable specific changes from + test-exec.sh. -commit 8c7203bcee4c4f98a22487b4631fe068b992099b -Author: Damien Miller -Date: Wed Jul 12 11:41:19 2023 +1000 +commit c54a50359b9cecddbf3ffcdc26efcb3cd6071ec1 +Author: dtucker@openbsd.org +Date: Fri Oct 20 07:37:07 2023 +0000 - replace deprecate selinux matchpathcon function + upstream: Allow overriding the locations of the Dropbear binaries - 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 + similar to what we do for the PuTTY ones. - ok dtucker@ + OpenBSD-Regress-ID: 7de0e00518fb0c8fdc5f243b7f82f523c936049c -commit 7e8800f5d701efffa39ccb63ca1e095ea777c31a +commit fbaa707d455a61d0aef8ae65e02a25bac5351e5c Author: dtucker@openbsd.org -Date: Thu Jul 6 22:17:59 2023 +0000 +Date: Fri Oct 20 06:56:45 2023 +0000 - upstream: minleft and maxsign are u_int so cast appropriately. Prompted + upstream: Add interop test with Dropbear. - by github PR#410, ok deraadt. + Right now this is only dbclient not the Dropbear server since it won't + currently run as a ProxyCommand. - OpenBSD-Commit-ID: 0514cd51db3ec60239966622a0d3495b15406ddd + OpenBSD-Regress-ID: 8cb898c414fcdb252ca6328896b0687acdaee496 -commit 94842bfe9b09fc93189c6ed0dc9bbebc1d44a426 -Author: dlg@openbsd.org -Date: Tue Jul 4 03:59:21 2023 +0000 +commit c2003d0dbdcdb61ca336c3f90c5c2b4a09c8e73f +Author: Fabio Pedretti +Date: Mon Oct 16 11:59:53 2023 +0200 - upstream: add support for unix domain sockets to ssh -W - - ok djm@ dtucker@ + Update openssl-devel dependency in RPM spec. - OpenBSD-Commit-ID: 3e6d47567b895c7c28855c7bd614e106c987a6d8 + 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 a95fc5eed09a0238fb127b6c50e8498432b79dae -Author: David Seifert -Date: Fri May 12 14:06:01 2023 +0200 +commit 064e09cd632721c7e6889904e07767443ee23821 +Author: Fabio Pedretti +Date: Mon Oct 16 10:13:06 2023 +0200 - gss-serv.c: `MAXHOSTNAMELEN` -> `HOST_NAME_MAX` - - `MAXHOSTNAMELEN` is not defined in POSIX, which breaks on musl: - https://pubs.opengroup.org/onlinepubs/9699919799/functions/gethostname.html + Remove reference of dropped sshd.pam.old file - Bug: https://bugs.gentoo.org/834044 + The file was removed in openssh 8.8 -commit 8a6cd08850f576e7527c52a1b086cae82fab290e -Author: Darren Tucker -Date: Fri Jun 23 09:49:02 2023 +1000 +commit 62db354b696b378a164b6e478cb6b0171dcb0c3d +Author: dtucker@openbsd.org +Date: Mon Oct 16 08:40:00 2023 +0000 - Update runner OS version for hardenedmalloc test. + 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. - Hardenedmalloc dropped support for "legacy glibc" versions in their - 64dad0a69 so use a newer Ubuntu version for the runner for that test. + OpenBSD-Commit-ID: e02e4b4af351946562a7caee905da60eff16ba29 -commit cfca6f17e64baed6822bb927ed9f372ce64d9c5b +commit 6eee8c972d5901d10e80634a006b4e346b2c8c19 Author: Damien Miller -Date: Thu Jun 22 15:04:03 2023 +1000 +Date: Fri Oct 13 15:15:05 2023 +1100 - handle sysconf(SC_OPEN_MAX) returning > INT_MAX; + run t-extra regress tests - bz3581; ok dtucker + 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 c1c2ca1365b3f7b626683690bd2c68265f6d8ffd -Author: djm@openbsd.org -Date: Wed Jun 21 05:10:26 2023 +0000 +commit 637624dbbac13f2bc3c8ec5b15c9d627d07f2935 +Author: Darren Tucker +Date: Thu Oct 12 22:01:23 2023 +1100 - upstream: better validate CASignatureAlgorithms in ssh_config and - - 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@ + Don't use make -j2. - OpenBSD-Commit-ID: a992d410c8a78ec982701bc3f91043dbdb359912 + 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 4e73cd0f4ab3e5b576c56cac9732da62c8fc0565 -Author: djm@openbsd.org -Date: Wed Jun 21 05:08:32 2023 +0000 +commit 971e0cfcfd52ef1d73cf5244074c306a60006e89 +Author: Darren Tucker +Date: Thu Oct 12 16:23:05 2023 +1100 - upstream: make `ssh -Q CASignatureAlgorithms` only list signature - - 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 + Correct arg order for ED255519 AC_LINK_IFELSE test. -commit a69062f1695ac9c3c3dea29d3044c72aaa6af0ea +commit c616e64688b2a0c1b4daad69b056099be998d121 Author: djm@openbsd.org -Date: Wed Jun 21 05:06:04 2023 +0000 +Date: Thu Oct 12 03:51:08 2023 +0000 - upstream: handle rlimits > INT_MAX (rlim_t is u64); ok dtucker - - bz3581 + upstream: typos and extra debug trace calls - OpenBSD-Commit-ID: 31cf59c041becc0e5ccb0a77106f812c4cd1cd74 + OpenBSD-Regress-ID: 98a2a6b9333743274359e3c0f0e65cf919a591d1 -commit 8d33f2aa6bb895a7f85a47189913639086347b75 +commit c49a3fbf10162128c67c59562348de2041188974 Author: djm@openbsd.org -Date: Tue Jun 20 23:59:33 2023 +0000 +Date: Thu Oct 12 03:48:53 2023 +0000 - upstream: prepare for support for connecting to unix domain sockets + upstream: ensure logs are owned by correct user; feedback/ok - 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. + dtucker@ - OpenBSD-Commit-ID: e5ac5f40d354096c51e8c118a5c1b2d2b7a31384 + OpenBSD-Regress-ID: c3297af8f07717f1d400a5d34529962f1a76b5a3 -commit b4ac435b4e67f8eb5932d8f59eb5b3cf7dc38df0 +commit 5ec0ed79ac074c3437b25f6cba8b8cf21c8d4587 Author: djm@openbsd.org -Date: Tue Jun 20 00:05:09 2023 +0000 - - upstream: reset comment=NULL for each key in do_fingerprint(); - - 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: 3cce84456fdcd67dc6b84e369f92c6686d111d9b - -commit b53a809a549dcd4fbde554c6aa283e597b15ea33 -Author: millert@openbsd.org -Date: Mon Jun 5 13:24:36 2023 +0000 +Date: Thu Oct 12 03:36:32 2023 +0000 - upstream: Store timeouts as int, not u_int as they are limited to + upstream: 64 %-expansion keys ought to be enough for anybody; ok - INT_MAX. Fixes sign compare warnings systems with 32-bit time_t due to type - promotion. OK djm@ + dtucker (we just hit the previous limit in some cases) - OpenBSD-Commit-ID: 48081e9ad35705c5f1705711704a4c2ff94e87b7 + OpenBSD-Commit-ID: 84070f8001ec22ff5d669f836b62f206e08c5787 -commit 2709809fd616a0991dc18e3a58dea10fb383c3f0 -Author: Philip Hands -Date: Wed May 24 19:41:14 2023 +0200 +commit f59a94e22e46db2c23eddeb871aa9e8d93ab0016 +Author: djm@openbsd.org +Date: Thu Oct 12 02:48:43 2023 +0000 - fixup! if -s & -p specified, mention 'sftp -P' on - - success + upstream: don't dereference NULL pointer when hashing jumphost - SSH-Copy-ID-Upstream: 32686e7c65b4fa2846e474d3315102dfa0f043b0 + OpenBSD-Commit-ID: 251c0263e1759a921341c7efe7f1d4c73e1c70f4 -commit 204e0bf05161b7641500d7ab266c21217412379f -Author: Darren Tucker -Date: Tue Aug 3 21:25:48 2021 +1000 +commit 281c79168edcc303abfd5bca983616eaa24c5f32 +Author: Damien Miller +Date: Thu Oct 12 13:20:01 2023 +1100 - Make ssh-copy-id(1) consistent with OpenSSH. - - 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. + Solaris: prefer PRIV_XPOLICY to PRIV_LIMIT - SSH-Copy-ID-Upstream: d8974cfb6242316460ed22a1ccc662800a50c5d3 + If the system support PRIV_XPOLICY and one is set, then don't + modify PRIV_LIMIT. bz2833, patch from Ron Jordan, ok dtucker@ -commit 9de79df66d1430d290fab670bb4b18612875e518 -Author: Philip Hands -Date: Wed May 24 11:45:43 2023 +0200 +commit 98fc34df837f3a3b79d2a111b96fe8a39adcab55 +Author: djm@openbsd.org +Date: Thu Oct 12 02:18:18 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. + upstream: add %j token that expands to the configured ProxyJump - 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. + hostname (or the empty string if this option is not being used). bz3610, ok + dtucker - SSH-Copy-ID-Upstream: 1c124d9bfafdbe28a00b683367ebf5750ce12eb2 + OpenBSD-Commit-ID: ce9983f7efe6a178db90dc5c1698df025df5e339 -commit 801cda54c00e0f4e7d89345a90874c8d05dc233a -Author: Philip Hands -Date: Tue May 23 23:07:11 2023 +0200 +commit 7f3180be8a85320b5d3221714b40c16e66881249 +Author: djm@openbsd.org +Date: Thu Oct 12 02:15:53 2023 +0000 - drop whitespace + upstream: release GSS OIDs only at end of authentication; bz2982, - 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 + ok dtucker@ - SSH-Copy-ID-Upstream: 3c4214704f427bd0654adf9b0fc079253db21cf4 + OpenBSD-Commit-ID: 0daa41e0525ae63cae4483519ecaa37ac485d94c -commit b79e7b88ed44f0e4339f0ff35c96c78a92175a8d -Author: Philip Hands -Date: Tue May 23 16:46:42 2023 +0200 +commit a612b93de5d86e955bfb6e24278f621118eea500 +Author: djm@openbsd.org +Date: Thu Oct 12 02:12:53 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 + upstream: mask SIGINT/TERM/QUIT/HUP before checking quit_pending - https://gitlab.com/phil_hands/ssh-copy-id/-/merge_requests/8 + and use ppoll() to unmask them in the mainloop. Avoids race condition between + signaling ssh to exit and polling. bz3531; ok dtucker - SSH-Copy-ID-Upstream: a942a0e076874adb6d8b2f0fb76d6c7918190fcd + OpenBSD-Commit-ID: 5c14e1aabcddedb95cdf972283d9c0d5083229e7 -commit 914f4ad138714c471ba72fb6d5496b6235320edd -Author: Carlos Rodríguez Gili -Date: Tue Apr 20 19:23:57 2021 +0200 +commit 531b27a006116fe7aff325510aaa576f24844452 +Author: djm@openbsd.org +Date: Wed Oct 11 23:23:58 2023 +0000 - Fix test error for /bin/sh on Solaris 10 and older - - 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. + upstream: sync usage() with ssh.1; spotted by kn@ - SSH-Copy-ID-Upstream: 98394072a3f985b2650c1e8eab2fef84e38cc065 + OpenBSD-Commit-ID: 191a85639477dcb5fa1616d270d93b7c8d5c1dfd -commit bd382dca316c721aed1e45edcf4c4e0f6374afb0 -Author: Jakub Jelen -Date: Tue Mar 2 21:34:05 2021 +0000 +commit 64f7ca881b19be754425dca60d1590d306c9d1d0 +Author: djm@openbsd.org +Date: Wed Oct 11 23:14:33 2023 +0000 - Remove outdated comment + upstream: ssh -Q does not make sense with other command-line options, - The commit b068122 removed the code dropping the trailing colon, but the comment stayed leaving the code confusing for future readers + so give it its own line in the manpage - SSH-Copy-ID-Upstream: 930d39f238117cd53810240ec989d0356aa1c1f6 + OpenBSD-Commit-ID: 00a747f0655c12122bbb77c2796be0013c105361 -commit bdcaf7939029433635d63aade8f9ac762aca2bbe -Author: Darren Tucker -Date: Wed May 10 18:50:46 2023 +1000 +commit a752a6c0e1001f93696d7025f0c867f0376e2ecf +Author: djm@openbsd.org +Date: Wed Oct 11 22:42:26 2023 +0000 - Special case OpenWrt instead of Dropbear. + upstream: add ChannelTimeout support to the client, mirroring the - 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. + same option in the server. ok markus@ - SSH-Copy-ID-Upstream: 0e1f5d443a9967483c33945793107ae3f3e4af2d + OpenBSD-Commit-ID: 55630b26f390ac063980cfe7ad8c54b03284ef02 -commit cf84498f67abe93f813a296167b406a0db7b288e -Author: Philip Hands -Date: Thu May 18 18:20:55 2023 +0200 +commit 76e91e7238cdc5662bc818e2a48d466283840d23 +Author: djm@openbsd.org +Date: Wed Oct 11 22:41:05 2023 +0000 - ssh-copy-id: add -x option (for debugging) + upstream: add support for reading ED25519 private keys in PEM PKCS8 - This option causes the ssh-copy-id to run with set -x + format; ok markus@ tb@ - SSH-Copy-ID-Upstream: a0ee367ea8c0a29c8b4515245e408d2d349e7844 + OpenBSD-Commit-ID: 01b85c91757e6b057e9b23b8a23f96415c3c7174 -commit b4a1efdcb88f03394c08e7f68ed4e11676830002 -Author: Philip Hands -Date: Thu May 18 17:14:41 2023 +0200 +commit fc77c8e352c0f44125425c05265e3a00c183d78a +Author: djm@openbsd.org +Date: Wed Oct 11 06:40:54 2023 +0000 - update copyright notices + upstream: mention "none" is a valid argument to IdentityFile; bz3080 - SSH-Copy-ID-Upstream: c284ed33b361814ea48ff68cbd01ca525b2bf117 + OpenBSD-Commit-ID: 1b4fb590ef731099349a7d468b77f02b240ac926 -commit fcd78e31cdd45a7e69ccfe6d8a3b1037dc1de290 +commit c97520d23d1fe53d30725a2af25d2dddd6f2faff Author: djm@openbsd.org -Date: Wed May 24 23:01:06 2023 +0000 +Date: Wed Oct 11 05:42:08 2023 +0000 - upstream: fix AuthorizedPrincipalsCommand when AuthorizedKeysCommand + upstream: in olde rcp/scp protocol mode, when rejecting a path from the - appears previously in configuration. Reported by John Meyers in bz3574 ok - dtucker@ + 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 - OpenBSD-Commit-ID: 1c92e4517284386703936e1d3abaa36cfacf1951 + OpenBSD-Commit-ID: 0bd8db8a595334ca86bca8f36e23fc0395315765 -commit 5ec5504f1d328d5bfa64280cd617c3efec4f78f3 -Author: dtucker@openbsd.org -Date: Wed May 10 10:04:20 2023 +0000 +commit 208c2b719879805983398160791d6a1ef9c2c3fc +Author: djm@openbsd.org +Date: Wed Oct 11 04:46:29 2023 +0000 - upstream: Remove unused prototypes for ssh1 RSA functions. + upstream: s/%.100s/%s/ in SSH- banner construction as there's no - From lengyijun via github PR#396. + reason to limit its size: the version string bring included is a compile time + constant going into an allocated banner string. - OpenBSD-Commit-ID: 379a5afa8b7a0f3cba0c8a9bcceb4e5e33a5c1ef - -commit fbf362b3891ae4b36052d1b39f37fc618b41c476 -Author: Darren Tucker -Date: Tue May 9 19:26:56 2023 +1000 - - main(void) to prevent unused variable warning. - -commit baf854c8bb0a6d0af5c696c801e631a48dabbaba -Author: Darren Tucker -Date: Tue May 9 19:25:45 2023 +1000 - - Remove warning pragma since clang doesn't like it. - -commit 5fbb7a1349fbbb48ccb1b8cafff2c1854370d87d -Author: Darren Tucker -Date: Tue May 9 17:13:33 2023 +1000 - - Suppress warning for snprintf truncation test. - -commit 47742c513e4e045ecc985c6483fc5c8b050acda2 -Author: Darren Tucker -Date: Tue May 9 17:12:50 2023 +1000 - - Update OpenSSL compat test for 3.x. - -commit 86ad25d455a2313126125540e61e0f9314283f88 -Author: Darren Tucker -Date: Mon May 8 20:23:08 2023 +1000 - - Add macos13 PAM test target. + OpenBSD-Commit-ID: 0ef73304b9bf3e534c60900cd84ab699f859ebcd -commit 77cca2c4b13bc6e5f389565583b6202b0d1bccc2 -Author: Darren Tucker -Date: Mon May 8 20:14:46 2023 +1000 +commit 0354790826b97c41bbd171a965574e159b58d83e +Author: tb@openbsd.org +Date: Tue Oct 10 06:49:54 2023 +0000 - Skip agent-peereid test on macos13. + upstream: Garbage collect cipher_get_keyiv_len() - sudo -S nobody doesn't work on the github runners (probably a - permission issue) so skip that test. - -commit b356b8e91678ea295bcf44df5248c3fbf499fdcf -Author: Darren Tucker -Date: Mon May 8 20:14:28 2023 +1000 - - Include config.guess in debug output. - -commit b7afd8a4ecaca8afd3179b55e9db79c0ff210237 -Author: Darren Tucker -Date: Mon May 8 20:12:59 2023 +1000 - - Handle OpenSSL >=3 ABI compatibility. + This is a compat20 leftover, unused since 2017. - 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 0e9e2663eb2c6e9c3e10d15d70418312ae67e542 -Author: dtucker@openbsd.org -Date: Mon May 1 08:57:29 2023 +0000 - - upstream: Import regenerated moduli. + ok djm - OpenBSD-Commit-ID: 3d5f811cfcaed8cc4a97e1db49ac61bdf118113c + OpenBSD-Commit-ID: 91fa5497c9dc6883064624ac27813a567883fdce -commit d9687f49682e1e93383fc15ab2018850b2ef38c3 -Author: Darren Tucker -Date: Mon May 1 11:45:14 2023 +1000 +commit 8d29ee4115001a02641386ae394992c65ed279e0 +Author: djm@openbsd.org +Date: Tue Oct 10 03:57:45 2023 +0000 - Add macos-13 test target. + upstream: Reserve a range of "local extension" message numbers that + + OpenSSH promises not to use (comment change only) - Also flatten OS list for clarity. + OpenBSD-Commit-ID: e61795b453d4892d2c99ce1039112c4a00250e03 -commit aacfd6767497b8fa6d41ecdd3f8e265d1e9ef1f6 +commit 90b0d73d63a706e85f6431f05a62d2ce1b476472 Author: djm@openbsd.org -Date: Sun Apr 30 22:54:22 2023 +0000 +Date: Fri Oct 6 03:32:15 2023 +0000 - upstream: adjust ftruncate() logic to handle servers that reorder - - requests. - - 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 + upstream: typo in error message - OpenBSD-Commit-ID: 4af7fac75958ad8507b4fea58706f3ff0cfddb1b + OpenBSD-Regress-ID: 6a8edf0dc39941298e3780b147b10c0a600b4fee -commit c8eb3941758615c8284a48fff47872db926da63c +commit e84517f51532ec913d8fb01a8aab7307134774bb Author: djm@openbsd.org -Date: Wed Apr 26 01:36:03 2023 +0000 +Date: Fri Oct 6 03:25:14 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 + upstream: Perform the softhsm2 setup as discrete steps rather than - bz3567; ok dtucker + as a long shell pipeline. Makes it easier to figure out what has happened + when it breaks. - OpenBSD-Commit-ID: 80a58e43c3a32f97361282f756ec8d3f37989efd + OpenBSD-Regress-ID: b3f1292115fed65765d0a95414df16e27772d81c -commit ac383f3a5c6f529a2e8a5bc44af79a08c7da294e -Author: jsg@openbsd.org -Date: Wed Apr 12 14:22:04 2023 +0000 +commit cb54becff4d776238e0e9072943ba0872260535d +Author: claudio@openbsd.org +Date: Sun Sep 24 08:14:13 2023 +0000 - upstream: remove duplicate signal.h include + upstream: REGRESS_FAIL_EARLY defaults to yes now. So no need to - 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@ + overload the value here anymore. OK tb@ bluhm@ - OpenBSD-Commit-ID: 44d3223902fbce5276422bdc8063ab72a4078489 + OpenBSD-Regress-ID: f063330f1bebbcd373100afccebc91a965b14496 -commit 6452f89577ec4f22440c31b8e19b061d1a7c4b2a -Author: Darren Tucker -Date: Tue Apr 11 16:49:19 2023 +1000 +commit f01f5137ceba65baf34ceac5a298c12ac01b1fef +Author: jmc@openbsd.org +Date: Wed Oct 4 05:42:10 2023 +0000 - Test against LibreSSL 3.7.2. + upstream: spelling fix; + + OpenBSD-Commit-ID: 493f95121567e5ab0d9dd1150f873b5535ca0195 diff --git a/INSTALL b/INSTALL index 3ad1659f36f6..56e351af60e1 100644 --- a/INSTALL +++ b/INSTALL @@ -245,7 +245,7 @@ manually using the following commands: ssh-keygen -t [type] -f /etc/ssh/ssh_host_key -N "" -for each of the types you wish to generate (rsa, dsa or ecdsa) or +for each of the types you wish to generate (rsa, ed25519 or ecdsa) or ssh-keygen -A diff --git a/Makefile.in b/Makefile.in index 4617cebcd5e4..760fbaa5b997 100644 --- a/Makefile.in +++ b/Makefile.in @@ -33,6 +33,7 @@ STRIP_OPT=@STRIP_OPT@ TEST_SHELL=@TEST_SHELL@ BUILDDIR=@abs_top_builddir@ SK_STANDALONE=@SK_STANDALONE@ +COMPATINCLUDES="$(BUILDDIR)/@COMPATINCLUDES@" PATHS= -DSSHDIR=\"$(sysconfdir)\" \ -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ @@ -50,7 +51,7 @@ CC=@CC@ LD=@LD@ CFLAGS=@CFLAGS@ CFLAGS_NOPIE=@CFLAGS_NOPIE@ -CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ +CPPFLAGS=-I. -I$(srcdir) -I$(COMPATINCLUDES) @CPPFLAGS@ $(PATHS) @DEFS@ PICFLAG=@PICFLAG@ LIBS=@LIBS@ CHANNELLIBS=@CHANNELLIBS@ @@ -76,15 +77,6 @@ MKDIR_P=@MKDIR_P@ TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) sshd-auth$(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) $(SK_STANDALONE) -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 \ @@ -94,8 +86,7 @@ LIBOPENSSH_OBJS=\ sshbuf-misc.o \ sshbuf-getput-crypto.o \ krl.o \ - bitmap.o \ - ${XMSS_OBJS} + bitmap.o LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ authfd.o authfile.o \ @@ -105,10 +96,10 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ 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 \ + monitor_fdpass.o rijndael.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 \ + msg.o dns.o entropy.o gss-genr.o umac.o umac128.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 \ @@ -116,18 +107,20 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ kexgexc.o kexgexs.o \ kexsntrup761x25519.o kexmlkem768x25519.o sntrup761.o kexgen.o \ sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ - sshbuf-io.o + sshbuf-io.o misc-agent.o + +P11OBJS= ssh-pkcs11-client.o SKOBJS= ssh-sk-client.o SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ - sshconnect.o sshconnect2.o mux.o $(SKOBJS) + sshconnect.o sshconnect2.o mux.o $(P11OBJS) $(SKOBJS) SSHDOBJS=sshd.o \ platform-listen.o \ servconf.o sshpty.o srclimit.o groupaccess.o auth2-methods.o \ dns.o fatal.o compat.o utf8.o authfd.o canohost.o \ - $(SKOBJS) + $(P11OBJS) $(SKOBJS) SSHD_SESSION_OBJS=sshd-session.o auth-rhosts.o auth-passwd.o \ audit.o audit-bsm.o audit-linux.o platform.o \ @@ -140,7 +133,7 @@ SSHD_SESSION_OBJS=sshd-session.o auth-rhosts.o auth-passwd.o \ auth2-gss.o gss-serv.o gss-serv-krb5.o \ loginrec.o auth-pam.o auth-shadow.o auth-sia.o \ sftp-server.o sftp-common.o \ - uidswap.o platform-listen.o $(SKOBJS) + uidswap.o platform-listen.o $(P11OBJS) $(SKOBJS) SSHD_AUTH_OBJS=sshd-auth.o \ auth2-methods.o \ @@ -155,25 +148,25 @@ SSHD_AUTH_OBJS=sshd-auth.o \ sandbox-null.o sandbox-rlimit.o sandbox-darwin.o \ sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-solaris.o \ sftp-server.o sftp-common.o \ - uidswap.o $(SKOBJS) + uidswap.o $(P11OBJS) $(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) +SSHADD_OBJS= ssh-add.o $(P11OBJS) $(SKOBJS) -SSHAGENT_OBJS= ssh-agent.o ssh-pkcs11-client.o $(SKOBJS) +SSHAGENT_OBJS= ssh-agent.o $(P11OBJS) $(SKOBJS) -SSHKEYGEN_OBJS= ssh-keygen.o sshsig.o $(SKOBJS) +SSHKEYGEN_OBJS= ssh-keygen.o sshsig.o $(P11OBJS) $(SKOBJS) -SSHKEYSIGN_OBJS=ssh-keysign.o readconf.o uidswap.o $(SKOBJS) +SSHKEYSIGN_OBJS=ssh-keysign.o readconf.o uidswap.o $(P11OBJS) $(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) +SSHKEYSCAN_OBJS=ssh-keyscan.o $(P11OBJS) $(SKOBJS) SFTPSERVER_OBJS=sftp-common.o sftp-server.o sftp-server-main.o @@ -194,7 +187,6 @@ PATHSUBS = \ -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' \ @@ -494,7 +486,6 @@ host-key: ssh-keygen$(EXEEXT) 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 \ @@ -557,7 +548,7 @@ regress-prep: ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile REGRESSLIBS=libssh.a $(LIBCOMPAT) -TESTLIBS=$(LIBS) $(CHANNELLIBS) +TESTLIBS=$(LIBS) $(CHANNELLIBS) @TESTLIBS@ regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/modpipe.c \ @@ -613,7 +604,7 @@ UNITTESTS_TEST_SSHKEY_OBJS=\ regress/unittests/sshkey/common.o \ regress/unittests/sshkey/test_file.o \ regress/unittests/sshkey/test_sshkey.o \ - $(SKOBJS) + $(P11OBJS) $(SKOBJS) regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a @@ -624,7 +615,7 @@ regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \ UNITTESTS_TEST_SSHSIG_OBJS=\ sshsig.o \ regress/unittests/sshsig/tests.o \ - $(SKOBJS) + $(P11OBJS) $(SKOBJS) regress/unittests/sshsig/test_sshsig$(EXEEXT): ${UNITTESTS_TEST_SSHSIG_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a @@ -644,7 +635,7 @@ regress/unittests/bitmap/test_bitmap$(EXEEXT): ${UNITTESTS_TEST_BITMAP_OBJS} \ UNITTESTS_TEST_AUTHOPT_OBJS=\ regress/unittests/authopt/tests.o \ auth-options.o \ - $(SKOBJS) + $(P11OBJS) $(SKOBJS) regress/unittests/authopt/test_authopt$(EXEEXT): \ ${UNITTESTS_TEST_AUTHOPT_OBJS} \ @@ -667,7 +658,7 @@ UNITTESTS_TEST_KEX_OBJS=\ regress/unittests/kex/tests.o \ regress/unittests/kex/test_kex.o \ regress/unittests/kex/test_proposal.o \ - $(SKOBJS) + $(P11OBJS) $(SKOBJS) regress/unittests/kex/test_kex$(EXEEXT): ${UNITTESTS_TEST_KEX_OBJS} \ regress/unittests/test_helper/libtest_helper.a libssh.a @@ -678,7 +669,7 @@ regress/unittests/kex/test_kex$(EXEEXT): ${UNITTESTS_TEST_KEX_OBJS} \ UNITTESTS_TEST_HOSTKEYS_OBJS=\ regress/unittests/hostkeys/tests.o \ regress/unittests/hostkeys/test_iterate.o \ - $(SKOBJS) + $(P11OBJS) $(SKOBJS) regress/unittests/hostkeys/test_hostkeys$(EXEEXT): \ ${UNITTESTS_TEST_HOSTKEYS_OBJS} \ @@ -705,7 +696,9 @@ UNITTESTS_TEST_MISC_OBJS=\ 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_ptimeout.o \ + regress/unittests/misc/test_xextendf.o \ + regress/unittests/misc/test_misc.o regress/unittests/misc/test_misc$(EXEEXT): \ ${UNITTESTS_TEST_MISC_OBJS} \ @@ -741,7 +734,7 @@ regress/misc/sk-dummy/sk-dummy.so: $(SK_DUMMY_OBJS) SSH_VERIFY_ATTESTATION_OBJS=\ regress/misc/ssh-verify-attestation/ssh-verify-attestation.o \ - $(SKOBJS) + $(P11OBJS) $(SKOBJS) ssh-verify-attestation: regress/misc/ssh-verify-attestation/ssh-verify-attestation$(EXEEXT) @@ -782,6 +775,13 @@ unit: regress-unit-binaries OBJ="$(BUILDDIR)/regress" \ $@ && echo $@ tests passed +unit-bench: regress-unit-binaries + cd $(srcdir)/regress || exit $$?; \ + $(MAKE) \ + .CURDIR="$(abs_top_srcdir)/regress" \ + .OBJDIR="$(BUILDDIR)/regress" \ + OBJ="$(BUILDDIR)/regress" $@ + TEST_SSH_SSHD="$(BUILDDIR)/sshd" interop-tests t-exec file-tests extra-tests: regress-prep regress-binaries $(TARGETS) diff --git a/PROTOCOL b/PROTOCOL index 26387793febc..a94b36ba6c7e 100644 --- a/PROTOCOL +++ b/PROTOCOL @@ -33,15 +33,11 @@ The method is documented in: https://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt -1.3. transport: New public key algorithms "ssh-rsa-cert-v01@openssh.com", - "ssh-dsa-cert-v01@openssh.com", - "ecdsa-sha2-nistp256-cert-v01@openssh.com", - "ecdsa-sha2-nistp384-cert-v01@openssh.com" and - "ecdsa-sha2-nistp521-cert-v01@openssh.com" +1.3. transport: Certificate key algorithms OpenSSH introduces new public key algorithms to support certificate authentication for users and host keys. These methods are documented -in the file PROTOCOL.certkeys +in at https://datatracker.ietf.org/doc/draft-miller-ssh-cert/ 1.4. transport: Elliptic Curve cryptography @@ -82,29 +78,20 @@ contains: 1.6 transport: AES-GCM OpenSSH supports the AES-GCM algorithm as specified in RFC 5647. -Because of problems with the specification of the key exchange -the behaviour of OpenSSH differs from the RFC as follows: +Because of problems with the design of the algorithm negotiation in this +RFC, OpenSSH (and other SSH implementations) use different rules as +described in: -AES-GCM is only negotiated as the cipher algorithms -"aes128-gcm@openssh.com" or "aes256-gcm@openssh.com" and never as -an MAC algorithm. Additionally, if AES-GCM is selected as the cipher -the exchanged MAC algorithms are ignored and there doesn't have to be -a matching MAC. +https://datatracker.ietf.org/doc/draft-miller-sshm-aes-gcm/ 1.7 transport: chacha20-poly1305@openssh.com authenticated encryption OpenSSH supports authenticated encryption using ChaCha20 and Poly1305 -as described in PROTOCOL.chacha20poly1305. +as described in: -1.8 transport: curve25519-sha256@libssh.org key exchange algorithm +https://datatracker.ietf.org/doc/draft-ietf-sshm-chacha20-poly1305/ -OpenSSH supports the use of ECDH in Curve25519 for key exchange as -described at: -http://git.libssh.org/users/aris/libssh.git/plain/doc/curve25519-sha256@libssh.org.txt?h=curve25519 - -This is identical to curve25519-sha256 as later published in RFC8731. - -1.9 transport: ping facility +1.8 transport: ping facility OpenSSH implements a transport level ping message SSH2_MSG_PING and a corresponding SSH2_MSG_PONG reply. @@ -137,34 +124,16 @@ than as a named global or channel request to allow pings with very short packet lengths, which would not be possible with other approaches. -1.10 transport: strict key exchange extension - -OpenSSH supports a number of transport-layer hardening measures under -a "strict KEX" feature. This feature is signalled similarly to the -RFC8308 ext-info feature: by including a additional algorithm in the -initial SSH2_MSG_KEXINIT kex_algorithms field. The client may append -"kex-strict-c-v00@openssh.com" to its kex_algorithms and the server -may append "kex-strict-s-v00@openssh.com". These pseudo-algorithms -are only valid in the initial SSH2_MSG_KEXINIT and MUST be ignored -if they are present in subsequent SSH2_MSG_KEXINIT packets. - -When an endpoint that supports this extension observes this algorithm -name in a peer's KEXINIT packet, it MUST make the following changes to -the protocol: - -a) During initial KEX, terminate the connection if out-of-sequence - packet or any message that is not strictly required by KEX is - received. This includes terminating the connection if the first - packet received is not SSH2_MSG_KEXINIT. Unexpected packets for - the purpose of strict KEX include messages that are otherwise - valid at any time during the connection such as SSH2_MSG_DEBUG, - SSH2_MSG_IGNORE or SSH2_MSG_UNIMPLEMENTED. -b) After sending or receiving a SSH2_MSG_NEWKEYS message, reset the - packet sequence number to zero. This behaviour persists for the - duration of the connection (i.e. not just the first - SSH2_MSG_NEWKEYS). - -1.11 transport: SSH2_MSG_EXT_INFO during user authentication +1.9 transport: strict key exchange extension + +OpenSSH supports a number of transport-layer hardening measures +designed to thwart the so-called "Terrapin" attack against the +early SSH protocol. These are collectively referred to as +"strict KEX" and documented in an Internet-Draft: + +https://datatracker.ietf.org/doc/draft-miller-sshm-strict-kex/ + +1.10 transport: SSH2_MSG_EXT_INFO during user authentication This protocol extension allows the SSH2_MSG_EXT_INFO to be sent during user authentication. RFC8308 does allow a second @@ -369,52 +338,9 @@ and "hostkeys-prove-00@openssh.com" OpenSSH supports a protocol extension allowing a server to inform a client of all its protocol v.2 host keys after user-authentication -has completed. - - byte SSH_MSG_GLOBAL_REQUEST - string "hostkeys-00@openssh.com" - char 0 /* want-reply */ - string[] hostkeys - -Upon receiving this message, a client should check which of the -supplied host keys are present in known_hosts. - -Note that the server may send key types that the client does not -support. The client should disregard such keys if they are received. - -If the client identifies any keys that are not present for the host, -it should send a "hostkeys-prove@openssh.com" message to request the -server prove ownership of the private half of the key. - - byte SSH_MSG_GLOBAL_REQUEST - string "hostkeys-prove-00@openssh.com" - char 1 /* want-reply */ - string[] hostkeys - -When a server receives this message, it should generate a signature -using each requested key over the following: - - string "hostkeys-prove-00@openssh.com" - string session identifier - string hostkey - -These signatures should be included in the reply, in the order matching -the hostkeys in the request: - - byte SSH_MSG_REQUEST_SUCCESS - string[] signatures - -When the client receives this reply (and not a failure), it should -validate the signatures and may update its known_hosts file, adding keys -that it has not seen before and deleting keys for the server host that -are no longer offered. +has completed. This is documented in an Internet-Draft -These extensions let a client learn key types that it had not previously -encountered, thereby allowing it to potentially upgrade from weaker -key algorithms to better ones. It also supports graceful key rotation: -a server may offer multiple keys of the same type for a period (to -give clients an opportunity to learn them using this extension) before -removing the deprecated key from those offered. +https://datatracker.ietf.org/doc/draft-miller-sshm-hostkey-update/ 2.6. connection: SIGINFO support for "signal" channel request @@ -765,15 +691,15 @@ authorized_keys files, are formatted as a single line of text consisting of the public key algorithm name followed by a base64-encoded key blob. The public key blob (before base64 encoding) is the same format used for the encoding of public keys sent on the wire: as described in RFC4253 -section 6.6 for RSA and DSA keys, RFC5656 section 3.1 for ECDSA keys -and the "New public key formats" section of PROTOCOL.certkeys for the -OpenSSH certificate formats. +section 6.6 for RSA keys, RFC5656 section 3.1 for ECDSA keys and +https://datatracker.ietf.org/doc/draft-miller-ssh-cert/ +for the OpenSSH certificate formats. 5.2 Private key format OpenSSH private keys, as generated by ssh-keygen(1) use the format described in PROTOCOL.key by default. As a legacy option, PEM format -(RFC7468) private keys are also supported for RSA, DSA and ECDSA keys +(RFC7468) private keys are also supported for RSA and ECDSA keys and were the default format before OpenSSH 7.8. 5.3 KRL format @@ -792,4 +718,4 @@ master instance and later clients. OpenSSH extends the usual agent protocol. These changes are documented in the PROTOCOL.agent file. -$OpenBSD: PROTOCOL,v 1.55 2024/01/08 05:05:15 djm Exp $ +$OpenBSD: PROTOCOL,v 1.59 2025/08/06 11:22:53 dtucker Exp $ diff --git a/PROTOCOL.agent b/PROTOCOL.agent index b6e14262d0f6..2af749b30b7b 100644 --- a/PROTOCOL.agent +++ b/PROTOCOL.agent @@ -73,17 +73,6 @@ identities and, in particular, signature requests will check the key constraints against the session-bind@openssh.com bindings recorded for the agent connection over which they were received. -3. SSH_AGENT_CONSTRAIN_MAXSIGN key constraint - -This key constraint allows communication to an agent of the maximum -number of signatures that may be made with an XMSS key. The format of -the constraint is: - - byte SSH_AGENT_CONSTRAIN_MAXSIGN (0x03) - uint32 max_signatures - -This option is only valid for XMSS keys. - 3. associated-certs-v00@openssh.com key constraint extension The key constraint extension allows certificates to be associated @@ -115,4 +104,4 @@ A SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED will return SSH_AGENT_SUCCESS if any key (plain private or certificate) was successfully loaded, or SSH_AGENT_FAILURE if no key was loaded. -$OpenBSD: PROTOCOL.agent,v 1.24 2024/11/27 13:27:34 djm Exp $ +$OpenBSD: PROTOCOL.agent,v 1.25 2025/08/29 03:50:38 djm Exp $ diff --git a/PROTOCOL.certkeys b/PROTOCOL.certkeys deleted file mode 100644 index 0a212c635c5d..000000000000 --- a/PROTOCOL.certkeys +++ /dev/null @@ -1,326 +0,0 @@ -This document describes a simple public-key certificate authentication -system for use by SSH. - -Background ----------- - -The SSH protocol currently supports a simple public key authentication -mechanism. Unlike other public key implementations, SSH eschews the use -of X.509 certificates and uses raw keys. This approach has some benefits -relating to simplicity of configuration and minimisation of attack -surface, but it does not support the important use-cases of centrally -managed, passwordless authentication and centrally certified host keys. - -These protocol extensions build on the simple public key authentication -system already in SSH to allow certificate-based authentication. The -certificates used are not traditional X.509 certificates, with numerous -options and complex encoding rules, but something rather more minimal: a -key, some identity information and usage options that have been signed -with some other trusted key. - -A sshd server may be configured to allow authentication via certified -keys, by extending the existing ~/.ssh/authorized_keys mechanism to -allow specification of certification authority keys in addition to -raw user keys. The ssh client will support automatic verification of -acceptance of certified host keys, by adding a similar ability to -specify CA keys in ~/.ssh/known_hosts. - -All certificate types include certification information along with the -public key that is used to sign challenges. In OpenSSH, ssh-keygen -performs the CA signing operation. - -Certified keys are represented using new key types: - - ssh-rsa-cert-v01@openssh.com - ssh-dss-cert-v01@openssh.com - ecdsa-sha2-nistp256-cert-v01@openssh.com - ecdsa-sha2-nistp384-cert-v01@openssh.com - ecdsa-sha2-nistp521-cert-v01@openssh.com - ssh-ed25519-cert-v01@openssh.com - -Two additional types exist for RSA certificates to force use of -SHA-2 signatures (SHA-256 and SHA-512 respectively): - - rsa-sha2-256-cert-v01@openssh.com - rsa-sha2-512-cert-v01@openssh.com - -These RSA/SHA-2 types should not appear in keys at rest or transmitted -on the wire, but do appear in a SSH_MSG_KEXINIT's host-key algorithms -field or in the "public key algorithm name" field of a "publickey" -SSH_USERAUTH_REQUEST to indicate that the signature will use the -specified algorithm. - -Protocol extensions -------------------- - -The SSH wire protocol includes several extensibility mechanisms. -These modifications shall take advantage of namespaced public key -algorithm names to add support for certificate authentication without -breaking the protocol - implementations that do not support the -extensions will simply ignore them. - -Authentication using the new key formats described below proceeds -using the existing SSH "publickey" authentication method described -in RFC4252 section 7. - -New public key formats ----------------------- - -The certificate key types take a similar high-level format (note: data -types and encoding are as per RFC4251 section 5). The serialised wire -encoding of these certificates is also used for storing them on disk. - -#define SSH_CERT_TYPE_USER 1 -#define SSH_CERT_TYPE_HOST 2 - -RSA certificate - - string "ssh-rsa-cert-v01@openssh.com" - string nonce - mpint e - mpint n - uint64 serial - uint32 type - string key id - string valid principals - uint64 valid after - uint64 valid before - string critical options - string extensions - string reserved - string signature key - string signature - -DSA certificate - - string "ssh-dss-cert-v01@openssh.com" - string nonce - mpint p - mpint q - mpint g - mpint y - uint64 serial - uint32 type - string key id - string valid principals - uint64 valid after - uint64 valid before - string critical options - string extensions - string reserved - string signature key - string signature - -ECDSA certificate - - string "ecdsa-sha2-nistp256-cert-v01@openssh.com" | - "ecdsa-sha2-nistp384-cert-v01@openssh.com" | - "ecdsa-sha2-nistp521-cert-v01@openssh.com" - string nonce - string curve - string public_key - uint64 serial - uint32 type - string key id - string valid principals - uint64 valid after - uint64 valid before - string critical options - string extensions - string reserved - string signature key - string signature - -ED25519 certificate - - string "ssh-ed25519-cert-v01@openssh.com" - string nonce - string pk - uint64 serial - uint32 type - string key id - string valid principals - uint64 valid after - uint64 valid before - string critical options - string extensions - string reserved - string signature key - string signature - -The nonce field is a CA-provided random bitstring of arbitrary length -(but typically 16 or 32 bytes) included to make attacks that depend on -inducing collisions in the signature hash infeasible. - -e and n are the RSA exponent and public modulus respectively. - -p, q, g, y are the DSA parameters as described in FIPS-186-2. - -curve and public key are respectively the ECDSA "[identifier]" and "Q" -defined in section 3.1 of RFC5656. - -pk is the encoded Ed25519 public key as defined by RFC8032. - -serial is an optional certificate serial number set by the CA to -provide an abbreviated way to refer to certificates from that CA. -If a CA does not wish to number its certificates, it must set this -field to zero. - -type specifies whether this certificate is for identification of a user -or a host using a SSH_CERT_TYPE_... value. - -key id is a free-form text field that is filled in by the CA at the time -of signing; the intention is that the contents of this field are used to -identify the identity principal in log messages. - -"valid principals" is a string containing zero or more principals as -strings packed inside it. These principals list the names for which this -certificate is valid; hostnames for SSH_CERT_TYPE_HOST certificates and -usernames for SSH_CERT_TYPE_USER certificates. As a special case, a -zero-length "valid principals" field means the certificate is valid for -any principal of the specified type. - -"valid after" and "valid before" specify a validity period for the -certificate. Each represents a time in seconds since 1970-01-01 -00:00:00. A certificate is considered valid if: - - valid after <= current time < valid before - -critical options is a set of zero or more key options encoded as -below. All such options are "critical" in the sense that an implementation -must refuse to authorise a key that has an unrecognised option. - -extensions is a set of zero or more optional extensions. These extensions -are not critical, and an implementation that encounters one that it does -not recognise may safely ignore it. - -Generally, critical options are used to control features that restrict -access where extensions are used to enable features that grant access. -This ensures that certificates containing unknown restrictions do not -inadvertently grant access while allowing new protocol features to be -enabled via extensions without breaking certificates' backwards -compatibility. - -The reserved field is currently unused and is ignored in this version of -the protocol. - -The signature key field contains the CA key used to sign the -certificate. The valid key types for CA keys are ssh-rsa, -ssh-dss, ssh-ed25519 and the ECDSA types ecdsa-sha2-nistp256, -ecdsa-sha2-nistp384, ecdsa-sha2-nistp521. "Chained" certificates, where -the signature key type is a certificate type itself are NOT supported. -Note that it is possible for a RSA certificate key to be signed by a -Ed25519 or ECDSA CA key and vice-versa. - -signature is computed over all preceding fields from the initial string -up to, and including the signature key. Signatures are computed and -encoded according to the rules defined for the CA's public key algorithm -(RFC4253 section 6.6 for ssh-rsa and ssh-dss, RFC5656 for the ECDSA -types, and RFC8032 for Ed25519). - -Critical options ----------------- - -The critical options section of the certificate specifies zero or more -options on the certificate's validity. The format of this field -is a sequence of zero or more tuples: - - string name - string data - -Options must be lexically ordered by "name" if they appear in the -sequence. Each named option may only appear once in a certificate. - -The name field identifies the option. The data field contains -option-specific information encoded as zero or more values inside -the string. I.e. an empty data field would be encoded as a zero- -length string (00 00 00 00), and data field that holds a single -string value "a" would be encoded as (00 00 00 05 00 00 00 01 65). - -All options are "critical"; if an implementation does not recognise -a option, then the validating party should refuse to accept the -certificate. - -Custom options should append the originating author or organisation's -domain name to the option name, e.g. "my-option@example.com". - -No critical options are defined for host certificates at present. The -supported user certificate options and the contents and structure of -their data fields are: - -Name Format Description ------------------------------------------------------------------------------ -force-command string Specifies a command that is executed - (replacing any the user specified on the - ssh command-line) whenever this key is - used for authentication. - -source-address string Comma-separated list of source addresses - from which this certificate is accepted - for authentication. Addresses are - specified in CIDR format (nn.nn.nn.nn/nn - or hhhh::hhhh/nn). - If this option is not present, then - certificates may be presented from any - source address. - -verify-required empty Flag indicating that signatures made - with this certificate must assert FIDO - user verification (e.g. PIN or - biometric). This option only makes sense - for the U2F/FIDO security key types that - support this feature in their signature - formats. - -Extensions ----------- - -The extensions section of the certificate specifies zero or more -non-critical certificate extensions. The encoding and ordering of -extensions in this field is identical to that of the critical options, -as is the requirement that each name appear only once. - -If an implementation does not recognise an extension, then it should -ignore it. - -Custom options should append the originating author or organisation's -domain name to the option name, e.g. "my-option@example.com". - -No extensions are defined for host certificates at present. The -supported user certificate extensions and the contents and structure of -their data fields are: - -Name Format Description ------------------------------------------------------------------------------ -no-touch-required empty Flag indicating that signatures made - with this certificate need not assert - FIDO user presence. This option only - makes sense for the U2F/FIDO security - key types that support this feature in - their signature formats. - -permit-X11-forwarding empty Flag indicating that X11 forwarding - should be permitted. X11 forwarding will - be refused if this option is absent. - -permit-agent-forwarding empty Flag indicating that agent forwarding - should be allowed. Agent forwarding - must not be permitted unless this - option is present. - -permit-port-forwarding empty Flag indicating that port-forwarding - should be allowed. If this option is - not present, then no port forwarding will - be allowed. - -permit-pty empty Flag indicating that PTY allocation - should be permitted. In the absence of - this option PTY allocation will be - disabled. - -permit-user-rc empty Flag indicating that execution of - ~/.ssh/rc should be permitted. Execution - of this script will not be permitted if - this option is not present. - -$OpenBSD: PROTOCOL.certkeys,v 1.20 2024/12/06 16:02:12 djm Exp $ diff --git a/PROTOCOL.chacha20poly1305 b/PROTOCOL.chacha20poly1305 deleted file mode 100644 index 0bfff28d70ef..000000000000 --- a/PROTOCOL.chacha20poly1305 +++ /dev/null @@ -1,107 +0,0 @@ -This document describes the chacha20-poly1305@openssh.com authenticated -encryption cipher supported by OpenSSH. - -Background ----------- - -ChaCha20 is a stream cipher designed by Daniel Bernstein and described -in [1]. It operates by permuting 128 fixed bits, 128 or 256 bits of key, -a 64 bit nonce and a 64 bit counter into 64 bytes of output. This output -is used as a keystream, with any unused bytes simply discarded. - -Poly1305[2], also by Daniel Bernstein, is a one-time Carter-Wegman MAC -that computes a 128 bit integrity tag given a message and a single-use -256 bit secret key. - -The chacha20-poly1305@openssh.com combines these two primitives into an -authenticated encryption mode. The construction used is based on that -proposed for TLS by Adam Langley in [3], but differs in the layout of -data passed to the MAC and in the addition of encryption of the packet -lengths. - -Negotiation ------------ - -The chacha20-poly1305@openssh.com offers both encryption and -authentication. As such, no separate MAC is required. If the -chacha20-poly1305@openssh.com cipher is selected in key exchange, -the offered MAC algorithms are ignored and no MAC is required to be -negotiated. - -Detailed Construction ---------------------- - -The chacha20-poly1305@openssh.com cipher requires 512 bits of key -material as output from the SSH key exchange. This forms two 256 bit -keys (K_1 and K_2), used by two separate instances of chacha20. -The first 256 bits constitute K_2 and the second 256 bits become -K_1. - -The instance keyed by K_1 is a stream cipher that is used only -to encrypt the 4 byte packet length field. The second instance, -keyed by K_2, is used in conjunction with poly1305 to build an AEAD -(Authenticated Encryption with Associated Data) that is used to encrypt -and authenticate the entire packet. - -Two separate cipher instances are used here so as to keep the packet -lengths confidential but not create an oracle for the packet payload -cipher by decrypting and using the packet length prior to checking -the MAC. By using an independently-keyed cipher instance to encrypt the -length, an active attacker seeking to exploit the packet input handling -as a decryption oracle can learn nothing about the payload contents or -its MAC (assuming key derivation, ChaCha20 and Poly1305 are secure). - -The AEAD is constructed as follows: for each packet, generate a Poly1305 -key by taking the first 256 bits of ChaCha20 stream output generated -using K_2, an IV consisting of the packet sequence number encoded as an -uint64 under the SSH wire encoding rules and a ChaCha20 block counter of -zero. The K_2 ChaCha20 block counter is then set to the little-endian -encoding of 1 (i.e. {1, 0, 0, 0, 0, 0, 0, 0}) and this instance is used -for encryption of the packet payload. - -Packet Handling ---------------- - -When receiving a packet, the length must be decrypted first. When 4 -bytes of ciphertext length have been received, they may be decrypted -using the K_1 key, a nonce consisting of the packet sequence number -encoded as a uint64 under the usual SSH wire encoding and a zero block -counter to obtain the plaintext length. - -Once the entire packet has been received, the MAC MUST be checked -before decryption. A per-packet Poly1305 key is generated as described -above and the MAC tag calculated using Poly1305 with this key over the -ciphertext of the packet length and the payload together. The calculated -MAC is then compared in constant time with the one appended to the -packet and the packet decrypted using ChaCha20 as described above (with -K_2, the packet sequence number as nonce and a starting block counter of -1). - -To send a packet, first encode the 4 byte length and encrypt it using -K_1. Encrypt the packet payload (using K_2) and append it to the -encrypted length. Finally, calculate a MAC tag and append it. - -Rekeying --------- - -ChaCha20 must never reuse a {key, nonce} for encryption nor may it be -used to encrypt more than 2^70 bytes under the same {key, nonce}. The -SSH Transport protocol (RFC4253) recommends a far more conservative -rekeying every 1GB of data sent or received. If this recommendation -is followed, then chacha20-poly1305@openssh.com requires no special -handling in this area. - -References ----------- - -[1] "ChaCha, a variant of Salsa20", Daniel Bernstein - http://cr.yp.to/chacha/chacha-20080128.pdf - -[2] "The Poly1305-AES message-authentication code", Daniel Bernstein - http://cr.yp.to/mac/poly1305-20050329.pdf - -[3] "ChaCha20 and Poly1305 based Cipher Suites for TLS", Adam Langley - http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-03 - -$OpenBSD: PROTOCOL.chacha20poly1305,v 1.5 2020/02/21 00:04:43 dtucker Exp $ - diff --git a/README b/README index 0ea77da1c1dd..e19b021e4fbc 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -See https://www.openssh.com/releasenotes.html#10.0p1 for the release +See https://www.openssh.com/releasenotes.html#10.1p1 for the release notes. Please read https://www.openssh.com/report.html for bug reporting diff --git a/TODO b/TODO index b76529c960a0..e9e2d96e6e1d 100644 --- a/TODO +++ b/TODO @@ -7,7 +7,7 @@ Documentation: - Install FAQ? -- General FAQ on S/Key, TIS, RSA, RSA2, DSA, etc and suggestions on when it +- General FAQ on S/Key, TIS, RSA, RSA2, etc and suggestions on when it would be best to use them. - Create a Documentation/ directory? diff --git a/atomicio.c b/atomicio.c index 765073357f67..58a9512d3e4a 100644 --- a/atomicio.c +++ b/atomicio.c @@ -31,13 +31,7 @@ #include #include -#ifdef HAVE_POLL_H #include -#else -# ifdef HAVE_SYS_POLL_H -# include -# endif -#endif #include #include #include diff --git a/audit-bsm.c b/audit-bsm.c index ccfcf6f7fc68..4bce22c37ed5 100644 --- a/audit-bsm.c +++ b/audit-bsm.c @@ -449,7 +449,7 @@ audit_event(struct ssh *ssh, ssh_audit_event_t event) break; default: - debug("%s: unhandled event %d", __func__, event); + debug_f("unhandled event %d", event); } } #endif /* BSM */ diff --git a/audit-linux.c b/audit-linux.c index 3fcbe5c53ef9..954eabe27807 100644 --- a/audit-linux.c +++ b/audit-linux.c @@ -51,6 +51,8 @@ linux_audit_record_event(int uid, const char *username, const char *hostname, else return 0; /* Must prevent login */ } + if (hostname != NULL && strcmp(hostname, "UNKNOWN") == 0) + hostname = NULL; rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN, NULL, "login", username ? username : "(unknown)", username == NULL ? uid : -1, hostname, ip, ttyn, success); @@ -117,7 +119,7 @@ audit_event(struct ssh *ssh, ssh_audit_event_t event) ssh_remote_ipaddr(ssh), "sshd", 0); break; default: - debug("%s: unhandled event %d", __func__, event); + debug_f("unhandled event %d", event); break; } } diff --git a/auth-krb5.c b/auth-krb5.c index c99e4e430e73..9d2f1f0ea2a0 100644 --- a/auth-krb5.c +++ b/auth-krb5.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-krb5.c,v 1.24 2021/04/03 06:18:40 djm Exp $ */ +/* $OpenBSD: auth-krb5.c,v 1.25 2025/09/29 21:29:22 dtucker Exp $ */ /* * Kerberos v5 authentication and ticket-passing routines. * diff --git a/auth-options.c b/auth-options.c index 27a6ef21d930..7e4633b699cd 100644 --- a/auth-options.c +++ b/auth-options.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.c,v 1.101 2023/07/14 07:44:21 dtucker Exp $ */ +/* $OpenBSD: auth-options.c,v 1.102 2025/09/15 04:38:00 djm Exp $ */ /* * Copyright (c) 2018 Damien Miller * @@ -24,9 +24,7 @@ #include #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include #include @@ -157,6 +155,7 @@ cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob, if (addr_match_cidr_list(NULL, allowed) == -1) { error("Certificate source-address " "contents invalid"); + free(allowed); goto out; } opts->required_from_host_cert = allowed; diff --git a/auth-pam.c b/auth-pam.c index 13c0a792e99e..5dee7601bf4b 100644 --- a/auth-pam.c +++ b/auth-pam.c @@ -229,7 +229,7 @@ pthread_join(sp_pthread_t thread, void **value) while (waitpid(thread, &status, 0) == -1) { if (errno == EINTR) continue; - fatal("%s: waitpid: %s", __func__, strerror(errno)); + fatal_f("waitpid: %s", strerror(errno)); } return (status); } @@ -287,10 +287,10 @@ sshpam_chauthtok_ruid(pam_handle_t *pamh, int flags) if (sshpam_authctxt == NULL) fatal("PAM: sshpam_authctxt not initialized"); if (setreuid(sshpam_authctxt->pw->pw_uid, -1) == -1) - fatal("%s: setreuid failed: %s", __func__, strerror(errno)); + fatal_f("setreuid failed: %s", strerror(errno)); result = pam_chauthtok(pamh, flags); if (setreuid(0, -1) == -1) - fatal("%s: setreuid failed: %s", __func__, strerror(errno)); + fatal_f("setreuid failed: %s", strerror(errno)); return result; } # define pam_chauthtok(a,b) (sshpam_chauthtok_ruid((a), (b))) @@ -302,9 +302,9 @@ sshpam_password_change_required(int reqd) extern struct sshauthopt *auth_opts; static int saved_port, saved_agent, saved_x11; - debug3("%s %d", __func__, reqd); + debug3_f("reqd=%d", reqd); if (sshpam_authctxt == NULL) - fatal("%s: PAM authctxt not initialized", __func__); + fatal_f("PAM authctxt not initialized"); sshpam_authctxt->force_pwchange = reqd; if (reqd) { saved_port = auth_opts->permit_port_forwarding_flag; @@ -331,22 +331,22 @@ import_environments(struct sshbuf *b) u_int n, i, num_env; int r; - debug3("PAM: %s entering", __func__); + debug3_f("entering"); #ifndef UNSUPPORTED_POSIX_THREADS_HACK /* Import variables set by do_pam_account */ if ((r = sshbuf_get_u32(b, &n)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); if (n > INT_MAX) - fatal("%s: invalid PAM account status %u", __func__, n); + fatal_f("invalid PAM account status %u", n); sshpam_account_status = (int)n; if ((r = sshbuf_get_u32(b, &n)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); sshpam_password_change_required(n != 0); /* Import environment from subprocess */ if ((r = sshbuf_get_u32(b, &num_env)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); if (num_env > 1024) { fatal_f("received %u environment variables, expected <= 1024", num_env); @@ -355,13 +355,13 @@ import_environments(struct sshbuf *b) debug3("PAM: num env strings %u", num_env); for(i = 0; i < num_env; i++) { if ((r = sshbuf_get_cstring(b, &(sshpam_env[i]), NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } sshpam_env[num_env] = NULL; /* Import PAM environment from subprocess */ if ((r = sshbuf_get_u32(b, &num_env)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); if (num_env > 1024) { fatal_f("received %u PAM env variables, expected <= 1024", num_env); @@ -369,7 +369,7 @@ import_environments(struct sshbuf *b) debug("PAM: num PAM env strings %u", num_env); for (i = 0; i < num_env; i++) { if ((r = sshbuf_get_cstring(b, &env, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); /* Errors are not fatal here */ if ((r = pam_putenv(sshpam_handle, env)) != PAM_SUCCESS) { error("PAM: pam_putenv: %s", @@ -378,7 +378,7 @@ import_environments(struct sshbuf *b) /* * XXX this possibly leaks env because it is not documented * what pam_putenv() does with it. Does it copy it? Does it - * take ownweship? We don't know, so it's safest just to leak. + * take ownership? We don't know, so it's safest just to leak. */ } #endif @@ -397,7 +397,7 @@ sshpam_thread_conv(int n, sshpam_const struct pam_message **msg, int r, i; u_char status; - debug3("PAM: %s entering, %d messages", __func__, n); + debug3_f("PAM: entering, %d messages", n); *resp = NULL; if (data == NULL) { @@ -467,6 +467,32 @@ sshpam_thread_conv(int n, sshpam_const struct pam_message **msg, return (PAM_CONV_ERR); } +static int +check_pam_user(Authctxt *authctxt) +{ + const char *pam_user; + + if (authctxt == NULL || authctxt->pw == NULL || + authctxt->pw->pw_name == NULL) + fatal_f("PAM authctxt user not initialized"); + + if ((sshpam_err = pam_get_item(sshpam_handle, PAM_USER, + (sshpam_const void **) &pam_user)) != PAM_SUCCESS) + return sshpam_err; + + if (pam_user == NULL) { + debug("PAM error: PAM_USER is NULL"); + return PAM_USER_UNKNOWN; + } + + if (strcmp(authctxt->pw->pw_name, pam_user) != 0) { + debug("PAM user \"%s\" does not match expected \"%s\"", + pam_user, authctxt->pw->pw_name); + return PAM_USER_UNKNOWN; + } + return PAM_SUCCESS; +} + /* * Authentication thread. */ @@ -507,10 +533,10 @@ sshpam_thread(void *ctxtp) sshpam_conv.appdata_ptr = ctxt; if (sshpam_authctxt == NULL) - fatal("%s: PAM authctxt not initialized", __func__); + fatal_f("PAM authctxt not initialized"); if ((buffer = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); sshpam_err = pam_set_item(sshpam_handle, PAM_CONV, (const void *)&sshpam_conv); @@ -521,6 +547,8 @@ sshpam_thread(void *ctxtp) sshpam_set_maxtries_reached(1); if (sshpam_err != PAM_SUCCESS) goto auth_fail; + if ((sshpam_err = check_pam_user(sshpam_authctxt)) != PAM_SUCCESS) + goto auth_fail; if (!do_pam_account()) { sshpam_err = PAM_ACCT_EXPIRED; @@ -535,38 +563,38 @@ sshpam_thread(void *ctxtp) } if ((r = sshbuf_put_cstring(buffer, "OK")) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); #ifndef UNSUPPORTED_POSIX_THREADS_HACK /* Export variables set by do_pam_account */ if ((r = sshbuf_put_u32(buffer, sshpam_account_status)) != 0 || (r = sshbuf_put_u32(buffer, sshpam_authctxt->force_pwchange)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); /* Export any environment strings set in child */ for (i = 0; environ[i] != NULL; i++) { /* Count */ if (i > INT_MAX) - fatal("%s: too many environment strings", __func__); + fatal_f("too many environment strings"); } if ((r = sshbuf_put_u32(buffer, i)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); for (i = 0; environ[i] != NULL; i++) { if ((r = sshbuf_put_cstring(buffer, environ[i])) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } /* Export any environment strings set by PAM in child */ env_from_pam = pam_getenvlist(sshpam_handle); for (i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++) { /* Count */ if (i > INT_MAX) - fatal("%s: too many PAM environment strings", __func__); + fatal_f("too many PAM environment strings"); } if ((r = sshbuf_put_u32(buffer, i)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); for (i = 0; env_from_pam != NULL && env_from_pam[i] != NULL; i++) { if ((r = sshbuf_put_cstring(buffer, env_from_pam[i])) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } #endif /* UNSUPPORTED_POSIX_THREADS_HACK */ @@ -578,7 +606,7 @@ sshpam_thread(void *ctxtp) auth_fail: if ((r = sshbuf_put_cstring(buffer, pam_strerror(sshpam_handle, sshpam_err))) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); /* XXX - can't do much about an error here */ if (sshpam_err == PAM_ACCT_EXPIRED) ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, buffer); @@ -597,7 +625,7 @@ sshpam_thread_cleanup(void) { struct pam_ctxt *ctxt = cleanup_ctxt; - debug3("PAM: %s entering", __func__); + debug3_f("entering"); if (ctxt != NULL && ctxt->pam_thread != 0) { pthread_cancel(ctxt->pam_thread); pthread_join(ctxt->pam_thread, NULL); @@ -612,7 +640,7 @@ static int sshpam_null_conv(int n, sshpam_const struct pam_message **msg, struct pam_response **resp, void *data) { - debug3("PAM: %s entering, %d messages", __func__, n); + debug3_f("PAM: entering, %d messages", n); return (PAM_CONV_ERR); } @@ -625,7 +653,7 @@ sshpam_store_conv(int n, sshpam_const struct pam_message **msg, struct pam_response *reply; int r, i; - debug3("PAM: %s called with %d messages", __func__, n); + debug3_f("PAM: called with %d messages", n); *resp = NULL; if (n <= 0 || n > PAM_MAX_NUM_MSG) @@ -686,8 +714,7 @@ sshpam_cleanup(void) static int sshpam_init(struct ssh *ssh, Authctxt *authctxt) { - const char *pam_user, *user = authctxt->user; - const char **ptr_pam_user = &pam_user; + const char *user = authctxt->user; int r; if (options.pam_service_name == NULL) @@ -706,12 +733,8 @@ sshpam_init(struct ssh *ssh, Authctxt *authctxt) } if (sshpam_handle != NULL) { /* We already have a PAM context; check if the user matches */ - sshpam_err = pam_get_item(sshpam_handle, - PAM_USER, (sshpam_const void **)ptr_pam_user); - if (sshpam_err == PAM_SUCCESS && strcmp(user, pam_user) == 0) - return (0); - pam_end(sshpam_handle, sshpam_err); - sshpam_handle = NULL; + if ((sshpam_err = check_pam_user(authctxt)) != PAM_SUCCESS) + fatal("PAM user mismatch"); } debug("PAM: initializing for \"%s\" with service \"%s\"", user, options.pam_service_name); @@ -788,7 +811,7 @@ expose_authinfo(const char *caller) auth_info = xstrdup(""); else if ((auth_info = sshbuf_dup_string( sshpam_authctxt->session_info)) == NULL) - fatal("%s: sshbuf_dup_string failed", __func__); + fatal_f("sshbuf_dup_string failed"); debug2("%s: auth information in SSH_AUTH_INFO_0", caller); do_pam_putenv("SSH_AUTH_INFO_0", auth_info); @@ -801,7 +824,7 @@ sshpam_init_ctx(Authctxt *authctxt) struct pam_ctxt *ctxt; int result, socks[2]; - debug3("PAM: %s entering", __func__); + debug3_f("entering"); /* * Refuse to start if we don't have PAM enabled or do_pam_account * has previously failed. @@ -851,9 +874,9 @@ sshpam_query(void *ctx, char **name, char **info, size_t len, mlen, nmesg = 0; int r; - debug3("PAM: %s entering", __func__); + debug3_f("entering"); if ((buffer = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); *name = xstrdup(""); *info = xstrdup(""); *prompts = xmalloc(sizeof(char *)); @@ -865,7 +888,7 @@ sshpam_query(void *ctx, char **name, char **info, fatal_f("too many query messages"); if ((r = sshbuf_get_u8(buffer, &type)) != 0 || (r = sshbuf_get_cstring(buffer, &msg, &mlen)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); switch (type) { case PAM_PROMPT_ECHO_ON: case PAM_PROMPT_ECHO_OFF: @@ -966,7 +989,7 @@ fake_password(const char *wire_password) size_t i, l = wire_password != NULL ? strlen(wire_password) : 0; if (l >= INT_MAX) - fatal("%s: password length too long: %zu", __func__, l); + fatal_f("password length too long: %zu", l); ret = malloc(l + 1); if (ret == NULL) @@ -986,7 +1009,7 @@ sshpam_respond(void *ctx, u_int num, char **resp) char *fake; int r; - debug2("PAM: %s entering, %u responses", __func__, num); + debug2_f("PAM: entering, %u responses", num); switch (ctxt->pam_done) { case 1: sshpam_authenticated = 1; @@ -1001,16 +1024,16 @@ sshpam_respond(void *ctx, u_int num, char **resp) return (-1); } if ((buffer = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if (sshpam_authctxt->valid && (sshpam_authctxt->pw->pw_uid != 0 || options.permit_root_login == PERMIT_YES)) { if ((r = sshbuf_put_cstring(buffer, *resp)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } else { fake = fake_password(*resp); if ((r = sshbuf_put_cstring(buffer, fake)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); free(fake); } if (ssh_msg_send(ctxt->pam_psock, PAM_AUTHTOK, buffer) == -1) { @@ -1026,7 +1049,7 @@ sshpam_free_ctx(void *ctxtp) { struct pam_ctxt *ctxt = ctxtp; - debug3("PAM: %s entering", __func__); + debug3_f("entering"); sshpam_thread_cleanup(); free(ctxt); /* @@ -1078,7 +1101,7 @@ finish_pam(void) u_int do_pam_account(void) { - debug("%s: called", __func__); + debug_f("called"); if (sshpam_account_status != -1) return (sshpam_account_status); @@ -1131,7 +1154,7 @@ sshpam_tty_conv(int n, sshpam_const struct pam_message **msg, struct pam_response *reply; int i; - debug3("PAM: %s called with %d messages", __func__, n); + debug3_f("PAM: called with %d messages", n); *resp = NULL; @@ -1292,7 +1315,7 @@ sshpam_passwd_conv(int n, sshpam_const struct pam_message **msg, int r, i; size_t len; - debug3("PAM: %s called with %d messages", __func__, n); + debug3_f("PAM: called with %d messages", n); *resp = NULL; @@ -1378,6 +1401,8 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password) sshpam_err = pam_authenticate(sshpam_handle, flags); sshpam_password = NULL; free(fake); + if (sshpam_err == PAM_SUCCESS) + sshpam_err = check_pam_user(authctxt); if (sshpam_err == PAM_MAXTRIES) sshpam_set_maxtries_reached(1); if (sshpam_err == PAM_SUCCESS && authctxt->valid) { diff --git a/auth-passwd.c b/auth-passwd.c index 85c9d77a2c7e..0a13b328fa45 100644 --- a/auth-passwd.c +++ b/auth-passwd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-passwd.c,v 1.48 2020/10/18 11:32:01 djm Exp $ */ +/* $OpenBSD: auth-passwd.c,v 1.49 2025/05/08 17:32:53 tedu Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -142,7 +142,7 @@ static void warn_expiry(Authctxt *authctxt, auth_session_t *as) { int r; - quad_t pwtimeleft, actimeleft, daysleft, pwwarntime, acwarntime; + int64_t pwtimeleft, actimeleft, daysleft, pwwarntime, acwarntime; pwwarntime = acwarntime = TWO_WEEKS; diff --git a/auth-rhosts.c b/auth-rhosts.c index d5d2c7a12988..3c1a62087c55 100644 --- a/auth-rhosts.c +++ b/auth-rhosts.c @@ -22,7 +22,7 @@ #include #include #ifdef HAVE_NETGROUP_H -# include +#include #endif #include #include diff --git a/auth-shadow.c b/auth-shadow.c index b1e3aa9fc1b3..81b31b56ecfc 100644 --- a/auth-shadow.c +++ b/auth-shadow.c @@ -74,7 +74,7 @@ auth_shadow_acctexpired(struct spwd *spw) if ((r = sshbuf_putf(loginmsg, "Your account will expire in %lld day%s.\n", daysleft, daysleft == 1 ? "" : "s")) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } return 0; @@ -133,7 +133,7 @@ auth_shadow_pwexpired(Authctxt *ctxt) if ((r = sshbuf_putf(loginmsg, "Your password will expire in %d day%s.\n", daysleft, daysleft == 1 ? "" : "s")) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } return 0; diff --git a/auth.c b/auth.c index d6608e740f32..fc7fbb8f44cc 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.162 2024/09/15 01:18:26 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.163 2025/09/15 04:39:15 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -36,7 +36,7 @@ #include #include #ifdef HAVE_PATHS_H -# include +#include #endif #include #ifdef HAVE_LOGIN_H @@ -791,6 +791,7 @@ auth_activate_options(struct ssh *ssh, struct sshauthopt *opts) error("Inconsistent authentication options: %s", emsg); return -1; } + sshauthopt_free(old); return 0; } diff --git a/auth2-chall.c b/auth2-chall.c index 021df8291736..a6d916598263 100644 --- a/auth2-chall.c +++ b/auth2-chall.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-chall.c,v 1.54 2020/10/18 11:32:01 djm Exp $ */ +/* $OpenBSD: auth2-chall.c,v 1.57 2025/10/02 08:38:43 dtucker Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2001 Per Allansson. All rights reserved. @@ -154,7 +154,7 @@ kbdint_next_device(Authctxt *authctxt, KbdintAuthctxt *kbdintctxt) { size_t len; char *t; - int i; + size_t i; if (kbdintctxt->device) kbdint_reset_device(kbdintctxt); @@ -165,11 +165,15 @@ kbdint_next_device(Authctxt *authctxt, KbdintAuthctxt *kbdintctxt) if (len == 0) break; for (i = 0; devices[i]; i++) { + if (i >= sizeof(kbdintctxt->devices_done) * 8 || + i >= sizeof(devices) / sizeof(devices[0])) + fatal_f("internal error: too may devices"); if ((kbdintctxt->devices_done & (1 << i)) != 0 || !auth2_method_allowed(authctxt, "keyboard-interactive", devices[i]->name)) continue; - if (strncmp(kbdintctxt->devices, devices[i]->name, + if (strlen(devices[i]->name) == len && + memcmp(kbdintctxt->devices, devices[i]->name, len) == 0) { kbdintctxt->device = devices[i]; kbdintctxt->devices_done |= 1 << i; diff --git a/auth2-hostbased.c b/auth2-hostbased.c index eb21479a0270..9d8b860eb14e 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.53 2024/05/17 00:30:23 djm Exp $ */ +/* $OpenBSD: auth2-hostbased.c,v 1.55 2025/08/14 09:26:53 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -213,8 +213,17 @@ hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, if (sshkey_is_cert(key) && sshkey_cert_check_authority_now(key, 1, 0, 0, lookup, &reason)) { - error("%s", reason); - auth_debug_add("%s", reason); + if ((fp = sshkey_fingerprint(key->cert->signature_key, + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) + fatal_f("sshkey_fingerprint fail"); + error("Refusing certificate ID \"%s\" serial=%llu signed by " + "%s CA %s: %s", key->cert->key_id, + (unsigned long long)key->cert->serial, + sshkey_type(key->cert->signature_key), fp, reason); + auth_debug_add("Refused Certificate ID \"%s\" serial=%llu: %s", + key->cert->key_id, (unsigned long long)key->cert->serial, + reason); + free(fp); return 0; } diff --git a/auth2-pubkey.c b/auth2-pubkey.c index f55c8f186246..f168398752a7 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.122 2024/12/12 09:09:09 dtucker Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.124 2025/08/14 09:44:39 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -31,7 +31,7 @@ #include #include #ifdef HAVE_PATHS_H -# include +#include #endif #include #include @@ -590,8 +590,14 @@ user_cert_trusted_ca(struct passwd *pw, struct sshkey *key, if ((final_opts = sshauthopt_merge(principals_opts, cert_opts, &reason)) == NULL) { fail_reason: - error("%s", reason); - auth_debug_add("%s", reason); + error("Refusing certificate ID \"%s\" serial=%llu " + "signed by %s CA %s: %s", key->cert->key_id, + (unsigned long long)key->cert->serial, + sshkey_type(key->cert->signature_key), ca_fp, + reason); + auth_debug_add("Refused Certificate ID \"%s\" " + "serial=%llu: %s", key->cert->key_id, + (unsigned long long)key->cert->serial, reason); goto out; } } diff --git a/auth2-pubkeyfile.c b/auth2-pubkeyfile.c index 051a37d9c6c1..85062d569021 100644 --- a/auth2-pubkeyfile.c +++ b/auth2-pubkeyfile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkeyfile.c,v 1.4 2023/03/05 05:34:09 dtucker Exp $ */ +/* $OpenBSD: auth2-pubkeyfile.c,v 1.6 2025/08/14 10:03:44 dtucker Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -350,15 +350,15 @@ auth_check_authkey_line(struct passwd *pw, struct sshkey *key, /* Parse and check options present in certificate */ if ((certopts = sshauthopt_from_cert(key)) == NULL) { reason = "Invalid certificate options"; - goto fail_reason; + goto cert_fail_reason; } if (auth_authorise_keyopts(pw, certopts, 0, remote_ip, remote_host, loc) != 0) { reason = "Refused by certificate options"; - goto fail_reason; + goto cert_fail_reason; } if ((finalopts = sshauthopt_merge(keyopts, certopts, &reason)) == NULL) - goto fail_reason; + goto cert_fail_reason; /* * If the user has specified a list of principals as @@ -368,12 +368,12 @@ auth_check_authkey_line(struct passwd *pw, struct sshkey *key, if (keyopts->cert_principals != NULL && !match_principals_option(keyopts->cert_principals, key->cert)) { reason = "Certificate does not contain an authorized principal"; - goto fail_reason; + goto cert_fail_reason; } if (sshkey_cert_check_authority_now(key, 0, 0, 0, keyopts->cert_principals == NULL ? pw->pw_name : NULL, &reason) != 0) - goto fail_reason; + goto cert_fail_reason; verbose("Accepted certificate ID \"%s\" (serial %llu) " "signed by CA %s %s found at %s", @@ -392,8 +392,17 @@ auth_check_authkey_line(struct passwd *pw, struct sshkey *key, ret = 0; goto out; + cert_fail_reason: + error("Refusing certificate ID \"%s\" serial=%llu " + "signed by %s CA %s via %s: %s", key->cert->key_id, + (unsigned long long)key->cert->serial, + sshkey_type(key->cert->signature_key), fp, loc, reason); + auth_debug_add("Refused Certificate ID \"%s\" serial=%llu: %s", + key->cert->key_id, (unsigned long long)key->cert->serial, reason); + goto out; + fail_reason: - error("%s", reason); + error("%s at %s", reason, loc); auth_debug_add("%s", reason); out: free(fp); diff --git a/auth2.c b/auth2.c index a0f6ca7ed83c..86b741db9713 100644 --- a/auth2.c +++ b/auth2.c @@ -148,7 +148,7 @@ userauth_send_banner(struct ssh *ssh, const char *msg) (r = sshpkt_put_cstring(ssh, "")) != 0 || /* language, unused */ (r = sshpkt_send(ssh)) != 0) fatal_fr(r, "send packet"); - debug("%s: sent", __func__); + debug_f("sent"); } static void diff --git a/authfd.c b/authfd.c index e04ad0cf2d02..2bbe646e304a 100644 --- a/authfd.c +++ b/authfd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.c,v 1.134 2023/12/18 14:46:56 djm Exp $ */ +/* $OpenBSD: authfd.c,v 1.136 2025/08/29 03:50:38 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -505,7 +505,7 @@ encode_dest_constraint(struct sshbuf *m, const struct dest_constraint *dc) static int encode_constraints(struct sshbuf *m, u_int life, u_int confirm, - u_int maxsign, const char *provider, + const char *provider, struct dest_constraint **dest_constraints, size_t ndest_constraints, int cert_only, struct sshkey **certs, size_t ncerts) { @@ -522,11 +522,6 @@ encode_constraints(struct sshbuf *m, u_int life, u_int confirm, 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 || @@ -585,13 +580,12 @@ encode_constraints(struct sshbuf *m, u_int life, u_int confirm, */ int ssh_add_identity_constrained(int sock, struct sshkey *key, - const char *comment, u_int life, u_int confirm, u_int maxsign, + const char *comment, u_int life, u_int confirm, const char *provider, struct dest_constraint **dest_constraints, size_t ndest_constraints) { struct sshbuf *msg; - int r, constrained = (life || confirm || maxsign || - provider || dest_constraints); + int r, constrained = (life || confirm || provider || dest_constraints); u_char type; if ((msg = sshbuf_new()) == NULL) @@ -601,8 +595,6 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, #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: @@ -612,14 +604,11 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, 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 = sshkey_private_serialize(key, msg)) != 0 || (r = sshbuf_put_cstring(msg, comment)) != 0) goto out; break; @@ -628,8 +617,8 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, goto out; } if (constrained && - (r = encode_constraints(msg, life, confirm, maxsign, - provider, dest_constraints, ndest_constraints, 0, NULL, 0)) != 0) + (r = encode_constraints(msg, life, confirm, provider, + dest_constraints, ndest_constraints, 0, NULL, 0)) != 0) goto out; if ((r = ssh_request_reply_decode(sock, msg)) != 0) goto out; @@ -705,7 +694,7 @@ ssh_update_card(int sock, int add, const char *reader_id, const char *pin, (r = sshbuf_put_cstring(msg, pin)) != 0) goto out; if (constrained && - (r = encode_constraints(msg, life, confirm, 0, NULL, + (r = encode_constraints(msg, life, confirm, NULL, dest_constraints, ndest_constraints, cert_only, certs, ncerts)) != 0) goto out; diff --git a/authfd.h b/authfd.h index c1e4b405ce29..958d480de6c7 100644 --- a/authfd.h +++ b/authfd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: authfd.h,v 1.52 2023/12/18 14:46:56 djm Exp $ */ +/* $OpenBSD: authfd.h,v 1.53 2025/08/29 03:50:38 djm Exp $ */ /* * Author: Tatu Ylonen @@ -48,9 +48,8 @@ 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); + const char *comment, u_int life, u_int confirm, 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, @@ -106,7 +105,6 @@ int ssh_agent_bind_hostkey(int sock, const struct sshkey *key, #define SSH_AGENT_CONSTRAIN_LIFETIME 1 #define SSH_AGENT_CONSTRAIN_CONFIRM 2 -#define SSH_AGENT_CONSTRAIN_MAXSIGN 3 #define SSH_AGENT_CONSTRAIN_EXTENSION 255 /* extended failure messages */ diff --git a/authfile.c b/authfile.c index 151fc21334c8..f81a4389c2e0 100644 --- a/authfile.c +++ b/authfile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: authfile.c,v 1.145 2024/09/22 12:56:21 jsg Exp $ */ +/* $OpenBSD: authfile.c,v 1.147 2025/08/29 03:50:38 djm Exp $ */ /* * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. * @@ -145,8 +145,6 @@ sshkey_load_private_type(int type, const char *filename, const char *passphrase, goto out; r = sshkey_load_private_type_fd(fd, type, passphrase, keyp, commentp); - if (r == 0 && keyp && *keyp) - r = sshkey_set_filename(*keyp, filename); out: close(fd); return r; @@ -198,8 +196,6 @@ sshkey_load_pubkey_from_private(const char *filename, struct sshkey **pubkeyp) (r = sshkey_parse_pubkey_from_private_fileblob_type(buffer, KEY_UNSPEC, &pubkey)) != 0) goto out; - if ((r = sshkey_set_filename(pubkey, filename)) != 0) - goto out; /* success */ if (pubkeyp != NULL) { *pubkeyp = pubkey; @@ -342,11 +338,9 @@ sshkey_load_private_cert(int type, const char *filename, const char *passphrase, switch (type) { #ifdef WITH_OPENSSL case KEY_RSA: - case KEY_DSA: case KEY_ECDSA: #endif /* WITH_OPENSSL */ case KEY_ED25519: - case KEY_XMSS: case KEY_UNSPEC: break; default: diff --git a/channels.c b/channels.c index 6caab482710e..6bf994f4e2c4 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.442 2024/12/05 06:49:26 dtucker Exp $ */ +/* $OpenBSD: channels.c,v 1.451 2025/09/25 06:33:19 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -46,9 +46,7 @@ #include #include #include -#ifdef HAVE_SYS_TIME_H -# include -#endif +#include #include #include @@ -57,13 +55,9 @@ #include #include #include -#ifdef HAVE_POLL_H #include -#endif #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include #include @@ -212,6 +206,10 @@ struct ssh_channels { /* Global timeout for all OPEN channels */ int global_deadline; time_t lastused; + /* pattern-lists used to classify channels as bulk */ + char *bulk_classifier_tty, *bulk_classifier_notty; + /* Number of active bulk channels (set by channel_handler) */ + u_int nbulk; }; /* helper */ @@ -239,6 +237,8 @@ channel_init_channels(struct ssh *ssh) sc->channels_alloc = 10; sc->channels = xcalloc(sc->channels_alloc, sizeof(*sc->channels)); sc->IPv4or6 = AF_UNSPEC; + sc->bulk_classifier_tty = xstrdup(CHANNEL_BULK_TTY); + sc->bulk_classifier_notty = xstrdup(CHANNEL_BULK_NOTTY); channel_handler_init(sc); ssh->chanctxt = sc; @@ -357,6 +357,17 @@ lookup_timeout(struct ssh *ssh, const char *type) return 0; } +static void +channel_classify(struct ssh *ssh, Channel *c) +{ + struct ssh_channels *sc = ssh->chanctxt; + const char *type = c->xctype == NULL ? c->ctype : c->xctype; + const char *classifier = c->isatty ? + sc->bulk_classifier_tty : sc->bulk_classifier_notty; + + c->bulk = type != NULL && match_pattern_list(type, classifier, 0) == 1; +} + /* * 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 @@ -375,6 +386,7 @@ channel_set_xtype(struct ssh *ssh, int id, const char *xctype) c->xctype = xstrdup(xctype); /* Type has changed, so look up inactivity deadline again */ c->inactive_deadline = lookup_timeout(ssh, c->xctype); + channel_classify(ssh, c); debug2_f("labeled channel %d as %s (inactive timeout %u)", id, xctype, c->inactive_deadline); } @@ -411,6 +423,13 @@ channel_get_expiry(struct ssh *ssh, Channel *c) return expiry; } +/* Returns non-zero if there is an open, non-interactive channel */ +int +channel_has_bulk(struct ssh *ssh) +{ + return ssh->chanctxt != NULL && ssh->chanctxt->nbulk != 0; +} + /* * Register filedescriptors for a channel, used when allocating a channel or * when the channel consumer/producer is ready, e.g. shell exec'd @@ -478,6 +497,7 @@ channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd, } /* channel might be entering a larval state, so reset global timeout */ channel_set_used_time(ssh, NULL); + channel_classify(ssh, c); } /* @@ -537,11 +557,19 @@ channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd, c->delayed = 1; /* prevent call to channel_post handler */ c->inactive_deadline = lookup_timeout(ssh, c->ctype); TAILQ_INIT(&c->status_confirms); + channel_classify(ssh, c); debug("channel %d: new %s [%s] (inactive timeout: %u)", found, c->ctype, remote_name, c->inactive_deadline); return c; } +void +channel_set_tty(struct ssh *ssh, Channel *c) +{ + c->isatty = 1; + channel_classify(ssh, c); +} + int channel_close_fd(struct ssh *ssh, Channel *c, int *fdp) { @@ -827,6 +855,27 @@ channel_free_all(struct ssh *ssh) sc->x11_fake_data_len = 0; } +void +channel_free_channels(struct ssh *ssh) +{ + struct ssh_channels *sc; + + if (ssh == NULL || ssh->chanctxt == NULL) + return; + channel_free_all(ssh); + channel_clear_permission(ssh, FORWARD_USER, FORWARD_LOCAL); + channel_clear_permission(ssh, FORWARD_USER, FORWARD_REMOTE); + channel_clear_permission(ssh, FORWARD_ADM, FORWARD_LOCAL); + channel_clear_permission(ssh, FORWARD_ADM, FORWARD_REMOTE); + sc = ssh->chanctxt; + free(sc->bulk_classifier_tty); + free(sc->bulk_classifier_notty); + free(sc->channel_pre); + free(sc->channel_post); + freezero(sc, sizeof(*sc)); + ssh->chanctxt = NULL; +} + /* * Closes the sockets/fds of all channels. This is used to close extra file * descriptors after a fork. @@ -1019,7 +1068,7 @@ channel_format_status(const Channel *c) char *ret = NULL; xasprintf(&ret, "t%d [%s] %s%u %s%u i%u/%zu o%u/%zu e[%s]/%zu " - "fd %d/%d/%d sock %d cc %d %s%u io 0x%02x/0x%02x", + "fd %d/%d/%d sock %d cc %d %s%u io 0x%02x/0x%02x %s%s", c->type, c->xctype != NULL ? c->xctype : c->ctype, c->have_remote_id ? "r" : "nr", c->remote_id, c->mux_ctx != NULL ? "m" : "nm", c->mux_downstream_id, @@ -1028,7 +1077,8 @@ channel_format_status(const Channel *c) channel_format_extended_usage(c), sshbuf_len(c->extended), c->rfd, c->wfd, c->efd, c->sock, c->ctl_chan, c->have_ctl_child_id ? "c" : "nc", c->ctl_child_id, - c->io_want, c->io_ready); + c->io_want, c->io_ready, + c->isatty ? "T" : "", c->bulk ? "B" : "I"); return ret; } @@ -1096,6 +1146,21 @@ channel_open_message(struct ssh *ssh) return ret; } +void +channel_report_open(struct ssh *ssh, int level) +{ + char *open, *oopen, *cp, ident[256]; + + sshpkt_fmt_connection_id(ssh, ident, sizeof(ident)); + do_log2(level, "Connection: %s (pid %ld)", ident, (long)getpid()); + open = oopen = channel_open_message(ssh); + while ((cp = strsep(&open, "\r\n")) != NULL) { + if (*cp != '\0') + do_log2(level, "%s", cp); + } + free(oopen); +} + static void open_preamble(struct ssh *ssh, const char *where, Channel *c, const char *type) { @@ -2615,10 +2680,13 @@ channel_handler(struct ssh *ssh, int table, struct timespec *timeout) time_t now; now = monotime(); - for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) { + for (sc->nbulk = i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) { c = sc->channels[i]; if (c == NULL) continue; + /* Count open channels in bulk state */ + if (c->type == SSH_CHANNEL_OPEN && c->bulk) + sc->nbulk++; /* Try to keep IO going while rekeying */ if (ssh_packet_is_rekeying(ssh) && c->type != SSH_CHANNEL_OPEN) continue; @@ -4527,7 +4595,7 @@ channel_add_permission(struct ssh *ssh, int who, int where, * host/port_to_connect. */ permission_set_add(ssh, who, where, - local ? host : 0, local ? port : 0, + local ? host : NULL, local ? port : 0, local ? NULL : host, NULL, local ? 0 : port, NULL); pset->all_permitted = 0; } @@ -4550,10 +4618,13 @@ void channel_clear_permission(struct ssh *ssh, int who, int where) { struct permission **permp; - u_int *npermp; + u_int i, *npermp; permission_set_get_array(ssh, who, where, &permp, &npermp); - *permp = xrecallocarray(*permp, *npermp, 0, sizeof(**permp)); + for (i = 0; i < *npermp; i++) + fwd_perm_clear((*permp) + i); + free(*permp); + *permp = NULL; *npermp = 0; } @@ -4686,8 +4757,7 @@ connect_to_helper(struct ssh *ssh, const char *name, int port, int socktype, * 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 = xcalloc(1, sizeof(*ai) + sizeof(*sunaddr)); ai->ai_addr = (struct sockaddr *)(ai + 1); ai->ai_addrlen = sizeof(*sunaddr); ai->ai_family = AF_UNIX; @@ -5019,7 +5089,7 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, return -1; for (display_number = x11_display_offset; - display_number < MAX_DISPLAYS; + display_number < x11_display_offset + MAX_DISPLAYS; display_number++) { port = X11_BASE_PORT + display_number; memset(&hints, 0, sizeof(hints)); @@ -5074,7 +5144,7 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, if (num_socks > 0) break; } - if (display_number >= MAX_DISPLAYS) { + if (display_number >= x11_display_offset + MAX_DISPLAYS) { error("Failed to allocate internet-domain X11 display socket."); return -1; } @@ -5142,7 +5212,7 @@ 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__); + error_f("display path too long"); return 0; } if (display[0] != '/') @@ -5363,7 +5433,8 @@ x11_channel_used_recently(struct ssh *ssh) { if (c == NULL || c->ctype == NULL || c->lastused == 0 || strcmp(c->ctype, "x11-connection") != 0) continue; - lastused = c->lastused; + if (c->lastused > lastused) + lastused = c->lastused; } - return lastused != 0 && monotime() > lastused + 1; + return lastused != 0 && monotime() <= lastused + 1; } diff --git a/channels.h b/channels.h index 134528d59c72..df7c7f364d22 100644 --- a/channels.h +++ b/channels.h @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.h,v 1.158 2024/10/13 22:20:06 djm Exp $ */ +/* $OpenBSD: channels.h,v 1.161 2025/09/25 06:33:19 djm Exp $ */ /* * Author: Tatu Ylonen @@ -82,6 +82,10 @@ #define FORWARD_ADM 0x100 #define FORWARD_USER 0x101 +/* default pattern-lists used to classify channel types as bulk */ +#define CHANNEL_BULK_TTY "" +#define CHANNEL_BULK_NOTTY "direct-*,forwarded-*,tun-*,x11-*,session*" + struct ssh; struct Channel; typedef struct Channel Channel; @@ -180,6 +184,7 @@ struct Channel { char *ctype; /* const type - NB. not freed on channel_free */ char *xctype; /* extended type */ + int bulk; /* channel is non-interactive */ /* callback */ channel_open_fn *open_confirm; @@ -277,8 +282,9 @@ struct Channel { c->efd != -1 && (!(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD)) || \ sshbuf_len(c->extended) > 0)) -/* Add channel management structures to SSH transport instance */ +/* Add/remove channel management structures to/from SSH transport instance */ void channel_init_channels(struct ssh *ssh); +void channel_free_channels(struct ssh *ssh); /* channel management */ @@ -289,6 +295,7 @@ 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_set_tty(struct ssh *, Channel *); void channel_free(struct ssh *, Channel *); void channel_free_all(struct ssh *); void channel_stop_listening(struct ssh *); @@ -308,6 +315,7 @@ void channel_register_status_confirm(struct ssh *, int, void channel_cancel_cleanup(struct ssh *, int); int channel_close_fd(struct ssh *, Channel *, int *); void channel_send_window_changes(struct ssh *); +int channel_has_bulk(struct ssh *); /* channel inactivity timeouts */ void channel_add_timeout(struct ssh *, const char *, int); @@ -344,6 +352,7 @@ 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 *); +void channel_report_open(struct ssh *, int); int channel_find_open(struct ssh *); /* tcp forwarding */ diff --git a/cipher.c b/cipher.c index 8a18da2df8d1..5e096cebfefa 100644 --- a/cipher.c +++ b/cipher.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cipher.c,v 1.124 2025/03/14 09:49:49 tb Exp $ */ +/* $OpenBSD: cipher.c,v 1.125 2025/09/02 11:08:34 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -116,25 +116,16 @@ static const struct sshcipher ciphers[] = { char * cipher_alg_list(char sep, int auth_only) { - char *tmp, *ret = NULL; - size_t nlen, rlen = 0; + char *ret = NULL; const struct sshcipher *c; + char sep_str[2] = {sep, '\0'}; 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; + xextendf(&ret, sep_str, "%s", c->name); } return ret; } diff --git a/clientloop.c b/clientloop.c index f3350a83b1fc..b80c148ba073 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.410 2024/12/03 22:30:03 jsg Exp $ */ +/* $OpenBSD: clientloop.c,v 1.415 2025/09/25 06:23:19 jsg Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -63,22 +63,16 @@ #include #include -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef HAVE_SYS_TIME_H -# include -#endif +#include #include +#include #include #include #ifdef HAVE_PATHS_H #include #endif -#ifdef HAVE_POLL_H #include -#endif #include #include #include @@ -147,7 +141,8 @@ extern char *forward_agent_sock_path; * 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; +static volatile sig_atomic_t siginfo_received = 0; +static volatile sig_atomic_t received_signal = 0; /* exit signals */ /* Time when backgrounded control master using ControlPersist should exit */ static time_t control_persist_exit_time = 0; @@ -224,6 +219,15 @@ window_change_handler(int sig) received_window_change_signal = 1; } +#ifdef SIGINFO +/* Signal handler for SIGINFO */ +static void +siginfo_handler(int sig) +{ + siginfo_received = 1; +} +#endif + /* * Signal handler for signals that cause the program to terminate. These * signals must be trapped to restore terminal modes. @@ -973,11 +977,11 @@ client_repledge(void) } 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) + if (pledge(PLEDGE_EXTRA_INET "stdio unix proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } else { debug("pledge: fork"); - if (pledge("stdio proc tty", NULL) == -1) + if (pledge(PLEDGE_EXTRA_INET "stdio proc tty", NULL) == -1) fatal_f("pledge(): %s", strerror(errno)); } /* XXX further things to do: @@ -1455,7 +1459,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, struct pollfd *pfd = NULL; u_int npfd_alloc = 0, npfd_active = 0; double start_time, total_time; - int channel_did_enqueue = 0, r; + int interactive = -1, channel_did_enqueue = 0, r; u_int64_t ibytes, obytes; int conn_in_ready, conn_out_ready; sigset_t bsigset, osigset; @@ -1522,6 +1526,9 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, if (ssh_signal(SIGTERM, SIG_IGN) != SIG_IGN) ssh_signal(SIGTERM, signal_handler); ssh_signal(SIGWINCH, window_change_handler); +#ifdef SIGINFO + ssh_signal(SIGINFO, siginfo_handler); +#endif if (have_pty) enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); @@ -1546,6 +1553,10 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, sigaddset(&bsigset, SIGQUIT) == -1 || sigaddset(&bsigset, SIGTERM) == -1) error_f("bsigset setup: %s", strerror(errno)); +#ifdef SIGINFO + if (sigaddset(&bsigset, SIGINFO) == -1) + error_f("bsigset setup: %s", strerror(errno)); +#endif /* Main loop of the client for the interactive session mode. */ while (!quit_pending) { @@ -1585,6 +1596,10 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, */ if (sigprocmask(SIG_BLOCK, &bsigset, &osigset) == -1) error_f("bsigset sigprocmask: %s", strerror(errno)); + if (siginfo_received) { + siginfo_received = 0; + channel_report_open(ssh, SYSLOG_LEVEL_INFO); + } if (quit_pending) break; client_wait_until_can_do_something(ssh, &pfd, &npfd_alloc, @@ -1615,6 +1630,12 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, * sender. */ if (conn_out_ready) { + if (interactive != !channel_has_bulk(ssh)) { + interactive = !channel_has_bulk(ssh); + debug2_f("session QoS is now %s", interactive ? + "interactive" : "non-interactive"); + ssh_packet_set_interactive(ssh, interactive); + } if ((r = ssh_packet_write_poll(ssh)) != 0) { sshpkt_fatal(ssh, r, "%s: ssh_packet_write_poll", __func__); @@ -1857,7 +1878,7 @@ client_request_tun_fwd(struct ssh *ssh, int tun_mode, char *ifname = NULL; if (tun_mode == SSH_TUNMODE_NO) - return 0; + return NULL; debug("Requesting tun unit %d in mode %d", local_tun, tun_mode); @@ -2428,6 +2449,7 @@ client_global_hostkeys_prove_confirm(struct ssh *ssh, int type, /* Make the edits to known_hosts */ update_known_hosts(ctx); out: + sshbuf_free(signdata); hostkeys_update_ctx_free(ctx); hostkeys_update_complete = 1; client_repledge(); @@ -2699,9 +2721,6 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, 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; diff --git a/config.h.in b/config.h.in index 6a0b89a75d3e..348bb306ae2b 100644 --- a/config.h.in +++ b/config.h.in @@ -371,6 +371,10 @@ don't. */ #undef HAVE_DECL_H_ERRNO +/* Define to 1 if you have the declaration of `INFINITY', and to 0 if you + don't. */ +#undef HAVE_DECL_INFINITY + /* Define to 1 if you have the declaration of `le32toh', and to 0 if you don't. */ #undef HAVE_DECL_LE32TOH @@ -443,6 +447,10 @@ don't. */ #undef HAVE_DECL__GETSHORT +/* Define to 1 if you have the declaration of `__builtin_inff', and to 0 if + you don't. */ +#undef HAVE_DECL___BUILTIN_INFF + /* Define to 1 if you have the `DES_crypt' function. */ #undef HAVE_DES_CRYPT @@ -464,12 +472,23 @@ /* Define to 1 if you have the `dlopen' function. */ #undef HAVE_DLOPEN -/* Define to 1 if you have the `DSA_generate_parameters_ex' function. */ -#undef HAVE_DSA_GENERATE_PARAMETERS_EX - /* Define to 1 if you have the `EC_KEY_METHOD_new' function. */ #undef HAVE_EC_KEY_METHOD_NEW +/* Define to 1 if you have the `EC_POINT_get_affine_coordinates' function. */ +#undef HAVE_EC_POINT_GET_AFFINE_COORDINATES + +/* Define to 1 if you have the `EC_POINT_get_affine_coordinates_GFp' function. + */ +#undef HAVE_EC_POINT_GET_AFFINE_COORDINATES_GFP + +/* Define to 1 if you have the `EC_POINT_set_affine_coordinates' function. */ +#undef HAVE_EC_POINT_SET_AFFINE_COORDINATES + +/* Define to 1 if you have the `EC_POINT_set_affine_coordinates_GFp' function. + */ +#undef HAVE_EC_POINT_SET_AFFINE_COORDINATES_GFP + /* Define to 1 if you have the header file. */ #undef HAVE_ELF_H @@ -635,6 +654,9 @@ /* Define to 1 if the system has the type `fsfilcnt_t'. */ #undef HAVE_FSFILCNT_T +/* Define to 1 if you have the `fstatat' function. */ +#undef HAVE_FSTATAT + /* Define to 1 if you have the `fstatfs' function. */ #undef HAVE_FSTATFS @@ -1002,6 +1024,12 @@ /* Define to 1 if you have the `ngetaddrinfo' function. */ #undef HAVE_NGETADDRINFO +/* Define to 1 if you have the `nlist' function. */ +#undef HAVE_NLIST + +/* Define to 1 if you have the header file. */ +#undef HAVE_NLIST_H + /* Define to 1 if you have the `nl_langinfo' function. */ #undef HAVE_NL_LANGINFO @@ -1361,6 +1389,9 @@ /* define if you have struct addrinfo data type */ #undef HAVE_STRUCT_ADDRINFO +/* Define to 1 if `d_type' is a member of `struct dirent'. */ +#undef HAVE_STRUCT_DIRENT_D_TYPE + /* define if you have struct in6_addr data type */ #undef HAVE_STRUCT_IN6_ADDR @@ -1580,6 +1611,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H +/* Define to 1 if you have the `unlinkat' function. */ +#undef HAVE_UNLINKAT + /* Define to 1 if you have the `unsetenv' function. */ #undef HAVE_UNSETENV @@ -1819,6 +1853,9 @@ /* System dirs owned by bin (uid 2) */ #undef PLATFORM_SYS_DIR_UID +/* need inet in pledge for setsockopt IP_TOS */ +#undef PLEDGE_EXTRA_INET + /* Port number of PRNGD/EGD random number socket */ #undef PRNGD_PORT diff --git a/configure b/configure index ae9866f288f6..74539c8e4ee6 100755 --- a/configure +++ b/configure @@ -688,6 +688,8 @@ LIBWTMPDB LIBEDIT LDNSCONFIG LIBOBJS +TESTLIBS +COMPATINCLUDES LD PATH_PASSWD_PROG STARTUP_SCRIPT_SHELL @@ -1941,122 +1943,122 @@ printf "%s\n" "$ac_res" >&6; } } # ac_fn_c_check_func -# ac_fn_c_check_type LINENO TYPE VAR INCLUDES -# ------------------------------------------- -# Tests whether TYPE exists after having included INCLUDES, setting cache -# variable VAR accordingly. -ac_fn_c_check_type () +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -printf %s "checking for $2... " >&6; } -if eval test \${$3+y} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +printf %s "checking for $2.$3... " >&6; } +if eval test \${$4+y} then : printf %s "(cached) " >&6 else $as_nop - eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$4 +$5 int main (void) { -if (sizeof ($2)) - return 0; +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : + eval "$4=yes" +else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$4 +$5 int main (void) { -if (sizeof (($2))) - return 0; +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : - + eval "$4=yes" else $as_nop - eval "$3=yes" + eval "$4=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -eval ac_res=\$$3 +eval ac_res=\$$4 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno -} # ac_fn_c_check_type +} # ac_fn_c_check_member -# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES -# ---------------------------------------------------- -# Tries to find if the field MEMBER exists in type AGGR, after including -# INCLUDES, setting cache variable VAR accordingly. -ac_fn_c_check_member () +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 -printf %s "checking for $2.$3... " >&6; } -if eval test \${$4+y} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +printf %s "checking for $2... " >&6; } +if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop + eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$5 +$4 int main (void) { -static $2 ac_aggr; -if (ac_aggr.$3) -return 0; +if (sizeof ($2)) + return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : - eval "$4=yes" -else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$5 +$4 int main (void) { -static $2 ac_aggr; -if (sizeof ac_aggr.$3) -return 0; +if (sizeof (($2))) + return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : - eval "$4=yes" + else $as_nop - eval "$4=no" + eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -eval ac_res=\$$4 +eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno -} # ac_fn_c_check_member +} # ac_fn_c_check_type # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- @@ -6115,8 +6117,14 @@ printf %s "checking clang version... " >&6; } printf "%s\n" "$CLANG_VER" >&6; } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -pipe" >&5 + ossh_cache_var=ossh_cv_cflag__pipe + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -pipe" >&5 printf %s "checking if $CC supports compile flag -pipe... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -pipe" _define_flag="" @@ -6181,14 +6189,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -6248,12 +6254,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -6262,16 +6266,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunknown-warning-option" >&5 + ossh_cache_var=ossh_cv_cflag__Wunknown_warning_option + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunknown-warning-option" >&5 printf %s "checking if $CC supports compile flag -Wunknown-warning-option... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wunknown-warning-option" _define_flag="" @@ -6336,14 +6350,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -6403,12 +6415,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -6417,16 +6427,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wno-error=format-truncation" >&5 + ossh_cache_var=ossh_cv_cflag__Wno_error_format_truncation + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wno-error=format-truncation" >&5 printf %s "checking if $CC supports compile flag -Wno-error=format-truncation... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wno-error=format-truncation" _define_flag="" @@ -6491,14 +6511,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -6558,12 +6576,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -6572,16 +6588,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Qunused-arguments" >&5 + ossh_cache_var=ossh_cv_cflag__Qunused_arguments + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Qunused-arguments" >&5 printf %s "checking if $CC supports compile flag -Qunused-arguments... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Qunused-arguments" _define_flag="" @@ -6646,14 +6672,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -6713,12 +6737,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -6727,16 +6749,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wall" >&5 + ossh_cache_var=ossh_cv_cflag__Wall + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wall" >&5 printf %s "checking if $CC supports compile flag -Wall... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wall" _define_flag="" @@ -6801,14 +6833,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -6868,12 +6898,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -6882,16 +6910,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wextra" >&5 + ossh_cache_var=ossh_cv_cflag__Wextra + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wextra" >&5 printf %s "checking if $CC supports compile flag -Wextra... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wextra" _define_flag="" @@ -6956,14 +6994,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -7023,12 +7059,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -7037,16 +7071,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wpointer-arith" >&5 + ossh_cache_var=ossh_cv_cflag__Wpointer_arith + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wpointer-arith" >&5 printf %s "checking if $CC supports compile flag -Wpointer-arith... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wpointer-arith" _define_flag="" @@ -7111,14 +7155,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -7178,12 +7220,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -7192,16 +7232,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wuninitialized" >&5 + ossh_cache_var=ossh_cv_cflag__Wuninitialized + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wuninitialized" >&5 printf %s "checking if $CC supports compile flag -Wuninitialized... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wuninitialized" _define_flag="" @@ -7266,14 +7316,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -7333,12 +7381,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -7347,16 +7393,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wsign-compare" >&5 + ossh_cache_var=ossh_cv_cflag__Wsign_compare + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wsign-compare" >&5 printf %s "checking if $CC supports compile flag -Wsign-compare... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wsign-compare" _define_flag="" @@ -7421,14 +7477,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -7488,12 +7542,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -7502,16 +7554,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wformat-security" >&5 + ossh_cache_var=ossh_cv_cflag__Wformat_security + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wformat-security" >&5 printf %s "checking if $CC supports compile flag -Wformat-security... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wformat-security" _define_flag="" @@ -7576,14 +7638,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -7643,12 +7703,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -7657,16 +7715,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wsizeof-pointer-memaccess" >&5 + ossh_cache_var=ossh_cv_cflag__Wsizeof_pointer_memaccess + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wsizeof-pointer-memaccess" >&5 printf %s "checking if $CC supports compile flag -Wsizeof-pointer-memaccess... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wsizeof-pointer-memaccess" _define_flag="" @@ -7731,14 +7799,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -7798,12 +7864,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -7812,16 +7876,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wpointer-sign" >&5 + ossh_cache_var=ossh_cv_cflag__Wpointer_sign + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wpointer-sign" >&5 printf %s "checking if $CC supports compile flag -Wpointer-sign... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wpointer-sign" _define_flag="-Wno-pointer-sign" @@ -7886,14 +7960,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -7953,12 +8025,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -7967,16 +8037,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunused-parameter" >&5 + ossh_cache_var=ossh_cv_cflag__Wunused_parameter + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunused-parameter" >&5 printf %s "checking if $CC supports compile flag -Wunused-parameter... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wunused-parameter" _define_flag="-Wno-unused-parameter" @@ -8041,14 +8121,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -8108,12 +8186,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -8122,16 +8198,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunused-result" >&5 + ossh_cache_var=ossh_cv_cflag__Wunused_result + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wunused-result" >&5 printf %s "checking if $CC supports compile flag -Wunused-result... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wunused-result" _define_flag="-Wno-unused-result" @@ -8196,14 +8282,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -8263,12 +8347,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -8277,16 +8359,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wimplicit-fallthrough" >&5 + ossh_cache_var=ossh_cv_cflag__Wimplicit_fallthrough + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wimplicit-fallthrough" >&5 printf %s "checking if $CC supports compile flag -Wimplicit-fallthrough... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wimplicit-fallthrough" _define_flag="" @@ -8351,14 +8443,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -8418,12 +8508,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -8432,16 +8520,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wmisleading-indentation" >&5 + ossh_cache_var=ossh_cv_cflag__Wmisleading_indentation + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wmisleading-indentation" >&5 printf %s "checking if $CC supports compile flag -Wmisleading-indentation... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wmisleading-indentation" _define_flag="" @@ -8506,14 +8604,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -8573,12 +8669,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -8587,16 +8681,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wbitwise-instead-of-logical" >&5 + ossh_cache_var=ossh_cv_cflag__Wbitwise_instead_of_logical + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wbitwise-instead-of-logical" >&5 printf %s "checking if $CC supports compile flag -Wbitwise-instead-of-logical... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wbitwise-instead-of-logical" _define_flag="" @@ -8661,14 +8765,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -8728,12 +8830,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -8742,16 +8842,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fno-strict-aliasing" >&5 + ossh_cache_var=ossh_cv_cflag__fno_strict_aliasing + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fno-strict-aliasing" >&5 printf %s "checking if $CC supports compile flag -fno-strict-aliasing... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -fno-strict-aliasing" _define_flag="" @@ -8816,14 +8926,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -8883,12 +8991,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -8897,17 +9003,27 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } if test "x$use_toolchain_hardening" = "x1"; then { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -D_FORTIFY_SOURCE=2" >&5 + ossh_cache_var=ossh_cv_cflag__D_FORTIFY_SOURCE_2 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -D_FORTIFY_SOURCE=2" >&5 printf %s "checking if $CC supports compile flag -D_FORTIFY_SOURCE=2... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -D_FORTIFY_SOURCE=2" _define_flag="" @@ -8972,14 +9088,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -9039,12 +9153,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -9053,16 +9165,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,relro" >&5 + ossh_cache_var=ossh_cv_ldflag__Wl__z_relro + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,relro" >&5 printf %s "checking if $LD supports link flag -Wl,-z,relro... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR -Wl,-z,relro" _define_flag="" @@ -9127,14 +9249,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" LDFLAGS="$saved_LDFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop @@ -9195,12 +9315,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" LDFLAGS="$saved_LDFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -9209,17 +9327,27 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" LDFLAGS="$saved_LDFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,now" >&5 + ossh_cache_var=ossh_cv_ldflag__Wl__z_now + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,now" >&5 printf %s "checking if $LD supports link flag -Wl,-z,now... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR -Wl,-z,now" _define_flag="" @@ -9284,14 +9412,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" LDFLAGS="$saved_LDFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop @@ -9352,12 +9478,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" LDFLAGS="$saved_LDFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -9366,17 +9490,27 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" LDFLAGS="$saved_LDFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,noexecstack" >&5 + ossh_cache_var=ossh_cv_ldflag__Wl__z_noexecstack + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,noexecstack" >&5 printf %s "checking if $LD supports link flag -Wl,-z,noexecstack... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR -Wl,-z,noexecstack" _define_flag="" @@ -9441,14 +9575,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" LDFLAGS="$saved_LDFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop @@ -9509,12 +9641,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" LDFLAGS="$saved_LDFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -9523,13 +9653,17 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" LDFLAGS="$saved_LDFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } # NB. -ftrapv expects certain support functions to be present in # the compiler library (libgcc or similar) to detect integer operations @@ -9537,8 +9671,14 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \ # actually links. The test program compiled/linked includes a number # of integer operations that should exercise this. { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -ftrapv and linking succeeds" >&5 + ossh_cache_var=ossh_cv_cflag__ftrapv + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -ftrapv and linking succeeds" >&5 printf %s "checking if $CC supports compile flag -ftrapv and linking succeeds... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -ftrapv" _define_flag="" @@ -9603,14 +9743,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -9670,12 +9808,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -9684,13 +9820,17 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } # clang 15 seems to have a bug in -fzero-call-used-regs=all. See # https://bugzilla.mindrot.org/show_bug.cgi?id=3475 and @@ -9699,8 +9839,14 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \ # flag at all (https://bugzilla.mindrot.org/show_bug.cgi?id=3629) case "$CLANG_VER" in apple-15*) { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fzero-call-used-regs=used and linking succeeds" >&5 + ossh_cache_var=ossh_cv_cflag__fzero_call_used_regs_used + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fzero-call-used-regs=used and linking succeeds" >&5 printf %s "checking if $CC supports compile flag -fzero-call-used-regs=used and linking succeeds... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -fzero-call-used-regs=used" _define_flag="" @@ -9765,14 +9911,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -9832,12 +9976,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -9846,18 +9988,28 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } ;; 17*) ;; *) { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fzero-call-used-regs=used and linking succeeds" >&5 + ossh_cache_var=ossh_cv_cflag__fzero_call_used_regs_used + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fzero-call-used-regs=used and linking succeeds" >&5 printf %s "checking if $CC supports compile flag -fzero-call-used-regs=used and linking succeeds... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -fzero-call-used-regs=used" _define_flag="" @@ -9922,14 +10074,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -9989,12 +10139,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -10003,18 +10151,28 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } ;; esac { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -ftrivial-auto-var-init=zero" >&5 + ossh_cache_var=ossh_cv_cflag__ftrivial_auto_var_init_zero + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -ftrivial-auto-var-init=zero" >&5 printf %s "checking if $CC supports compile flag -ftrivial-auto-var-init=zero... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -ftrivial-auto-var-init=zero" _define_flag="" @@ -10079,14 +10237,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -10146,12 +10302,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -10160,18 +10314,28 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } fi if test "x$use_retpoline" = "x1"; then { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -mretpoline" >&5 + ossh_cache_var=ossh_cv_cflag__mretpoline + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -mretpoline" >&5 printf %s "checking if $CC supports compile flag -mretpoline... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -mretpoline" _define_flag="" @@ -10236,14 +10400,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -10303,12 +10465,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -10317,16 +10477,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } # clang { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,retpolineplt" >&5 + ossh_cache_var=ossh_cv_ldflag__Wl__z_retpolineplt + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -Wl,-z,retpolineplt" >&5 printf %s "checking if $LD supports link flag -Wl,-z,retpolineplt... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR -Wl,-z,retpolineplt" _define_flag="" @@ -10391,14 +10561,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" LDFLAGS="$saved_LDFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop @@ -10459,12 +10627,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" LDFLAGS="$saved_LDFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -10473,13 +10639,17 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" LDFLAGS="$saved_LDFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } fi @@ -10886,12 +11056,6 @@ if test "x$ac_cv_header_dirent_h" = xyes then : printf "%s\n" "#define HAVE_DIRENT_H 1" >>confdefs.h -fi -ac_fn_c_check_header_compile "$LINENO" "endian.h" "ac_cv_header_endian_h" "$ac_includes_default" -if test "x$ac_cv_header_endian_h" = xyes -then : - printf "%s\n" "#define HAVE_ENDIAN_H 1" >>confdefs.h - fi ac_fn_c_check_header_compile "$LINENO" "elf.h" "ac_cv_header_elf_h" "$ac_includes_default" if test "x$ac_cv_header_elf_h" = xyes @@ -10952,12 +11116,6 @@ if test "x$ac_cv_header_iaf_h" = xyes then : printf "%s\n" "#define HAVE_IAF_H 1" >>confdefs.h -fi -ac_fn_c_check_header_compile "$LINENO" "ifaddrs.h" "ac_cv_header_ifaddrs_h" "$ac_includes_default" -if test "x$ac_cv_header_ifaddrs_h" = xyes -then : - printf "%s\n" "#define HAVE_IFADDRS_H 1" >>confdefs.h - fi ac_fn_c_check_header_compile "$LINENO" "inttypes.h" "ac_cv_header_inttypes_h" "$ac_includes_default" if test "x$ac_cv_header_inttypes_h" = xyes @@ -11012,30 +11170,12 @@ if test "x$ac_cv_header_netdb_h" = xyes then : printf "%s\n" "#define HAVE_NETDB_H 1" >>confdefs.h -fi -ac_fn_c_check_header_compile "$LINENO" "netgroup.h" "ac_cv_header_netgroup_h" "$ac_includes_default" -if test "x$ac_cv_header_netgroup_h" = xyes -then : - printf "%s\n" "#define HAVE_NETGROUP_H 1" >>confdefs.h - fi ac_fn_c_check_header_compile "$LINENO" "pam/pam_appl.h" "ac_cv_header_pam_pam_appl_h" "$ac_includes_default" if test "x$ac_cv_header_pam_pam_appl_h" = xyes then : printf "%s\n" "#define HAVE_PAM_PAM_APPL_H 1" >>confdefs.h -fi -ac_fn_c_check_header_compile "$LINENO" "paths.h" "ac_cv_header_paths_h" "$ac_includes_default" -if test "x$ac_cv_header_paths_h" = xyes -then : - printf "%s\n" "#define HAVE_PATHS_H 1" >>confdefs.h - -fi -ac_fn_c_check_header_compile "$LINENO" "poll.h" "ac_cv_header_poll_h" "$ac_includes_default" -if test "x$ac_cv_header_poll_h" = xyes -then : - printf "%s\n" "#define HAVE_POLL_H 1" >>confdefs.h - fi ac_fn_c_check_header_compile "$LINENO" "pty.h" "ac_cv_header_pty_h" "$ac_includes_default" if test "x$ac_cv_header_pty_h" = xyes @@ -11078,12 +11218,6 @@ if test "x$ac_cv_header_stddef_h" = xyes then : printf "%s\n" "#define HAVE_STDDEF_H 1" >>confdefs.h -fi -ac_fn_c_check_header_compile "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default" -if test "x$ac_cv_header_stdint_h" = xyes -then : - printf "%s\n" "#define HAVE_STDINT_H 1" >>confdefs.h - fi ac_fn_c_check_header_compile "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default" if test "x$ac_cv_header_string_h" = xyes @@ -11228,12 +11362,6 @@ if test "x$ac_cv_header_sys_sysmacros_h" = xyes then : printf "%s\n" "#define HAVE_SYS_SYSMACROS_H 1" >>confdefs.h -fi -ac_fn_c_check_header_compile "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" -if test "x$ac_cv_header_sys_time_h" = xyes -then : - printf "%s\n" "#define HAVE_SYS_TIME_H 1" >>confdefs.h - fi ac_fn_c_check_header_compile "$LINENO" "sys/timers.h" "ac_cv_header_sys_timers_h" "$ac_includes_default" if test "x$ac_cv_header_sys_timers_h" = xyes @@ -11246,12 +11374,6 @@ if test "x$ac_cv_header_sys_vfs_h" = xyes then : printf "%s\n" "#define HAVE_SYS_VFS_H 1" >>confdefs.h -fi -ac_fn_c_check_header_compile "$LINENO" "time.h" "ac_cv_header_time_h" "$ac_includes_default" -if test "x$ac_cv_header_time_h" = xyes -then : - printf "%s\n" "#define HAVE_TIME_H 1" >>confdefs.h - fi ac_fn_c_check_header_compile "$LINENO" "tmpdir.h" "ac_cv_header_tmpdir_h" "$ac_includes_default" if test "x$ac_cv_header_tmpdir_h" = xyes @@ -11282,12 +11404,6 @@ if test "x$ac_cv_header_usersec_h" = xyes then : printf "%s\n" "#define HAVE_USERSEC_H 1" >>confdefs.h -fi -ac_fn_c_check_header_compile "$LINENO" "util.h" "ac_cv_header_util_h" "$ac_includes_default" -if test "x$ac_cv_header_util_h" = xyes -then : - printf "%s\n" "#define HAVE_UTIL_H 1" >>confdefs.h - fi ac_fn_c_check_header_compile "$LINENO" "utime.h" "ac_cv_header_utime_h" "$ac_includes_default" if test "x$ac_cv_header_utime_h" = xyes @@ -11321,6 +11437,39 @@ then : fi +# Create replacement header files for common headers that are missing on this +# platform. Usually these are just empty, but in some cases they'll include +# the equivalent file. This avoids having to wrap those includes in +# '#ifdef HAVE_FOO_H'. If we create any such headers, add the path to includes. +COMPATINCLUDES="" + for ac_header in endian.h ifaddrs.h libgen.h paths.h netgroup.h nlist.h poll.h stdint.h sys/stat.h sys/time.h sys/un.h time.h util.h +do : + as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes" +then : + cat >>confdefs.h <<_ACEOF +#define `printf "%s\n" "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +else $as_nop + + COMPATINCLUDES="openbsd-compat/include" + header="$COMPATINCLUDES/$ac_header" + dir=`dirname "$header"` + mkdir -p "$dir" + case "$ac_header" in + poll.h) echo '#ifdef HAVE_SYS_POLL_H' + echo '#include ' + echo '#endif' ;; + *) ;; + esac >"$header" + +fi + +done + + ac_fn_check_decl "$LINENO" "le32toh" "ac_cv_have_decl_le32toh" " #ifdef HAVE_SYS_TYPES_H # include @@ -11564,6 +11713,9 @@ SOLARIS_PRIVS="no" # Default shared library extension SHLIBEXT=".so" +# See OpenBSD section in $host case below. +need_pledge_inet="" + # Check for some target-specific stuff case "$host" in *-*-aix*) @@ -11879,8 +12031,14 @@ printf "%s\n" "#define FILESYSTEM_NO_BACKSLASH 1" >>confdefs.h # Cygwin defines optargs, optargs as declspec(dllimport) for historical # reasons which cause compile warnings, so we disable those warnings. { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wno-attributes" >&5 + ossh_cache_var=ossh_cv_cflag__Wno_attributes + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -Wno-attributes" >&5 printf %s "checking if $CC supports compile flag -Wno-attributes... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -Wno-attributes" _define_flag="" @@ -11945,14 +12103,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -12012,12 +12168,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -12026,12 +12180,16 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } SHLIBEXT=".dll" ;; @@ -12746,6 +12904,9 @@ printf "%s\n" "#define LOCKED_PASSWD_PREFIX \"*LOCKED*\"" >>confdefs.h printf "%s\n" "#define SSH_TUN_FREEBSD 1" >>confdefs.h + +printf "%s\n" "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h + ac_fn_c_check_header_compile "$LINENO" "net/if_tap.h" "ac_cv_header_net_if_tap_h" "$ac_includes_default" if test "x$ac_cv_header_net_if_tap_h" = xyes then : @@ -12808,6 +12969,53 @@ printf "%s\n" "#define SSH_TUN_OPENBSD 1" >>confdefs.h printf "%s\n" "#define SYSLOG_R_SAFE_IN_SIGHAND 1" >>confdefs.h TEST_MALLOC_OPTIONS="SJRU" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pledge(2) allows IP_TOS" >&5 +printf %s "checking whether pledge(2) allows IP_TOS... " >&6; } + if test "$cross_compiling" = yes +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: cannot test" >&5 +printf "%s\n" "$as_me: WARNING: cross compiling: cannot test" >&2;} +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#include +#include +#include + +int +main (void) +{ + +int s, one = 1; +if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) + err(1, "socket"); +if (pledge("stdio", NULL) == -1) + err(1, "pledge"); +if (setsockopt(s, IPPROTO_IP, IP_TOS, &one, sizeof(one)) == -1) + err(1, "setsockopt"); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO" +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } +else $as_nop + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + need_pledge_inet=1 + +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + ;; *-*-solaris*) if test "x$withval" != "xno" ; then @@ -13458,6 +13666,15 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ fi +if test -z "$need_pledge_inet" ; then + printf "%s\n" "#define PLEDGE_EXTRA_INET /**/" >>confdefs.h + +else + +printf "%s\n" "#define PLEDGE_EXTRA_INET \"inet \"" >>confdefs.h + +fi + # Checks for libraries. ac_fn_c_check_func "$LINENO" "setsockopt" "ac_cv_func_setsockopt" if test "x$ac_cv_func_setsockopt" = xyes @@ -13741,6 +13958,55 @@ printf "%s\n" "#define HAVE_BASENAME 1" >>confdefs.h fi +ac_fn_c_check_func "$LINENO" "sqrt" "ac_cv_func_sqrt" +if test "x$ac_cv_func_sqrt" = xyes +then : + +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sqrt in -lm" >&5 +printf %s "checking for sqrt in -lm... " >&6; } +if test ${ac_cv_lib_m_sqrt+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char sqrt (); +int +main (void) +{ +return sqrt (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_m_sqrt=yes +else $as_nop + ac_cv_lib_m_sqrt=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_sqrt" >&5 +printf "%s\n" "$ac_cv_lib_m_sqrt" >&6; } +if test "x$ac_cv_lib_m_sqrt" = xyes +then : + TESTLIBS="$TESTLIBS -lm" +fi + +fi + + + zlib=yes # Check whether --with-zlib was given. @@ -15122,6 +15388,21 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ fi +ac_fn_c_check_member "$LINENO" "struct dirent" "d_type" "ac_cv_member_struct_dirent_d_type" " +#ifdef HAVE_DIRENT_H +#include +#endif + +" +if test "x$ac_cv_member_struct_dirent_d_type" = xyes +then : + +printf "%s\n" "#define HAVE_STRUCT_DIRENT_D_TYPE 1" >>confdefs.h + + +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for /proc/pid/fd directory" >&5 printf %s "checking for /proc/pid/fd directory... " >&6; } if test -d "/proc/$$/fd" ; then @@ -15713,8 +15994,14 @@ if test "x$use_pie" != "xno"; then SAVED_CFLAGS="$CFLAGS" SAVED_LDFLAGS="$LDFLAGS" { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fPIE" >&5 + ossh_cache_var=ossh_cv_cflag__fPIE + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $CC supports compile flag -fPIE" >&5 printf %s "checking if $CC supports compile flag -fPIE... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR -fPIE" _define_flag="" @@ -15779,14 +16066,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -15846,12 +16131,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -15860,16 +16143,26 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } { - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -pie" >&5 + ossh_cache_var=ossh_cv_ldflag__pie + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $LD supports link flag -pie" >&5 printf %s "checking if $LD supports link flag -pie... " >&6; } +if eval test \${$ossh_cache_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR -pie" _define_flag="" @@ -15934,14 +16227,12 @@ then : if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" LDFLAGS="$saved_LDFLAGS" else if test "$cross_compiling" = yes then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop @@ -16002,12 +16293,10 @@ int main(int argc, char **argv) { _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } + eval "$ossh_cache_var=yes" LDFLAGS="$saved_LDFLAGS $_define_flag" else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, fails at run time" >&5 -printf "%s\n" "no, fails at run time" >&6; } + eval "$ossh_cache_var='no, fails at run time'" LDFLAGS="$saved_LDFLAGS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ @@ -16016,13 +16305,17 @@ fi fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } + eval "$ossh_cache_var=no" LDFLAGS="$saved_LDFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext + +fi +eval ac_res=\$$ossh_cache_var + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } } # We use both -fPIE and -pie or neither. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether both -fPIE and -pie are supported" >&5 @@ -16289,6 +16582,12 @@ if test "x$ac_cv_func_freezero" = xyes then : printf "%s\n" "#define HAVE_FREEZERO 1" >>confdefs.h +fi +ac_fn_c_check_func "$LINENO" "fstatat" "ac_cv_func_fstatat" +if test "x$ac_cv_func_fstatat" = xyes +then : + printf "%s\n" "#define HAVE_FSTATAT 1" >>confdefs.h + fi ac_fn_c_check_func "$LINENO" "fstatfs" "ac_cv_func_fstatfs" if test "x$ac_cv_func_fstatfs" = xyes @@ -16499,6 +16798,12 @@ if test "x$ac_cv_func_ngetaddrinfo" = xyes then : printf "%s\n" "#define HAVE_NGETADDRINFO 1" >>confdefs.h +fi +ac_fn_c_check_func "$LINENO" "nlist" "ac_cv_func_nlist" +if test "x$ac_cv_func_nlist" = xyes +then : + printf "%s\n" "#define HAVE_NLIST 1" >>confdefs.h + fi ac_fn_c_check_func "$LINENO" "nsleep" "ac_cv_func_nsleep" if test "x$ac_cv_func_nsleep" = xyes @@ -16859,6 +17164,12 @@ if test "x$ac_cv_func_truncate" = xyes then : printf "%s\n" "#define HAVE_TRUNCATE 1" >>confdefs.h +fi +ac_fn_c_check_func "$LINENO" "unlinkat" "ac_cv_func_unlinkat" +if test "x$ac_cv_func_unlinkat" = xyes +then : + printf "%s\n" "#define HAVE_UNLINKAT 1" >>confdefs.h + fi ac_fn_c_check_func "$LINENO" "unsetenv" "ac_cv_func_unsetenv" if test "x$ac_cv_func_unsetenv" = xyes @@ -17536,6 +17847,32 @@ fi printf "%s\n" "#define HAVE_DECL_OFFSETOF $ac_have_decl" >>confdefs.h +ac_fn_check_decl "$LINENO" "INFINITY" "ac_cv_have_decl_INFINITY" "#include + +" "$ac_c_undeclared_builtin_options" "CFLAGS" +if test "x$ac_cv_have_decl_INFINITY" = xyes +then : + ac_have_decl=1 +else $as_nop + ac_have_decl=0 +fi +printf "%s\n" "#define HAVE_DECL_INFINITY $ac_have_decl" >>confdefs.h +if test $ac_have_decl = 1 +then : + +else $as_nop + ac_fn_check_decl "$LINENO" "__builtin_inff" "ac_cv_have_decl___builtin_inff" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS" +if test "x$ac_cv_have_decl___builtin_inff" = xyes +then : + ac_have_decl=1 +else $as_nop + ac_have_decl=0 +fi +printf "%s\n" "#define HAVE_DECL___BUILTIN_INFF $ac_have_decl" >>confdefs.h + +fi + + # extra bits for select(2) ac_fn_check_decl "$LINENO" "howmany" "ac_cv_have_decl_howmany" " #include @@ -18159,6 +18496,9 @@ printf %s "checking whether snprintf can declare const char *fmt... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ +#ifdef _FORTIFY_SOURCE +#undef _FORTIFY_SOURCE +#endif #include int snprintf(char *a, size_t b, const char *c, ...) { return 0; } @@ -19004,8 +19344,8 @@ then : *) ;; # Assume all other versions are good. esac ;; - 30*) - # OpenSSL 3; we use the 1.1x API + 30*|40*) + # OpenSSL 3 & 4; we use the 1.1x API # https://openssl.org/policies/general/versioning-policy.html CPPFLAGS="$CPPFLAGS -DOPENSSL_API_COMPAT=0x10100000L" ;; @@ -19168,12 +19508,6 @@ if test "x$ac_cv_func_DES_crypt" = xyes then : printf "%s\n" "#define HAVE_DES_CRYPT 1" >>confdefs.h -fi -ac_fn_c_check_func "$LINENO" "DSA_generate_parameters_ex" "ac_cv_func_DSA_generate_parameters_ex" -if test "x$ac_cv_func_DSA_generate_parameters_ex" = xyes -then : - printf "%s\n" "#define HAVE_DSA_GENERATE_PARAMETERS_EX 1" >>confdefs.h - fi ac_fn_c_check_func "$LINENO" "EVP_DigestSign" "ac_cv_func_EVP_DigestSign" if test "x$ac_cv_func_EVP_DigestSign" = xyes @@ -19259,7 +19593,31 @@ fi # LibreSSL/OpenSSL API differences - ac_fn_c_check_func "$LINENO" "EVP_CIPHER_CTX_iv" "ac_cv_func_EVP_CIPHER_CTX_iv" + ac_fn_c_check_func "$LINENO" "EC_POINT_get_affine_coordinates" "ac_cv_func_EC_POINT_get_affine_coordinates" +if test "x$ac_cv_func_EC_POINT_get_affine_coordinates" = xyes +then : + printf "%s\n" "#define HAVE_EC_POINT_GET_AFFINE_COORDINATES 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "EC_POINT_get_affine_coordinates_GFp" "ac_cv_func_EC_POINT_get_affine_coordinates_GFp" +if test "x$ac_cv_func_EC_POINT_get_affine_coordinates_GFp" = xyes +then : + printf "%s\n" "#define HAVE_EC_POINT_GET_AFFINE_COORDINATES_GFP 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "EC_POINT_set_affine_coordinates" "ac_cv_func_EC_POINT_set_affine_coordinates" +if test "x$ac_cv_func_EC_POINT_set_affine_coordinates" = xyes +then : + printf "%s\n" "#define HAVE_EC_POINT_SET_AFFINE_COORDINATES 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "EC_POINT_set_affine_coordinates_GFp" "ac_cv_func_EC_POINT_set_affine_coordinates_GFp" +if test "x$ac_cv_func_EC_POINT_set_affine_coordinates_GFp" = xyes +then : + printf "%s\n" "#define HAVE_EC_POINT_SET_AFFINE_COORDINATES_GFP 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "EVP_CIPHER_CTX_iv" "ac_cv_func_EVP_CIPHER_CTX_iv" if test "x$ac_cv_func_EVP_CIPHER_CTX_iv" = xyes then : printf "%s\n" "#define HAVE_EVP_CIPHER_CTX_IV 1" >>confdefs.h @@ -19697,9 +20055,6 @@ if test "x$ac_cv_have_decl_OPENSSL_IS_AWSLC" = xyes then : enable_pkcs11="disabled; PKCS#11 not supported with AWS-LC" fi -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)" diff --git a/configure.ac b/configure.ac index ee77a0484b19..3eb6d4697f98 100644 --- a/configure.ac +++ b/configure.ac @@ -457,7 +457,6 @@ AC_CHECK_HEADERS([ \ crypt.h \ crypto/sha2.h \ dirent.h \ - endian.h \ elf.h \ err.h \ features.h \ @@ -468,7 +467,6 @@ AC_CHECK_HEADERS([ \ glob.h \ ia.h \ iaf.h \ - ifaddrs.h \ inttypes.h \ langinfo.h \ limits.h \ @@ -478,10 +476,7 @@ AC_CHECK_HEADERS([ \ 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 \ @@ -489,7 +484,6 @@ AC_CHECK_HEADERS([ \ sha2.h \ shadow.h \ stddef.h \ - stdint.h \ string.h \ strings.h \ sys/bitypes.h \ @@ -514,16 +508,13 @@ AC_CHECK_HEADERS([ \ 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 \ @@ -531,6 +522,38 @@ AC_CHECK_HEADERS([ \ wchar.h \ ]) +# Create replacement header files for common headers that are missing on this +# platform. Usually these are just empty, but in some cases they'll include +# the equivalent file. This avoids having to wrap those includes in +# '#ifdef HAVE_FOO_H'. If we create any such headers, add the path to includes. +COMPATINCLUDES="" +AC_CHECK_HEADERS([ \ + endian.h \ + ifaddrs.h \ + libgen.h \ + paths.h \ + netgroup.h \ + nlist.h \ + poll.h \ + stdint.h \ + sys/stat.h \ + sys/time.h \ + sys/un.h \ + time.h \ + util.h], [], [ + COMPATINCLUDES="openbsd-compat/include" + header="$COMPATINCLUDES/$ac_header" + dir=`dirname "$header"` + mkdir -p "$dir" + case "$ac_header" in + poll.h) echo '#ifdef HAVE_SYS_POLL_H' + echo '#include ' + echo '#endif' ;; + *) ;; + esac >"$header" +]) +AC_SUBST([COMPATINCLUDES]) + AC_CHECK_DECLS([le32toh, le64toh, htole64], [], [], [ #ifdef HAVE_SYS_TYPES_H # include @@ -629,6 +652,9 @@ SOLARIS_PRIVS="no" # Default shared library extension SHLIBEXT=".so" +# See OpenBSD section in $host case below. +need_pledge_inet="" + # Check for some target-specific stuff case "$host" in *-*-aix*) @@ -1092,6 +1118,8 @@ mips-sony-bsd|mips-sony-newsos4) *-*-freebsd*) AC_DEFINE([LOCKED_PASSWD_PREFIX], ["*LOCKED*"], [Account locked with pw(1)]) 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_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]) @@ -1128,6 +1156,28 @@ mips-sony-bsd|mips-sony-newsos4) AC_DEFINE([SYSLOG_R_SAFE_IN_SIGHAND], [1], [syslog_r function is safe to use in in a signal handler]) TEST_MALLOC_OPTIONS="SJRU" + AC_MSG_CHECKING([whether pledge(2) allows IP_TOS]) + AC_RUN_IFELSE( + [AC_LANG_PROGRAM([[ +#include +#include +#include +#include +#include + ]], [[ +int s, one = 1; +if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) + err(1, "socket"); +if (pledge("stdio", NULL) == -1) + err(1, "pledge"); +if (setsockopt(s, IPPROTO_IP, IP_TOS, &one, sizeof(one)) == -1) + err(1, "setsockopt"); + ]])], + [ AC_MSG_RESULT([yes]) ], [ + AC_MSG_RESULT([no]) + need_pledge_inet=1 + ], + [ AC_MSG_WARN([cross compiling: cannot test]) ]) ;; *-*-solaris*) if test "x$withval" != "xno" ; then @@ -1401,6 +1451,14 @@ AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ exit(0); ]])], [ AC_MSG_WARN([cross compiling: not checking compiler sanity]) ] ) +dnl Finish up special pledge(2) handling from above. +if test -z "$need_pledge_inet" ; then + AC_DEFINE_UNQUOTED([PLEDGE_EXTRA_INET], []) +else + AC_DEFINE_UNQUOTED([PLEDGE_EXTRA_INET], ["inet "], + [need inet in pledge for setsockopt IP_TOS]) +fi + dnl Checks for header files. # Checks for libraries. AC_CHECK_FUNC([setsockopt], , [AC_CHECK_LIB([socket], [setsockopt])]) @@ -1449,6 +1507,11 @@ AC_CHECK_FUNC([getspnam], , AC_SEARCH_LIBS([basename], [gen], [AC_DEFINE([HAVE_BASENAME], [1], [Define if you have the basename function.])]) +dnl sqrt() only used in unit tests. +AC_CHECK_FUNC([sqrt], , + [AC_CHECK_LIB([m], [sqrt], [TESTLIBS="$TESTLIBS -lm"])]) +AC_SUBST([TESTLIBS]) + dnl zlib defaults to enabled zlib=yes AC_ARG_WITH([zlib], @@ -1695,6 +1758,12 @@ AC_RUN_IFELSE( ] ) +AC_CHECK_MEMBERS([struct dirent.d_type], [], [], [[ +#ifdef HAVE_DIRENT_H +#include +#endif +]]) + 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]) @@ -1999,6 +2068,7 @@ AC_CHECK_FUNCS([ \ fnmatch \ freeaddrinfo \ freezero \ + fstatat \ fstatfs \ fstatvfs \ futimes \ @@ -2034,6 +2104,7 @@ AC_CHECK_FUNCS([ \ memset_s \ mkdtemp \ ngetaddrinfo \ + nlist \ nsleep \ ogetaddrinfo \ openlog_r \ @@ -2094,6 +2165,7 @@ AC_CHECK_FUNCS([ \ timegm \ timingsafe_bcmp \ truncate \ + unlinkat \ unsetenv \ updwtmpx \ utimensat \ @@ -2275,6 +2347,11 @@ AC_CHECK_DECLS([offsetof], , , [ #include ]) +AC_CHECK_DECLS([INFINITY], , + AC_CHECK_DECLS(__builtin_inff), + [#include ] +) + # extra bits for select(2) AC_CHECK_DECLS([howmany, NFDBITS], [], [], [[ #include @@ -2485,6 +2562,9 @@ fi # This is only useful for when BROKEN_SNPRINTF AC_MSG_CHECKING([whether snprintf can declare const char *fmt]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#ifdef _FORTIFY_SOURCE +#undef _FORTIFY_SOURCE +#endif #include int snprintf(char *a, size_t b, const char *c, ...) { return 0; } ]], [[ @@ -2975,8 +3055,8 @@ if test "x$openssl" = "xyes" ; then *) ;; # Assume all other versions are good. esac ;; - 30*) - # OpenSSL 3; we use the 1.1x API + 30*|40*) + # OpenSSL 3 & 4; we use the 1.1x API # https://openssl.org/policies/general/versioning-policy.html CPPFLAGS="$CPPFLAGS -DOPENSSL_API_COMPAT=0x10100000L" ;; @@ -3066,7 +3146,6 @@ if test "x$openssl" = "xyes" ; then AC_CHECK_FUNCS([ \ BN_is_prime_ex \ DES_crypt \ - DSA_generate_parameters_ex \ EVP_DigestSign \ EVP_DigestVerify \ EVP_DigestFinal_ex \ @@ -3090,6 +3169,10 @@ if test "x$openssl" = "xyes" ; then # LibreSSL/OpenSSL API differences AC_CHECK_FUNCS([ \ + EC_POINT_get_affine_coordinates \ + EC_POINT_get_affine_coordinates_GFp \ + EC_POINT_set_affine_coordinates \ + EC_POINT_set_affine_coordinates_GFp \ EVP_CIPHER_CTX_iv \ EVP_CIPHER_CTX_iv_noconst \ EVP_CIPHER_CTX_get_iv \ @@ -3298,9 +3381,6 @@ AC_CHECK_DECL([OPENSSL_IS_AWSLC], [], [#include ] ) -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)" diff --git a/contrib/Makefile b/contrib/Makefile index 45d878bdcf22..1482783a8097 100644 --- a/contrib/Makefile +++ b/contrib/Makefile @@ -1,7 +1,7 @@ PKG_CONFIG = pkg-config all: - @echo "Valid targets: gnome-ssh-askpass1 gnome-ssh-askpass2 gnome-ssk-askpass3" + @echo "Valid targets: gnome-ssh-askpass1 gnome-ssh-askpass2 gnome-ssk-askpass3 gnome-ssh-askpass4" gnome-ssh-askpass1: gnome-ssh-askpass1.c $(CC) $(CFLAGS) `gnome-config --cflags gnome gnomeui` \ @@ -18,5 +18,10 @@ gnome-ssh-askpass3: gnome-ssh-askpass3.c gnome-ssh-askpass3.c -o gnome-ssh-askpass3 \ `$(PKG_CONFIG) --libs gtk+-3.0 x11` +gnome-ssh-askpass4: gnome-ssh-askpass4.c + $(CC) $(CFLAGS) `$(PKG_CONFIG) --cflags gcr-4 gio-2.0` \ + gnome-ssh-askpass4.c -o gnome-ssh-askpass4 \ + `$(PKG_CONFIG) --libs gcr-4 gio-2.0` + clean: rm -f *.o gnome-ssh-askpass gnome-ssh-askpass[123] diff --git a/contrib/README b/contrib/README index 60e19ba9faa8..614152a123aa 100644 --- a/contrib/README +++ b/contrib/README @@ -30,10 +30,12 @@ ssh-copy-id: Phil Hands' shell script to automate the process of adding your public key to a remote machine's ~/.ssh/authorized_keys file. -gnome-ssh-askpass[12]: +gnome-ssh-askpass[1234]: -A GNOME and Gtk2 passphrase requesters. Use "make gnome-ssh-askpass1" or -"make gnome-ssh-askpass2" to build. +Graphical passhrase requesters. Use "make gnome-ssh-askpass1" to build +a variant for ancient GNOME desktop, "make gnome-ssh-askpass2" +for a GTK 2-based one, "make gnome-ssh-askpass3" for a GTK 3-based one, +or "make gnome-ssh-askpass4" for a version for modern GNOME. sshd.pam.generic: diff --git a/contrib/cygwin/ssh-user-config b/contrib/cygwin/ssh-user-config index 3858722f646d..35802d06ecba 100644 --- a/contrib/cygwin/ssh-user-config +++ b/contrib/cygwin/ssh-user-config @@ -246,9 +246,8 @@ done check_user_homedir check_user_dot_ssh_dir create_identity id_rsa rsa "SSH2 RSA" -create_identity id_dsa dsa "SSH2 DSA" +create_identity id_ed25519 ed25519 "SSH2 Ed25519" create_identity id_ecdsa ecdsa "SSH2 ECDSA" -create_identity identity rsa1 "(deprecated) SSH1 RSA" fix_authorized_keys_perms echo diff --git a/contrib/gnome-ssh-askpass4.c b/contrib/gnome-ssh-askpass4.c new file mode 100644 index 000000000000..182bce0cc63b --- /dev/null +++ b/contrib/gnome-ssh-askpass4.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2000-2002 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. + */ + +/* GCR support by Jan Tojnar */ + +/* + * This is a simple SSH passphrase grabber for GNOME. To use it, set the + * environment variable SSH_ASKPASS to point to the location of + * gnome-ssh-askpass before calling "ssh-add < /dev/null". + */ + +/* + * Known problems: + * - This depends on unstable libgcr features + * - long key fingerprints may be truncted: + * https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6781 + */ + +/* + * Compile with: + * + * cc -Wall `pkg-config --cflags gcr-4 gio-2.0` \ + * gnome-ssh-askpass4.c -o gnome-ssh-askpass \ + * `pkg-config --libs gcr-4 gio-2.0` + * + */ + +#include +#include + +#include + +#define GCR_API_SUBJECT_TO_CHANGE 1 +#include + +typedef enum _PromptType { + PROMPT_ENTRY, + PROMPT_CONFIRM, + PROMPT_NONE, +} PromptType; + +typedef struct _PromptState { + GApplication *app; + char* message; + PromptType type; + int exit_status; +} PromptState; + +static PromptState * +prompt_state_new(GApplication *app, char* message, PromptType type) +{ + PromptState *state = g_malloc(sizeof(PromptState)); + state->app = g_object_ref(app); + state->message = g_strdup(message); + state->type = type; + state->exit_status = -1; + return state; +} + +static void +prompt_state_free(PromptState *state) +{ + g_clear_object(&state->app); + g_free(state->message); + g_free(state); +} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(PromptState, prompt_state_free) + +static void +prompt_password_done(GObject *source_object, GAsyncResult *res, + gpointer user_data) +{ + GcrPrompt *prompt = GCR_PROMPT(source_object); + PromptState *state = user_data; + g_autoptr(GError) error = NULL; + + /* + * “The returned password is valid until the next time a method + * is called to display another prompt.” + */ + const char *pw = gcr_prompt_password_finish(prompt, res, &error); + + if ((!pw && !error) || (error && error->code == G_IO_ERROR_CANCELLED)) { + /* Operation was cancelled or timed out. */ + state->exit_status = -1; + } else if (error) { + warnx("Failed to prompt for ssh-askpass: %s", error->message); + state->exit_status = 1; + } else { + /* Report passphrase if user selected Continue. */ + g_autofree char *local = g_locale_from_utf8(pw, strlen(pw), + NULL, NULL, NULL); + + if (local != NULL) { + puts(local); + memset(local, '\0', strlen(local)); + } else { + puts(pw); + } + state->exit_status = 0; + } + + g_application_release(state->app); +} + +static void +prompt_confirm_done(GObject *source_object, GAsyncResult *res, + gpointer user_data) +{ + GcrPrompt *prompt = GCR_PROMPT(source_object); + PromptState *state = user_data; + g_autoptr(GError) error = NULL; + + GcrPromptReply reply = gcr_prompt_confirm_finish(prompt, res, &error); + if (error) { + if (error->code == G_IO_ERROR_CANCELLED) { + /* Operation was cancelled or timed out. */ + state->exit_status = -1; + } else { + state->exit_status = 1; + warnx("Failed to prompt for ssh-askpass: %s", + error->message); + } + } else if (reply == GCR_PROMPT_REPLY_CONTINUE || + state->type == PROMPT_NONE) { + /* + * Since Gcr doesn’t yet support one button message + * boxes treat Cancel the same as Continue. + */ + state->exit_status = 0; + } else { + /* GCR_PROMPT_REPLY_CANCEL */ + state->exit_status = -1; + } + + g_application_release(state->app); +} + +static int +command_line(GApplication* app, G_GNUC_UNUSED GApplicationCommandLine *cmdline, + gpointer user_data) +{ + PromptState *state = user_data; + + /* Prevent app from exiting while waiting for the async callback. */ + g_application_hold(app); + + /* Wait indefinitely. */ + int timeout_seconds = -1; + g_autoptr(GError) error = NULL; + GcrPrompt* prompt = gcr_system_prompt_open(timeout_seconds, NULL, &error); + + if (!prompt) { + if (error->code == GCR_SYSTEM_PROMPT_IN_PROGRESS) { + /* + * This means the timeout elapsed, but no prompt + * was ever shown. + */ + warnx("Timeout: the Gcr system prompter was " + "already in use."); + } else { + warnx("Couldn’t create prompt for ssh-askpass: %s", + error->message); + } + + return 1; + } + + gcr_prompt_set_message(prompt, "OpenSSH"); + gcr_prompt_set_description(prompt, state->message); + + /* + * XXX: Remove the Cancel button for PROMPT_NONE when GCR + * supports that. + */ + if (state->type == PROMPT_ENTRY) { + gcr_prompt_password_async(prompt, NULL, prompt_password_done, state); + } else { + gcr_prompt_confirm_async(prompt, NULL, prompt_confirm_done, state); + } + + /* The exit status will be changed in the async callbacks. */ + return 1; +} + +int +main(int argc, char **argv) +{ + g_autoptr(GApplication) app = g_application_new( + "com.openssh.gnome-ssh-askpass4", + G_APPLICATION_HANDLES_COMMAND_LINE); + g_autofree char *message = NULL; + + if (argc > 1) { + message = g_strjoinv(" ", argv + 1); + } else { + message = g_strdup("Enter your OpenSSH passphrase:"); + } + + const char *prompt_mode = getenv("SSH_ASKPASS_PROMPT"); + PromptType type = PROMPT_ENTRY; + if (prompt_mode != NULL) { + if (strcasecmp(prompt_mode, "confirm") == 0) { + type = PROMPT_CONFIRM; + } else if (strcasecmp(prompt_mode, "none") == 0) { + type = PROMPT_NONE; + } + } + + g_autoptr(PromptState) state = prompt_state_new(app, message, type); + + g_signal_connect(app, "command-line", G_CALLBACK(command_line), state); + + /* + * Since we are calling g_application_hold, we cannot use + * g_application_command_line_set_exit_status. + * To change the exit status returned by g_application_run: + * “If the commandline invocation results in the mainloop running + * (ie: because the use-count of the application increased to a + * non-zero value) then the application is considered to have been + * ‘successful’ in a certain sense, and the exit status is always + * zero.” + */ + (void)(g_application_run(app, argc, argv)); + + return state->exit_status; +} diff --git a/contrib/redhat/openssh.spec b/contrib/redhat/openssh.spec index 74116b485135..a8fe2ecd0620 100644 --- a/contrib/redhat/openssh.spec +++ b/contrib/redhat/openssh.spec @@ -1,4 +1,4 @@ -%global ver 10.0p1 +%global ver 10.1p1 %global rel 1%{?dist} # OpenSSH privilege separation requires a user & group ID @@ -281,20 +281,6 @@ 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 @@ -367,6 +353,7 @@ fi %defattr(-,root,root) %dir %attr(0111,root,root) %{_var}/empty/sshd %attr(0755,root,root) %{_sbindir}/sshd +%attr(0755,root,root) %{_libexecdir}/openssh/sshd-auth %attr(0755,root,root) %{_libexecdir}/openssh/sshd-session %attr(0755,root,root) %{_libexecdir}/openssh/sftp-server %attr(0644,root,root) %{_mandir}/man8/sshd.8* diff --git a/contrib/redhat/sshd.init b/contrib/redhat/sshd.init index 8ee5fcd3bb4f..b82545956ac8 100755 --- a/contrib/redhat/sshd.init +++ b/contrib/redhat/sshd.init @@ -41,7 +41,7 @@ start() /usr/bin/ssh-keygen -A if [ -x /sbin/restorecon ]; then /sbin/restorecon /etc/ssh/ssh_host_rsa_key.pub - /sbin/restorecon /etc/ssh/ssh_host_dsa_key.pub + /sbin/restorecon /etc/ssh/ssh_host_ed25519_key.pub /sbin/restorecon /etc/ssh/ssh_host_ecdsa_key.pub fi diff --git a/contrib/ssh-copy-id b/contrib/ssh-copy-id index dcf579843a74..afb9beca497d 100644 --- a/contrib/ssh-copy-id +++ b/contrib/ssh-copy-id @@ -1,12 +1,14 @@ #!/bin/sh -# Copyright (c) 1999-2024 Philip Hands +# Copyright (c) 1999-2025 Philip Hands +# 2025 Denis Ovsienko +# 2024 Frank Fischer # 2021 Carlos Rodríguez Gili # 2020 Matthias Blümel # 2017 Sebastien Boyron # 2013 Martin Kletzander # 2010 Adeodato =?iso-8859-1?Q?Sim=F3?= -# 2010 Eric Moret +# 2010 Eric Moret # 2009 Xr # 2007 Justin Pryzby # 2004 Reini Urban @@ -284,14 +286,17 @@ installkeys_sh() { # the -z `tail ...` checks for a trailing newline. The echo adds one if was missing # the cat adds the keys we're getting via STDIN # and if available restorecon is used to restore the SELinux context - # OpenWrt has a special case for root only. - INSTALLKEYS_SH=$(tr '\t\n' ' ' <<-EOF + # OpenWrt has a special case for root/UID:0. Haiku is also special. + INSTALLKEYS_SH=$(tr -s '\t\n' ' ' <<-EOF $SET_X cd; umask 077; AUTH_KEY_FILE="${TARGET_PATH}"; - [ -f /etc/openwrt_release ] && [ "\$LOGNAME" = "root" ] && + [ -f /etc/openwrt_release ] && + { [ "\$LOGNAME" = "root" ] || [ "\$(id -u)" = "0" ]; } && AUTH_KEY_FILE=/etc/dropbear/authorized_keys; + [ "\`uname -s\`" = "Haiku" ] && + AUTH_KEY_FILE=config/settings/ssh/authorized_keys; AUTH_KEY_DIR=\`dirname "\${AUTH_KEY_FILE}"\`; mkdir -p "\${AUTH_KEY_DIR}" && { [ -z "\`tail -1c "\${AUTH_KEY_FILE}" 2>/dev/null\`" ] || diff --git a/contrib/suse/openssh.spec b/contrib/suse/openssh.spec index 849e9b61f3b8..63ea57064d10 100644 --- a/contrib/suse/openssh.spec +++ b/contrib/suse/openssh.spec @@ -13,7 +13,7 @@ Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation Name: openssh -Version: 10.0p1 +Version: 10.1p1 URL: https://www.openssh.com/ Release: 1 Source0: openssh-%{version}.tar.gz @@ -211,6 +211,7 @@ rm -rf $RPM_BUILD_ROOT %attr(0755,root,root) %{_sbindir}/sshd %attr(0755,root,root) %dir %{_libdir}/ssh %attr(0755,root,root) %{_libdir}/ssh/sftp-server +%attr(0755,root,root) %{_libdir}/ssh/sshd-auth %attr(0755,root,root) %{_libdir}/ssh/sshd-session %attr(4711,root,root) %{_libdir}/ssh/ssh-keysign %attr(0755,root,root) %{_libdir}/ssh/ssh-pkcs11-helper diff --git a/contrib/win32/openssh/config.h.vs b/contrib/win32/openssh/config.h.vs index 3a19ea051ca9..3de8b5b4fb48 100644 --- a/contrib/win32/openssh/config.h.vs +++ b/contrib/win32/openssh/config.h.vs @@ -352,7 +352,9 @@ /* #undef HAVE_DIRENT_H */ /* Define to 1 if you have the `dirfd' function. */ -/* #undef HAVE_DIRFD */ +/* Defined on Windows to suppress upstream's dirfd() compat prototype which + * pulls in and conflicts with the win32compat mkdir macro mapping. */ +#define HAVE_DIRFD 1 /* Define to 1 if you have the `dirname' function. */ /* #define HAVE_DIRNAME 1 */ @@ -1391,6 +1393,9 @@ with an extra level of indirection */ /* #undef PAM_SUN_CODEBASE */ +/* need inet in pledge for setsockopt IP_TOS; not required on Windows (pledge is a no-op) */ +#define PLEDGE_EXTRA_INET + /* Work around problematic Linux PAM modules handling of PAM_TTY */ /* #undef PAM_TTY_KLUDGE */ diff --git a/contrib/win32/openssh/libssh.vcxproj b/contrib/win32/openssh/libssh.vcxproj index c6cfe93058f3..f2b5e634465d 100644 --- a/contrib/win32/openssh/libssh.vcxproj +++ b/contrib/win32/openssh/libssh.vcxproj @@ -177,7 +177,7 @@ x64-custom arm-custom arm64-custom - --overlay-triplets=$(SolutionDir)vcpkg_triplets --overlay-ports=$(SolutionDir)vcpkg_overlay_ports + $(VcpkgAdditionalInstallOptions) --overlay-triplets=$(SolutionDir)vcpkg_triplets --overlay-ports=$(SolutionDir)vcpkg_overlay_ports true @@ -422,9 +422,6 @@ - - true - true diff --git a/contrib/win32/openssh/sshd-auth.vcxproj b/contrib/win32/openssh/sshd-auth.vcxproj index fd3a28e06214..40b2e7cb6b5b 100644 --- a/contrib/win32/openssh/sshd-auth.vcxproj +++ b/contrib/win32/openssh/sshd-auth.vcxproj @@ -474,6 +474,7 @@ + diff --git a/contrib/win32/openssh/sshd-session.vcxproj b/contrib/win32/openssh/sshd-session.vcxproj index 45895f0e1bf2..75630f07ebaa 100644 --- a/contrib/win32/openssh/sshd-session.vcxproj +++ b/contrib/win32/openssh/sshd-session.vcxproj @@ -476,6 +476,7 @@ + diff --git a/contrib/win32/openssh/unittest-misc.vcxproj b/contrib/win32/openssh/unittest-misc.vcxproj index 51ad471ecb6a..c4689d7e2388 100644 --- a/contrib/win32/openssh/unittest-misc.vcxproj +++ b/contrib/win32/openssh/unittest-misc.vcxproj @@ -186,7 +186,7 @@ x64-custom arm-custom arm64-custom - --overlay-triplets=$(SolutionDir)vcpkg_triplets --overlay-ports=$(SolutionDir)vcpkg_overlay_ports + $(VcpkgAdditionalInstallOptions) --overlay-triplets=$(SolutionDir)vcpkg_triplets --overlay-ports=$(SolutionDir)vcpkg_overlay_ports true @@ -431,6 +431,12 @@ true + + true + + + true + true diff --git a/contrib/win32/openssh/version.rc b/contrib/win32/openssh/version.rc index 6436c00e398f..2f0bab437a7a 100644 --- a/contrib/win32/openssh/version.rc +++ b/contrib/win32/openssh/version.rc @@ -51,8 +51,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 10,0,0,0 - PRODUCTVERSION 10,0,0,0 + FILEVERSION 10,1,0,0 + PRODUCTVERSION 10,1,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -67,9 +67,9 @@ BEGIN BEGIN BLOCK "040904b0" BEGIN - VALUE "FileVersion", "10.0.0.0" + VALUE "FileVersion", "10.1.0.0" VALUE "ProductName", "OpenSSH for Windows" - VALUE "ProductVersion", "OpenSSH_10.0p2 for Windows" + VALUE "ProductVersion", "OpenSSH_10.1p1 for Windows" END END BLOCK "VarFileInfo" diff --git a/contrib/win32/win32compat/inc/sys/stat.h b/contrib/win32/win32compat/inc/sys/stat.h index 5e654fa7053b..69c9e7441dba 100644 --- a/contrib/win32/win32compat/inc/sys/stat.h +++ b/contrib/win32/win32compat/inc/sys/stat.h @@ -16,6 +16,10 @@ #define S_IFLNK _S_IFLNK #define S_IFSOCK _S_IFSOCK +#ifndef S_ISSOCK +#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +#endif + # define S_ISUID 0x800 # define S_ISGID 0x400 diff --git a/contrib/win32/win32compat/w32-doexec.c b/contrib/win32/win32compat/w32-doexec.c index f996f7ebe5e0..32defa6bc22b 100644 --- a/contrib/win32/win32compat/w32-doexec.c +++ b/contrib/win32/win32compat/w32-doexec.c @@ -473,15 +473,9 @@ int do_exec_windows(struct ssh *ssh, Session *s, const char *command, int pty) { * handle the case that fdin and fdout are the same. */ if (pty) { - /* Set interactive/non-interactive mode */ - ssh_packet_set_interactive(ssh, 1, options.ip_qos_interactive, - options.ip_qos_bulk); session_set_fds(ssh, s, pipein[1], pipeout[0], -1, 1, 1); } else { - /* Set interactive/non-interactive mode */ - ssh_packet_set_interactive(ssh, s->display != NULL, options.ip_qos_interactive, - options.ip_qos_bulk); session_set_fds(ssh, s, pipein[1], pipeout[0], pipeerr[0], s->is_subsystem, 0); } diff --git a/crypto_api.h b/crypto_api.h index 8bbc3a08aaeb..693b67bbc0e7 100644 --- a/crypto_api.h +++ b/crypto_api.h @@ -10,9 +10,7 @@ #include "includes.h" -#ifdef HAVE_STDINT_H -# include -#endif +#include #include typedef int8_t crypto_int8; diff --git a/defines.h b/defines.h index d2baeb9407bd..a1bd6fad345e 100644 --- a/defines.h +++ b/defines.h @@ -515,6 +515,13 @@ struct winsize { } while (0) #endif +#ifndef timespeccmp +#define timespeccmp(tsp, usp, cmp) \ + (((tsp)->tv_sec == (usp)->tv_sec) ? \ + ((tsp)->tv_nsec cmp (usp)->tv_nsec) : \ + ((tsp)->tv_sec cmp (usp)->tv_sec)) +#endif + #ifndef TIMEVAL_TO_TIMESPEC #define TIMEVAL_TO_TIMESPEC(tv, ts) { \ (ts)->tv_sec = (tv)->tv_sec; \ @@ -986,4 +993,11 @@ struct winsize { /* The ML-KEM768 implementation also uses C89 features */ # define USE_MLKEM768X25519 1 #endif + +#if defined(HAVE_DECL_INFINITY) && HAVE_DECL_INFINITY == 0 +# if defined(HAVE_DECL___BUILTIN_INFF) && HAVE_DECL___BUILTIN_INFF == 1 +# define INFINITY __builtin_inff() +# endif +#endif + #endif /* _DEFINES_H */ diff --git a/digest-libc.c b/digest-libc.c index 6e77a4492dd4..b187bc9faf2c 100644 --- a/digest-libc.c +++ b/digest-libc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: digest-libc.c,v 1.7 2020/02/26 13:40:09 jsg Exp $ */ +/* $OpenBSD: digest-libc.c,v 1.8 2025/09/05 09:31:31 dtucker Exp $ */ /* * Copyright (c) 2013 Damien Miller * Copyright (c) 2014 Markus Friedl. All rights reserved. @@ -27,7 +27,6 @@ #if 0 #include -#include #endif #ifdef HAVE_SHA1_H #include diff --git a/dispatch.c b/dispatch.c index 6118147bf140..430b6afda1d3 100644 --- a/dispatch.c +++ b/dispatch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dispatch.c,v 1.33 2023/03/05 05:34:09 dtucker Exp $ */ +/* $OpenBSD: dispatch.c,v 1.34 2025/05/21 06:44:24 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -41,7 +41,7 @@ dispatch_protocol_error(int type, u_int32_t seq, struct ssh *ssh) { int r; - logit("dispatch_protocol_error: type %d seq %u", type, seq); + logit_f("type %d seq %u", type, seq); if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || (r = sshpkt_put_u32(ssh, seq)) != 0 || (r = sshpkt_send(ssh)) != 0 || @@ -53,7 +53,7 @@ dispatch_protocol_error(int type, u_int32_t seq, struct ssh *ssh) int dispatch_protocol_ignore(int type, u_int32_t seq, struct ssh *ssh) { - logit("dispatch_protocol_ignore: type %d seq %u", type, seq); + logit_f("type %d seq %u", type, seq); return 0; } diff --git a/dns.c b/dns.c index 939241440777..e8693cee8313 100644 --- a/dns.c +++ b/dns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dns.c,v 1.44 2023/03/10 04:06:21 dtucker Exp $ */ +/* $OpenBSD: dns.c,v 1.46 2025/08/29 03:50:38 djm Exp $ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. @@ -88,18 +88,12 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, case KEY_RSA: *algorithm = SSHFP_KEY_RSA; break; - case KEY_DSA: - *algorithm = SSHFP_KEY_DSA; - break; case KEY_ECDSA: *algorithm = SSHFP_KEY_ECDSA; break; case KEY_ED25519: *algorithm = SSHFP_KEY_ED25519; break; - case KEY_XMSS: - *algorithm = SSHFP_KEY_XMSS; - break; default: *algorithm = SSHFP_KEY_RESERVED; /* 0 */ } diff --git a/dns.h b/dns.h index 864ab7d00ac7..ab2df061e987 100644 --- a/dns.h +++ b/dns.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dns.h,v 1.20 2023/02/10 04:56:30 djm Exp $ */ +/* $OpenBSD: dns.h,v 1.21 2025/08/29 03:50:38 djm Exp $ */ /* * Copyright (c) 2003 Wesley Griffin. All rights reserved. @@ -33,8 +33,7 @@ enum sshfp_types { SSHFP_KEY_RSA = 1, SSHFP_KEY_DSA = 2, SSHFP_KEY_ECDSA = 3, - SSHFP_KEY_ED25519 = 4, - SSHFP_KEY_XMSS = 5 + SSHFP_KEY_ED25519 = 4 }; enum sshfp_hashes { diff --git a/groupaccess.c b/groupaccess.c index 9d03ded0cd5d..046d0e6bcaf9 100644 --- a/groupaccess.c +++ b/groupaccess.c @@ -50,21 +50,32 @@ int ga_init(const char *user, gid_t base) { gid_t *groups_bygid; - int i, j, retry = 0; + int ongroups, i, j, retry = 0; struct group *gr; if (ngroups > 0) ga_free(); - ngroups = NGROUPS_MAX; + ongroups = ngroups = NGROUPS_MAX; #if defined(HAVE_SYSCONF) && defined(_SC_NGROUPS_MAX) - ngroups = MAX(NGROUPS_MAX, sysconf(_SC_NGROUPS_MAX)); + ongroups = ngroups = MAX(NGROUPS_MAX, sysconf(_SC_NGROUPS_MAX)); #endif groups_bygid = xcalloc(ngroups, sizeof(*groups_bygid)); while (getgrouplist(user, base, groups_bygid, &ngroups) == -1) { - if (retry++ > 0) - fatal("getgrouplist: groups list too small"); + if (ngroups <= ongroups) { + error("getgrouplist(\"%s\", %ld): failed", + user, (long)base); + free(groups_bygid); + groups_bygid = NULL; + ngroups = 0; + return 0; + } + if (retry++ > 0) { + fatal("getgrouplist(\"%s\", %ld): groups list too big " + "(have %ld, need %ld)", user, (long)base, + (long)ongroups, (long)ngroups); + } groups_bygid = xreallocarray(groups_bygid, ngroups, sizeof(*groups_bygid)); } diff --git a/gss-genr.c b/gss-genr.c index aa34b71c5558..8f1f54afb4be 100644 --- a/gss-genr.c +++ b/gss-genr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gss-genr.c,v 1.29 2024/02/01 02:37:33 djm Exp $ */ +/* $OpenBSD: gss-genr.c,v 1.30 2025/09/29 21:28:33 dtucker Exp $ */ /* * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. diff --git a/gss-serv.c b/gss-serv.c index 0dd35752a407..7ea141412ba7 100644 --- a/gss-serv.c +++ b/gss-serv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gss-serv.c,v 1.32 2020/03/13 03:17:07 djm Exp $ */ +/* $OpenBSD: gss-serv.c,v 1.33 2025/09/29 21:30:15 dtucker Exp $ */ /* * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. diff --git a/hmac.c b/hmac.c index 7b588019e74b..8641edf4a6b3 100644 --- a/hmac.c +++ b/hmac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hmac.c,v 1.14 2020/02/26 13:40:09 jsg Exp $ */ +/* $OpenBSD: hmac.c,v 1.15 2025/09/05 09:49:26 dtucker Exp $ */ /* * Copyright (c) 2014 Markus Friedl. All rights reserved. * diff --git a/hostfile.c b/hostfile.c index c5669c703735..4cec57da50c6 100644 --- a/hostfile.c +++ b/hostfile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hostfile.c,v 1.95 2023/02/21 06:48:18 dtucker Exp $ */ +/* $OpenBSD: hostfile.c,v 1.99 2025/05/06 05:40:56 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -150,8 +150,8 @@ host_hash(const char *host, const char *name_from_hostfile, u_int src_len) } /* - * Parses an RSA (number of bits, e, n) or DSA key from a string. Moves the - * pointer over the key. Skips any whitespace at the beginning and at end. + * Parses an RSA key from a string. Moves the pointer over the key. + * Skips any whitespace at the beginning and at end. */ int @@ -434,7 +434,7 @@ lookup_marker_in_hostkeys(struct hostkeys *hostkeys, int want_marker) } static int -write_host_entry(FILE *f, const char *host, const char *ip, +format_host_entry(struct sshbuf *entry, const char *host, const char *ip, const struct sshkey *key, int store_hash) { int r, success = 0; @@ -449,22 +449,50 @@ write_host_entry(FILE *f, const char *host, const char *ip, free(lhost); return 0; } - fprintf(f, "%s ", hashed_host); - } else if (ip != NULL) - fprintf(f, "%s,%s ", lhost, ip); - else { - fprintf(f, "%s ", lhost); + if ((r = sshbuf_putf(entry, "%s ", hashed_host)) != 0) + fatal_fr(r, "sshbuf_putf"); + } else if (ip != NULL) { + if ((r = sshbuf_putf(entry, "%s,%s ", lhost, ip)) != 0) + fatal_fr(r, "sshbuf_putf"); + } else { + if ((r = sshbuf_putf(entry, "%s ", lhost)) != 0) + fatal_fr(r, "sshbuf_putf"); } free(hashed_host); free(lhost); - if ((r = sshkey_write(key, f)) == 0) + if ((r = sshkey_format_text(key, entry)) == 0) success = 1; else error_fr(r, "sshkey_write"); - fputc('\n', f); + if ((r = sshbuf_putf(entry, "\n")) != 0) + fatal_fr(r, "sshbuf_putf"); + /* If hashing is enabled, the IP address needs to go on its own line */ if (success && store_hash && ip != NULL) - success = write_host_entry(f, ip, NULL, key, 1); + success = format_host_entry(entry, ip, NULL, key, 1); + return success; +} + +static int +write_host_entry(FILE *f, const char *host, const char *ip, + const struct sshkey *key, int store_hash) +{ + int r, success = 0; + struct sshbuf *entry = NULL; + + if ((entry = sshbuf_new()) == NULL) + fatal_f("allocation failed"); + if ((r = format_host_entry(entry, host, ip, key, store_hash)) != 1) { + debug_f("failed to format host entry"); + goto out; + } + if ((r = fwrite(sshbuf_ptr(entry), sshbuf_len(entry), 1, f)) != 1) { + error_f("fwrite: %s", strerror(errno)); + goto out; + } + success = 1; + out: + sshbuf_free(entry); return success; } @@ -520,9 +548,9 @@ add_host_to_hostfile(const char *filename, const char *host, if (key == NULL) return 1; /* XXX ? */ hostfile_create_user_ssh_dir(filename, 0); - f = fopen(filename, "a+"); - if (!f) + if ((f = fopen(filename, "a+")) == NULL) return 0; + setvbuf(f, NULL, _IONBF, 0); /* Make sure we have a terminating newline. */ if (fseek(f, -1L, SEEK_END) == 0 && fgetc(f) != '\n') addnl = 1; @@ -810,6 +838,12 @@ hostkeys_foreach_file(const char *path, FILE *f, hostkeys_foreach_fn *callback, /* Find the end of the host name portion. */ for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++) ; + if (*cp2 == '\0') { + verbose_f("truncated line at %s:%lu", path, linenum); + if ((options & HKF_WANT_MATCH) == 0) + goto bad; + continue; + } lineinfo.hosts = cp; *cp2++ = '\0'; diff --git a/kex-names.c b/kex-names.c index ec840c1f9dbc..a20ce602ab51 100644 --- a/kex-names.c +++ b/kex-names.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex-names.c,v 1.4 2024/09/09 02:39:57 djm Exp $ */ +/* $OpenBSD: kex-names.c,v 1.6 2025/09/02 11:08:34 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -50,65 +50,57 @@ struct kexalg { u_int type; int ec_nid; int hash_alg; + int pq_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 }, + { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1, KEX_NOT_PQ }, + { KEX_DH14_SHA1, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1, KEX_NOT_PQ }, + { KEX_DH14_SHA256, KEX_DH_GRP14_SHA256, 0, SSH_DIGEST_SHA256, KEX_NOT_PQ }, + { KEX_DH16_SHA512, KEX_DH_GRP16_SHA512, 0, SSH_DIGEST_SHA512, KEX_NOT_PQ }, + { KEX_DH18_SHA512, KEX_DH_GRP18_SHA512, 0, SSH_DIGEST_SHA512, KEX_NOT_PQ }, + { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1, KEX_NOT_PQ }, #ifdef HAVE_EVP_SHA256 - { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, + { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256, KEX_NOT_PQ }, #endif /* HAVE_EVP_SHA256 */ #ifdef OPENSSL_HAS_ECC { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, - NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, + NID_X9_62_prime256v1, SSH_DIGEST_SHA256, KEX_NOT_PQ }, { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, - SSH_DIGEST_SHA384 }, + SSH_DIGEST_SHA384, KEX_NOT_PQ }, # ifdef OPENSSL_HAS_NISTP521 { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, - SSH_DIGEST_SHA512 }, + SSH_DIGEST_SHA512, KEX_NOT_PQ }, # endif /* OPENSSL_HAS_NISTP521 */ #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ #if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL) - { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, - { KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, + { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256, KEX_NOT_PQ }, + { KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256, KEX_NOT_PQ }, #ifdef USE_SNTRUP761X25519 { KEX_SNTRUP761X25519_SHA512, KEX_KEM_SNTRUP761X25519_SHA512, 0, - SSH_DIGEST_SHA512 }, + SSH_DIGEST_SHA512, KEX_IS_PQ }, { KEX_SNTRUP761X25519_SHA512_OLD, KEX_KEM_SNTRUP761X25519_SHA512, 0, - SSH_DIGEST_SHA512 }, + SSH_DIGEST_SHA512, KEX_IS_PQ }, #endif #ifdef USE_MLKEM768X25519 { KEX_MLKEM768X25519_SHA256, KEX_KEM_MLKEM768X25519_SHA256, 0, - SSH_DIGEST_SHA256 }, + SSH_DIGEST_SHA256, KEX_IS_PQ }, #endif #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ - { NULL, 0, -1, -1}, + { NULL, 0, -1, -1, 0 }, }; char * kex_alg_list(char sep) { - char *ret = NULL, *tmp; - size_t nlen, rlen = 0; + char *ret = NULL; const struct kexalg *k; + char sep_str[2] = {sep, '\0'}; + + for (k = kexalgs; k->name != NULL; k++) + xextendf(&ret, sep_str, "%s", k->name); - 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; } @@ -130,6 +122,16 @@ kex_name_valid(const char *name) return kex_alg_by_name(name) != NULL; } +int +kex_is_pq_from_name(const char *name) +{ + const struct kexalg *k; + + if ((k = kex_alg_by_name(name)) == NULL) + return 0; + return k->pq_alg == KEX_IS_PQ; +} + u_int kex_type_from_name(const char *name) { diff --git a/kex.c b/kex.c index 1e70f66d59a9..29cee5fe31fb 100644 --- a/kex.c +++ b/kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.c,v 1.187 2024/08/23 04:51:00 deraadt Exp $ */ +/* $OpenBSD: kex.c,v 1.189 2025/09/15 04:40:34 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * @@ -33,9 +33,7 @@ #include #include #include -#ifdef HAVE_POLL_H #include -#endif #ifdef WITH_OPENSSL #include @@ -567,8 +565,6 @@ kex_input_newkeys(int type, u_int32_t seq, struct ssh *ssh) kex->flags &= ~KEX_INITIAL; sshbuf_reset(kex->peer); kex->flags &= ~KEX_INIT_SENT; - free(kex->name); - kex->name = NULL; return 0; } @@ -624,6 +620,8 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) error_f("no kex"); return SSH_ERR_INTERNAL_ERROR; } + free(kex->name); + kex->name = NULL; ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error); ptr = sshpkt_ptr(ssh, &dlen); if (ptr == NULL) { // fix CodeQL SM02313 @@ -750,6 +748,7 @@ kex_free(struct kex *kex) free(kex->failed_choice); free(kex->hostkey_alg); free(kex->name); + free(kex->server_sig_algs); free(kex); } diff --git a/kex.h b/kex.h index d08988b3e141..55baa6a1e641 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.126 2024/09/02 12:13:56 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.127 2025/08/11 10:55:38 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -115,6 +115,10 @@ enum kex_exchange { #define KEX_HAS_PING 0x0020 #define KEX_HAS_EXT_INFO_IN_AUTH 0x0040 +/* kex->pq */ +#define KEX_NOT_PQ 0 +#define KEX_IS_PQ 1 + struct sshenc { char *name; const struct sshcipher *cipher; @@ -189,6 +193,7 @@ int kex_name_valid(const char *); u_int kex_type_from_name(const char *); int kex_hash_from_name(const char *); int kex_nid_from_name(const char *); +int kex_is_pq_from_name(const char *); int kex_names_valid(const char *); char *kex_alg_list(char); char *kex_names_cat(const char *, const char *); diff --git a/kexdh.c b/kexdh.c index c1084f2146e1..191bdced09c7 100644 --- a/kexdh.c +++ b/kexdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdh.c,v 1.34 2020/12/04 02:29:25 djm Exp $ */ +/* $OpenBSD: kexdh.c,v 1.35 2025/10/03 00:08:02 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl. All rights reserved. * @@ -34,6 +34,7 @@ #include #include "openbsd-compat/openssl-compat.h" +#include #include #include "sshkey.h" diff --git a/kexecdh.c b/kexecdh.c index efb2e55a6d42..500ec5725edd 100644 --- a/kexecdh.c +++ b/kexecdh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdh.c,v 1.10 2019/01/21 10:40:11 djm Exp $ */ +/* $OpenBSD: kexecdh.c,v 1.11 2025/10/03 00:08:02 djm Exp $ */ /* * Copyright (c) 2010 Damien Miller. All rights reserved. * Copyright (c) 2019 Markus Friedl. All rights reserved. @@ -34,6 +34,7 @@ #include #include +#include #include #include "sshkey.h" diff --git a/kexgen.c b/kexgen.c index 40d688d62fda..494d4b233561 100644 --- a/kexgen.c +++ b/kexgen.c @@ -113,7 +113,7 @@ kex_gen_client(struct ssh *ssh) case KEX_ECDH_SHA2: r = kex_ecdh_keypair(kex); break; -#endif +#endif /* WITH_OPENSSL */ case KEX_C25519_SHA256: r = kex_c25519_keypair(kex); break; @@ -187,7 +187,7 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh) case KEX_ECDH_SHA2: r = kex_ecdh_dec(kex, server_blob, &shared_secret); break; -#endif +#endif /* WITH_OPENSSL */ case KEX_C25519_SHA256: r = kex_c25519_dec(kex, server_blob, &shared_secret); break; @@ -310,7 +310,7 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey, &shared_secret); break; -#endif +#endif /* WITH_OPENSSL */ case KEX_C25519_SHA256: r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, &shared_secret); diff --git a/kexgexc.c b/kexgexc.c index e99e0cf216e7..097d83f3072a 100644 --- a/kexgexc.c +++ b/kexgexc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexc.c,v 1.38 2021/12/19 22:08:06 djm Exp $ */ +/* $OpenBSD: kexgexc.c,v 1.39 2025/10/03 00:08:02 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -30,6 +30,8 @@ #include +#include "openbsd-compat/openssl-compat.h" +#include #include #include @@ -37,8 +39,6 @@ #include #include -#include "openbsd-compat/openssl-compat.h" - #include "sshkey.h" #include "cipher.h" #include "digest.h" diff --git a/kexgexs.c b/kexgexs.c index 100be0316d5a..d02cca6dcf82 100644 --- a/kexgexs.c +++ b/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.47 2024/05/17 00:30:23 djm Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.49 2025/10/03 00:09:26 djm Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -28,15 +28,14 @@ #ifdef WITH_OPENSSL - #include #include #include #include -#include - #include "openbsd-compat/openssl-compat.h" +#include +#include #include "sshkey.h" #include "cipher.h" diff --git a/kexmlkem768x25519.c b/kexmlkem768x25519.c index 2b5d39608238..7ade7a7f904f 100644 --- a/kexmlkem768x25519.c +++ b/kexmlkem768x25519.c @@ -28,9 +28,7 @@ #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include #include diff --git a/krl.c b/krl.c index 0d0f69534182..bea5b1b98c43 100644 --- a/krl.c +++ b/krl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: krl.c,v 1.60 2025/02/18 08:02:48 djm Exp $ */ +/* $OpenBSD: krl.c,v 1.62 2025/09/15 04:41:20 djm Exp $ */ /* * Copyright (c) 2012 Damien Miller * @@ -149,6 +149,8 @@ revoked_certs_free(struct revoked_certs *rc) struct revoked_serial *rs, *trs; struct revoked_key_id *rki, *trki; + if (rc == NULL) + return; RB_FOREACH_SAFE(rs, revoked_serial_tree, &rc->revoked_serials, trs) { RB_REMOVE(revoked_serial_tree, &rc->revoked_serials, rs); free(rs); @@ -159,6 +161,7 @@ revoked_certs_free(struct revoked_certs *rc) free(rki); } sshkey_free(rc->ca_key); + freezero(rc, sizeof(*rc)); } void diff --git a/log.c b/log.c index 0259f3f1efdb..ec73ea18fb24 100644 --- a/log.c +++ b/log.c @@ -1,4 +1,4 @@ -/* $OpenBSD: log.c,v 1.64 2024/12/07 10:05:36 djm Exp $ */ +/* $OpenBSD: log.c,v 1.65 2025/09/02 09:34:48 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -511,7 +511,7 @@ sshlogdirect(LogLevel level, int forced, const char *fmt, ...) * To prevent flipping in and out of rate-limiting, there is a hysteresis * timer that delays leaving the rate-limited state. * - * While in the rate-limited state, events can be periodically allowed though + * While in the rate-limited state, events can be periodically allowed through * and the number of dropped events since the last log obtained. * * XXX a moving average rate of events might be a better approach here rather diff --git a/loginrec.c b/loginrec.c index c4a9bd4853e3..af7588b34285 100644 --- a/loginrec.c +++ b/loginrec.c @@ -129,9 +129,7 @@ #include #include #include -#ifdef HAVE_SYS_TIME_H -# include -#endif +#include #include @@ -139,7 +137,7 @@ #include #include #ifdef HAVE_PATHS_H -# include +#include #endif #include #include @@ -853,7 +851,7 @@ utmp_write_direct(struct logininfo *li, struct utmp *ut) endttyent(); if (NULL == ty) { - logit("%s: tty not found", __func__); + logit_f("tty not found"); return (0); } #else /* FIXME */ @@ -867,7 +865,7 @@ utmp_write_direct(struct logininfo *li, struct utmp *ut) pos = (off_t)tty * sizeof(struct utmp); if ((ret = lseek(fd, pos, SEEK_SET)) == -1) { - logit("%s: lseek: %s", __func__, strerror(errno)); + logit_f("lseek: %s", strerror(errno)); close(fd); return (0); } @@ -889,7 +887,7 @@ utmp_write_direct(struct logininfo *li, struct utmp *ut) memcpy(ut->ut_host, old_ut.ut_host, sizeof(ut->ut_host)); if ((ret = lseek(fd, pos, SEEK_SET)) == -1) { - logit("%s: lseek: %s", __func__, strerror(errno)); + logit_f("lseek: %s", strerror(errno)); close(fd); return (0); } @@ -922,12 +920,12 @@ utmp_perform_login(struct logininfo *li) construct_utmp(li, &ut); # ifdef UTMP_USE_LIBRARY if (!utmp_write_library(li, &ut)) { - logit("%s: utmp_write_library() failed", __func__); + logit_f("utmp_write_library() failed"); return (0); } # else if (!utmp_write_direct(li, &ut)) { - logit("%s: utmp_write_direct() failed", __func__); + logit_f("utmp_write_direct() failed"); return (0); } # endif @@ -943,12 +941,12 @@ utmp_perform_logout(struct logininfo *li) construct_utmp(li, &ut); # ifdef UTMP_USE_LIBRARY if (!utmp_write_library(li, &ut)) { - logit("%s: utmp_write_library() failed", __func__); + logit_f("utmp_write_library() failed"); return (0); } # else if (!utmp_write_direct(li, &ut)) { - logit("%s: utmp_write_direct() failed", __func__); + logit_f("utmp_write_direct() failed"); return (0); } # endif @@ -967,7 +965,7 @@ utmp_write_entry(struct logininfo *li) return (utmp_perform_logout(li)); default: - logit("%s: invalid type field", __func__); + logit_f("invalid type field"); return (0); } } @@ -1008,7 +1006,7 @@ utmpx_write_library(struct logininfo *li, struct utmpx *utx) static int utmpx_write_direct(struct logininfo *li, struct utmpx *utx) { - logit("%s: not implemented!", __func__); + logit_f("not implemented!"); return (0); } # endif /* UTMPX_USE_LIBRARY */ @@ -1021,12 +1019,12 @@ utmpx_perform_login(struct logininfo *li) construct_utmpx(li, &utx); # ifdef UTMPX_USE_LIBRARY if (!utmpx_write_library(li, &utx)) { - logit("%s: utmp_write_library() failed", __func__); + logit_f("utmp_write_library() failed"); return (0); } # else if (!utmpx_write_direct(li, &utx)) { - logit("%s: utmp_write_direct() failed", __func__); + logit_f("utmp_write_direct() failed"); return (0); } # endif @@ -1064,7 +1062,7 @@ utmpx_write_entry(struct logininfo *li) case LTYPE_LOGOUT: return (utmpx_perform_logout(li)); default: - logit("%s: invalid type field", __func__); + logit_f("invalid type field"); return (0); } } @@ -1132,7 +1130,7 @@ wtmp_write_entry(struct logininfo *li) case LTYPE_LOGOUT: return (wtmp_perform_logout(li)); default: - logit("%s: invalid type field", __func__); + logit_f("invalid type field"); return (0); } } @@ -1311,7 +1309,7 @@ wtmpx_write_entry(struct logininfo *li) case LTYPE_LOGOUT: return (wtmpx_perform_logout(li)); default: - logit("%s: invalid type field", __func__); + logit_f("invalid type field"); return (0); } } @@ -1453,7 +1451,7 @@ wtmpdb_write_entry(struct logininfo *li) case LTYPE_LOGOUT: return (wtmpdb_perform_logout(li)); default: - logit("%s: invalid type field", __func__); + logit_f("invalid type field"); return (0); } } @@ -1486,7 +1484,7 @@ syslogin_perform_logout(struct logininfo *li) (void)line_stripname(line, li->line, sizeof(line)); if (!logout(line)) - logit("%s: logout() returned an error", __func__); + logit_f("logout() returned an error"); # ifdef HAVE_LOGWTMP else logwtmp(line, "", ""); @@ -1508,7 +1506,7 @@ syslogin_write_entry(struct logininfo *li) case LTYPE_LOGOUT: return (syslogin_perform_logout(li)); default: - logit("%s: Invalid type field", __func__); + logit_f("Invalid type field"); return (0); } } @@ -1612,7 +1610,7 @@ lastlog_write_entry(struct logininfo *li) close(fd); return (1); default: - logit("%s: Invalid type field", __func__); + logit_f("Invalid type field"); return (0); } } @@ -1704,7 +1702,7 @@ utmpx_get_entry(struct logininfo *li) /* * Logs failed login attempts in _PATH_BTMP if that exists. * The most common login failure is to give password instead of username. - * So the _PATH_BTMP file checked for the correct permission, so that only + * So the _PATH_BTMP file is checked for the correct permission, so that only * root can read it. */ void diff --git a/logintest.c b/logintest.c index 6ee1cdc23645..1056bba0e73a 100644 --- a/logintest.c +++ b/logintest.c @@ -41,9 +41,7 @@ #include #include #include -#ifdef HAVE_TIME_H #include -#endif #include "loginrec.h" diff --git a/m4/openssh.m4 b/m4/openssh.m4 index 176a8d1c9282..f420146f1442 100644 --- a/m4/openssh.m4 +++ b/m4/openssh.m4 @@ -62,7 +62,8 @@ 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]) + ossh_cache_var=AS_TR_SH([ossh_cv_cflag_$1]) + AC_CACHE_CHECK([if $CC supports compile flag $1], [$ossh_cache_var], [ saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR $1" _define_flag="$2" @@ -71,22 +72,23 @@ AC_DEFUN([OSSH_CHECK_CFLAG_COMPILE], [{ [ if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - AC_MSG_RESULT([no]) + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else dnl If we are compiling natively, try running the program. AC_RUN_IFELSE([OSSH_COMPILER_FLAG_TEST_PROGRAM], - [ AC_MSG_RESULT([yes]) + [ eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" ], - [ AC_MSG_RESULT([no, fails at run time]) + [ eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" ], - [ AC_MSG_RESULT([yes]) + [ eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" ], ) fi], - [ AC_MSG_RESULT([no]) + [ eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" ] ) + ]) }]) dnl OSSH_CHECK_CFLAG_LINK(check_flag[, define_flag]) @@ -94,7 +96,8 @@ 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]) + ossh_cache_var=AS_TR_SH([ossh_cv_cflag_$1]) + AC_CACHE_CHECK([if $CC supports compile flag $1 and linking succeeds], [$ossh_cache_var], [ saved_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $WERROR $1" _define_flag="$2" @@ -103,22 +106,23 @@ AC_DEFUN([OSSH_CHECK_CFLAG_LINK], [{ [ if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - AC_MSG_RESULT([no]) + eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" else dnl If we are compiling natively, try running the program. AC_RUN_IFELSE([OSSH_COMPILER_FLAG_TEST_PROGRAM], - [ AC_MSG_RESULT([yes]) + [ eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" ], - [ AC_MSG_RESULT([no, fails at run time]) + [ eval "$ossh_cache_var='no, fails at run time'" CFLAGS="$saved_CFLAGS" ], - [ AC_MSG_RESULT([yes]) + [ eval "$ossh_cache_var=yes" CFLAGS="$saved_CFLAGS $_define_flag" ], ) fi], - [ AC_MSG_RESULT([no]) + [ eval "$ossh_cache_var=no" CFLAGS="$saved_CFLAGS" ] ) + ]) }]) dnl OSSH_CHECK_LDFLAG_LINK(check_flag[, define_flag]) @@ -126,7 +130,8 @@ 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]) + ossh_cache_var=AS_TR_SH([ossh_cv_ldflag_$1]) + AC_CACHE_CHECK([if $LD supports link flag $1], [$ossh_cache_var], [ saved_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $WERROR $1" _define_flag="$2" @@ -135,22 +140,23 @@ AC_DEFUN([OSSH_CHECK_LDFLAG_LINK], [{ [ if $ac_cv_path_EGREP -i "unrecognized option|warning.*ignored" conftest.err >/dev/null then - AC_MSG_RESULT([no]) + eval "$ossh_cache_var=no" LDFLAGS="$saved_LDFLAGS" else dnl If we are compiling natively, try running the program. AC_RUN_IFELSE([OSSH_COMPILER_FLAG_TEST_PROGRAM], - [ AC_MSG_RESULT([yes]) + [ eval "$ossh_cache_var=yes" LDFLAGS="$saved_LDFLAGS $_define_flag" ], - [ AC_MSG_RESULT([no, fails at run time]) + [ eval "$ossh_cache_var='no, fails at run time'" LDFLAGS="$saved_LDFLAGS" ], - [ AC_MSG_RESULT([yes]) + [ eval "$ossh_cache_var=yes" LDFLAGS="$saved_LDFLAGS $_define_flag" ] ) fi ], - [ AC_MSG_RESULT([no]) + [ eval "$ossh_cache_var=no" LDFLAGS="$saved_LDFLAGS" ] ) + ]) }]) dnl OSSH_CHECK_HEADER_FOR_FIELD(field, header, symbol) diff --git a/mac.c b/mac.c index f3dda6692866..c95f5ea06856 100644 --- a/mac.c +++ b/mac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mac.c,v 1.35 2019/09/06 04:53:27 djm Exp $ */ +/* $OpenBSD: mac.c,v 1.37 2025/09/05 10:01:35 dtucker Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -27,9 +27,9 @@ #include +#include #include #include -#include #include "digest.h" #include "hmac.h" @@ -83,22 +83,13 @@ static const struct macalg macs[] = { char * mac_alg_list(char sep) { - char *ret = NULL, *tmp; - size_t nlen, rlen = 0; + char *ret = NULL; const struct macalg *m; + char sep_str[2] = {sep, '\0'}; + + for (m = macs; m->name != NULL; m++) + xextendf(&ret, sep_str, "%s", m->name); - for (m = macs; m->name != NULL; m++) { - if (ret != NULL) - ret[rlen++] = sep; - nlen = strlen(m->name); - if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) { - free(ret); - return NULL; - } - ret = tmp; - memcpy(ret + rlen, m->name, nlen + 1); - rlen += nlen; - } return ret; } diff --git a/misc-agent.c b/misc-agent.c new file mode 100644 index 000000000000..07c8fb136ec4 --- /dev/null +++ b/misc-agent.c @@ -0,0 +1,357 @@ +/* $OpenBSD: misc-agent.c,v 1.6 2025/06/17 01:19:27 djm Exp $ */ +/* + * Copyright (c) 2025 Damien Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "includes.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "digest.h" +#include "log.h" +#include "misc.h" +#include "pathnames.h" +#include "ssh.h" +#include "xmalloc.h" + +/* stuff shared by agent listeners (ssh-agent and sshd agent forwarding) */ + +#define SOCKET_HOSTNAME_HASHLEN 10 /* length of hostname hash in socket path */ + +/* used for presenting random strings in unix_listener_tmp and hostname_hash */ +static const char presentation_chars[] = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +/* returns a text-encoded hash of the hostname of specified length (max 64) */ +static char * +hostname_hash(size_t len) +{ + char hostname[NI_MAXHOST], p[65]; + u_char hash[64]; + int r; + size_t l, i; + + l = ssh_digest_bytes(SSH_DIGEST_SHA512); + if (len > 64) { + error_f("bad length %zu >= max %zd", len, l); + return NULL; + } + if (gethostname(hostname, sizeof(hostname)) == -1) { + error_f("gethostname: %s", strerror(errno)); + return NULL; + } + if ((r = ssh_digest_memory(SSH_DIGEST_SHA512, + hostname, strlen(hostname), hash, sizeof(hash))) != 0) { + error_fr(r, "ssh_digest_memory"); + return NULL; + } + memset(p, '\0', sizeof(p)); + for (i = 0; i < l; i++) + p[i] = presentation_chars[ + hash[i] % (sizeof(presentation_chars) - 1)]; + /* debug3_f("hostname \"%s\" => hash \"%s\"", hostname, p); */ + p[len] = '\0'; + return xstrdup(p); +} + +char * +agent_hostname_hash(void) +{ + return hostname_hash(SOCKET_HOSTNAME_HASHLEN); +} + +/* + * Creates a unix listener at a mkstemp(3)-style path, e.g. "/dir/sock.XXXXXX" + * Supplied path is modified to the actual one used. + */ +static int +unix_listener_tmp(char *path, int backlog) +{ + struct sockaddr_un sunaddr; + int good, sock = -1; + size_t i, xstart; + mode_t prev_mask; + + /* Find first 'X' template character back from end of string */ + xstart = strlen(path); + while (xstart > 0 && path[xstart - 1] == 'X') + xstart--; + + memset(&sunaddr, 0, sizeof(sunaddr)); + sunaddr.sun_family = AF_UNIX; + prev_mask = umask(0177); + for (good = 0; !good;) { + sock = -1; + /* Randomise path suffix */ + for (i = xstart; path[i] != '\0'; i++) { + path[i] = presentation_chars[ + arc4random_uniform(sizeof(presentation_chars)-1)]; + } + debug_f("trying path \"%s\"", path); + + 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); + break; + } + + if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) { + error_f("socket: %.100s", strerror(errno)); + break; + } + if (bind(sock, (struct sockaddr *)&sunaddr, + sizeof(sunaddr)) == -1) { + if (errno == EADDRINUSE) { + error_f("bind \"%s\": %.100s", + path, strerror(errno)); + close(sock); + sock = -1; + continue; + } + error_f("bind \"%s\": %.100s", path, strerror(errno)); + break; + } + if (listen(sock, backlog) == -1) { + error_f("listen \"%s\": %s", path, strerror(errno)); + break; + } + good = 1; + } + umask(prev_mask); + if (good) { + debug3_f("listening on unix socket \"%s\" as fd=%d", + path, sock); + } else if (sock != -1) { + close(sock); + sock = -1; + } + return sock; +} + +/* + * Create a subdirectory under the supplied home directory if it + * doesn't already exist + */ +static int +ensure_mkdir(const char *homedir, const char *subdir) +{ + char *path; + + xasprintf(&path, "%s/%s", homedir, subdir); + if (mkdir(path, 0700) == 0) + debug("created directory %s", path); + else if (errno != EEXIST) { + error_f("mkdir %s: %s", path, strerror(errno)); + free(path); + return -1; + } + free(path); + return 0; +} + +static int +agent_prepare_sockdir(const char *homedir) +{ + if (homedir == NULL || *homedir == '\0' || + ensure_mkdir(homedir, _PATH_SSH_USER_DIR) != 0 || + ensure_mkdir(homedir, _PATH_SSH_AGENT_SOCKET_DIR) != 0) + return -1; + return 0; +} + + +/* Get a path template for an agent socket in the user's homedir */ +static char * +agent_socket_template(const char *homedir, const char *tag) +{ + char *hostnamehash, *ret; + + if ((hostnamehash = hostname_hash(SOCKET_HOSTNAME_HASHLEN)) == NULL) + return NULL; + xasprintf(&ret, "%s/%s/s.%s.%s.XXXXXXXXXX", + homedir, _PATH_SSH_AGENT_SOCKET_DIR, hostnamehash, tag); + free(hostnamehash); + return ret; +} + +int +agent_listener(const char *homedir, const char *tag, int *sockp, char **pathp) +{ + int sock; + char *path; + + *sockp = -1; + *pathp = NULL; + + if (agent_prepare_sockdir(homedir) != 0) + return -1; /* error already logged */ + if ((path = agent_socket_template(homedir, tag)) == NULL) + return -1; /* error already logged */ + if ((sock = unix_listener_tmp(path, SSH_LISTEN_BACKLOG)) == -1) { + free(path); + return -1; /* error already logged */ + } + /* success */ + *sockp = sock; + *pathp = path; + return 0; +} + +static int +socket_is_stale(const char *path) +{ + int fd, r; + struct sockaddr_un sunaddr; + socklen_t l = sizeof(r); + + /* attempt non-blocking connect on socket */ + memset(&sunaddr, '\0', sizeof(sunaddr)); + sunaddr.sun_family = AF_UNIX; + if (strlcpy(sunaddr.sun_path, path, + sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) { + debug_f("path for \"%s\" too long for sockaddr_un", path); + return 0; + } + if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) { + error_f("socket: %s", strerror(errno)); + return 0; + } + set_nonblock(fd); + /* a socket without a listener should yield an error immediately */ + if (connect(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) { + debug_f("connect \"%s\": %s", path, strerror(errno)); + close(fd); + return 1; + } + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &r, &l) == -1) { + debug_f("getsockopt: %s", strerror(errno)); + close(fd); + return 0; + } + if (r != 0) { + debug_f("socket error on %s: %s", path, strerror(errno)); + close(fd); + return 1; + } + close(fd); + debug_f("socket %s seems still active", path); + return 0; +} + +#ifndef HAVE_FSTATAT +# define fstatat(x, y, buf, z) lstat(path, buf) +#endif +#ifndef HAVE_UNLINKAT +# define unlinkat(x, y, z) unlink(path) +#endif + +void +agent_cleanup_stale(const char *homedir, int ignore_hosthash) +{ + DIR *d = NULL; + struct dirent *dp; + struct stat sb; + char *prefix = NULL, *dirpath = NULL, *path = NULL; + struct timespec now, sub, *mtimp = NULL; + + /* Only consider sockets last modified > 1 hour ago */ + if (clock_gettime(CLOCK_REALTIME, &now) != 0) { + error_f("clock_gettime: %s", strerror(errno)); + return; + } + sub.tv_sec = 60 * 60; + sub.tv_nsec = 0; + timespecsub(&now, &sub, &now); + + /* Only consider sockets from the same hostname */ + if (!ignore_hosthash) { + if ((path = agent_hostname_hash()) == NULL) { + error_f("couldn't get hostname hash"); + return; + } + xasprintf(&prefix, "s.%s.", path); + free(path); + path = NULL; + } + + xasprintf(&dirpath, "%s/%s", homedir, _PATH_SSH_AGENT_SOCKET_DIR); + if ((d = opendir(dirpath)) == NULL) { + if (errno != ENOENT) + error_f("opendir \"%s\": %s", dirpath, strerror(errno)); + goto out; + } + + path = NULL; + while ((dp = readdir(d)) != NULL) { + free(path); + xasprintf(&path, "%s/%s", dirpath, dp->d_name); +#ifdef HAVE_DIRENT_D_TYPE + if (dp->d_type != DT_SOCK && dp->d_type != DT_UNKNOWN) + continue; +#endif + if (fstatat(dirfd(d), dp->d_name, + &sb, AT_SYMLINK_NOFOLLOW) != 0 && errno != ENOENT) { + error_f("stat \"%s/%s\": %s", + dirpath, dp->d_name, strerror(errno)); + continue; + } + if (!S_ISSOCK(sb.st_mode)) + continue; +#ifdef HAVE_STRUCT_STAT_ST_MTIM + mtimp = &sb.st_mtim; +#else + sub.tv_sec = sb.st_mtime; + sub.tv_nsec = 0; + mtimp = ⊂ +#endif + if (timespeccmp(mtimp, &now, >)) { + debug3_f("Ignoring recent socket \"%s/%s\"", + dirpath, dp->d_name); + continue; + } + if (!ignore_hosthash && + strncmp(dp->d_name, prefix, strlen(prefix)) != 0) { + debug3_f("Ignoring socket \"%s/%s\" " + "from different host", dirpath, dp->d_name); + continue; + } + if (socket_is_stale(path)) { + debug_f("cleanup stale socket %s", path); + unlinkat(dirfd(d), dp->d_name, 0); + } + } + out: + if (d != NULL) + closedir(d); + free(path); + free(dirpath); + free(prefix); +} + +#undef unlinkat +#undef fstatat diff --git a/misc.c b/misc.c index f8c8a7beac29..e015f1c5f74e 100644 --- a/misc.c +++ b/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.198 2024/10/24 03:14:37 djm Exp $ */ +/* $OpenBSD: misc.c,v 1.208 2025/09/25 06:33:19 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2005-2020 Damien Miller. All rights reserved. @@ -32,21 +32,15 @@ #include #include -#ifdef HAVE_LIBGEN_H -# include -#endif -#ifdef HAVE_POLL_H +#include #include -#endif -#ifdef HAVE_NLIST_H +#ifdef HAVE_NLIST #include #endif #include #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include #include @@ -63,10 +57,10 @@ #include #include #ifdef HAVE_PATHS_H -# include +#include +#endif #include #include -#endif #ifdef SSH_TUN_OPENBSD #include #endif @@ -103,10 +97,13 @@ rtrim(char *s) if ((i = strlen(s)) == 0) return; - for (i--; i > 0; i--) { + do { + i--; if (isspace((unsigned char)s[i])) s[i] = '\0'; - } + else + break; + } while (i > 0); } /* @@ -299,6 +296,10 @@ set_sock_tos(int fd, int tos) #ifndef IP_TOS_IS_BROKEN int af; + if (tos < 0 || tos == INT_MAX) { + debug_f("invalid TOS %d", tos); + return; + } switch ((af = get_sock_af(fd))) { case -1: /* assume not a socket */ @@ -509,7 +510,7 @@ strdelim_internal(char **s, int split_equals) } /* - * Return next token in configuration line; splts on whitespace or a + * Return next token in configuration line; splits on whitespace or a * single '=' character. */ char * @@ -519,7 +520,7 @@ strdelim(char **s) } /* - * Return next token in configuration line; splts on whitespace only. + * Return next token in configuration line; splits on whitespace only. */ char * strdelimw(char **s) @@ -535,7 +536,7 @@ pwcopy(struct passwd *pw) 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); + copy->pw_gecos = xstrdup(pw->pw_gecos == NULL ? "" : pw->pw_gecos); #endif copy->pw_uid = pw->pw_uid; copy->pw_gid = pw->pw_gid; @@ -546,14 +547,32 @@ pwcopy(struct passwd *pw) copy->pw_change = pw->pw_change; #endif #ifdef HAVE_STRUCT_PASSWD_PW_CLASS - copy->pw_class = xstrdup(pw->pw_class); + copy->pw_class = xstrdup(pw->pw_class == NULL ? "" : pw->pw_class); #endif - copy->pw_dir = xstrdup(pw->pw_dir); - copy->pw_shell = xstrdup(pw->pw_shell); - + copy->pw_dir = xstrdup(pw->pw_dir == NULL ? "" : pw->pw_dir); + copy->pw_shell = xstrdup(pw->pw_shell == NULL ? "" : pw->pw_shell); return copy; } +void +pwfree(struct passwd *pw) +{ + if (pw == NULL) + return; + free(pw->pw_name); + freezero(pw->pw_passwd, + pw->pw_passwd == NULL ? 0 : strlen(pw->pw_passwd)); +#ifdef HAVE_STRUCT_PASSWD_PW_GECOS + free(pw->pw_gecos); +#endif +#ifdef HAVE_STRUCT_PASSWD_PW_CLASS + free(pw->pw_class); +#endif + free(pw->pw_dir); + free(pw->pw_shell); + freezero(pw, sizeof(*pw)); +} + /* * Convert ASCII string to TCP/IP port number. * Port must be >=0 and <=65535. @@ -1028,7 +1047,7 @@ urldecode(const char *src) size_t srclen; if ((srclen = strlen(src)) >= SIZE_MAX) - fatal_f("input too large"); + return NULL; ret = xmalloc(srclen + 1); for (dst = ret; *src != '\0'; src++) { switch (*src) { @@ -1036,9 +1055,10 @@ urldecode(const char *src) *dst++ = ' '; break; case '%': + /* note: don't allow \0 characters */ if (!isxdigit((unsigned char)src[1]) || !isxdigit((unsigned char)src[2]) || - (ch = hexchar(src + 1)) == -1) { + (ch = hexchar(src + 1)) == -1 || ch == 0) { free(ret); return NULL; } @@ -1965,9 +1985,9 @@ static const struct { { "cs7", IPTOS_DSCP_CS7 }, { "ef", IPTOS_DSCP_EF }, { "le", IPTOS_DSCP_LE }, - { "lowdelay", IPTOS_LOWDELAY }, - { "throughput", IPTOS_THROUGHPUT }, - { "reliability", IPTOS_RELIABILITY }, + { "lowdelay", INT_MIN }, /* deprecated */ + { "throughput", INT_MIN }, /* deprecated */ + { "reliability", INT_MIN }, /* deprecated */ { NULL, -1 } }; @@ -2062,7 +2082,7 @@ sock_set_v6only(int s) #if defined(IPV6_V6ONLY) && !defined(__OpenBSD__) int on = 1; - debug3("%s: set socket %d IPV6_V6ONLY", __func__, s); + debug3_f("set socket %d IPV6_V6ONLY", s); if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) error("setsockopt IPV6_V6ONLY: %s", strerror(errno)); #endif @@ -2343,7 +2363,7 @@ 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 buf[PATH_MAX], buf2[PATH_MAX], homedir[PATH_MAX]; char *cp; int comparehome = 0; struct stat st; @@ -2369,7 +2389,12 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir, /* for each component of the canonical path, walking upwards */ for (;;) { - if ((cp = dirname(buf)) == NULL) { + /* + * POSIX allows dirname to modify its argument and return a + * pointer into it, so make a copy to avoid overlapping strlcpy. + */ + strlcpy(buf2, buf, sizeof(buf2)); + if ((cp = dirname(buf2)) == NULL) { snprintf(err, errlen, "dirname() failed"); return -1; } @@ -2624,8 +2649,10 @@ 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); + if (localtime_r(&tt, &tm) == NULL) + strlcpy(buf, "UNKNOWN-TIME", len); + else + strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm); } /* @@ -3194,7 +3221,7 @@ int lib_contains_symbol(const char *path, const char *s) { #ifndef WINDOWS -#ifdef HAVE_NLIST_H +#ifdef HAVE_NLIST struct nlist nl[2]; int ret = -1, r; @@ -3214,7 +3241,7 @@ lib_contains_symbol(const char *path, const char *s) out: free(nl[0].n_name); return ret; -#else /* HAVE_NLIST_H */ +#else /* HAVE_NLIST */ int fd, ret = -1; struct stat st; void *m = NULL; @@ -3256,7 +3283,7 @@ lib_contains_symbol(const char *path, const char *s) munmap(m, sz); close(fd); return ret; -#endif /* HAVE_NLIST_H */ +#endif /* HAVE_NLIST */ #else /* WINDOWS */ return 0; #endif /* WINDOWS */ @@ -3277,3 +3304,18 @@ signal_is_crash(int sig) } return 0; } + +char * +get_homedir(void) +{ + char *cp; + struct passwd *pw; + + if ((cp = getenv("HOME")) != NULL && *cp != '\0') + return xstrdup(cp); + + if ((pw = getpwuid(getuid())) != NULL && *pw->pw_dir != '\0') + return xstrdup(pw->pw_dir); + + return NULL; +} diff --git a/misc.h b/misc.h index ace2a2ffb72a..300bd8c8dc06 100644 --- a/misc.h +++ b/misc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.h,v 1.110 2024/09/25 01:24:04 djm Exp $ */ +/* $OpenBSD: misc.h,v 1.112 2025/09/25 06:33:19 djm Exp $ */ /* * Author: Tatu Ylonen @@ -108,10 +108,12 @@ 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 *); +char *get_homedir(void); void sock_set_v6only(int); struct passwd *pwcopy(struct passwd *); +void pwfree(struct passwd *); /* NB. only use with pwcopy */ const char *ssh_gai_strerror(int); typedef void privdrop_fn(struct passwd *); @@ -234,6 +236,11 @@ int ptimeout_get_ms(struct timespec *pt); struct timespec *ptimeout_get_tsp(struct timespec *pt); int ptimeout_isset(struct timespec *pt); +/* misc-agent.c */ +char *agent_hostname_hash(void); +int agent_listener(const char *, const char *, int *, char **); +void agent_cleanup_stale(const char *, int); + /* readpass.c */ #define RP_ECHO 0x0001 diff --git a/moduli b/moduli index ab7fd2bb0c27..2fe04ab76032 100644 --- a/moduli +++ b/moduli @@ -1,434 +1,427 @@ -# $OpenBSD: moduli,v 1.39 2024/11/29 00:13:36 dtucker Exp $ +# $OpenBSD: moduli,v 1.40 2025/05/23 01:14:35 dtucker Exp $ # Time Type Tests Tries Size Generator Modulus -20240828044144 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63216235F7 -20240828044149 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63217EB4CB -20240828044153 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF632197445F -20240828044203 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6321E28D7F -20240828044206 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6321F5D65F -20240828044207 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6321F5F783 -20240828044210 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63220959FB -20240828044217 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63223CB053 -20240828044224 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63226F7A83 -20240828044233 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6322B452E7 -20240828044240 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6322E58253 -20240828044251 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF632334AB77 -20240828044259 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF632379357B -20240828044311 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6323D336A7 -20240828044323 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63242A969B -20240828044326 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63243E12C3 -20240828044349 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6324EA98FF -20240828044351 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6324F33C17 -20240828044406 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF632569D1BF -20240828044412 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF632591055B -20240828044416 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6325A64983 -20240828044426 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6325F39C73 -20240828044435 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63263987CF -20240828044440 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63265B2A5F -20240828044445 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63267C888B -20240828044453 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6326B9D6C3 -20240828044505 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF63270DF46F -20240828044509 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF632725FB3B -20240828044510 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF632728D6F3 -20240828044525 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6327A20713 -20240828044536 2 6 100 2047 5 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6327FA0007 -20240828044603 2 6 100 2047 2 C2CE9B70B9DD5860C0846274F1FF29B2E3D5EFFA5A8568C6B9829BD8C42422F0BEE2D6D74503BCD91A002B09EB75174B87734CFFAC12682D49D50AF5B9837E3B30675E93087C5279A431B40D8219B2292A0EBB23ED0856BACF21F7A8C801FC3B0A1D2C76C4372109A24587D8E09F91CA0018EB2FB7D75BDD8FE230D49CC593E2152A7EFB4B7FCAA9228D061120DED56DDF6019817221B4D9A0F5DECF928148EB22AC583AC3BF37541CC285C6BB4E0C028E7140C133B12EB80354C01C053F5B435EA2798404749664674966DFB7113F86BC74FD37333330A664FA86AE1B40006717AC6091961C45164F3714777CC776DB2C7C72FA6A89EF3DEB98EF6328C7601B -20240828044621 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602100B138DB -20240828044622 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602100BA7D33 -20240828044630 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602100F35A77 -20240828044634 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021010E6E03 -20240828044637 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021011F7EAB -20240828044646 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021016091AB -20240828044657 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602101B2C867 -20240828044658 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602101B60E87 -20240828044721 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602102652CD7 -20240828044731 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602102B160B7 -20240828044737 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602102DA0A57 -20240828044755 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD260210367434B -20240828044803 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602103A3B7DF -20240828044807 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602103C2D9CB -20240828044812 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602103DE1313 -20240828044821 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602104264E53 -20240828044835 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602104909817 -20240828044855 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602105309B8B -20240828044903 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021056A2A5F -20240828044903 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021056A52EB -20240828044921 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602105F6DDD3 -20240828044930 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021063AE353 -20240828044934 2 6 100 2047 5 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD260210651B5C7 -20240828044937 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602106651B4B -20240828044944 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021069D4573 -20240828045003 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021072D06EB -20240828045023 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD2602107C5C8DB -20240828045043 2 6 100 2047 2 E8198A1A9FF997DF62B131D5C187C3160A61128E5DC14FED2EC25E38EE627FC070B240AFA70179A5981739E7F1CC1EFD94BECAA338C8BEFCA1C036EF1F7804AD1BBE8B86C3BDDDA7868F9302E45F47BABB6A8D54E1871678AB37855761AAD6408EA4CEE8B4DE9A5972981B07EAC9CD496331C4E1104ED49ACB5F4F37DC9B98098C04053775DB2994B23CA4561C739DB5A19638C0D1D97C07EF26ADC912A5C6A3506B5E935E4C11E18769334B4D02CDB4802ACE68B55D2D3CD354B0DE2D4DB4727FAD43694110D90A4A18206A731466E83FCE2A6F8E042E1D244F7EA4DD2FF3B9E3910C2B7672E4605A2025BDAA0D67455F8FD50FD241B5074FD26021085D358B -20240828045540 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DB83F1177 -20240828045614 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DB8AA8ABF -20240828045644 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DB90E7B73 -20240828045720 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DB984B19F -20240828045813 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBA2CAEB7 -20240828045858 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBABFBAAB -20240828045903 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBACAA69F -20240828045912 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBAE15E2B -20240828045932 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBB1CB097 -20240828050005 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBB86CA4F -20240828050036 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBBEDB4C7 -20240828050043 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBBFC577F -20240828050107 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBC490C0B -20240828050136 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBCA8444F -20240828050201 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBCFC24F3 -20240828050209 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBD0E9213 -20240828050303 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBDBBE653 -20240828050329 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBE0AE17B -20240828050406 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBE8344F3 -20240828050430 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBEC9D58B -20240828050438 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBEDF58FB -20240828050528 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DBF858DCB -20240828050633 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC0619997 -20240828050638 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC06A2A8B -20240828050712 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC0D40C6F -20240828050715 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC0D78F7F -20240828050743 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC12FBEF7 -20240828050851 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC216E8EB -20240828050903 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC235154F -20240828050905 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC235B9E3 -20240828050941 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC2AA4F87 -20240828051038 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC36951FB -20240828051046 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC37DE073 -20240828051104 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC3B311A3 -20240828051215 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC4A3904B -20240828051246 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC502215B -20240828051312 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC5506613 -20240828051329 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC57E32D3 -20240828051336 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC58E630B -20240828051520 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC6DF9DDB -20240828051549 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC736A7B3 -20240828051622 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC7A11C13 -20240828051823 2 6 100 3071 2 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC933AB0B -20240828051906 2 6 100 3071 5 F0E30849E47025007BE82AED18F1B234816DC958D27A2133A1FEA5C9D5B00C107D4C3563B295FB10AA1BEFB5C160159F85A69C3990D6A5078FEE7D5462F14890168BF2AA6B06729778AF1CDA95F5EB5FD024D9A4B904FB6501213268D69167449CCEF555129648DA0C6C1500DB898ABAEBE716B468AFDADB8E499D0043B7D4070A957EF41EF2ED3D9DB4EB8607B620C714084F6909D0B980FC54E7BA3A4F7C6716BC8430C5D73475A95F64B8AA9BB6F9CD524EFEC35E322F10DA32826E005EBA1C81EA662FB1517EED4D778DB6658C7D6150F144BBA60DAE6B75499E70CD7D70842131C00E04319DB1B53867E6BF820B1D74692227A574F937B668F25017F6DB3D6FEB2A61F8E377FA73E8652089A0ECBE15AD1CB8C44D738AB114BBE7AB9985545DE182011208113A56C5D84D8E7640517C5EFA28670168906BA869583EFEE72F89C1B3CA019C4D544B711A9A0297911CBEEB124EA9D7076696F62AC9E8814CDA985B35800D4DB253497725F131169F56AF543DD51EED43501A249DC9BF25EF -20240828052009 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BBF34E3B -20240828052030 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BC38F533 -20240828052045 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BC632227 -20240828052153 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BD42ABFF -20240828052207 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BD6986DF -20240828052211 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BD7241F7 -20240828052259 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BE0ECA0B -20240828052336 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BE863B2B -20240828052339 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BE899267 -20240828052415 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BF03197B -20240828052431 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BF33F3BB -20240828052513 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BFBAA987 -20240828052522 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BFD18B5B -20240828052527 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79BFDA82D3 -20240828052609 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C0656637 -20240828052616 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C07626F3 -20240828052621 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C07E39AB -20240828052816 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C2033C13 -20240828052903 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C29B2063 -20240828052932 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C2FB438B -20240828052959 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C35070C3 -20240828053054 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C4050DE3 -20240828053223 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C52F78A7 -20240828053319 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C5E6180B -20240828053339 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C61E1503 -20240828053345 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C62B8123 -20240828053430 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C6B80C6B -20240828053549 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C7B7959F -20240828053758 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C95C0E23 -20240828053817 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C9938013 -20240828053837 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79C9D0494F -20240828053914 2 6 100 3071 5 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79CA42683F -20240828054013 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79CB06EC0B -20240828054258 2 6 100 3071 2 F92C6D0F2F9D19FE24813B351098A85FABD54907EA3F2B1DDC129631277DD947357AAEA3FBDAF717CF7FB244ED5EA7475AA7AB9F8CC8E92BFEBA6B9F4394EFEFDAB17F42338B58FEB6B09CD728221C9261C1FB59A2EEBDD7A974CD3D56031DA903E422D77061725705DC1366F17C530CFB45A704C00018D78004241F3CF6AD1C934F576F8D4C542FD83BBE0C8C3B122063A7457D3A47D1EC0A2266A36ABB664E96959D60C46344757771F7DBD79B25F033CA5E7674DDD2AC03F79C7C8E2B637CF3C9DD55D3FD5BDDB1CEE1B5F57B72B01F91BCD385AF7AD03C183EA95D95D07838BE129BDF7B724A27FC2ED5AF6AE17C995ACDB42C783845342A07BB2318A392B21912B8E4165B1A4688C35FFBB23B733DCD0136373E308F9320A5C2BAF95492F6E4F5964B18917846376B2ADB2E2892B1D51DDC63578DFA361EA5190E39B6E93772B2A3F66CD6B0B183F41A68A31AA7E9A23DDBE383AC2E262C368DC859989BA361A683A9B7F3B158A1BC9ECF4F8669F363DAF10ECE0EB29581CB79CD234BAB -20240828060009 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A70951B13 -20240828060511 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A726F0C37 -20240828060714 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7335AED3 -20240828061156 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7501901B -20240828061217 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A751A9A43 -20240828061522 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A763D53FF -20240828061600 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7675A20F -20240828061619 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A768B4D03 -20240828061636 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A769E17B3 -20240828062452 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A79B996BB -20240828062521 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A79E2492B -20240828062623 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7A419E13 -20240828062831 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7B0C50CB -20240828062854 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7B27FC2B -20240828063249 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7CA08843 -20240828063334 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7CE52E4F -20240828063443 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7D4D4863 -20240828063548 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7DAC7243 -20240828063629 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7DE88D73 -20240828064128 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A7FCA819B -20240828064626 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A819B3083 -20240828064816 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8247AB73 -20240828065323 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A84385B67 -20240828065513 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A84DF9C03 -20240828070128 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A872AEE03 -20240828070200 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A87566497 -20240828070537 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A88AEB07F -20240828070904 2 6 100 4095 5 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8A00154F -20240828071020 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8A740023 -20240828071247 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8B633D9B -20240828071353 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8BC1DD33 -20240828071426 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8BF0634B -20240828071455 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8C19F3D3 -20240828071541 2 6 100 4095 2 C1FD462836A96C337420C7007228E616EC573732284C62893AB8CC4E3F3E182E3A2FC77E35BC37FC6A207BB3B56EEAD789DFE450ECA8A88518B4EBACEF11D667EA651A91285ED252C792EB32026784FE21B43F3E4B61DBB0E26D3DC6EE8B9090CCDFA2876C4CABA186BA994026CF4AE3D17DC5A0D1B4D70F58EA021ACA38F9D1EC7CFF066D1F0C1DEEAED46C531E9719664DC3AD0E61FE171E558BD54FB13004B7E19B3AD908A5FDA716B1AFF98F48527F12F755CB53E0ACE01192CD0CFAA0B7623D1E035DED85CD39B69922E719FFD315DEADD6AEA9064B7DBB7F1079FB06C0442AB9E364E2E756D6EA8C07A92E9BB03EA11678BD0AE1ECC81748068B0658EC1E0C54886933C5BC69BED9334255F55748403F957CE5F314D8F154E213068BAC299C0D323623D4FECF1C17601E347500A00F8AFB1FD63C936842FE87831519613BD966C1653F623A42F236CCB0AEE2E81F702C8CC6E560999B686E3C5B4DE07ABD8DE477D0475F5CE1C61D3D8B1919C378D9AC041F21AC522530F7A4D62125D8DB8F8217BDB3E330A04758448AF7093A65591A0E7E82BA13F6F92CCC68AFD64A965D13A7C36ED85916B3EF9C3AB022E6F66A4317AA01B201BED766AFF938563E93784662AF2F72AE5BA52CF2B0C4ADAF6C20689296CF729D5A643A64A20E4380DE5E3C932CD162C12D55650AECDAAA74FEA3C85B534EF588D2693B7A8C5E63D3 -20240828071923 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9B3CF4313 -20240828072226 2 6 100 4095 5 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9B4F5B7EF -20240828072458 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9B5EF31DB -20240828073047 2 6 100 4095 5 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9B82262CF -20240828073253 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9B8EDB05B -20240828074035 2 6 100 4095 5 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9BBE344BF -20240828074440 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9BD60A58B -20240828074721 2 6 100 4095 5 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9BE6938F7 -20240828075138 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9C00C2AD3 -20240828075304 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9C0911F9B -20240828075632 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9C1E1F5EB -20240828080239 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9C432FEB3 -20240828080841 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9C68352A3 -20240828081126 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9C78B996B -20240828081614 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9C9536B03 -20240828082258 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9CBE55E03 -20240828082637 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9CD49EF1B -20240828082710 2 6 100 4095 5 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9CD7A6C07 -20240828082726 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9CD8C1A83 -20240828082826 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9CDEC8AA3 -20240828082907 2 6 100 4095 5 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9CE27CDDF -20240828083210 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9CF4E290B -20240828083415 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9D01153B3 -20240828083603 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9D0BAF663 -20240828083703 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9D11A10CB -20240828083816 2 6 100 4095 5 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9D18C60B7 -20240828084040 2 6 100 4095 2 E36F035A457FE7C42A6DFEA5F5F192B2FB147FA8B29FD9BE0FB4DB472F5668038712145FFD9C047435AAA518C55B975D814D566AA3233887D5C2C886B754D50B133FE132D81A0851637D6085F2289D8584BF5130452AD24DD87D7158CDAC16832D42476486F0EC2DBBCD38CEE963C5E367ADE50C9502735AD3583445AABEE10E63480E3791FFC7BCF4BD5C1F6E9768E1B1D9B6B75E177F95914B6D5F06CA7CB001B15CAD26B9C20565F8351E69B5E6CA74D30E770523BA7E05475050DCF81A3F9B7C38EF1C31447E35543AE5B00E0BB13C63F8F1DCE0397BF523882AB79E2DF4BDF7E18ED799142089E79CE6AC0E562A587B055D9F963260DAA84A1C520A0D46A01138F20B0EAF73300DD4196A403892EC30B2C84860C4EC4A1FE5778512F546F5B813380393D3BABC535668515BEEFA350207C3BFA1502B52A775146FA97E4CBF701C2DC7845FF604EC73052F217185E74813FD18D3EBA6489E0BD00852B156193735F5A34952DCFD4BD493ECD2C9948E9D4436A79B1F5B6BB7991F1253B8B68BA7511EF94B87D4D9843A5A510837C7AFCD7F42A9657C78BA516606F94BC27F1579BBC0776216AC8B96C2D6D485B6C6EE489C504E32A6B4979287D53E42D120D411F849C748B31FCB2CEB1663C813A0E327DCC18242B484CBF5F9191063933EFEC4C6A600C415B0F29365F6DBBD2DE794D7E14D62CFD7F1E570D1A9D26C42A3 -20240828090009 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F2258E4DB -20240828090718 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F233F2A7B -20240828091256 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F23ED9417 -20240828091549 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F243D1C03 -20240828092905 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F25E8D11F -20240828093653 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F26E25303 -20240828100014 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F29D9C7A3 -20240828100324 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F2A3C434F -20240828105814 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F3151094F -20240828111427 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F33641C63 -20240828113247 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F35BB7B0B -20240828113333 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F35CD9A97 -20240828113540 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F360A482B -20240828115349 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F3862A7B3 -20240828115426 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F386EC997 -20240828120438 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F39B5CC43 -20240828121629 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F3B334FB3 -20240828121657 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F3B3B734B -20240828122545 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F3C524DB3 -20240828123158 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F3D1B196F -20240828130157 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F40EB0D47 -20240828130238 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F40F7E253 -20240828134737 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F46C46D3B -20240828135646 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F47E7985B -20240828144149 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F4DB24103 -20240828145157 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F4EF2EE0B -20240828145816 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F4FB0AC7F -20240828151150 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F515FD9BF -20240828151822 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F5229B63F -20240828153933 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F54CF3923 -20240828154759 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F55E07A93 -20240828161625 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F598D643B -20240828162500 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F5A998FB7 -20240828162916 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F5B1CC43B -20240828163955 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F5C71914B -20240828164552 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F5D2E5D1F -20240828170129 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F5F34D397 -20240828172001 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F6192353F -20240828172046 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F61A3C147 -20240828172320 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F61EF7817 -20240828173414 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F6352E0CB -20240828173441 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F6359E007 -20240828180730 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F679AD6CB -20240828180915 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F67CD41EB -20240828180941 2 6 100 6143 2 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F67D23A63 -20240828181257 2 6 100 6143 5 FC9BE67A111C24C58B9D8DFF78C575F1AC8199BA90C7C86923636AEFB38B41C1282E5A8232B7B9AECD439830D372F7B8D22004BD6BD64F326ABA86F1FEA022C374CDDD3CA3F161873B1D51326B69BC26112479F45CDBBB0DF942D942333DEBECD3E705804408C841D2EA09535C2B5779315396B517A6C628C9E23DE15EEE013BB18D7B40EDEA8655765566F3923B6EEA21853E436480D25D1D7172F02B16814BE600FBE715963C7576E022AAA046EA7D25B4642F7626582BE4ADF0E251A6677DFC67C49260C444D7825A03685A5BD789A13E1AAF1970ED54C71B234682E3AAF67EEFC3875C8868086EE6068A48E6C4E7A7BBEE17505D4AB7E8ACA56E336490553B41E1ED5D023D2D2DBAFC3362D8CDEC1809F4A37845A1DB87AE4D7AE6F6D941B0AF97921C9E659331B524F47EF80EAF574D5961DB05724C17F45686389361D29A234BE063DA02D889905B8B1B5BA87355B60F5FB44CFF859415F439DAC677F1D5A1563B22236386D0CED95BE925C51D22F2173B579B1EBAE7E8B8EDB26A8532FD6DE7E1F33D6BF984BAF3AF00A2C382A7B354C77F029D041FB132BF27C430320DFAD34530246D6CB04D7A78F5364186A9A86B359A9F5FD28D4B9ABCF51BE2C955CF8102D64B322A50FEF96DD5C4D21268D7E044CC52AB57AD26BEFED1634C24BA947F1DBD024BA9A3CD94EEE0DA0CA9FD481BEB41BF6DB6ACF409E732C482643D5D5A5B720B26E618C7AA244B8F7506CB8FC8299195D03E30B03C6263A75AACBC3A32C9A7DD5D7653537125BC0FE7241A410DBF8E04ECCD1486DA3A321EAF36C5A5DC40A0FB262A64727CF7AE645BAF538E8784ECA49E1A277B29C56B8D1AFF2BE2E1665906C48A58230497091B47EF239C5D34FB19C25D89BB0B8573E8417AE90FEEB6FAC06F9F60A6C57F1D4E3325FB0AB1A3A088B4133A319158CBDDCF0CCC2938F64E0029F0389FAC55BFC1F0D0F15B2E70799562C53FC3D1D97CCFA25ED83FF115503D44A7A91FF295AD2F1BC598FE86B8AE7DA77773179A4A0EB0ED618102D880D9963798BF91EB6E16870A4AB9E8137E1D6503ADD39D8E8F683B05BF -20240828182555 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3180CE228BB -20240828184406 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3180F2F287B -20240828185315 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3181059FDFB -20240828191106 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31812A21FB3 -20240828191122 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31812A28277 -20240828195243 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE318180489DB -20240828195610 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31818728F67 -20240828201325 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3181AAF829B -20240828202233 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3181BD9FE33 -20240828202820 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3181C96132B -20240828204913 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3181F3FE8A3 -20240828205946 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE318209CB6D7 -20240828211537 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31822AC1387 -20240828220459 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE318290F4E1F -20240828224012 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3182D9E3A03 -20240828232844 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31833F1DD7B -20240828233400 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3183494A423 -20240828235802 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31837ADEA57 -20240829001115 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE318395E7B83 -20240829004718 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3183E0E5603 -20240829004844 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3183E34D98F -20240829005431 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3183EECD0DF -20240829010933 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31840CEA00B -20240829014049 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31844D61FFB -20240829014355 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3184533474F -20240829014829 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31845BEB5C7 -20240829015142 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31846235FD3 -20240829015517 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3184695C7FB -20240829020608 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31847F7E373 -20240829023600 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3184BC56B47 -20240829025737 2 6 100 6143 2 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE3184E74875B -20240829031846 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE318511B9B7F -20240829033452 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE318531C0F27 -20240829034004 2 6 100 6143 5 C272750D88E88AEF9E0F2188FF6C61DE6B22B20E1C1D5A5E5B13A9C97ACB497B050868137519E1EC9CAEC9ABE3D69DC4C96ADA353B3809627C938691FCC17E260254A0ABF1FB7629416CF61DE72AC7B91EAC39F9A9CC38B729272D78976679C9F93E0E67BAC79B88598FA5B160A9403FB851D2046A6A319C55E028AF6AEDCE7588403635FDFEABCF52C2EB9D7CB86F1CEB17DF39D951744D332D51302626F56AF310A3E20B3BED391B713FF8589D35E44DE1DA41D70EE06762C2789444107C50101D55738975C05B61243016DBEFAF2521C724FCFF279D34EE418052A2AE927474EC5C055ECAB0B2E1F5E6EF378EEB15A7ECAB59638A0A7163577121789E3301236F63178910C6AEDEC6664DED0F0762D6F6854B44BC811A03E8627DB90D7A2E9FC85D32B498E8E5A92BC771A6D9C8E9A967F3EC3C0927926021B97FA8A201C22422BD61E330920F35AE966B43CDD8B6EC853AA8F1CE0C1061C152826F9769746EA7E06325B50A9C3D9B7A88C5D22B68556E24ADD0664F0230DF4896F53319223F39D68B6507E213ACD50EEDE83AAB51E3C4B020B6F0B0AB06CB071460D139DC597ADB530E51FEC7EEF6D5111BA3A7EE874B4708ADC8186D2D5326DBDF692E60C6170AE64590151BB6ECA0AA51E6233148C7D78034812FA93C6A7F7864182D576BB83714C3A4E17228B0D4569F70C451632477265A2A40B9419A13408BD7C3B33979589A112D6156484AD84560272D7717F763507AF92C86F4475669962B63A2BAB2EE0CAA835B90A7DB43CF8A2879674B60B1B1EC25933019968455AC054BCA392EF57C3C76D79AE684894BD009B97AAC3754537E85C93C9F96D59B8359C055B1B7109086E4DC7F55CEB628BFAB792B931B955AADA57FA6A8CB019B1ACE092199C0E5F94855DFBB08E3DCA886337842F363B8117751C5DD48DD431E903C2B1C7677FE2AD42A0CCCD2677B9A4774E9168A2C4C1B8EA5267971D0DD6BB91320A677928D2087069C7D460BB4E72698AED4F7127975D49F87D52724DE830C66F422547D0B934F32F4E9FC0617A6D2BB022987EE13330BDBA970A8FAE31853C097B7 -20240829043625 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187E5F08523 -20240829053823 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187EA33BB33 -20240829061611 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187ECC3E213 -20240829064111 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187EE73FD37 -20240829065111 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187EF1CB167 -20240829082003 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187F52294C3 -20240829091934 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187F92CC467 -20240829093659 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187FA58CCB3 -20240829103319 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD187FE2DC683 -20240829123824 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18806C1B393 -20240829130958 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18808EFDAAB -20240829135456 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1880C119733 -20240829150211 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18810B3AE03 -20240829152452 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18812362547 -20240829171859 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1881A26609B -20240829181704 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1881E2C3E3B -20240829182818 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1881EED38A3 -20240829184006 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1881FB9391B -20240829190814 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18821A70EA7 -20240829195154 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18824BB04C7 -20240829200011 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1882546EC8F -20240829203003 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD188274D620B -20240829220907 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1882E2608EB -20240829221444 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1882E810C9B -20240829222440 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1882F2EBA7B -20240829230449 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18831F68C1B -20240829231044 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18832552757 -20240829233827 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD188343C3EAB -20240829235120 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD188351A81B3 -20240830003221 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18837F06443 -20240830011832 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1883B1C9E73 -20240830013013 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1883BE3681B -20240830014610 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1883CF597DB -20240830032931 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD188443580AB -20240830042102 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18847CB52C7 -20240830042255 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18847E4A687 -20240830052035 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1884BDB09B7 -20240830053449 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1884CD217AB -20240830054036 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1884D30808F -20240830060721 2 6 100 7679 2 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD1884F02040B -20240830071657 2 6 100 7679 5 EF541828E23A6BB90EFE9D9BEEDD3F9DE2E08069B8FD3ED88F27CD7E4F00AA272010368A26104FDBE69743D020951E909C76D9EF11E8050208720244763E9D59526B99F462FAC17E3A1ABD3B328C80753B1777D032397E4E3BDC90FB275DE027A21362A8FF88456ED3A9F397C045745B0C4D090D10304B86631AE9561AE9FD3C9FEB4490FD074E78702F4187A8E5CE8E7AE1E66593C34B9F08153994E70FE56B9CA823FCF1C176E875F6654CCECDF52463CDA61BE848C5B0E9CFF4E908CD0AA9BD4F4A58DF5996AAC3D411270CAD4BAC154467F91184713B4EFCFEE7922C8F58F9259937935A94A7791E99F4838EE1981A3EC9E6A2C44CBC10ACE390882CA40592D13E91AF49C78C4D518D9EFA98142A9102970E721D6ED83981164C488AD25BBC424C235C7AF62C4B4170EFFC11FA6EBEA4661D320013FFA6A4DA1EAE2F0545B95FD4E13B182BFEC226A01C3B46229FCE86A9E11B3E026326C1BA745510DDE4FCEB777BE42D1057DAD45ACEAB111C907760669A0C1F15DA4F5B8180E844DD5D602F7FAE7D16A5E8A2929E804A1BD17D38866A5EE3B1F50C3054C5E397969BCA2008DC96503513217BE8D2F15FB9DA26A8A5FE981111EC64CBEE1420D2DF7853B17E40766873E712977C1043237B39E2DE3868D079D96D76ACB24123AFDB5C6A6A9BCD40ED4C696EDAC4FE015CA982535A2A84B1A42767E1FBFB936B9FBD72CF98993C6B1EBDA16BF03FE325FA62511128CB669EE148067ED9A10338F87E4D3D39FE695A2F99B5D645A7653C3EBEA517FAFDD9CFF12B54E947A64BE8564A3851EA0F7A09C8C2E3D78FE0D3739ECA465A81194B8760F4F7213737C3FBE0E2F13704E7FDE2EDC91E22F1B76327CAA49BEBCDB1A33F178DA6F38666D09942532843CD95E61891A54EE7745D731FC2AD6B434D42F300D19176DBDD94594E3EB018EDC8666E89FB4C205A3D70F07F96AFA887F6D4A2FE573E77FDDD28D76F5C15C34CADDA8B9652FBEBEAA4CF56260833B160E8122141D17DE72CAF4859EB84CCACC341B7790A2D9B297538549451FBA5C47A37C7A99E31AED087BDF7F9E79D99CB6FADDBA30ACD5CF06FAC18DE33A94A8FC08ED8D93A24CDD7DAE09CD8CFF1C918173B32C10CE0F5EE9ED40D2BB3173370E941158C448617E4251E522CCE793B1A4399E8A39B923BC594AB453CE0145ADD622DCDF98D7D9A1E3C3C4BF128194857AC3959468BA2C2540EB5438D165F04D0A0D15BD19A5EBA1F7D6F82848877E480A20859C002F448716156AAD2008E4A7694E4F4C346C4EF359B21BB984C2073FE3E95DF3B183EFAC45BC426E3A569703F6C48DB20F7A32CB7E7C2ADD18853C7A8E7 -20240830084720 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FEF75703DB -20240830094656 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FEFB626A2F -20240830095006 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FEFB909467 -20240830110930 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF0108EC1F -20240830112637 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF02315BCB -20240830113545 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF02D19C77 -20240830134211 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF0BA3E697 -20240830134427 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF0BC3CC37 -20240830134817 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF0C009ED3 -20240830145923 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF10E44067 -20240830161320 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF15FCEA4B -20240830170319 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF197243AF -20240830171339 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF1A211BAF -20240830173745 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF1BC7E24F -20240830181908 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF1E96C5DF -20240830181940 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF1E9711DB -20240830183135 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF1F5C367B -20240830190740 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF21D6FFCB -20240830192133 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF22C8073B -20240830213430 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF2BE900AB -20240830213722 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF2C10C36F -20240830221923 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF2EF2814B -20240830225347 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF314EE303 -20240830231356 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF32AF8B0B -20240830234723 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF34FE61CB -20240831004647 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF3918C417 -20240831020149 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF3E4B559F -20240831022637 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF4002F243 -20240831030552 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF42BB548F -20240831033741 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF44F1D9D7 -20240831034841 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF45ACBE37 -20240831035452 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF460E12C3 -20240831053706 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF4D2CFB27 -20240831055400 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF4E512613 -20240831073419 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF5532694B -20240831074414 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF55DB1637 -20240831081807 2 6 100 7679 5 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF583421DF -20240831090302 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF5B405DA3 -20240831093205 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF5D338B6B -20240831103110 2 6 100 7679 2 D5949FC6991BCA2FAE324A3249CCAE8A99AEB0E6E81054670B5BCEA51FAB2D6C0A271648412828FAE2E356A85355BD9DF43DDD71F82F93494A6E4F0F78E998A4B13481478A814CE13A471D3BC48EF5A2BFDF48E920696BA74DFE2672ED7FC456B46C6CE48C129701E0D0DE344FED8581E2F1D010735EBDC6E9683D892CB2C2A164B500A5D2A9A41D8FCE24CDFD4A8DBAB66671B3FD8B6275C3482A10A73D2C1FD50627B4AAB5F81C67FDAA3D3AD28E916D9DF4F6E9035BACC614A3FC352650DCB94BBB4C3E40CDF33B242FC97C9D5BF655DF4672F496FA8B619B515DCB37932CDF25313659B982542675BA0300768C7BEB3EEC64BA9E0EB247B0B9D000E0BB07C3E054B5DAA9CE521C54EF0A1DC00203A4F723FC2361DAD5AC276C723044DD3B56A3B4C38C46CD3E9510AD9264BCB2AE52EA59F4B3CD500B7134135784D994C42CF8DCA5E90937C53A19D8DD356BB868CCE05A982F7204F1D3C19CCD16873CBC7CA44BA2D34B57E63F092B93C075530ED66177BE42F1677E4EB1A18EA0ED62C654F04B68DE9DD4A9C1AC509CE5DF1CF266C6A16696F858C024C16A95AF16105D9E778BD3A9FFE09CCBE4454EFFE6A309F629434FCB894B42BA2FAD7C4BA7091301422C347ACCB39FF801F97F36B3464A7B84C4C4A85503DD7BCFD97462AFCFDE1CF4C8FDA6FC5019B262C3E58C77E28BED5A2583B28DBA0E59D5665E7A5339A02C976FD31B4797DB945851DE5164A9AA3359F1A35E31357314DB6C82B5DB62D70BB7C22B3C110A0495E2B7200104FBD230C9C11824601EF4FA78ABDA0D5BF866B2CA6087E20AB2C8FBE1FFCEA5D19F11EB801002A801D9A72678009269FEFE57A4B8D389047D05F03C5472F5FB731C5BB3C5E2A9BA907D496E10FB953D953F650602639F37EED2F65424056F92CDCAA33DD65E714EF3D5419E7B4C1CE77A40D441962F2D42135ADD4951E90CC0FC85C2946C82F74C9B1398D6A086BC7EAA1763173AEF572969FA738EE079BF5C5EFAF8E4D99DB8618E646876342CC8BF3B1A62F969265FB633700F4CC598AB407F84BD2B1AD496AF8E785063078688A86AD6B4E4ED2CA31AF2F7899D0AD613A57BFA5746F743A62F66105DEEEBF637D9ADCBF941E4728DDD5D03AFE58EAD827B154BD22C00A94822A240DFE575479E9C00E38064BBBD1A5B511957045BFE40951312B2F5F5CC45CD94823AFC0CD2BE902C2E9DF92D87C8E24308E788EC48187B2EB69516AC9D7CA97C0E1C610320AFDC5767FFAFBBE16EA80B8E2CF1AA030FD86E803A19CC2BEF8CDCF8A7A1BCF82A1ADE289ED2733AEFAFA82296C331088447B110D8AC831708F631EB967936B2FF61456293 -20240831121754 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB1349E143 -20240831124443 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB14CB7AFF -20240831135558 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB18CC80A3 -20240831145738 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB1C36864B -20240831165313 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB22B0FAD7 -20240831185249 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB29880B2B -20240831185952 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB29E5889B -20240831194619 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB2C7FC84F -20240831230544 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB37F47B7F -20240901001522 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB3BE4A76B -20240901013228 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB404463B7 -20240901015829 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB41B1142F -20240901025646 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB44FDAE87 -20240901031615 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB461000EB -20240901042008 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB49A1BE47 -20240901044227 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB4AE1A82B -20240901064528 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB51D37F37 -20240901073955 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB54DB30B7 -20240901080825 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB56740653 -20240901083546 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB57EF4EAF -20240901093005 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB5AF60F7B -20240901122015 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB64814643 -20240901124800 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB661018A7 -20240901134700 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB695D723F -20240901135853 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB6A06CAEB -20240901140005 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB6A0E0D2F -20240901141551 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB6AEB6337 -20240901141841 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB6B0A7C53 -20240901144342 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB6C6CC963 -20240901151624 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB6E3F7CCF -20240901173158 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB75F13437 -20240901180438 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB77CD90AB -20240901182042 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB78AD2B63 -20240901193908 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB7D18983B -20240901195652 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB7E1244DF -20240901202100 2 6 100 8191 5 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB7F6CD3C7 -20240901210156 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB81BA121B -20240901220732 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB8571A7D3 -20240901233244 2 6 100 8191 2 FE0FE5928DE815B6A6B360EA50D7859C014FC47CB277FE8AA545E89E2D34791ADC80654D6B276978CAD4E12481459D6E40E32CD8500BBE14ABFBD4E72A14280C66F25A30CB81F885761B07BABB863C9DA0ABEA9EAC4ABB8BB272AD3ABA2B808CB6B12A4A5D68AF9B47FBF91C1AA08C7738B911583E29F339BFB9C46B193071A3BD7297521767A34B002F0EB1470246325AD1D48E7C7EBCFEED0866747ACC8FB2C731FC1D73C52F3868C1071D92BDF96037BBAE974A789968F22ECB1CBA7129FD2D524F0D4109DCA2E056483DDBC90FA159982AEB86F929E0D05188B4434C0AC1F071B6F431D08201E683F95CE6D2B4FA354E74F346144E52DB92A0F468ACCC0F8AE53C8BD1818CC577F65DE4188A6E2E10EB84FF9A31B04506E2E8ABD48FCA067B44348667922B7479EBFB9E6E5B8583C4AED84CEC8CCF3A3C3082A3519D2EE53917A09BBE4A52D1F8EA458F493D9D272B49529E6FD509A4EBC7E0927ADACF86C5C8BE31DE98EE65F3FA6CCDB9C308971118C68AF076C64A42745E9485C79AD78880C9DDD03D9529A71C4AE4D8A976C6461119E8CB44536420EDF4AC2499748F3078A1749E6FB4F8F8DCBE64962610695F1DB0BE4FE879A34D7A9BC94DAF492A9259C521F690EC1B00966F855C4B42C2D189B8AFDC34CFE3D49D974820287EE978495D640D80766C4CCA16D92117610A7DF97F444FC5B9B72C10BB8D632255C465F4128092C57B99426E4B0FD336BFC2455538E48FFCDC8CFFFC2064FFBC5FC0FA3CFC6A37140EBADEBF6C1F60C32F650C42988212D00CFFE0DB9D975F991A950D2D8C6B47676672EDB553FD8AA505E69BCCB9C89096FF1F5F5369F285EB8CE629FA7B56923824C3FFD7A2050471A4D90EC9DF24C22D9427267ACC6A13AABA1710B9469EE96E106468410866076B98D19B3E36F4CD052B89A35786D318FFE6EC0805E73A23E41C79B5287E0FC7618C2B4AA89CA27C8DEB5D016109ABEF7651589F4CBC413D3219945E35D243E8A6D3908735B01333F527C9CD10E5F0B2467C9F3623BCBC0008106B6732BD0CCABEBC331A463726BA783A8C036339D60B6B9AF8671D2AD57E07B6C445F23DD6B6FCF82F7B856FFCCC57A5C0B1D53F2E7930107B24009AB14883B20371E427A4FDBB0EFABB9B182071FF7BD4675D7CF47CFE9C17D9B9EFF98210EAF8D87638848AF6A6E1A5DE6AB975C96DE99352B534F639697EB6463F5F66A8613E24E462C92518A663725C023F18975A943FE89E9EF2C075F0FCA2AED88C2D61D0BCBE05629A88CA424A70B7EBEF17ADFC9005531FC01E2132C6AC685B36CCAF52DA039D0139E7E52E435374F4FF898005B84E75CACF730D262E66977FA18D5653538E9D7DF66B5684D7E3107E9F4A7A5EA5949A292D2CE9EB0B2AA76D737623614130364318DF1EBDE95676B507EF5CC76F08A8FB8A40CE93 -20240902012852 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D46ED77CB9B -20240902013705 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D46EDE42B6B -20240902022309 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D46F07C42B3 -20240902023700 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D46F13D6B9B -20240902033157 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D46F444A467 -20240902074115 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D470264825B -20240902081217 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D47041D069B -20240902085634 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D4706993BE7 -20240902095212 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D4709C080DB -20240902103310 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D470C00A7DB -20240902113925 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D470FB7C81B -20240902145636 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D471ADD1BC7 -20240902162039 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D471F910B07 -20240902162513 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D471FCD9837 -20240902170958 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D47224EBF47 -20240902195925 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D472BED92A7 -20240902201041 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D472C8835C3 -20240902212334 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D4730A0A15F -20240903001824 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D473A91EE3B -20240903003705 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D473B9B08CB -20240903010010 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D473CDEB7B3 -20240903010348 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D473D0B3A67 -20240903034119 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D474614297B -20240903040728 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D4747910563 -20240903051146 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D474B45E3DB -20240903064823 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D4750BE2633 -20240903064907 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D4750C0835B -20240903101831 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D475C6B64DB -20240903113322 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D4760A047BF -20240903122505 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D47638D75FB -20240903124220 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D476482E71B -20240903133142 2 6 100 8191 5 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D476752BA3F -20240903143834 2 6 100 8191 2 E90C219E279F374756F460D972C0503655CE6346FD0F611E8808CD4ADDDCE308981860661516592055313E99D7CC26BBCEE76FDE697801AA2827379287137910127F9107DEA68C3FAD7DBC9DADC15102DA2C4D890186E4279C8590E5D3F90E1B93EAFA540386086C4B55AE83AE5C7EB5FD9478B16F1143BB97202E24CE3FEE6E314B308A8CBC1F2938D7013654B6A5D141D4422375EDDEA2C2011231C5C83F318FCBE6A8FBEA20D8E9C2618D45DEBE36611557447900B4B8248A25E4D523C3D9DCAB1F1C1A7CE5EFD7FA4B1BF34486F5737F61A94C20D9268CCC52785FBF8CE06D605997A8DE54E76D7F566582C8C064E244151FD43E7B97368891F274FF1D1EBB9627BEBE9B9B202E656445873198D32286D9D8F9F0387D3ABC6C0C74C9FEC8FA935C5F43287AA191591A6ADF80EBD6EB5B58C2524BE2E2E3000A25345A7D082B7AD136133E87B4BFED4C20EE58055EDA6E9D2E2F15E299D14E11919F2C3029CE1C818D5D30EA68D0458F3B1AB30923F55F84A3BCF14137B547D56CA353F3BB7EC6F22705CC0B14FBD8D7E869325B688AA759C30FAFC74A01567BD785F4ED1F0ED1B7B82F00467A687EC3BB12A246B620B2FE0B9783C222F999CCB7CEF6FA2E3FE4DE652FC0C4B21FC4DF2CEF7981F644FB2158B208C71C68C6974D4D1090C830379707BC30C7748487EB922A4B40CB0FE33B5B4A8E22354ADB2020315D043706D608B1213A2974ED5CC6EA8A520E3147667DD81F4294313AF935C528C82B659B7A169F4B11CD03A3D35546A4E4E2FF79DB6173F3A762B22EBE4BE5B49DD4951A6BC27D5EDD8486E2105561B9BE23F1826BC0579A482AFFD99508E09F17A20419F56A31AEFADCBF816706BC1B47420A7C66A19AF1A725D691CED949F9135404B35237E6B07A037F87F4515B7F1FD5B2A7B3B562ED121A12C1B4BF9E408A0221922B10B78B9D75B81381853BBF734BBE33E12602D4191BCD47B57FA20803F1D75FD4D5A077D50DD537A6B38AB09A1A3C1B30845A0D92AA38BD1B7D1F1AA1AC9FE9CD0A0DE23BD1943A99793D18FC08BD9D7744B62D460263F879087A996FC2868675FE43F7026C6C3C93187C629AF58038F61E3072D8A4B42ABFD1639C5F2289E0A974FFBBC67FD2BAC657BC3C582664A6AD8B940E8F8596FDB8B6429C1A1F06AB1249C9A03F271F66550503E9613277D38DC63031F21AA7C8C9B2D91D6F6B7C036BAB18B5FC8900E4679992DE4BAA2CF202787D521D1545AF4A090E8E17F7E8012C104791D2F6025A41C543F9D85C1DD3EE5757CA2445697075C87D0334FD0F5C9AA8EAFF4A8A4AAEDBE7F2C80151066C7A0F05B3A6B6E5EFD1DE7FE9C53421A00BA9917C732D4735ECEE42CDE994FA6DE2C171207B2A4ADE76EC4411C2171F7C7A0E05C37E3BE842F224A3F8FF6A55DC806FC3F7904147910B6D476B1AC6BB +20241129001801 2 6 100 2047 5 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E329A8EFF +20241129001804 2 6 100 2047 5 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E32AA678F +20241129001808 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E32C4EBAB +20241129001813 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E32EB8EAB +20241129001817 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E3308D17B +20241129001819 2 6 100 2047 5 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E330EB1EF +20241129001825 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E333E0923 +20241129001832 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E3370EFD3 +20241129001904 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E3471A693 +20241129001908 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E348736C3 +20241129001923 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E35021F83 +20241129001930 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E352FB613 +20241129001942 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E3591257B +20241129001946 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E35AB042B +20241129001947 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E35B082CB +20241129002012 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E36777D7B +20241129002017 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E3697886B +20241129002030 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E36F5B2EB +20241129002036 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E37249BD3 +20241129002045 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E3769C1B3 +20241129002059 2 6 100 2047 5 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E37D6FDAF +20241129002102 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E37EDB2E3 +20241129002105 2 6 100 2047 5 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E37FA449F +20241129002109 2 6 100 2047 5 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E381694E7 +20241129002127 2 6 100 2047 5 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E38A56437 +20241129002141 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E391852F3 +20241129002144 2 6 100 2047 5 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E3927ECD7 +20241129002150 2 6 100 2047 5 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E3952495F +20241129002154 2 6 100 2047 2 CAA48956B64FC48DD5A4823E073002797519479815F1B8D4AAAB1748CB28F30774053A901B0A52BB700F0AFB1C23E06C63EEC4326CFA484724954492B3703B50C706447754E091B6F69DEF32413B230FBC521D3912A2A030258ED841F28BD56BF27A3543756DEA1BBD62A44E66D80B22D9B41045E6DB0AFA700156862E4D24F682327787A9E10BC63D2E5F303F19109E1E3BA661635E34BBDC98BA711DFF7F7710CF632D3DDAD5B3B2539B61A309AD1BA93A60A03F1ACF9F89A6B166EDBBBA0B8160993BEF2FE072E278CDACBA5BBE44D9D5F353158DC4AECABC6EF9E16CC7DB9E5D697D3B42E02B675FB800D91F7CE79F553C6B610320EEA13FC56E3971FEDB +20241129002226 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C8F34FC6B +20241129002249 2 6 100 2047 5 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C8FE809EF +20241129002253 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C9008BDF3 +20241129002312 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C9099D883 +20241129002320 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C90D2E5BB +20241129002328 2 6 100 2047 5 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C9111A1E7 +20241129002329 2 6 100 2047 5 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C9113E88F +20241129002336 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C9148164B +20241129002339 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C915E0DCB +20241129002340 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C915EB103 +20241129002420 2 6 100 2047 5 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C92A19C97 +20241129002428 2 6 100 2047 5 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C92E090AF +20241129002433 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C93040BCB +20241129002434 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C930B22CB +20241129002436 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C931188B3 +20241129002446 2 6 100 2047 5 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C935DB5F7 +20241129002507 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C9408C96B +20241129002510 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C941D429B +20241129002527 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C94A15E73 +20241129002528 2 6 100 2047 5 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C94AA3DAF +20241129002531 2 6 100 2047 5 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C94BA0ED7 +20241129002538 2 6 100 2047 5 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C94ECC017 +20241129002543 2 6 100 2047 5 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C9511A1BF +20241129002558 2 6 100 2047 5 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C95871257 +20241129002602 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C95A7B2AB +20241129002617 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C961AFC4B +20241129002644 2 6 100 2047 2 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C96F5DDA3 +20241129002646 2 6 100 2047 5 D62BDAF38E54FDFF0C708C3A9D5A49ADD950102DDCE4017B0B90CB32FE8736EE054C70F834E7196596829647330A22260674F15C124DFD61BD6304ED8DAA2BAF03E37A43714575DC4E50D30EB36E31B994DA55D6CCE62E854F087F56587D5C04E2907BF39AE275B9B5E0353A50453DA96E714E11E5A00F72680903B482731C04A0791B018B4FDB5D2EA1DE235C20CF300B0C1CED91A218390A09DF78C1877BB35E0D92D22ED647E32EA5C9F877B589B4A8F7F6685715AC5E0E5F93DB5671E028A9DFE1C66662C94A47C19FE0ED1B9C9BCBEA281F705C358F792091DE4A2F110B6B68E4AB15D6B30C59C8850D1E436BDDABADF17ED1E8881271CD1E7C9701A557 +20241129003212 2 6 100 3071 5 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD31A6F92F +20241129003232 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD31E1E02B +20241129003238 2 6 100 3071 5 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD31F02307 +20241129003247 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD32089003 +20241129003331 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD328EF3EB +20241129003450 2 6 100 3071 5 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3388738F +20241129003549 2 6 100 3071 5 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD344433C7 +20241129003558 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD345EB43B +20241129003708 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD353F77AB +20241129003723 2 6 100 3071 5 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD356DF4FF +20241129003747 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD35B352CB +20241129003812 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD36020023 +20241129003842 2 6 100 3071 5 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3660A2C7 +20241129003859 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD368F747B +20241129003902 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3695A29B +20241129003921 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD36C9F673 +20241129004005 2 6 100 3071 5 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3753CA0F +20241129004008 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3758F683 +20241129004208 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD38E3CD3B +20241129004221 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD390C377B +20241129004322 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD39CE5ACB +20241129004335 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD39EC486B +20241129004341 2 6 100 3071 5 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD39F7B37F +20241129004348 2 6 100 3071 5 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3A089907 +20241129004413 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3A5136DB +20241129004447 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3ABE89AB +20241129004614 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3BD9A0DB +20241129004627 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3BFC1AC3 +20241129004630 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3BFE5DDB +20241129004648 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3C3863FB +20241129004754 2 6 100 3071 5 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3D09984F +20241129004835 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3D875973 +20241129004842 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3D958953 +20241129004906 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3DDF57FB +20241129005005 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3E9E3063 +20241129005036 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3EFEEAC3 +20241129005052 2 6 100 3071 2 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD3F2A5E03 +20241129005537 2 6 100 3071 5 C94F41FDB4E54DBDD1C7A49F586104E6D74F4CD07A2B9730A4FB5D40C24AB929C55B955144ADC62AEF2DF80D151E4F20E946F69C9B7AC7F01D1A916F3C1D23984DAF12A5CF18C5FDD9922AE0DBFFB31E9EAC765DCF315EBB0524E8B9246BC97169BE71440DF64D5884F63D9ECC8C96E312169E71BC1D25DCE1AE142F6C4D265BA36CBAAC0860E6C83C26B287461F4FE90C5D2CAF4A87937E12407CC632618086D75FB5A17ED87F8EEE71893A6890E74AA378BD6B91CD4CF264F0826110494D2492F6A45567AB8FF4C28142582D3E66E9D3961881DFA1877E2EC993E31A35017C8291B0C74BCF285F94BC6E8B5D0EDEE7F571BEDDEB32184688CB221D1E42A74657FE9AC83679E51B925D617069FF259975C40D370D0D51F18D1C17358B9C197B00893AEE90BA06517787E8C4884E783F2A4B7633C62E7843B743688FA6296F11A6F4D584C2905EADA2076D289449F5DB07E2788F021D435DD188563CDAA1C89B0E7E87017788634AF18CAD9ADB8BA18E80C5BD0BE1424FF9135B07DD42DD9C2F +20241129005637 2 6 100 3071 5 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB14E5B5E8F +20241129005819 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB14FA714FB +20241129010001 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB150F56483 +20241129010010 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB1510A25CB +20241129010049 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15189B8EB +20241129010057 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB1519DABAB +20241129010104 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB151AE01C3 +20241129010114 2 6 100 3071 5 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB151C91AA7 +20241129010216 2 6 100 3071 5 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB1528CD42F +20241129010239 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB152D65F33 +20241129010312 2 6 100 3071 5 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB1533E97D7 +20241129010433 2 6 100 3071 5 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB1544811A7 +20241129010523 2 6 100 3071 5 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB154E65E7F +20241129010605 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB1556C058B +20241129010625 2 6 100 3071 5 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB155A73F37 +20241129010718 2 6 100 3071 5 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB156533A8F +20241129010827 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15733560B +20241129010830 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15735A50B +20241129011308 2 6 100 3071 5 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15AD92877 +20241129011325 2 6 100 3071 5 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15B0BC97F +20241129011417 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15BB2F9E3 +20241129011431 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15BDC12E3 +20241129011445 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15C01B8F3 +20241129011511 2 6 100 3071 5 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15C508C4F +20241129011527 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15C8110EB +20241129011531 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15C85C703 +20241129011741 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15E32BC9B +20241129011800 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15E6A8F93 +20241129011821 2 6 100 3071 5 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15EACC9EF +20241129011823 2 6 100 3071 5 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15EAE50DF +20241129011852 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15F060CCB +20241129011901 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15F1D181B +20241129011909 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15F313CBB +20241129011934 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15F7E3BAB +20241129011958 2 6 100 3071 2 F72B9D5B478FC38253834B862A5C515BA6212BAD106C43D243A9D021FF22434E6A1EA03FBACFA23A6FC66FE5C68B40013BA6D15844D35AA2127408DE731CCA98380661EE30E2480E9DB14A8EB484BF564838B45678ECB78800E41E499307253A0E4462C7E119ECAA096D496FF72C5CB823C5C38CC165B9EE0B5307005F9FE72FE34EF3C2EF456A3A4561245680205533E2C2DC31816DDFFB036922109B985F291F7ADDCA11FADD48E7D20C9F8D0E8AE073C4DD7269B1EF46ACC81BE52A053EFE3BEAB1BFA3822A10ABF2C95B27D406BF960FAA48A79D332A7138AAAB8828B1BD11BCE47ACFE934887A2B2DC6C7061EF8412B4912925FD5A9CE787C434B3FD5B39FA863EDA542574E22331F98E74F69283A9A8F9330FE597B1EE96E37C8DEBB0E861213F3BF5281F3753CC16B2AF1EAB12540517E0482FDF47C92B66C4CD5FA5C8725956DB4C5F435EFC44D2ABD17A078687DD7716CAC4683729BD6211E0CBADA144F28932906724F3B96501D1A897C088607B522F8C7586DAFC64CB15FCAB1D3 +20241129012819 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE61ABEADA7 +20241129013011 2 6 100 4095 2 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE61B67DAEB +20241129013110 2 6 100 4095 2 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE61BBE4D2B +20241129013508 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE61D3A05EF +20241129013753 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE61E425677 +20241129014404 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE6208D8717 +20241129014416 2 6 100 4095 2 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE6209BD93B +20241129014459 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE620D787FF +20241129015136 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE6235DF3D7 +20241129015320 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE6240443EF +20241129015547 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE624F1AF5F +20241129015908 2 6 100 4095 2 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE626346E0B +20241129020133 2 6 100 4095 2 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE6271DA71B +20241129020353 2 6 100 4095 2 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE627F5147B +20241129020617 2 6 100 4095 2 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE628DC3E63 +20241129021223 2 6 100 4095 2 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE62B25B8A3 +20241129021913 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE62DC6E86F +20241129021949 2 6 100 4095 2 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE62DFA5673 +20241129022203 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE62ED03D1F +20241129022443 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE62FC9341F +20241129022708 2 6 100 4095 2 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE630ACA413 +20241129023102 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE6322B2317 +20241129023226 2 6 100 4095 2 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE632AFA783 +20241129023234 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE632B59A57 +20241129023429 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE633681547 +20241129023526 2 6 100 4095 2 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE633BFD83B +20241129023744 2 6 100 4095 2 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE634998373 +20241129023820 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE634CA05CF +20241129023919 2 6 100 4095 2 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE635285DD3 +20241129024116 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE635E04407 +20241129024436 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE637222687 +20241129024611 2 6 100 4095 5 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE637B833A7 +20241129024935 2 6 100 4095 2 D14DC7A20FAA787E8E505E1CCA5C3EC8C5344CE26B9E5E776858C7048EECCB2CE278073BA42E21E4512A91D9A94F6460E86A914FC8D560A29DDC6B3E45CA1F9E8C5C52057BAF6A992E0C04192CEDF05010493D9CED8F97D3891C7DB13865BCD4BC19EA746AFB39E7AC2D60A32D9B77EECFFA53E7022137B7587E5D18E2B100845108104A79B878405B8900A0837BE74494F45DF726B88990607580414CEA1358A78BF832447919460F37395E69BC30E81983D60BB71D4E86164317138B99B545416467AA1F8592A16CEA1B050D2554487A749408A8339FFCA98A5F23D4EEF7A4254C6E56BFD6B95AD3C822B83324BEC5DD85A7064C6233899F7C6D00749D9DEDBAD9ED72CCC9CF154EF3989752DF907B24E587CD6B29A22846CD1B9623A3AEF69D191E8C048046FBCA2BC2C2A0883C8738F72D612745419080B7D72D8EC2E696CF5CB5EB6F23A9BBFF4BDD129970E881DBAA81E2F1A1445C773D4445ED516D1D954C64593DF72B7B31810B7493B8334F57E79FB26554EE1B4E7B7BDAA2C707D8E4798549DB60AE0A064CA8C6AA36021EB1657E72810E676D0F312325F2FAF956DC336D6B8E1496553362292D98225D61A74827C43FD4B4E0242B19FECBA7C102940C24AC56BB287C739608441EAA2EAA6DE0D1323E6D45204A1FF07BC3D3A48F954597EE865531D8A32C1DC2A3A48C8A0D47BE16919C3DF9E0514CE63905717B +20241129025344 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD87AD5A3B +20241129025405 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD87C61B07 +20241129025445 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD88010893 +20241129025701 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD88DA8ABB +20241129025807 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD893E4473 +20241129025930 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD89BD17B7 +20241129025947 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD89D220C3 +20241129030824 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD8D22E89B +20241129031329 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD8F0BC07B +20241129031515 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD8FB3CF27 +20241129031807 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD90C1CCE7 +20241129032416 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD9313280B +20241129032613 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD93CCA2C7 +20241129032705 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD941819BF +20241129033035 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD9564B557 +20241129033357 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD96B187EB +20241129033421 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD96CEF60B +20241129033539 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD974904EB +20241129033708 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD97D1728B +20241129033818 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD983ADCCF +20241129033844 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD985DB957 +20241129033919 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD9890287F +20241129034126 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD9958DADF +20241129034406 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD9A557F5B +20241129034820 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD9BEF30FF +20241129035154 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD9D4E229B +20241129035209 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD9D5EE0CF +20241129035316 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD9DC2D03F +20241129035349 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD9DF64ABB +20241129035856 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FD9FE86E1F +20241129040054 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FDA0A085D3 +20241129040234 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FDA13D2323 +20241129040334 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FDA19957FB +20241129040452 2 6 100 4095 5 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FDA2168307 +20241129040614 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FDA29615EB +20241129040924 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FDA3C1BBEB +20241129041726 2 6 100 4095 2 F32300D8DFCB79ECFB80E433E6CFA1923915D80120F52648A7AE7E8058B5DB869F2B3A9DD940E53B7D74E3214FA03234F8B026AFF16B646B39F003882F1DC17D3F6DBB89283A01B4C22168A354D6D2FDBDE3F2B0C91E9472AF1DB386DD34477F47CB24D4AFB71BB283A9760CF4EC582F1401A4F259D4AADE2BC7648A6920207DFB149BB7A4483D5E22D9DC627A8A4954C18AAAEF921CE0C597C11C95EC7C8888050124D01C43E6A33A02DACDB2EEE70920BAF2A296EB38CEADCB98CC7789BA309A5AD7916B9F7F86B0D808346E28447C4E3F31C5BC319D29A0D338EE8FC88BC9288C75004CC278BB218AA86929360079EAA71628FEFB796FFFBAD3764F677FECC0F274582ED2E371ACB500F35F378DDEDB0FA32B1B55699E41EBE958E6614811999433D934CCD54A03CC4BF359798F90EC809CFA6E58C1CE68B5AF397E8E35951F9CC4BCD0EC8655486543B4CF7605CE15969A2D88E8CD6BCA82671A06FC54397840BBA9DB2750B0F1FBC61ECF6E514450A7E06C6E6BBBB2CFA5E045335F04A5C407EC6467D471226ED2CB3AE9FBA9E956F8F3D05A911F9CD131BC3D95A10792097AC1C4339F8C12E40ABD274A25CF26EF286187E91261273E39856C471D861056EC3F6F5E58EB727134F9BFB870C8DD6978F247EAF67C1368BCB0BA105CDDC2BA067EBAC9C00DC15F1667664AA2A688D45E843F62467892EE9348FDA6CBD37B +20241129044525 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33DDF12A47 +20241129045351 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33DEF75143 +20241129045821 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33DF7D9E33 +20241129045943 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33DFA1A9DF +20241129050501 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33E044C313 +20241129051930 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33E20AE0AF +20241129052029 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33E221299B +20241129052420 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33E294985B +20241129053040 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33E35A621F +20241129053505 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33E3E2DAAB +20241129054958 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33E5C2C407 +20241129060731 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33E7EF06DB +20241129060801 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33E7F7359B +20241129063045 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33EAD325DB +20241129065049 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33ED529283 +20241129065931 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33EE615997 +20241129070906 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33EF8D1D07 +20241129072522 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33F19250B7 +20241129080348 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33F6682AF3 +20241129082342 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33F8DD796F +20241129082407 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33F8E28AB3 +20241129082555 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33F917C303 +20241129082910 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33F97B2DB3 +20241129083433 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33FA1DB177 +20241129090902 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33FE76C9B3 +20241129090942 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33FE840CCF +20241129091044 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33FE9F0AB3 +20241129091214 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F33FEC8962B +20241129100858 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F3405C51773 +20241129101114 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F3405F7D2BB +20241129101614 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F34068F4943 +20241129103634 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F340916E6EB +20241129103953 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F34097696F3 +20241129104959 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F340AAE5B3B +20241129112051 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F340E9853AF +20241129124108 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F3418BD011B +20241129125049 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F3419E8F797 +20241129125233 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F341A1B7937 +20241129130334 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F341B7BA49B +20241129130855 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F341C2258EB +20241129130953 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F341C3B9397 +20241129131555 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F341CF54C93 +20241129131844 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F341D474B9F +20241129132228 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F341DB5BA4F +20241129134604 2 6 100 6143 2 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F3420A2EA6B +20241129135907 2 6 100 6143 5 DCBE8A152DD5DE612BFCCD18CAB2BDE17391AF9DA865DCC59A1B454144ADE2EB8BE3CDBA7948CD1236CFC25D66DDC0E91095FB7E17715247413BBFD5435223F46488AD93808AF9FAF7D473C7CCE55DAA83B417FC6C09BFF7E332BD4B3BC59CBA4FE035A6C416D32BDCF8C3B9AFC5E1120CFD420023FD8EB207DB965509E2D362B0EB3D8CBD191D2750EBEB05F32C4BE08154D991F08DE4914BC40FAA7172440F2FEFB0FBF604DDA9C18BA9FD55F34218FD5D7CA2AC491CEDC3C5743D143BAF6C06CCAB7E5B22AB4E46CD51962CC7931F4D35581D5DD3047B946044BF7E71955EB63DD546644D7D2A19777DA39A48B4CF5A011A5C41F1BFF7C463F057F2F7AF6F910E7E06398B0AF7EF38CD5BBAE4C5FF42572CFFFCA6A8E9D34F64A7BECDC93216B55C20FAECAF04A8956C4D26DEE34493510BC49144A32A1B0AAE64B50DCA0C27361692242FE3145A6B36B830DEBF9E8A07A886E8DA6F38F3E99906F6AC9317ADF73222C4C75ABD153F1112E01E7CBB49665F213A1C1470CDC442D7CDC72EE2DD80D37251333C34FFDC5C38ADA3F5E52F5A5B2A1224B0CA60211B430E9554F0C4CA672476562C4A182B6707EBE80DFA6247A1F870F74EC81D03558F2718409EBF8E7F2FD2C6AB1F246F7E3FE0D919DB4016A7D76F6378D05EA74766CBB93340F2CBDDF18073F39242F3E9EC88020D1E8F801183C00F0239B2F2B4E8F6B46DBC17F469A857C291C985D8AC2099A6FEDC462B5EAEF737831EA2B6C9D787DC5AC8DA2C2E8F7F676FDA4CDD79E400EED959882C78C279C4D0A5918A0F5FC3B695E0034F7C2665D52D94106744D6B0CD6A66AB3275324EFDC06ECCF431D446446A00818ECDBE77B845699FB4F699825702D00F71373D80452039ECA1237AD2A0DF9112BA1EC90FB9FB87CF4E46BD0319B64F2EFD4B9640469707DB549468781D0BA6F3C49AF035D441173786BB1F2F5DCCE07BBF5536A0EB5B976814ABFDB44B90E55455972701A8F0D8EFB860A082ABA960E704754F61C2E3956922833F3D7E1656476DEE3C4F09244AC15697EA4A73041F03EEDE1F30BF899098A70F34223A233F +20241129143314 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C7A9949CB +20241129150941 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C7F2EAC9B +20241129152304 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C80D59DCB +20241129153351 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C82259357 +20241129153442 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C8239CBD7 +20241129154346 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C835408BB +20241129154536 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C8387126F +20241129161648 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C87770FCF +20241129162459 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C887B826F +20241129162918 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C89023DAB +20241129165526 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C8C3FAA43 +20241129170725 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C8DB7E57F +20241129171144 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C8E389D1F +20241129172847 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C90533393 +20241129173154 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C90AFE143 +20241129174539 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C92621483 +20241129180732 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C951D8D97 +20241129181538 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C961A0AFB +20241129182310 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C97054E47 +20241129183550 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C989CFDEF +20241129184809 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C9A2A2BAB +20241129185633 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C9B335EE3 +20241129190213 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708C9BDDE8CF +20241129203945 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708CA834CF13 +20241129204138 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708CA86A90F7 +20241129205210 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708CA9BFC2E7 +20241129210035 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708CAAC70D2B +20241129210423 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708CAB389E37 +20241129213344 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708CAEE209F7 +20241129215808 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708CB1F2A1D3 +20241129221635 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708CB440830B +20241129222503 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708CB545F1FF +20241129233015 2 6 100 6143 5 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708CBD76AB7F +20241129234110 2 6 100 6143 2 D530FFAD12BC56C29F02BEFEC6CFD700AE6DA852D7256FC0A8978C13FABF9851425A26917CD40A9919A06A5B17FA05456642891442CCBBBD9BB5B74068213AA6F029B3419F6B2CCB828CF9F6F0069F43A2496921ED8133BF2D9C598486282EB38B3B6E849B7D80B33869CDE1D71379C694BB9C229B5CCE5E96692F81DA73EC38942CE60A81657F34A6B1B536ADEADD76144A209815A88E081E0B96438B11A34E4F8082ACC6DD77D787EEA90E1764F7393D3869707FCFCD4BFEEA3582BBD39C17E2CE70B6A193700A055A50D2F5ED473DD9B4401C2138BAD8FA3331BDD4FF79E230C10B13FFE7CCDB3210F8DB42147BB8349CAEA97EBCBC708B9CE16360D573D3327BBCAA6387234E9A4DCB2E67784408ADB72B2E05643520211C581EBB38E57C2F69C9034143DBAB4C13221D501B892918779C6E9AC5B39F2F412E31EF7F7F0610C2AFE150FA56A5E3CF9DACA6C96F3BC6B57D56B2869019C5114247C080752E4D42B1A0E34302B69B8516E8FB93BE58CC45F6E5ADB47A89A00050A12D560BEEA8997F5A0FA526C107BA34ECB0C678079C6DD4C1F4666BBD45733E019C292A17661B79E6AEED002EF4F6E7F4D569690E140C8BA1BA47E626499E01DA1EACDA4B917507A472DDB03A86734994C4B16551C5DFED3C8C976D15B5BF68CC6C982355930E37F096629E6F3BDC8027C722C12EF76854F1C607341E48FBF8C9064EB48EFDA87E1D111B557FBE7A15A580EDD87AC2CEC0EB25BE057FC20D578DF34632977F4698D58B2025C50AD4AD77D16D32E6157F89F58C692A83279A2EB58F8E448A13AA32B8C3DF07A58100EC4BB319F824446ECDD643C4A7F959CBA4E356A9E5DB7332107B2EB478703BF44383DDF80CA297F5E52A4424AF64B50CAB4E9C95C7288B96F8E77CDC63D07C6394853DF32F926652A12122B5531F90CFDFDAAC5D0642F84CF3901717B652122E8622CF31C06D134AD921EC80D175BBFC45B855EB9ABF001686BC52730F754DBFAE781BB629F1E530632D813AA256D0063202AEEE0AB64C7829C1A6C4702E27C88219FF31500D8F76BEFE4AEF726D6E3B708CBED26FD3 +20241130004028 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C6132BC003 +20241130023838 2 6 100 7679 5 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C61B09AE47 +20241130030155 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C61C91151B +20241130032532 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C61E1854B3 +20241130035131 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C61FD56C8B +20241130035951 2 6 100 7679 5 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C6205D0C3F +20241130040156 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C6207AF313 +20241130042927 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C6224FB4F3 +20241130043039 2 6 100 7679 5 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C6225C64C7 +20241130054524 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C62750439B +20241130063335 2 6 100 7679 5 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C62A7BB5C7 +20241130074248 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C62F113613 +20241130074437 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C62F28387B +20241130083311 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C6325DE613 +20241130093434 2 6 100 7679 5 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C636728027 +20241130105425 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C63BCFA3E3 +20241130105534 2 6 100 7679 5 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C63BDA41EF +20241130105809 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C63BFFF55B +20241130123724 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C642A90F43 +20241130131041 2 6 100 7679 5 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C644DFE51F +20241130150424 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C64C717C8B +20241130162824 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C65210D3FB +20241130172212 2 6 100 7679 5 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C655A47F4F +20241130174557 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C657367ECB +20241130215425 2 6 100 7679 5 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C66800A377 +20241130230337 2 6 100 7679 5 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C66C9D27F7 +20241201025521 2 6 100 7679 5 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C67C131CEF +20241201034250 2 6 100 7679 5 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C67F375247 +20241201035354 2 6 100 7679 2 C4FD13B23C1EF3F1B888E9E24F6E6F0D1E538D5C17287A04247451367BAAC3EB0FF3633A10C1B2BEA19F91DA18C0C52A465FA0F0371A2189AC36BFEA58F33B013352F321A0B71BF61553330EC7735E66BF920F0AB9C918AC6796F3B2C5CC7B0E9F6695400B692026845D93807363115D8E1EF92072B84941DE896DC222F2493FA43169DC5C94E9F7C645CDDC38AC8C8F8790A2078B755BF65EB099CA5682E186E7DE95CBCF7036B0BFC761137EB0B297A140C1683E9A14E78F31935D873DFB2CC33563980FD7C6EB609427A9A63D9A7ECE43889783FAF17D129A4F00A7DBA8FAFCBDD57FA7599C944D03297B7106E02A82D695E8BC0ACC860295F357FD2F60CC4A09E49450CF735A8756174A8E1458E3BE2BEA10F38D2C30E6AD7DBFA6835328A64BDFCA2318E1753C922D3AA467BB770C03BE0D3381E31655F4969009A35E4CF90B1EF5CB71A7BE424E952AEF1368142BB6E5AEECB9F7EC2034179009B7E57DF234CDDC3818BE6E637DAC7F44B109BCAA519CA77B27E4A119712A325ACC29E82C5A3E43CDED00A550ABF99495C802578A6ACB7DBCCCECD3A3857F01A9582671D87C9407409355199D627D316938076334BCDEC6635E0D6696A53E2475AAF9412167245779FA0C89CC3C08BF90313C68710D0153A3B8FA06862B6670E9498296D2C1840812D51FFEADDAE3D714A6EA7D0DAF18C134A0E26AAA99AB8B605E5FAC1814D13F5BCA134DBCF40B5C21F39EF9B4089A759876E5F22DEAF3C64DAA159B9AFEB76109429E3E42FF8DB74EF84954405C4D7B826CFBE041FF996CB053ED44BD32742681CCC843CBD031CD9DDF299EF150378F87B5F67768C77A69F779AABC032BCC3031DDAD83701E475D16040D1E064208D99313C4047BA2AA44E15CF631E4337A47318F34060DAE2ED3FB2F77F26CAF51805D86F82786B8CED61C0A0A7A8CBECD9AE3FDD266BDA632E6F6095A8E2C82A709EF2ACE20D66CC6709A5EF4EBFBA3B020BD15A5451673CA3780A459C277EEA72A1C9EF8502281BF903B2409971DC1F215C899CBBDED194CAB8A5EBB2273E3B67AEEE9A18CD03A1CC46312AAE59AEA0EFB0E5EAC8A62D6C49DC5B5D5CAC7B12CC2B293ED1D258149C6E8ADFB311328C1D5ACD4A92DFC71E9575A62920166893D715358DAE87159E39267079FA5D2EF41D756E01E0D9701BE7F715E4DCEF5667576A883DC034E36022AB62707C4E9FF9C7400BD29770FC07C66BB041F17204A63B6A52177F32B1E8AF15A818E946421552673488AA76253A5CCAEF2368C6464A36DEA011A56FFACF5F592099BADEFA4B7A72059FF1869864BDDBD14B4D32460CFD30E78C4F057F011C67FEC05DB +20241201043654 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0D77EFCE3 +20241201045113 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0D867EE3B +20241201061048 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0DDAE0C8F +20241201072458 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0E29A61DF +20241201073945 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0E39422AB +20241201081137 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0E5B1C16B +20241201084445 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0E7E0CB7B +20241201085943 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0E8D1F5CB +20241201092406 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0EA661BD3 +20241201094424 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0EBB93913 +20241201104106 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0EF85D8F7 +20241201104452 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0EFBC6D8F +20241201115450 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0F464B243 +20241201120212 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0F4DBBAFF +20241201123240 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0F6DA27E3 +20241201130824 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED0F939BADF +20241201171234 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED109A1419B +20241201182756 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED10EB1D8A3 +20241201190812 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED11163FE8F +20241201191642 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED111F0947B +20241201195706 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED11498BEA3 +20241201200433 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED115134B17 +20241201200527 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED1151A85B7 +20241201205110 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED1181F734F +20241201205604 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED1186965DF +20241201232404 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED1224C1B97 +20241202014307 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED12B98711F +20241202022245 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED12E394097 +20241202032328 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED1324BD55B +20241202042741 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED1368D4BB7 +20241202043950 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED1375589FB +20241202051314 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED1398AB80B +20241202054231 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED13B77C653 +20241202054750 2 6 100 7679 5 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED13BCC7297 +20241202061721 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED13DC0C9B3 +20241202074137 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED1435661B3 +20241202074315 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED14369BF1B +20241202081741 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED145AABB1B +20241202082834 2 6 100 7679 2 F02D40B37C40876939E4D2A62AF7EC21A676D8E2B04081BA98E23F464A47514FB40DC99F7B8046B48CD3052C7AC080E4B496C16ED18695CA27493A129088F5829BBEAD02DFD521829FFD8B1120330E2BBA10C55A1EAD0641006827DA4725BFD2A2559C363C33BC78C2D83B4A075099EC57634D0AD4AEDA3302441B7005C728C0371B51877A97B442C5E3C3D53C244EFF3B65CDCCB0C017723F1EBD0B91E220116ACF14703268A11B7FC7564F7BEDBFFB3CE046261DD9D83E6078CD7AB5AC97595EF53D6C4C56D24588C6D130C0CD2C967AB90C31497186A06A93FB9338D4F30E0104BC8EFF2518D0644174BD1FF1FD7BAC2AAFF151D733A14F456A189ECA2D5F11D7C3AF1DA06192D36251B050E1AC576E3C369678D12823870FFC6E5809903382F9FBE36156F294C94FF5369E8D24D085A326870A998A10683495CEF15EFF0A45C781B5156B82D9AA07852040A96A0D5ACDF094B9DD91EA893382F95A6B72F0A2090F036A1B23CF9CF544753EA5B9ED86FA52EBB4C5421C5B485AE932F5837822C91257EC4953ACA79F2D94261DC40B3D44CB44056D4025EC459563865000B8C5F5D7724ED27CA4A8ADE299E5C898F4BD09F430781A68C261E4FA0BA2FEE567434B057C5D5F2899A1547B780B91315CC631C0552DB403DF53A6059BE895242FDA4AE1F6C5129E3643DF1A20C28BBF4328B4E623DCBC1149CE838BBC4A9944A6B6ACB4AA29B50FC7AFFAB0075BB4CC190F15B2C17847560F1B4C591EFE90D5AAA307A3FCC091DF44E3B219F7EE86EA01704D652983CE0D475896C1EB94E09314D386233D706FE0F5415BAF51746F3E8A6AC74E6F68CCF665CCEC4BE0B9CE19308C0423491F5914EA8ABE6081F38282D4994A4B640DCE56F4D616CED59B80938E4E7C486AB64E7C740FCD6ADB5494906520FD66A02069D3C11085157142CDDBFB004023C5CDFCCEAC5296636A77C127DEC4182A36D6A34D980F778452271C80CABAFE15A629302EFE9CD9105353B719581D4DD2E1BCF9411A4CCB0D010B5954291453E761A3B9EAF533119EEF1C30C4E53FEFAF2D2300162786963D54ECE0376CC797CBBDD757B596FAB26716ECEA7C47FB6C6DC6A80FC435D5CADB36D5ACB6760CAC6272B61E64A920EC7D4E5FBD680B2B906F1CF78EFD380A47692E1DC6C06AC21255E65C3757E32C301B5ACD8BA136FEE7C19B858D8B60595946BF1D0520912ACD17E397C9FC156C741AD1104F403B363B4E6B4AD06E8C60928CCD6AB3FE6AEFECBC57DB5CFF431A2D44533D9A92C483B56AE56698F02622D3A65E09B6EBFDFD5DCAF34E09DEDA100B40DD4C40ADCEF30787E527C4F613A08BDED1465C7B4B +20241202090408 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474B4AD895B +20241202092818 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474B5FD49CB +20241202101356 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474B8749EB7 +20241202105709 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474BACEBBE3 +20241202110503 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474BB359FFB +20241202111809 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474BBDFE367 +20241202113338 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474BCAC42D7 +20241202114109 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474BD0F195B +20241202140045 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474C4C2C8C3 +20241202145509 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474C7B5B2B3 +20241202180737 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474D23791E7 +20241202190603 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474D562B49F +20241202192303 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474D64A0887 +20241202194604 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474D788F30B +20241202202723 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474D9CE5387 +20241202210310 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474DBCBA17F +20241202232141 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474E3833667 +20241202234441 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474E4C55853 +20241202234813 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474E4ED7847 +20241203020245 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474EC649497 +20241203022338 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474ED8847BF +20241203022652 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474EDAC6223 +20241203031204 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474F0205823 +20241203043100 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474F484158B +20241203044332 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474F537BA23 +20241203051425 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474F6E6415B +20241203055801 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474F953468F +20241203062624 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474FAD661D7 +20241203075312 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F474FFA46B5B +20241203095857 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F4750696836B +20241203111915 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F4750B055A7B +20241203151709 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F4751817A103 +20241203162310 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F4751BBFB51F +20241203173052 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F4751F72906F +20241203182303 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F475224CDDDB +20241203194121 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F47526993A97 +20241203203340 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F475298312DB +20241203203518 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F475299334C7 +20241203220054 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F4752E4DBDDF +20241203220341 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F4752E6D1DC3 +20241203221452 2 6 100 8191 2 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F4752F062A3B +20241203224318 2 6 100 8191 5 C3301F39F3E2DCD097FBF5454401BF52BF4745AFD35F3DEBDFB34DE2518B0F7BB10DE2FDBE6C35E1B63AA67E9FC179EB3DB8A0FA7E01618BB625B3EC326A001A253FB737B2461999BAB5A5FBCA4AFAD88A8BCBEB5990D4E25225F203B2CE75A3A1C23BFFD78E697275BDB6B6153AA3C21D2063047D44EDDF0483220CD672280D4D67C4726EA476A5C094B7E8DBE62B760EBA6B62C200D456A99E87875B4B2FFF4AA87661D89CAF8CA36D9CE00E0C3BDA443B7CCC3EA892F524AD10DD6960196EC4497E1DDC9F5C13BAED9A8F240196633AB9EC597D0A2FFEEE9320147E73FB295039605EA79376C00D1C60EB421D1BF2BD36A9B68A32E5F5003F0C984E1A57B3C8A261E451D912FCBF27924078BAB0879F85B78D097B2651A17AD9266B39E7AF73DAE54319B2902E0A0D11653B38EDA14B9DE8431E9382AC7EF5F1705C05239DDEA7F533234FA640D2E1EE392D23BF46D57D6FD0E167174E6242F5455DC299BB03BF2EBAEDB14539E9025B84BF66C185AD45C6B1FBF47E3C17D4A1F2C99DCA7151039D71DB7BD2E025E67C2ABB9A2DE6D9C5150651385B270511AA50E8728707B1E0920F3A83DEC0F733090CE96DCACDB93CD756AB1F572DA2BBF4908C17E905848C09CF31424833D1D4894FCB6BD93162EC74E836A523E97F35152EBA28AF63DEC47A32C09E0F0451A4D60949C8CDB07642F5A705075F4A1380B327596C319A135C9C43BBAF2D25C90030BA43FC55701B2854ABFEA710D98AFB8341E46778616A9E9B31CF11652B47A76A99F096BDB35C9CFA78E47CFC980E5E8683E1E13AA3FCA5171C07B5E27C1A5002C02643DC760431C2750A29E838F6ED5A892146D8015F5879DA988DF030BB2FA4D501FB7F0AD9A82ED3C48B70979428C39DB04116DCC8337567B6DB4A0DFE0C704B3F46983BBF092847AED87699EE88AEB27756850D008583CD37FC8521968EB1D17FC42D742B7E6756303412A3AD011DD5CE2BA1A4E3B0B2EBB68736C76B02164C41204734B731DF4C00C937CFB49D4648A7808A34E6162526240AB221071C6C2669DB4787AF7D516F4E72EF81C7D907A37634E8CEC5BF4B3502A6A05224B269B29A8E44603DB2A890F9B64BC94AEC7D2923DC52985CC18E123C7D6CC3DEF885725E0BD2D3EC0466DBE2E94350368068E5FC1CFB6BAC40F47600EB8520A8E29E855D96B556002207CA234BE3620189767ED74ABA3D1A1CF3F66864312B7502C37C9543A36F24FD38A25137128FFE4C6CC7C078AEF1F799DA7F3E3BA0E19F21A707E66EE95189BDD74EDF32E0F18052384A2A180D90545EF1B9F2710074BC8AED5F7625C0851C34E9F3AE5C57BE65862CEE2891052CC442574EBFAAE1BEC7AB63F25C80951AD65A41089DE526946D858146E446FCAD6915BD59B0D112255083A711279990F87453A6D8F7D057055217F4753098A4FF +20241204023709 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C4569DF3BDB +20241204025228 2 6 100 8191 5 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C456AB453E7 +20241204030908 2 6 100 8191 5 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C456B95242F +20241204033647 2 6 100 8191 5 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C456D1E7FC7 +20241204055147 2 6 100 8191 5 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45749787B7 +20241204060833 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45757D2FFB +20241204064719 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45779594EB +20241204075858 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C457B89C8B3 +20241204095845 2 6 100 8191 5 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C4582223CAF +20241204102632 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C4583A5E7A3 +20241204133310 2 6 100 8191 5 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C458E07A8DF +20241204134006 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C458E603BF3 +20241204153923 2 6 100 8191 5 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C459507D47F +20241204154043 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45951265E3 +20241204161206 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C4596CC6423 +20241204161425 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C4596E4BA93 +20241204172055 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C459A8DA68B +20241204192705 2 6 100 8191 5 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45A16C53A7 +20241204212358 2 6 100 8191 5 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45A7E3BB4F +20241204213330 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45A86569BB +20241204221629 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45AAC0BC23 +20241205021404 2 6 100 8191 5 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45B80CC4F7 +20241205023328 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45B9166F1B +20241205040105 2 6 100 8191 5 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45BE03F83F +20241205055343 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45C44A5013 +20241205065151 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45C77D34CB +20241205065416 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45C79803AB +20241205074544 2 6 100 8191 5 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45CA71FBC7 +20241205081641 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45CC1BDF6B +20241205092757 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45CFFBAE8B +20241205110223 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45D53D4193 +20241205112040 2 6 100 8191 5 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45D6362177 +20241205112359 2 6 100 8191 5 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45D65CAD37 +20241205134041 2 6 100 8191 5 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45DDF2FF47 +20241205135041 2 6 100 8191 2 DC5E734609D91DA7E5180C89891C148715345D3A56F96DDFF41EE0B90992E9901E55850A78D9DF296A83F5AAF22675720E58E1F6D01F3B45315B818EF9CE880CE92F022763911796D4F86361BEB151ACB400BA017186C1DDCDE5F1853260ECF1082E072C2B7E2FD33E51B5076675269EC247AAE3DF3C1E6853E5D0E58FF7268255E91A9BF6FD43750F114BCA5DC70176ECACAF59C812798941D04FFFF200B53F9843066568A5EF6B324692239A9DC94383C53DA447D942BD51E17F51C22106DC3A2FC7A8942E20E5DA369D19124D184A96589E66EE15C4A8E4CB0FBB6B5E629875DEB3C6AAF622ABC4A4057E0B95533A03C94C514D2129CD6ECE739D9E3A98A54461DF577CC508BF4D5EE7FBE6178B248E3F51C59FE57BFBDE33DD833D0CF22DB22AE0F4F9F03EEF8E0E1DB0EDF7BB4C755148AD2D3FECED23DE1F028A3A6396D7F8F721D11023BD58335ADE175939E140A92C7B532A3D77168E566B7AADEA6F137A158AF3D2608FD4C1081018C1BC2B860A2830A097BDAFA96A3D5B5E1130D2C0778837C63ACBE958573B4ADAC2AE629D17728313AB9064D890006B2F0EC1869E35480B96651B9B3837B876190D5F1876A151A87C58A1CE2A9AD0744BE4CF955BFA9FA5653300FF6ECD64667ECD836D61DC3675048A8EB5AE945B50CB699F7FB4E36167515A2054199687DEC77D5117DF28B63F383403C49097F23AA4DE5857A0D865AFC7E4D0994B46386C20A41E9B41963CD425A82B30C4EE72FB3EFACD6C4090D740E44C196E51F41894FDB26142B72EF1E65A676C30EFB65C937C0F64CDEC167ECC16F0CAA3C932F3DD5C6F7A1EB073F03F2CB9F2059BE75EBAE32FA3170B5FA93D69CAB8275935686242E1F43ED23FE8784A0AD694442D35193DAAF5F7DA49B267B716C38F36C92AE7986DF8126904B11EA74323F3AB3AF436D64AC41996529AB95876EE4DF3739130460A50E2EC8463F2306454F08745CE40938858B6237A5D38B33FD6541BB98EFB39A7B0B501B7943FF594DF0964BF535CBD35105E35BA14C40E62D57F3B110AE82CD7F9FF73C3A28740C8EB397494F6D7CF5F0F147385424D70B276C6AD849E56C9985115EAF2CCF3D3A6C828F2A303178EC48BB08F36AF3800739E841F7B758FF06EFA10F6467E98DA4B1B302EFED0EF5A7D3AD74100E41C168ACBBF10EC5FFC497B43409D02D942C144408C32C83ED49334BC48FD1D446FDEBB71CA1F9276F3180ECA057E4B8F19FAFE368D0097EE2A5736D72BE661382939491A244B068D26A071E55E25DF2C8706ADEFD8245BC97A691AB57A8D39CE24469E9CC69198F4F795CACCB45053F464CA0C2F04C71E9CD6BB6D378E917C413B7FADEACD41A7A43E9A1FC04576658DBF7420A35252A899B51F9ED9B2D0B5534A696C2465C950EF5880636D96CC963AF6C314D00834969C45DE752163 diff --git a/moduli.0 b/moduli.0 index f72ca5249640..90700a16fde4 100644 --- a/moduli.0 +++ b/moduli.0 @@ -71,4 +71,4 @@ STANDARDS M. Friedl, N. Provos, and W. Simpson, Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006. -OpenBSD 7.6 April 16, 2022 OpenBSD 7.6 +OpenBSD 7.7 April 16, 2022 OpenBSD 7.7 diff --git a/moduli.c b/moduli.c index 481ca2aa8ffc..999a90984e18 100644 --- a/moduli.c +++ b/moduli.c @@ -1,4 +1,4 @@ -/* $OpenBSD: moduli.c,v 1.39 2023/03/02 06:41:56 dtucker Exp $ */ +/* $OpenBSD: moduli.c,v 1.40 2025/05/24 03:39:48 dtucker Exp $ */ /* * Copyright 1994 Phil Karn * Copyright 1996-1998, 2003 William Allen Simpson @@ -87,13 +87,6 @@ #define SHIFT_MEGABYTE (20) #define SHIFT_MEGAWORD (SHIFT_MEGABYTE-SHIFT_BYTE) -/* - * Using virtual memory can cause thrashing. This should be the largest - * number that is supported without a large amount of disk activity -- - * that would increase the run time from hours to days or weeks! - */ -#define LARGE_MINIMUM (8UL) /* megabytes */ - /* * Do not increase this number beyond the unsigned integer bit size. * Due to a multiple of 4, it must be LESS than 128 (yielding 2**30 bits). @@ -142,7 +135,7 @@ static u_int32_t *LargeSieve, largewords, largetries, largenumbers; static u_int32_t largebits, largememory; /* megabytes */ static BIGNUM *largebase; -int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); +int gen_candidates(FILE *, u_int32_t, BIGNUM *); int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *, unsigned long, unsigned long); @@ -242,7 +235,7 @@ sieve_large(u_int32_t s32) * The list is checked against small known primes (less than 2**30). */ int -gen_candidates(FILE *out, u_int32_t memory, u_int32_t power, BIGNUM *start) +gen_candidates(FILE *out, u_int32_t power, BIGNUM *start) { BIGNUM *q; u_int32_t j, r, s, t; @@ -252,15 +245,6 @@ gen_candidates(FILE *out, u_int32_t memory, u_int32_t power, BIGNUM *start) u_int32_t i; int ret = 0; - largememory = memory; - - if (memory != 0 && - (memory < LARGE_MINIMUM || memory > LARGE_MAXIMUM)) { - error("Invalid memory amount (min %ld, max %ld)", - LARGE_MINIMUM, LARGE_MAXIMUM); - return (-1); - } - /* * Set power to the length in bits of the prime to be generated. * This is changed to 1 less than the desired safe prime moduli p. @@ -274,33 +258,9 @@ gen_candidates(FILE *out, u_int32_t memory, u_int32_t power, BIGNUM *start) } power--; /* decrement before squaring */ - /* - * The density of ordinary primes is on the order of 1/bits, so the - * density of safe primes should be about (1/bits)**2. Set test range - * to something well above bits**2 to be reasonably sure (but not - * guaranteed) of catching at least one safe prime. - */ - largewords = ((power * power) >> (SHIFT_WORD - TEST_POWER)); - - /* - * Need idea of how much memory is available. We don't have to use all - * of it. - */ - if (largememory > LARGE_MAXIMUM) { - logit("Limited memory: %u MB; limit %lu MB", - largememory, LARGE_MAXIMUM); - largememory = LARGE_MAXIMUM; - } - - if (largewords <= (largememory << SHIFT_MEGAWORD)) { - logit("Increased memory: %u MB; need %u bytes", - largememory, (largewords << SHIFT_BYTE)); - largewords = (largememory << SHIFT_MEGAWORD); - } else if (largememory > 0) { - logit("Decreased memory: %u MB; want %u bytes", - largememory, (largewords << SHIFT_BYTE)); - largewords = (largememory << SHIFT_MEGAWORD); - } + /* Always use the maximum amount of memory supported by the algorithm. */ + largememory = LARGE_MAXIMUM; + largewords = (largememory << SHIFT_MEGAWORD); TinySieve = xcalloc(tinywords, sizeof(u_int32_t)); tinybits = tinywords << SHIFT_WORD; @@ -308,12 +268,7 @@ gen_candidates(FILE *out, u_int32_t memory, u_int32_t power, BIGNUM *start) SmallSieve = xcalloc(smallwords, sizeof(u_int32_t)); smallbits = smallwords << SHIFT_WORD; - /* - * dynamically determine available memory - */ - while ((LargeSieve = calloc(largewords, sizeof(u_int32_t))) == NULL) - largewords -= (1L << (SHIFT_MEGAWORD - 2)); /* 1/4 MB chunks */ - + LargeSieve = xcalloc(largewords, sizeof(u_int32_t)); largebits = largewords << SHIFT_WORD; largenumbers = largebits * 2; /* even numbers excluded */ diff --git a/monitor.c b/monitor.c index 56a796ff48bb..f62fbdebec86 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.247 2024/12/03 22:30:03 jsg Exp $ */ +/* $OpenBSD: monitor.c,v 1.249 2025/09/25 06:45:50 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -39,21 +39,13 @@ #endif #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include #include #include #include -#ifdef HAVE_POLL_H #include -#else -# ifdef HAVE_SYS_POLL_H -# include -# endif -#endif #ifdef WITH_OPENSSL #include @@ -277,7 +269,7 @@ void monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) { struct mon_table *ent; - int authenticated = 0, partial = 0; + int status, authenticated = 0, partial = 0; debug3("preauth child monitor started"); @@ -380,11 +372,29 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) ; + /* Wait for the child's exit status */ + while (waitpid(pmonitor->m_pid, &status, 0) == -1) { + if (errno == EINTR) + continue; + fatal_f("waitpid: %s", strerror(errno)); + } + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != 0) + fatal_f("preauth child %ld exited with status %d", + (long)pmonitor->m_pid, WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + fatal_f("preauth child %ld terminated by signal %d", + (long)pmonitor->m_pid, WTERMSIG(status)); + } + debug3_f("preauth child %ld terminated successfully", + (long)pmonitor->m_pid); + if (pmonitor->m_recvfd >= 0) close(pmonitor->m_recvfd); if (pmonitor->m_log_sendfd >= 0) close(pmonitor->m_log_sendfd); pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1; + pmonitor->m_pid = -1; } static void @@ -611,16 +621,14 @@ monitor_reset_key_state(void) } int -mm_answer_state(struct ssh *ssh, int sock, struct sshbuf *m) +mm_answer_state(struct ssh *ssh, int sock, struct sshbuf *unused) { - struct sshbuf *inc = NULL, *hostkeys = NULL; + struct sshbuf *m = NULL, *inc = NULL, *hostkeys = NULL; struct sshbuf *opts = NULL, *confdata = NULL; struct include_item *item = NULL; int postauth; int r; - sshbuf_reset(m); - debug_f("config len %zu", sshbuf_len(cfg)); if ((m = sshbuf_new()) == NULL || @@ -678,9 +686,10 @@ mm_answer_state(struct ssh *ssh, int sock, struct sshbuf *m) sshbuf_free(inc); sshbuf_free(opts); sshbuf_free(confdata); + sshbuf_free(hostkeys); mm_request_send(sock, MONITOR_ANS_STATE, m); - + sshbuf_free(m); debug3_f("done"); return (0); @@ -1045,7 +1054,6 @@ mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m) fatal_fr(r, "assemble PAM"); #endif - debug3("%s: sending result %d", __func__, authenticated); debug3_f("sending result %d", authenticated); mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m); @@ -1132,7 +1140,7 @@ int mm_answer_pam_start(struct ssh *ssh, int sock, struct sshbuf *m) { if (!options.use_pam) - fatal("UsePAM not set, but ended up in %s anyway", __func__); + fatal_f("UsePAM not set, but ended up in %s anyway", __func__); start_pam(ssh); @@ -1150,13 +1158,13 @@ mm_answer_pam_account(struct ssh *ssh, int sock, struct sshbuf *m) int r; if (!options.use_pam) - fatal("%s: PAM not enabled", __func__); + fatal_f("PAM not enabled"); ret = do_pam_account(); if ((r = sshbuf_put_u32(m, ret)) != 0 || (r = sshbuf_put_stringb(m, loginmsg)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); mm_request_send(sock, MONITOR_ANS_PAM_ACCOUNT, m); @@ -1172,11 +1180,11 @@ mm_answer_pam_init_ctx(struct ssh *ssh, int sock, struct sshbuf *m) u_int ok = 0; int r; - debug3("%s", __func__); + debug3_f("entering"); if (!options.kbd_interactive_authentication) - fatal("%s: kbd-int authentication not enabled", __func__); + fatal_f("kbd-int authentication not enabled"); if (sshpam_ctxt != NULL) - fatal("%s: already called", __func__); + fatal_f("already called"); sshpam_ctxt = (sshpam_device.init_ctx)(authctxt); sshpam_authok = NULL; sshbuf_reset(m); @@ -1186,7 +1194,7 @@ mm_answer_pam_init_ctx(struct ssh *ssh, int sock, struct sshbuf *m) ok = 1; } if ((r = sshbuf_put_u32(m, ok)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); mm_request_send(sock, MONITOR_ANS_PAM_INIT_CTX, m); return (0); } @@ -1198,10 +1206,10 @@ mm_answer_pam_query(struct ssh *ssh, int sock, struct sshbuf *m) u_int i, num = 0, *echo_on = 0; int r, ret; - debug3("%s", __func__); + debug3_f("entering"); sshpam_authok = NULL; if (sshpam_ctxt == NULL) - fatal("%s: no context", __func__); + fatal_f("no context"); ret = (sshpam_device.query)(sshpam_ctxt, &name, &info, &num, &prompts, &echo_on); if (ret == 0 && num == 0) @@ -1215,13 +1223,13 @@ mm_answer_pam_query(struct ssh *ssh, int sock, struct sshbuf *m) (r = sshbuf_put_cstring(m, info)) != 0 || (r = sshbuf_put_u32(m, sshpam_get_maxtries_reached())) != 0 || (r = sshbuf_put_u32(m, num)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); free(name); free(info); for (i = 0; i < num; ++i) { if ((r = sshbuf_put_cstring(m, prompts[i])) != 0 || (r = sshbuf_put_u32(m, echo_on[i])) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); free(prompts[i]); } free(prompts); @@ -1239,12 +1247,12 @@ mm_answer_pam_respond(struct ssh *ssh, int sock, struct sshbuf *m) u_int i, num; int r, ret; - debug3("%s", __func__); + debug3_f("entering"); if (sshpam_ctxt == NULL) - fatal("%s: no context", __func__); + fatal_f("no context"); sshpam_authok = NULL; if ((r = sshbuf_get_u32(m, &num)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); if (num > PAM_MAX_NUM_MSG) { fatal_f("Too many PAM messages, got %u, expected <= %u", num, (unsigned)PAM_MAX_NUM_MSG); @@ -1265,7 +1273,7 @@ mm_answer_pam_respond(struct ssh *ssh, int sock, struct sshbuf *m) } sshbuf_reset(m); if ((r = sshbuf_put_u32(m, ret)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m); auth_method = "keyboard-interactive"; auth_submethod = "pam"; @@ -1279,9 +1287,9 @@ mm_answer_pam_free_ctx(struct ssh *ssh, int sock, struct sshbuf *m) { int r = sshpam_authok != NULL && sshpam_authok == sshpam_ctxt; - debug3("%s", __func__); + debug3_f("entering"); if (sshpam_ctxt == NULL) - fatal("%s: no context", __func__); + fatal_f("no context"); (sshpam_device.free_ctx)(sshpam_ctxt); sshpam_ctxt = sshpam_authok = NULL; sshbuf_reset(m); @@ -1812,10 +1820,10 @@ mm_answer_audit_event(struct ssh *ssh, int socket, struct sshbuf *m) ssh_audit_event_t event; int r; - debug3("%s entering", __func__); + debug3_f("entering"); if ((r = sshbuf_get_u32(m, &n)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); event = (ssh_audit_event_t)n; switch (event) { case SSH_AUTH_FAIL_PUBKEY: @@ -1840,9 +1848,9 @@ mm_answer_audit_command(struct ssh *ssh, int socket, struct sshbuf *m) char *cmd; int r; - debug3("%s entering", __func__); + debug3_f("entering"); if ((r = sshbuf_get_cstring(m, &cmd, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); /* sanity check command, if so how? */ audit_run_command(cmd); free(cmd); diff --git a/monitor_fdpass.c b/monitor_fdpass.c index a07727a8e743..21697ca88937 100644 --- a/monitor_fdpass.c +++ b/monitor_fdpass.c @@ -29,21 +29,13 @@ #include #include #include -#ifdef HAVE_SYS_UN_H #include -#endif #include #include #include -#ifdef HAVE_POLL_H -# include -#else -# ifdef HAVE_SYS_POLL_H -# include -# endif -#endif +#include #include "log.h" #include "monitor_fdpass.h" @@ -103,7 +95,7 @@ mm_send_fd(int sock, int fd) } return 0; #else - error("%s: file descriptor passing not supported", __func__); + error_f("file descriptor passing not supported"); return -1; #endif } diff --git a/monitor_wrap.c b/monitor_wrap.c index c237f0c4016e..b0b9d524d160 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.138 2024/10/22 06:13:00 dtucker Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.142 2025/09/25 06:31:42 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -139,17 +139,17 @@ mm_reap(void) } if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) { - debug_f("preauth child exited with status %d", + debug_f("child exited with status %d", WEXITSTATUS(status)); cleanup_exit(255); } } else if (WIFSIGNALED(status)) { - error_f("preauth child terminated by signal %d", + error_f("child terminated by signal %d", WTERMSIG(status)); cleanup_exit(signal_is_crash(WTERMSIG(status)) ? EXIT_CHILD_CRASH : 255); } else { - error_f("preauth child terminated abnormally (status=0x%x)", + error_f("child terminated abnormally (status=0x%x)", status); cleanup_exit(EXIT_CHILD_CRASH); } @@ -163,7 +163,7 @@ mm_request_send(int sock, enum monitor_reqtype type, struct sshbuf *m) debug3_f("entering, type %d", type); - if (mlen >= 0xffffffff) + if (mlen >= MONITOR_MAX_MSGLEN) fatal_f("bad length %zu", mlen); POKE_U32(buf, mlen + 1); buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */ @@ -196,7 +196,7 @@ mm_request_receive(int sock, struct sshbuf *m) fatal_f("read: %s", strerror(errno)); } msg_len = PEEK_U32(buf); - if (msg_len > 256 * 1024) + if (msg_len > MONITOR_MAX_MSGLEN) fatal_f("read: bad msg_len %d", msg_len); sshbuf_reset(m); if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) @@ -332,6 +332,17 @@ mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m) log_verbose_reset(); for (i = 0; i < options.num_log_verbose; i++) log_verbose_add(options.log_verbose[i]); + + /* use the macro hell to clean up too */ +#define M_CP_STROPT(x) free(newopts->x) +#define M_CP_STRARRAYOPT(x, nx) do { \ + for (i = 0; i < newopts->nx; i++) \ + free(newopts->x[i]); \ + free(newopts->x); \ + } while (0) + COPY_MATCH_STRING_OPTS(); +#undef M_CP_STROPT +#undef M_CP_STRARRAYOPT free(newopts); } @@ -705,11 +716,11 @@ mm_start_pam(struct ssh *ssh) { struct sshbuf *m; - debug3("%s entering", __func__); + debug3_f("entering"); if (!options.use_pam) - fatal("UsePAM=no, but ended up in %s anyway", __func__); + fatal_f("UsePAM=no, but ended up in %s anyway", __func__); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, m); sshbuf_free(m); @@ -724,12 +735,12 @@ mm_do_pam_account(void) size_t msglen; int r; - debug3("%s entering", __func__); + debug3_f("entering"); if (!options.use_pam) - fatal("UsePAM=no, but ended up in %s anyway", __func__); + fatal_f("UsePAM=no, but ended up in %s anyway", __func__); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_ACCOUNT, m); mm_request_receive_expect(pmonitor->m_recvfd, @@ -737,12 +748,12 @@ mm_do_pam_account(void) 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)); + fatal_fr(r, "buffer error"); free(msg); sshbuf_free(m); - debug3("%s returning %d", __func__, ret); + debug3_f("returning %d", ret); return (ret); } @@ -753,17 +764,17 @@ mm_sshpam_init_ctx(Authctxt *authctxt) struct sshbuf *m; int r, success; - debug3("%s", __func__); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_INIT_CTX, m); - debug3("%s: waiting for MONITOR_ANS_PAM_INIT_CTX", __func__); + debug3_f("waiting for MONITOR_ANS_PAM_INIT_CTX"); 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)); + fatal_fr(r, "buffer error"); if (success == 0) { - debug3("%s: pam_init_ctx failed", __func__); + debug3_f("pam_init_ctx failed"); sshbuf_free(m); return (NULL); } @@ -779,19 +790,19 @@ mm_sshpam_query(void *ctx, char **name, char **info, u_int i, n; int r, ret; - debug3("%s", __func__); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_QUERY, m); - debug3("%s: waiting for MONITOR_ANS_PAM_QUERY", __func__); + debug3_f("waiting for MONITOR_ANS_PAM_QUERY"); 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); + fatal_fr(r, "buffer error"); + debug3_f("pam_query returned %d", ret); sshpam_set_maxtries_reached(n); if (*num > PAM_MAX_NUM_MSG) fatal("%s: received %u PAM messages, expected <= %u", @@ -801,7 +812,7 @@ mm_sshpam_query(void *ctx, char **name, char **info, 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)); + fatal_fr(r, "buffer error"); } sshbuf_free(m); return (ret); @@ -814,23 +825,23 @@ mm_sshpam_respond(void *ctx, u_int num, char **resp) u_int n, i; int r, ret; - debug3("%s", __func__); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u32(m, num)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); for (i = 0; i < num; ++i) { if ((r = sshbuf_put_cstring(m, resp[i])) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); } mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_RESPOND, m); - debug3("%s: waiting for MONITOR_ANS_PAM_RESPOND", __func__); + debug3_f("waiting for MONITOR_ANS_PAM_RESPOND"); 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)); + fatal_fr(r, "buffer error"); ret = (int)n; /* XXX */ - debug3("%s: pam_respond returned %d", __func__, ret); + debug3_f("pam_respond returned %d", ret); sshbuf_free(m); return (ret); } @@ -840,11 +851,11 @@ mm_sshpam_free_ctx(void *ctxtp) { struct sshbuf *m; - debug3("%s", __func__); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_FREE_CTX, m); - debug3("%s: waiting for MONITOR_ANS_PAM_FREE_CTX", __func__); + debug3_f("waiting for MONITOR_ANS_PAM_FREE_CTX"); mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PAM_FREE_CTX, m); sshbuf_free(m); @@ -1013,12 +1024,12 @@ mm_audit_event(struct ssh *ssh, ssh_audit_event_t event) struct sshbuf *m; int r; - debug3("%s entering", __func__); + debug3_f("entering"); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_u32(m, event)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_EVENT, m); sshbuf_free(m); @@ -1030,12 +1041,12 @@ mm_audit_run_command(const char *command) struct sshbuf *m; int r; - debug3("%s entering command %s", __func__, command); + debug3_f("entering command %s", command); if ((m = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); if ((r = sshbuf_put_cstring(m, command)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, m); sshbuf_free(m); diff --git a/monitor_wrap.h b/monitor_wrap.h index 7134afeecf4e..c87295388fd0 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.h,v 1.51 2024/05/17 06:42:04 jsg Exp $ */ +/* $OpenBSD: monitor_wrap.h,v 1.53 2025/07/04 07:47:35 djm Exp $ */ /* * Copyright 2002 Niels Provos @@ -28,6 +28,10 @@ #ifndef _MM_WRAP_H_ #define _MM_WRAP_H_ +#define MONITOR_MAX_MSGLEN (4 * 1024 * 1024) +/* The configuration has to fit in a monitor message along with other state */ +#define MONITOR_MAX_CFGLEN (MONITOR_MAX_MSGLEN - (64 * 1024)) + enum mm_keytype { MM_NOKEY, MM_HOSTKEY, MM_USERKEY }; struct ssh; diff --git a/mux.c b/mux.c index 415024f74e8f..37bcb91037ef 100644 --- a/mux.c +++ b/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.103 2024/10/12 10:50:37 jsg Exp $ */ +/* $OpenBSD: mux.c,v 1.107 2025/09/30 00:03:09 djm Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -34,21 +34,11 @@ #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 #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" @@ -460,6 +450,8 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid, 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); + if (cctx->want_tty) + channel_set_tty(ssh, nc); nc->ctl_chan = c->self; /* link session -> control channel */ c->ctl_child_id = nc->self; /* link control -> session channel */ @@ -676,6 +668,7 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) if (c->mux_pause <= 0) fatal_f("mux_pause %d", c->mux_pause); c->mux_pause = 0; /* start processing messages again */ + free(fctx); } static int @@ -931,7 +924,7 @@ mux_master_process_close_fwd(struct ssh *ssh, u_int rid, } else { /* local and dynamic forwards */ /* Ditto */ if (channel_cancel_lport_listener(ssh, &fwd, fwd.connect_port, - &options.fwd_opts) == -1) + &options.fwd_opts) != 1) error_reason = "port not found"; } @@ -2202,8 +2195,10 @@ mux_client_request_stdio_fwd(int fd) sshbuf_reset(m); if (mux_client_read_packet(fd, m) != 0) { if (errno == EPIPE || - (errno == EINTR && muxclient_terminate != 0)) + (errno == EINTR && muxclient_terminate != 0)) { + sshbuf_free(m); return 0; + } fatal_f("mux_client_read_packet: %s", strerror(errno)); } fatal_f("master returned unexpected message %u", type); diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in index 1d549954f9d6..53c87db6d01e 100644 --- a/openbsd-compat/Makefile.in +++ b/openbsd-compat/Makefile.in @@ -3,12 +3,14 @@ piddir=@piddir@ srcdir=@srcdir@ top_srcdir=@top_srcdir@ +BUILDDIR=@abs_top_builddir@ VPATH=@srcdir@ CC=@CC@ LD=@LD@ CFLAGS=@CFLAGS@ CFLAGS_NOPIE=@CFLAGS_NOPIE@ -CPPFLAGS=-I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ +COMPATINCLUDES="$(BUILDDIR)/@COMPATINCLUDES@" +CPPFLAGS=-I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(COMPATINCLUDES) @CPPFLAGS@ @DEFS@ PICFLAG=@PICFLAG@ LIBS=@LIBS@ AR=@AR@ @@ -120,3 +122,4 @@ clean: distclean: clean rm -f Makefile *~ + rm -rf include diff --git a/openbsd-compat/arc4random.c b/openbsd-compat/arc4random.c index af6f32b883f6..585bcf62a7d8 100644 --- a/openbsd-compat/arc4random.c +++ b/openbsd-compat/arc4random.c @@ -32,9 +32,7 @@ #include #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include #include diff --git a/openbsd-compat/arc4random_uniform.c b/openbsd-compat/arc4random_uniform.c index 591f92d150fa..59d516884eb1 100644 --- a/openbsd-compat/arc4random_uniform.c +++ b/openbsd-compat/arc4random_uniform.c @@ -20,9 +20,7 @@ #include "includes.h" -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #ifndef HAVE_ARC4RANDOM_UNIFORM diff --git a/openbsd-compat/bsd-misc.c b/openbsd-compat/bsd-misc.c index 226a5915bd1d..2c196ec23eee 100644 --- a/openbsd-compat/bsd-misc.c +++ b/openbsd-compat/bsd-misc.c @@ -21,9 +21,7 @@ #ifdef HAVE_SYS_SELECT_H # include #endif -#ifdef HAVE_SYS_TIME_H -# include -#endif +#include #include #include @@ -158,6 +156,15 @@ utimensat(int fd, const char *path, const struct timespec times[2], } #endif +#ifndef HAVE_DIRFD +int +dirfd(void *dir) +{ + errno = ENOSYS; + return -1; +} +#endif + #ifndef HAVE_FCHOWNAT /* * A limited implementation of fchownat() that only implements the @@ -220,6 +227,46 @@ fchmodat(int fd, const char *path, mode_t mode, int flag) } #endif +#ifndef HAVE_FSTATAT +/* + * A limited implementation of fstatat that just has what OpenSSH uses: + * cwd-relative and absolute paths, with or without following symlinks. + */ +int +fstatat(int dirfd, const char *path, struct stat *sb, int flag) +{ + if (dirfd != AT_FDCWD && path && path[0] != '/') { + errno = ENOSYS; + return -1; + } + if (flag == 0) + return stat(path, sb); + else if (flag == AT_SYMLINK_NOFOLLOW) + return lstat(path, sb); + errno = ENOSYS; + return -1; +} +#endif + +#ifndef HAVE_UNLINKAT +/* + * A limited implementation of unlinkat that just has what OpenSSH uses: + * cwd-relative and absolute paths. + */ +int +unlinkat(int dirfd, const char *path, int flag) +{ + if (dirfd != AT_FDCWD && path && path[0] != '/') { + errno = ENOSYS; + return -1; + } + if (flag == 0) + return unlink(path); + errno = ENOSYS; + return -1; +} +#endif + #ifndef HAVE_TRUNCATE int truncate(const char *path, off_t length) { @@ -356,7 +403,7 @@ getpgid(pid_t pid) #ifndef HAVE_PLEDGE int -pledge(const char *promises, const char *paths[]) +pledge(const char *promises, const char *execpromises) { return 0; } @@ -447,6 +494,30 @@ localtime_r(const time_t *timep, struct tm *result) } #endif +#ifndef HAVE_CLOCK_GETTIME +int +clock_gettime(clockid_t clockid, struct timespec *ts) +{ + struct timeval tv; + + if (clockid != CLOCK_REALTIME) { + errno = ENOSYS; + return -1; + } + if (ts == NULL) { + errno = EFAULT; + return -1; + } + + if (gettimeofday(&tv, NULL) == -1) + return -1; + + ts->tv_sec = tv.tv_sec; + ts->tv_nsec = (long)tv.tv_usec * 1000; + return 0; +} +#endif + #ifdef ASAN_OPTIONS const char *__asan_default_options(void) { return ASAN_OPTIONS; diff --git a/openbsd-compat/bsd-misc.h b/openbsd-compat/bsd-misc.h index 61ead1b7fad0..8495f471c285 100644 --- a/openbsd-compat/bsd-misc.h +++ b/openbsd-compat/bsd-misc.h @@ -65,6 +65,10 @@ struct timeval { int utimes(const char *, struct timeval *); #endif /* HAVE_UTIMES */ +#ifndef HAVE_DIRFD +int dirfd(void *); +#endif + #ifndef AT_FDCWD # define AT_FDCWD (-2) #endif @@ -77,6 +81,14 @@ int fchmodat(int, const char *, mode_t, int); int fchownat(int, const char *, uid_t, gid_t, int); #endif +#ifdef HAVE_FSTATAT +int fstatat(int, const char *, struct stat *, int); +#endif + +#ifdef HAVE_UNLINKAT +int unlinkat(int, const char *, int); +#endif + #ifndef HAVE_TRUNCATE int truncate (const char *, off_t); #endif /* HAVE_TRUNCATE */ @@ -144,7 +156,7 @@ int pselect(int, fd_set *, fd_set *, fd_set *, const struct timespec *, #endif #ifndef HAVE_PLEDGE -int pledge(const char *promises, const char *paths[]); +int pledge(const char *promises, const char *execpromises); #endif /* bsd-err.h */ @@ -190,6 +202,14 @@ int flock(int, int); struct tm *localtime_r(const time_t *, struct tm *); #endif +#ifndef HAVE_CLOCK_GETTIME +typedef int clockid_t; +#ifndef CLOCK_REALTIME +# define CLOCK_REALTIME 0 +#endif +int clock_gettime(clockid_t, struct timespec *); +#endif + #ifndef HAVE_REALPATH #define realpath(x, y) (sftp_realpath((x), (y))) #endif diff --git a/openbsd-compat/bsd-openpty.c b/openbsd-compat/bsd-openpty.c index f5507000a5cb..f08d6156d284 100644 --- a/openbsd-compat/bsd-openpty.c +++ b/openbsd-compat/bsd-openpty.c @@ -39,9 +39,7 @@ #include -#ifdef HAVE_SYS_STAT_H -# include -#endif +#include #ifdef HAVE_SYS_IOCTL_H # include #endif @@ -50,9 +48,7 @@ # include #endif -#ifdef HAVE_UTIL_H -# include -#endif /* HAVE_UTIL_H */ +#include #ifdef HAVE_PTY_H # include diff --git a/openbsd-compat/bsd-poll.h b/openbsd-compat/bsd-poll.h index ae865a6e2622..67fd8c66f803 100644 --- a/openbsd-compat/bsd-poll.h +++ b/openbsd-compat/bsd-poll.h @@ -31,11 +31,7 @@ #define _COMPAT_POLL_H_ #include -#ifdef HAVE_POLL_H -# include -#elif HAVE_SYS_POLL_H -# include -#endif +#include #ifndef HAVE_STRUCT_POLLFD_FD typedef struct pollfd { diff --git a/openbsd-compat/daemon.c b/openbsd-compat/daemon.c index 3efe14c68c41..256466959621 100644 --- a/openbsd-compat/daemon.c +++ b/openbsd-compat/daemon.c @@ -36,9 +36,7 @@ #include -#ifdef HAVE_SYS_STAT_H -# include -#endif +#include #ifdef HAVE_FCNTL_H # include diff --git a/openbsd-compat/glob.c b/openbsd-compat/glob.c index fe33ca8b817b..3c7095baa525 100644 --- a/openbsd-compat/glob.c +++ b/openbsd-compat/glob.c @@ -70,9 +70,7 @@ #include #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include diff --git a/openbsd-compat/memmem.c b/openbsd-compat/memmem.c index 2637401d7c6e..afc20c669b08 100644 --- a/openbsd-compat/memmem.c +++ b/openbsd-compat/memmem.c @@ -30,9 +30,7 @@ #ifndef HAVE_MEMMEM #include -#ifdef HAVE_STDINT_H #include -#endif static char * twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) diff --git a/openbsd-compat/openssl-compat.c b/openbsd-compat/openssl-compat.c index 14865077e469..48938920cda7 100644 --- a/openbsd-compat/openssl-compat.c +++ b/openbsd-compat/openssl-compat.c @@ -32,7 +32,8 @@ #include "openssl-compat.h" /* - * OpenSSL version numbers: MNNFFPPS: major minor fix patch status + * OpenSSL version numbers: MNNFFPPS: major minor fix patch status. + * See the OpenSSL_version_num(3ssl) man page. * Versions >=3 require only major versions to match. * For versions <3, we accept compatible fix versions (so we allow 1.0.1 * to work with 1.0.0). Going backwards is only allowed within a patch series. @@ -49,10 +50,10 @@ ssh_compatible_openssl(long headerver, long libver) return 1; /* - * For versions >= 3.0, only the major and status must match. + * For versions >= 3.0, only the major must match. */ - if (headerver >= 0x3000000f) { - mask = 0xf000000fL; /* major,status */ + if (headerver >= 0x30000000) { + mask = 0xf0000000L; /* major only */ return (headerver & mask) == (libver & mask); } diff --git a/openbsd-compat/openssl-compat.h b/openbsd-compat/openssl-compat.h index 6b8fff412951..d07928b17b6d 100644 --- a/openbsd-compat/openssl-compat.h +++ b/openbsd-compat/openssl-compat.h @@ -23,8 +23,8 @@ #include #include #include +#include #include -#include #ifdef OPENSSL_HAS_ECC #include #endif @@ -45,9 +45,6 @@ void ssh_libcrypto_init(void); #ifndef OPENSSL_RSA_MAX_MODULUS_BITS # define OPENSSL_RSA_MAX_MODULUS_BITS 16384 #endif -#ifndef OPENSSL_DSA_MAX_MODULUS_BITS -# define OPENSSL_DSA_MAX_MODULUS_BITS 10000 -#endif #ifdef LIBRESSL_VERSION_NUMBER # if LIBRESSL_VERSION_NUMBER < 0x3010000fL @@ -64,6 +61,20 @@ void ssh_libcrypto_init(void); # define BN_set_flags(a, b) #endif +/* LibreSSL <3.4 has the _GFp variants but not the equivalent modern ones. */ +#ifndef HAVE_EC_POINT_GET_AFFINE_COORDINATES +# ifdef HAVE_EC_POINT_GET_AFFINE_COORDINATES_GFP +# define EC_POINT_get_affine_coordinates(a, b, c, d, e) \ + (EC_POINT_get_affine_coordinates_GFp(a, b, c, d, e)) +# endif +#endif +#ifndef HAVE_EC_POINT_SET_AFFINE_COORDINATES +# ifdef HAVE_EC_POINT_SET_AFFINE_COORDINATES_GFP +# define EC_POINT_set_affine_coordinates(a, b, c, d, e) \ + (EC_POINT_set_affine_coordinates_GFp(a, b, c, d, e)) +# endif +#endif + #ifndef HAVE_EVP_CIPHER_CTX_GET_IV # ifdef HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV # define EVP_CIPHER_CTX_get_iv EVP_CIPHER_CTX_get_updated_iv diff --git a/openbsd-compat/port-prngd.c b/openbsd-compat/port-prngd.c index 6afa8f913ae3..ac4f27082b74 100644 --- a/openbsd-compat/port-prngd.c +++ b/openbsd-compat/port-prngd.c @@ -26,9 +26,7 @@ #include #include -#ifdef HAVE_SYS_UN_H -# include -#endif +#include #include #include diff --git a/openbsd-compat/reallocarray.c b/openbsd-compat/reallocarray.c index 1a52acc623fe..cffe9b5efe7b 100644 --- a/openbsd-compat/reallocarray.c +++ b/openbsd-compat/reallocarray.c @@ -22,9 +22,7 @@ #include #include -#ifdef HAVE_STDINT_H #include -#endif #include /* diff --git a/openbsd-compat/recallocarray.c b/openbsd-compat/recallocarray.c index 3e1156ce2d95..c281f75e94d1 100644 --- a/openbsd-compat/recallocarray.c +++ b/openbsd-compat/recallocarray.c @@ -22,9 +22,7 @@ #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include diff --git a/openbsd-compat/regress/utimensattest.c b/openbsd-compat/regress/utimensattest.c index bbc66c48523e..b4405e464d03 100644 --- a/openbsd-compat/regress/utimensattest.c +++ b/openbsd-compat/regress/utimensattest.c @@ -77,11 +77,17 @@ main(void) fail("utimensat", 0, 0); if (stat(TMPFILE, &sb) == -1) - fail("stat", 0, 0 ); + fail("stat", 0, 0); +#if 0 + /* + * This test only works on filesystems mounted 'noatime', otherwise the + * stat() above resets atime. Skip by default. + */ if (sb.st_atime != 12345678) - fail("st_atime", 0, 0 ); + fail("st_atime", 0, 0); +#endif if (sb.st_mtime != 34567890) - fail("st_mtime", 0, 0 ); + fail("st_mtime", 0, 0); #if 0 /* * Results expected to be rounded to the nearest microsecond. diff --git a/packet.c b/packet.c index 75268bad3ac9..3ca45a28cd4e 100644 --- a/packet.c +++ b/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.318 2025/02/18 08:02:12 djm Exp $ */ +/* $OpenBSD: packet.c,v 1.323 2025/09/25 06:33:19 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -42,9 +42,7 @@ #include #include "openbsd-compat/sys-queue.h" #include -#ifdef HAVE_SYS_TIME_H -# include -#endif +#include #include #include @@ -58,9 +56,7 @@ #include #include #include -#ifdef HAVE_POLL_H #include -#endif #include #include @@ -210,8 +206,8 @@ struct session_state { /* Used in ssh_packet_send_mux() */ int mux; - /* Used in packet_set_interactive */ - int set_interactive_called; + /* QoS handling */ + int qos_interactive, qos_other; /* Used in packet_set_maxsize */ int set_maxsize_called; @@ -219,6 +215,15 @@ struct session_state { /* One-off warning about weak ciphers */ int cipher_warning_done; + /* + * Disconnect in progress. Used to prevent reentry in + * ssh_packet_disconnect() + */ + int disconnecting; + + /* Nagle disabled on socket */ + int nodelay_set; + /* Hook for fuzzing inbound packets */ ssh_packet_hook_fn *hook_in; void *hook_in_ctx; @@ -247,6 +252,8 @@ ssh_alloc_session_state(void) state->connection_out = -1; state->max_packet_size = 32768; state->packet_timeout_ms = -1; + state->interactive_mode = 1; + state->qos_interactive = state->qos_other = -1; state->p_send.packets = state->p_read.packets = 0; state->initialized = 1; /* @@ -675,6 +682,7 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) { struct session_state *state = ssh->state; u_int mode; + struct packet *p; if (!state->initialized) return; @@ -691,6 +699,11 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) sshbuf_free(state->output); sshbuf_free(state->outgoing_packet); sshbuf_free(state->incoming_packet); + while ((p = TAILQ_FIRST(&state->outgoing))) { + sshbuf_free(p->payload); + TAILQ_REMOVE(&state->outgoing, p, next); + free(p); + } for (mode = 0; mode < MODE_MAX; mode++) { kex_free_newkeys(state->newkeys[mode]); /* current keys */ state->newkeys[mode] = NULL; @@ -739,6 +752,13 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) } } +void +ssh_packet_free(struct ssh *ssh) +{ + ssh_packet_close_internal(ssh, 1); + freezero(ssh, sizeof(*ssh)); +} + void ssh_packet_close(struct ssh *ssh) { @@ -2066,12 +2086,12 @@ ssh_packet_disconnect(struct ssh *ssh, const char *fmt,...) { char buf[1024], remote_id[512]; va_list args; - static int disconnecting = 0; int r; - if (disconnecting) /* Guard against recursive invocations. */ + /* Guard against recursive invocations. */ + if (ssh->state->disconnecting) fatal("packet_disconnect called recursively."); - disconnecting = 1; + ssh->state->disconnecting = 1; /* * Format the message. Note that the caller must make sure the @@ -2208,41 +2228,41 @@ ssh_packet_interactive_data_to_write(struct ssh *ssh) sshbuf_len(ssh->state->output) < 256; } -void -ssh_packet_set_tos(struct ssh *ssh, int tos) +static void +apply_qos(struct ssh *ssh) { - if (!ssh_packet_connection_is_on_socket(ssh) || tos == INT_MAX) + struct session_state *state = ssh->state; + int qos = state->interactive_mode ? + state->qos_interactive : state->qos_other; + + if (!ssh_packet_connection_is_on_socket(ssh)) return; - set_sock_tos(ssh->state->connection_in, tos); + if (!state->nodelay_set) { + set_nodelay(state->connection_in); + state->nodelay_set = 1; + } + set_sock_tos(ssh->state->connection_in, qos); } -/* Informs that the current session is interactive. Sets IP flags for that. */ - +/* Informs that the current session is interactive. */ void -ssh_packet_set_interactive(struct ssh *ssh, int interactive, int qos_interactive, int qos_bulk) +ssh_packet_set_interactive(struct ssh *ssh, int interactive) { struct session_state *state = ssh->state; - if (state->set_interactive_called) - return; - state->set_interactive_called = 1; - - /* Record that we are in interactive mode. */ state->interactive_mode = interactive; - - /* Only set socket options if using a socket. */ - if (!ssh_packet_connection_is_on_socket(ssh)) - return; - set_nodelay(state->connection_in); - ssh_packet_set_tos(ssh, interactive ? qos_interactive : qos_bulk); + apply_qos(ssh); } -/* Returns true if the current connection is interactive. */ - -int -ssh_packet_is_interactive(struct ssh *ssh) +/* Set QoS flags to be used for interactive and non-interactive sessions */ +void +ssh_packet_set_qos(struct ssh *ssh, int qos_interactive, int qos_other) { - return ssh->state->interactive_mode; + struct session_state *state = ssh->state; + + state->qos_interactive = qos_interactive; + state->qos_other = qos_other; + apply_qos(ssh); } int @@ -2417,6 +2437,7 @@ ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m) struct session_state *state = ssh->state; int r; +#define ENCODE_INT(v) (((v) < 0) ? 0xFFFFFFFF : (u_int)v) if ((r = kex_to_blob(m, ssh->kex)) != 0 || (r = newkeys_to_blob(m, ssh, MODE_OUT)) != 0 || (r = newkeys_to_blob(m, ssh, MODE_IN)) != 0 || @@ -2431,9 +2452,12 @@ ssh_packet_get_state(struct ssh *ssh, struct sshbuf *m) (r = sshbuf_put_u32(m, state->p_read.packets)) != 0 || (r = sshbuf_put_u64(m, state->p_read.bytes)) != 0 || (r = sshbuf_put_stringb(m, state->input)) != 0 || - (r = sshbuf_put_stringb(m, state->output)) != 0) + (r = sshbuf_put_stringb(m, state->output)) != 0 || + (r = sshbuf_put_u32(m, ENCODE_INT(state->interactive_mode))) != 0 || + (r = sshbuf_put_u32(m, ENCODE_INT(state->qos_interactive))) != 0 || + (r = sshbuf_put_u32(m, ENCODE_INT(state->qos_other))) != 0) return r; - +#undef ENCODE_INT return 0; } @@ -2552,6 +2576,7 @@ ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m) const u_char *input, *output; size_t ilen, olen; int r; + u_int interactive, qos_interactive, qos_other; if ((r = kex_from_blob(m, &ssh->kex)) != 0 || (r = newkeys_from_blob(m, ssh, MODE_OUT)) != 0 || @@ -2588,6 +2613,16 @@ ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m) (r = sshbuf_put(state->output, output, olen)) != 0) return r; + if ((r = sshbuf_get_u32(m, &interactive)) != 0 || + (r = sshbuf_get_u32(m, &qos_interactive)) != 0 || + (r = sshbuf_get_u32(m, &qos_other)) != 0) + return r; +#define DECODE_INT(v) ((v) > INT_MAX ? -1 : (int)(v)) + state->interactive_mode = DECODE_INT(interactive); + state->qos_interactive = DECODE_INT(qos_interactive); + state->qos_other = DECODE_INT(qos_other); +#undef DECODE_INT + if (sshbuf_len(m)) return SSH_ERR_INVALID_FORMAT; debug3_f("done"); diff --git a/packet.h b/packet.h index 49bb87f0750b..072f274259ee 100644 --- a/packet.h +++ b/packet.h @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.h,v 1.99 2024/08/15 00:51:51 djm Exp $ */ +/* $OpenBSD: packet.h,v 1.103 2025/09/25 06:33:19 djm Exp $ */ /* * Author: Tatu Ylonen @@ -101,6 +101,7 @@ int ssh_packet_connection_af(struct ssh *); void ssh_packet_set_nonblocking(struct ssh *); int ssh_packet_get_connection_in(struct ssh *); int ssh_packet_get_connection_out(struct ssh *); +void ssh_packet_free(struct ssh *); void ssh_packet_close(struct ssh *); void ssh_packet_set_input_hook(struct ssh *, ssh_packet_hook_fn *, void *); void ssh_packet_clear_keys(struct ssh *); @@ -110,9 +111,8 @@ int ssh_packet_is_rekeying(struct ssh *); int ssh_packet_check_rekey(struct ssh *); void ssh_packet_set_protocol_flags(struct ssh *, u_int); u_int ssh_packet_get_protocol_flags(struct ssh *); -void ssh_packet_set_tos(struct ssh *, int); -void ssh_packet_set_interactive(struct ssh *, int, int, int); -int ssh_packet_is_interactive(struct ssh *); +void ssh_packet_set_interactive(struct ssh *, int); +void ssh_packet_set_qos(struct ssh *, int, int); void ssh_packet_set_server(struct ssh *); void ssh_packet_set_authenticated(struct ssh *); void ssh_packet_set_mux(struct ssh *); diff --git a/pathnames.h b/pathnames.h index 3b5b5aa9befb..730000f29a99 100644 --- a/pathnames.h +++ b/pathnames.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pathnames.h,v 1.32 2024/05/17 00:30:24 djm Exp $ */ +/* $OpenBSD: pathnames.h,v 1.36 2025/08/29 03:50:38 djm Exp $ */ /* * Author: Tatu Ylonen @@ -36,10 +36,8 @@ */ #define _PATH_SERVER_CONFIG_FILE SSHDIR "/sshd_config" #define _PATH_HOST_CONFIG_FILE SSHDIR "/ssh_config" -#define _PATH_HOST_DSA_KEY_FILE SSHDIR "/ssh_host_dsa_key" #define _PATH_HOST_ECDSA_KEY_FILE SSHDIR "/ssh_host_ecdsa_key" #define _PATH_HOST_ED25519_KEY_FILE SSHDIR "/ssh_host_ed25519_key" -#define _PATH_HOST_XMSS_KEY_FILE SSHDIR "/ssh_host_xmss_key" #define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key" #define _PATH_DH_MODULI SSHDIR "/moduli" @@ -75,6 +73,13 @@ */ #define _PATH_SSH_USER_DIR ".ssh" + +/* + * The directory in which ssh-agent sockets and agent sockets forwarded by + * sshd reside. This directory should not be world-readable. + */ +#define _PATH_SSH_AGENT_SOCKET_DIR _PATH_SSH_USER_DIR "/agent" + /* * Per-user file containing host keys of known hosts. This file need not be * readable by anyone except the user him/herself, though this does not @@ -88,11 +93,9 @@ * Name of the default file containing client-side authentication key. This * file should only be readable by the user him/herself. */ -#define _PATH_SSH_CLIENT_ID_DSA _PATH_SSH_USER_DIR "/id_dsa" #define _PATH_SSH_CLIENT_ID_ECDSA _PATH_SSH_USER_DIR "/id_ecdsa" #define _PATH_SSH_CLIENT_ID_RSA _PATH_SSH_USER_DIR "/id_rsa" #define _PATH_SSH_CLIENT_ID_ED25519 _PATH_SSH_USER_DIR "/id_ed25519" -#define _PATH_SSH_CLIENT_ID_XMSS _PATH_SSH_USER_DIR "/id_xmss" #define _PATH_SSH_CLIENT_ID_ECDSA_SK _PATH_SSH_USER_DIR "/id_ecdsa_sk" #define _PATH_SSH_CLIENT_ID_ED25519_SK _PATH_SSH_USER_DIR "/id_ed25519_sk" diff --git a/pkcs11.h b/pkcs11.h index b01d58f9483a..707333f02f0f 100644 --- a/pkcs11.h +++ b/pkcs11.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pkcs11.h,v 1.3 2013/11/26 19:15:09 deraadt Exp $ */ +/* $OpenBSD: pkcs11.h,v 1.4 2025/07/25 13:06:07 djm Exp $ */ /* pkcs11.h Copyright 2006, 2007 g10 Code GmbH Copyright 2006 Andreas Jellinghaus @@ -64,9 +64,9 @@ extern "C" { version of this file, please consider deleting the revision macro (you may use a macro with a different name to keep track of your versions). */ -#define CRYPTOKI_VERSION_MAJOR 2 -#define CRYPTOKI_VERSION_MINOR 20 -#define CRYPTOKI_VERSION_REVISION 6 +#define CRYPTOKI_VERSION_MAJOR 3 +#define CRYPTOKI_VERSION_MINOR 0 +#define CRYPTOKI_VERSION_REVISION 0 /* Compatibility interface is default, unless CRYPTOKI_GNU is @@ -96,7 +96,6 @@ extern "C" { #endif - #ifdef CRYPTOKI_COMPAT /* If we are in compatibility mode, switch all exposed names to the PKCS #11 variant. There are corresponding #undefs below. */ @@ -155,6 +154,8 @@ extern "C" { #define ck_mechanism_type_t CK_MECHANISM_TYPE +#define ck_rsa_pkcs_mgf_type_t CK_RSA_PKCS_MGF_TYPE + #define ck_mechanism _CK_MECHANISM #define parameter pParameter #define parameter_len ulParameterLen @@ -166,7 +167,10 @@ extern "C" { #define ck_rv_t CK_RV #define ck_notify_t CK_NOTIFY +#define ck_interface CK_INTERFACE + #define ck_function_list _CK_FUNCTION_LIST +#define ck_function_list_3_0 _CK_FUNCTION_LIST_3_0 #define ck_createmutex_t CK_CREATEMUTEX #define ck_destroymutex_t CK_DESTROYMUTEX @@ -183,7 +187,6 @@ extern "C" { #endif /* CRYPTOKI_COMPAT */ - typedef unsigned long ck_flags_t; struct ck_version @@ -205,7 +208,7 @@ struct ck_info typedef unsigned long ck_notification_t; -#define CKN_SURRENDER (0) +#define CKN_SURRENDER (0UL) typedef unsigned long ck_slot_id_t; @@ -221,10 +224,10 @@ struct ck_slot_info }; -#define CKF_TOKEN_PRESENT (1 << 0) -#define CKF_REMOVABLE_DEVICE (1 << 1) -#define CKF_HW_SLOT (1 << 2) -#define CKF_ARRAY_ATTRIBUTE (1 << 30) +#define CKF_TOKEN_PRESENT (1UL << 0) +#define CKF_REMOVABLE_DEVICE (1UL << 1) +#define CKF_HW_SLOT (1UL << 2) +#define CKF_ARRAY_ATTRIBUTE (1UL << 30) struct ck_token_info @@ -250,48 +253,48 @@ struct ck_token_info }; -#define CKF_RNG (1 << 0) -#define CKF_WRITE_PROTECTED (1 << 1) -#define CKF_LOGIN_REQUIRED (1 << 2) -#define CKF_USER_PIN_INITIALIZED (1 << 3) -#define CKF_RESTORE_KEY_NOT_NEEDED (1 << 5) -#define CKF_CLOCK_ON_TOKEN (1 << 6) -#define CKF_PROTECTED_AUTHENTICATION_PATH (1 << 8) -#define CKF_DUAL_CRYPTO_OPERATIONS (1 << 9) -#define CKF_TOKEN_INITIALIZED (1 << 10) -#define CKF_SECONDARY_AUTHENTICATION (1 << 11) -#define CKF_USER_PIN_COUNT_LOW (1 << 16) -#define CKF_USER_PIN_FINAL_TRY (1 << 17) -#define CKF_USER_PIN_LOCKED (1 << 18) -#define CKF_USER_PIN_TO_BE_CHANGED (1 << 19) -#define CKF_SO_PIN_COUNT_LOW (1 << 20) -#define CKF_SO_PIN_FINAL_TRY (1 << 21) -#define CKF_SO_PIN_LOCKED (1 << 22) -#define CKF_SO_PIN_TO_BE_CHANGED (1 << 23) +#define CKF_RNG (1UL << 0) +#define CKF_WRITE_PROTECTED (1UL << 1) +#define CKF_LOGIN_REQUIRED (1UL << 2) +#define CKF_USER_PIN_INITIALIZED (1UL << 3) +#define CKF_RESTORE_KEY_NOT_NEEDED (1UL << 5) +#define CKF_CLOCK_ON_TOKEN (1UL << 6) +#define CKF_PROTECTED_AUTHENTICATION_PATH (1UL << 8) +#define CKF_DUAL_CRYPTO_OPERATIONS (1UL << 9) +#define CKF_TOKEN_INITIALIZED (1UL << 10) +#define CKF_SECONDARY_AUTHENTICATION (1UL << 11) +#define CKF_USER_PIN_COUNT_LOW (1UL << 16) +#define CKF_USER_PIN_FINAL_TRY (1UL << 17) +#define CKF_USER_PIN_LOCKED (1UL << 18) +#define CKF_USER_PIN_TO_BE_CHANGED (1UL << 19) +#define CKF_SO_PIN_COUNT_LOW (1UL << 20) +#define CKF_SO_PIN_FINAL_TRY (1UL << 21) +#define CKF_SO_PIN_LOCKED (1UL << 22) +#define CKF_SO_PIN_TO_BE_CHANGED (1UL << 23) #define CK_UNAVAILABLE_INFORMATION ((unsigned long) -1) -#define CK_EFFECTIVELY_INFINITE (0) +#define CK_EFFECTIVELY_INFINITE (0UL) typedef unsigned long ck_session_handle_t; -#define CK_INVALID_HANDLE (0) +#define CK_INVALID_HANDLE (0UL) typedef unsigned long ck_user_type_t; -#define CKU_SO (0) -#define CKU_USER (1) -#define CKU_CONTEXT_SPECIFIC (2) +#define CKU_SO (0UL) +#define CKU_USER (1UL) +#define CKU_CONTEXT_SPECIFIC (2UL) typedef unsigned long ck_state_t; -#define CKS_RO_PUBLIC_SESSION (0) -#define CKS_RO_USER_FUNCTIONS (1) -#define CKS_RW_PUBLIC_SESSION (2) -#define CKS_RW_USER_FUNCTIONS (3) -#define CKS_RW_SO_FUNCTIONS (4) +#define CKS_RO_PUBLIC_SESSION (0UL) +#define CKS_RO_USER_FUNCTIONS (1UL) +#define CKS_RW_PUBLIC_SESSION (2UL) +#define CKS_RW_USER_FUNCTIONS (3UL) +#define CKS_RW_SO_FUNCTIONS (4UL) struct ck_session_info @@ -302,8 +305,8 @@ struct ck_session_info unsigned long device_error; }; -#define CKF_RW_SESSION (1 << 1) -#define CKF_SERIAL_SESSION (1 << 2) +#define CKF_RW_SESSION (1UL << 1) +#define CKF_SERIAL_SESSION (1UL << 2) typedef unsigned long ck_object_handle_t; @@ -311,149 +314,194 @@ typedef unsigned long ck_object_handle_t; typedef unsigned long ck_object_class_t; -#define CKO_DATA (0) -#define CKO_CERTIFICATE (1) -#define CKO_PUBLIC_KEY (2) -#define CKO_PRIVATE_KEY (3) -#define CKO_SECRET_KEY (4) -#define CKO_HW_FEATURE (5) -#define CKO_DOMAIN_PARAMETERS (6) -#define CKO_MECHANISM (7) -#define CKO_VENDOR_DEFINED (1U << 31) - +#define CKO_DATA (0UL) +#define CKO_CERTIFICATE (1UL) +#define CKO_PUBLIC_KEY (2UL) +#define CKO_PRIVATE_KEY (3UL) +#define CKO_SECRET_KEY (4UL) +#define CKO_HW_FEATURE (5UL) +#define CKO_DOMAIN_PARAMETERS (6UL) +#define CKO_MECHANISM (7UL) +#define CKO_OTP_KEY (8UL) +#define CKO_PROFILE (9UL) +#define CKO_VENDOR_DEFINED (1UL << 31) + +#define CKP_INVALID_ID (0UL) +#define CKP_BASELINE_PROVIDER (1UL) +#define CKP_EXTENDED_PROVIDER (2UL) +#define CKP_AUTHENTICATION_TOKEN (3UL) +#define CKP_PUBLIC_CERTIFICATES_TOKEN (4UL) +#define CKP_VENDOR_DEFINED (1UL << 31) typedef unsigned long ck_hw_feature_type_t; -#define CKH_MONOTONIC_COUNTER (1) -#define CKH_CLOCK (2) -#define CKH_USER_INTERFACE (3) -#define CKH_VENDOR_DEFINED (1U << 31) +#define CKH_MONOTONIC_COUNTER (1UL) +#define CKH_CLOCK (2UL) +#define CKH_USER_INTERFACE (3UL) +#define CKH_VENDOR_DEFINED (1UL << 31) typedef unsigned long ck_key_type_t; -#define CKK_RSA (0) -#define CKK_DSA (1) -#define CKK_DH (2) -#define CKK_ECDSA (3) -#define CKK_EC (3) -#define CKK_X9_42_DH (4) -#define CKK_KEA (5) -#define CKK_GENERIC_SECRET (0x10) -#define CKK_RC2 (0x11) -#define CKK_RC4 (0x12) -#define CKK_DES (0x13) -#define CKK_DES2 (0x14) -#define CKK_DES3 (0x15) -#define CKK_CAST (0x16) -#define CKK_CAST3 (0x17) -#define CKK_CAST128 (0x18) -#define CKK_RC5 (0x19) -#define CKK_IDEA (0x1a) -#define CKK_SKIPJACK (0x1b) -#define CKK_BATON (0x1c) -#define CKK_JUNIPER (0x1d) -#define CKK_CDMF (0x1e) -#define CKK_AES (0x1f) -#define CKK_BLOWFISH (0x20) -#define CKK_TWOFISH (0x21) -#define CKK_VENDOR_DEFINED (1U << 31) +#define CKK_RSA (0UL) +#define CKK_DSA (1UL) +#define CKK_DH (2UL) +#define CKK_ECDSA (3UL) +#define CKK_EC (3UL) +#define CKK_X9_42_DH (4UL) +#define CKK_KEA (5UL) +#define CKK_GENERIC_SECRET (0x10UL) +#define CKK_RC2 (0x11UL) +#define CKK_RC4 (0x12UL) +#define CKK_DES (0x13UL) +#define CKK_DES2 (0x14UL) +#define CKK_DES3 (0x15UL) +#define CKK_CAST (0x16UL) +#define CKK_CAST3 (0x17UL) +#define CKK_CAST128 (0x18UL) +#define CKK_RC5 (0x19UL) +#define CKK_IDEA (0x1aUL) +#define CKK_SKIPJACK (0x1bUL) +#define CKK_BATON (0x1cUL) +#define CKK_JUNIPER (0x1dUL) +#define CKK_CDMF (0x1eUL) +#define CKK_AES (0x1fUL) +#define CKK_BLOWFISH (0x20UL) +#define CKK_TWOFISH (0x21UL) +#define CKK_GOSTR3410 (0x30UL) +#define CKK_GOSTR3411 (0x31UL) +#define CKK_GOST28147 (0x32UL) +#define CKK_EC_EDWARDS (0x40UL) +#define CKK_EC_MONTGOMERY (0x41UL) +#define CKK_HKDF (0x42UL) +#define CKK_VENDOR_DEFINED (1UL << 31) + +/* + * A mask for new GOST algorithms. + * For details visit https://tc26.ru/standarts/perevody/guidelines-the-pkcs-11-extensions-for-implementing-the-gost-r-34-10-2012-and-gost-r-34-11-2012-russian-standards-.html + */ +#define NSSCK_VENDOR_PKCS11_RU_TEAM (CKK_VENDOR_DEFINED | 0x54321000) +#define CK_VENDOR_PKCS11_RU_TEAM_TK26 NSSCK_VENDOR_PKCS11_RU_TEAM + +#define CKK_GOSTR3410_512 (CK_VENDOR_PKCS11_RU_TEAM_TK26 | 0x003) typedef unsigned long ck_certificate_type_t; -#define CKC_X_509 (0) -#define CKC_X_509_ATTR_CERT (1) -#define CKC_WTLS (2) -#define CKC_VENDOR_DEFINED (1U << 31) +#define CKC_X_509 (0UL) +#define CKC_X_509_ATTR_CERT (1UL) +#define CKC_WTLS (2UL) +#define CKC_VENDOR_DEFINED (1UL << 31) typedef unsigned long ck_attribute_type_t; -#define CKA_CLASS (0) -#define CKA_TOKEN (1) -#define CKA_PRIVATE (2) -#define CKA_LABEL (3) -#define CKA_APPLICATION (0x10) -#define CKA_VALUE (0x11) -#define CKA_OBJECT_ID (0x12) -#define CKA_CERTIFICATE_TYPE (0x80) -#define CKA_ISSUER (0x81) -#define CKA_SERIAL_NUMBER (0x82) -#define CKA_AC_ISSUER (0x83) -#define CKA_OWNER (0x84) -#define CKA_ATTR_TYPES (0x85) -#define CKA_TRUSTED (0x86) -#define CKA_CERTIFICATE_CATEGORY (0x87) -#define CKA_JAVA_MIDP_SECURITY_DOMAIN (0x88) -#define CKA_URL (0x89) -#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY (0x8a) -#define CKA_HASH_OF_ISSUER_PUBLIC_KEY (0x8b) -#define CKA_CHECK_VALUE (0x90) -#define CKA_KEY_TYPE (0x100) -#define CKA_SUBJECT (0x101) -#define CKA_ID (0x102) -#define CKA_SENSITIVE (0x103) -#define CKA_ENCRYPT (0x104) -#define CKA_DECRYPT (0x105) -#define CKA_WRAP (0x106) -#define CKA_UNWRAP (0x107) -#define CKA_SIGN (0x108) -#define CKA_SIGN_RECOVER (0x109) -#define CKA_VERIFY (0x10a) -#define CKA_VERIFY_RECOVER (0x10b) -#define CKA_DERIVE (0x10c) -#define CKA_START_DATE (0x110) -#define CKA_END_DATE (0x111) -#define CKA_MODULUS (0x120) -#define CKA_MODULUS_BITS (0x121) -#define CKA_PUBLIC_EXPONENT (0x122) -#define CKA_PRIVATE_EXPONENT (0x123) -#define CKA_PRIME_1 (0x124) -#define CKA_PRIME_2 (0x125) -#define CKA_EXPONENT_1 (0x126) -#define CKA_EXPONENT_2 (0x127) -#define CKA_COEFFICIENT (0x128) -#define CKA_PRIME (0x130) -#define CKA_SUBPRIME (0x131) -#define CKA_BASE (0x132) -#define CKA_PRIME_BITS (0x133) -#define CKA_SUB_PRIME_BITS (0x134) -#define CKA_VALUE_BITS (0x160) -#define CKA_VALUE_LEN (0x161) -#define CKA_EXTRACTABLE (0x162) -#define CKA_LOCAL (0x163) -#define CKA_NEVER_EXTRACTABLE (0x164) -#define CKA_ALWAYS_SENSITIVE (0x165) -#define CKA_KEY_GEN_MECHANISM (0x166) -#define CKA_MODIFIABLE (0x170) -#define CKA_ECDSA_PARAMS (0x180) -#define CKA_EC_PARAMS (0x180) -#define CKA_EC_POINT (0x181) -#define CKA_SECONDARY_AUTH (0x200) -#define CKA_AUTH_PIN_FLAGS (0x201) -#define CKA_ALWAYS_AUTHENTICATE (0x202) -#define CKA_WRAP_WITH_TRUSTED (0x210) -#define CKA_HW_FEATURE_TYPE (0x300) -#define CKA_RESET_ON_INIT (0x301) -#define CKA_HAS_RESET (0x302) -#define CKA_PIXEL_X (0x400) -#define CKA_PIXEL_Y (0x401) -#define CKA_RESOLUTION (0x402) -#define CKA_CHAR_ROWS (0x403) -#define CKA_CHAR_COLUMNS (0x404) -#define CKA_COLOR (0x405) -#define CKA_BITS_PER_PIXEL (0x406) -#define CKA_CHAR_SETS (0x480) -#define CKA_ENCODING_METHODS (0x481) -#define CKA_MIME_TYPES (0x482) -#define CKA_MECHANISM_TYPE (0x500) -#define CKA_REQUIRED_CMS_ATTRIBUTES (0x501) -#define CKA_DEFAULT_CMS_ATTRIBUTES (0x502) -#define CKA_SUPPORTED_CMS_ATTRIBUTES (0x503) -#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x211) -#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x212) -#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x600) -#define CKA_VENDOR_DEFINED (1U << 31) +#define CKA_CLASS (0UL) +#define CKA_TOKEN (1UL) +#define CKA_PRIVATE (2UL) +#define CKA_LABEL (3UL) +#define CKA_UNIQUE_ID (4UL) +#define CKA_APPLICATION (0x10UL) +#define CKA_VALUE (0x11UL) +#define CKA_OBJECT_ID (0x12UL) +#define CKA_CERTIFICATE_TYPE (0x80UL) +#define CKA_ISSUER (0x81UL) +#define CKA_SERIAL_NUMBER (0x82UL) +#define CKA_AC_ISSUER (0x83UL) +#define CKA_OWNER (0x84UL) +#define CKA_ATTR_TYPES (0x85UL) +#define CKA_TRUSTED (0x86UL) +#define CKA_CERTIFICATE_CATEGORY (0x87UL) +#define CKA_JAVA_MIDP_SECURITY_DOMAIN (0x88UL) +#define CKA_URL (0x89UL) +#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY (0x8aUL) +#define CKA_HASH_OF_ISSUER_PUBLIC_KEY (0x8bUL) +#define CKA_CHECK_VALUE (0x90UL) +#define CKA_KEY_TYPE (0x100UL) +#define CKA_SUBJECT (0x101UL) +#define CKA_ID (0x102UL) +#define CKA_SENSITIVE (0x103UL) +#define CKA_ENCRYPT (0x104UL) +#define CKA_DECRYPT (0x105UL) +#define CKA_WRAP (0x106UL) +#define CKA_UNWRAP (0x107UL) +#define CKA_SIGN (0x108UL) +#define CKA_SIGN_RECOVER (0x109UL) +#define CKA_VERIFY (0x10aUL) +#define CKA_VERIFY_RECOVER (0x10bUL) +#define CKA_DERIVE (0x10cUL) +#define CKA_START_DATE (0x110UL) +#define CKA_END_DATE (0x111UL) +#define CKA_MODULUS (0x120UL) +#define CKA_MODULUS_BITS (0x121UL) +#define CKA_PUBLIC_EXPONENT (0x122UL) +#define CKA_PRIVATE_EXPONENT (0x123UL) +#define CKA_PRIME_1 (0x124UL) +#define CKA_PRIME_2 (0x125UL) +#define CKA_EXPONENT_1 (0x126UL) +#define CKA_EXPONENT_2 (0x127UL) +#define CKA_COEFFICIENT (0x128UL) +#define CKA_PUBLIC_KEY_INFO (0x129UL) +#define CKA_PRIME (0x130UL) +#define CKA_SUBPRIME (0x131UL) +#define CKA_BASE (0x132UL) +#define CKA_PRIME_BITS (0x133UL) +#define CKA_SUB_PRIME_BITS (0x134UL) +#define CKA_VALUE_BITS (0x160UL) +#define CKA_VALUE_LEN (0x161UL) +#define CKA_EXTRACTABLE (0x162UL) +#define CKA_LOCAL (0x163UL) +#define CKA_NEVER_EXTRACTABLE (0x164UL) +#define CKA_ALWAYS_SENSITIVE (0x165UL) +#define CKA_KEY_GEN_MECHANISM (0x166UL) +#define CKA_MODIFIABLE (0x170UL) +#define CKA_COPYABLE (0x171UL) +#define CKA_DESTROYABLE (0x172UL) +#define CKA_ECDSA_PARAMS (0x180UL) +#define CKA_EC_PARAMS (0x180UL) +#define CKA_EC_POINT (0x181UL) +#define CKA_SECONDARY_AUTH (0x200UL) +#define CKA_AUTH_PIN_FLAGS (0x201UL) +#define CKA_ALWAYS_AUTHENTICATE (0x202UL) +#define CKA_WRAP_WITH_TRUSTED (0x210UL) +#define CKA_GOSTR3410_PARAMS (0x250UL) +#define CKA_GOSTR3411_PARAMS (0x251UL) +#define CKA_GOST28147_PARAMS (0x252UL) +#define CKA_HW_FEATURE_TYPE (0x300UL) +#define CKA_RESET_ON_INIT (0x301UL) +#define CKA_HAS_RESET (0x302UL) +#define CKA_PIXEL_X (0x400UL) +#define CKA_PIXEL_Y (0x401UL) +#define CKA_RESOLUTION (0x402UL) +#define CKA_CHAR_ROWS (0x403UL) +#define CKA_CHAR_COLUMNS (0x404UL) +#define CKA_COLOR (0x405UL) +#define CKA_BITS_PER_PIXEL (0x406UL) +#define CKA_CHAR_SETS (0x480UL) +#define CKA_ENCODING_METHODS (0x481UL) +#define CKA_MIME_TYPES (0x482UL) +#define CKA_MECHANISM_TYPE (0x500UL) +#define CKA_REQUIRED_CMS_ATTRIBUTES (0x501UL) +#define CKA_DEFAULT_CMS_ATTRIBUTES (0x502UL) +#define CKA_SUPPORTED_CMS_ATTRIBUTES (0x503UL) +#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x211UL) +#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x212UL) +#define CKA_OTP_FORMAT (0x220UL) +#define CKA_OTP_LENGTH (0x221UL) +#define CKA_OTP_TIME_INTERVAL (0x222UL) +#define CKA_OTP_USER_FRIENDLY_MODE (0x223UL) +#define CKA_OTP_CHALLENGE_REQUIREMENT (0x224UL) +#define CKA_OTP_TIME_REQUIREMENT (0x225UL) +#define CKA_OTP_COUNTER_REQUIREMENT (0x226UL) +#define CKA_OTP_PIN_REQUIREMENT (0x227UL) +#define CKA_OTP_USER_IDENTIFIER (0x22AUL) +#define CKA_OTP_SERVICE_IDENTIFIER (0x22BUL) +#define CKA_OTP_SERVICE_LOGO (0x22CUL) +#define CKA_OTP_SERVICE_LOGO_TYPE (0x22DUL) +#define CKA_OTP_COUNTER (0x22EUL) +#define CKA_OTP_TIME (0x22FUL) +#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x600UL) +#define CKA_PROFILE_ID (0x601UL) +#define CKA_VENDOR_DEFINED (1UL << 31) struct ck_attribute @@ -474,206 +522,304 @@ struct ck_date typedef unsigned long ck_mechanism_type_t; -#define CKM_RSA_PKCS_KEY_PAIR_GEN (0) -#define CKM_RSA_PKCS (1) -#define CKM_RSA_9796 (2) -#define CKM_RSA_X_509 (3) -#define CKM_MD2_RSA_PKCS (4) -#define CKM_MD5_RSA_PKCS (5) -#define CKM_SHA1_RSA_PKCS (6) -#define CKM_RIPEMD128_RSA_PKCS (7) -#define CKM_RIPEMD160_RSA_PKCS (8) -#define CKM_RSA_PKCS_OAEP (9) -#define CKM_RSA_X9_31_KEY_PAIR_GEN (0xa) -#define CKM_RSA_X9_31 (0xb) -#define CKM_SHA1_RSA_X9_31 (0xc) -#define CKM_RSA_PKCS_PSS (0xd) -#define CKM_SHA1_RSA_PKCS_PSS (0xe) -#define CKM_DSA_KEY_PAIR_GEN (0x10) -#define CKM_DSA (0x11) -#define CKM_DSA_SHA1 (0x12) -#define CKM_DH_PKCS_KEY_PAIR_GEN (0x20) -#define CKM_DH_PKCS_DERIVE (0x21) -#define CKM_X9_42_DH_KEY_PAIR_GEN (0x30) -#define CKM_X9_42_DH_DERIVE (0x31) -#define CKM_X9_42_DH_HYBRID_DERIVE (0x32) -#define CKM_X9_42_MQV_DERIVE (0x33) -#define CKM_SHA256_RSA_PKCS (0x40) -#define CKM_SHA384_RSA_PKCS (0x41) -#define CKM_SHA512_RSA_PKCS (0x42) -#define CKM_SHA256_RSA_PKCS_PSS (0x43) -#define CKM_SHA384_RSA_PKCS_PSS (0x44) -#define CKM_SHA512_RSA_PKCS_PSS (0x45) -#define CKM_RC2_KEY_GEN (0x100) -#define CKM_RC2_ECB (0x101) -#define CKM_RC2_CBC (0x102) -#define CKM_RC2_MAC (0x103) -#define CKM_RC2_MAC_GENERAL (0x104) -#define CKM_RC2_CBC_PAD (0x105) -#define CKM_RC4_KEY_GEN (0x110) -#define CKM_RC4 (0x111) -#define CKM_DES_KEY_GEN (0x120) -#define CKM_DES_ECB (0x121) -#define CKM_DES_CBC (0x122) -#define CKM_DES_MAC (0x123) -#define CKM_DES_MAC_GENERAL (0x124) -#define CKM_DES_CBC_PAD (0x125) -#define CKM_DES2_KEY_GEN (0x130) -#define CKM_DES3_KEY_GEN (0x131) -#define CKM_DES3_ECB (0x132) -#define CKM_DES3_CBC (0x133) -#define CKM_DES3_MAC (0x134) -#define CKM_DES3_MAC_GENERAL (0x135) -#define CKM_DES3_CBC_PAD (0x136) -#define CKM_CDMF_KEY_GEN (0x140) -#define CKM_CDMF_ECB (0x141) -#define CKM_CDMF_CBC (0x142) -#define CKM_CDMF_MAC (0x143) -#define CKM_CDMF_MAC_GENERAL (0x144) -#define CKM_CDMF_CBC_PAD (0x145) -#define CKM_MD2 (0x200) -#define CKM_MD2_HMAC (0x201) -#define CKM_MD2_HMAC_GENERAL (0x202) -#define CKM_MD5 (0x210) -#define CKM_MD5_HMAC (0x211) -#define CKM_MD5_HMAC_GENERAL (0x212) -#define CKM_SHA_1 (0x220) -#define CKM_SHA_1_HMAC (0x221) -#define CKM_SHA_1_HMAC_GENERAL (0x222) -#define CKM_RIPEMD128 (0x230) -#define CKM_RIPEMD128_HMAC (0x231) -#define CKM_RIPEMD128_HMAC_GENERAL (0x232) -#define CKM_RIPEMD160 (0x240) -#define CKM_RIPEMD160_HMAC (0x241) -#define CKM_RIPEMD160_HMAC_GENERAL (0x242) -#define CKM_SHA256 (0x250) -#define CKM_SHA256_HMAC (0x251) -#define CKM_SHA256_HMAC_GENERAL (0x252) -#define CKM_SHA384 (0x260) -#define CKM_SHA384_HMAC (0x261) -#define CKM_SHA384_HMAC_GENERAL (0x262) -#define CKM_SHA512 (0x270) -#define CKM_SHA512_HMAC (0x271) -#define CKM_SHA512_HMAC_GENERAL (0x272) -#define CKM_CAST_KEY_GEN (0x300) -#define CKM_CAST_ECB (0x301) -#define CKM_CAST_CBC (0x302) -#define CKM_CAST_MAC (0x303) -#define CKM_CAST_MAC_GENERAL (0x304) -#define CKM_CAST_CBC_PAD (0x305) -#define CKM_CAST3_KEY_GEN (0x310) -#define CKM_CAST3_ECB (0x311) -#define CKM_CAST3_CBC (0x312) -#define CKM_CAST3_MAC (0x313) -#define CKM_CAST3_MAC_GENERAL (0x314) -#define CKM_CAST3_CBC_PAD (0x315) -#define CKM_CAST5_KEY_GEN (0x320) -#define CKM_CAST128_KEY_GEN (0x320) -#define CKM_CAST5_ECB (0x321) -#define CKM_CAST128_ECB (0x321) -#define CKM_CAST5_CBC (0x322) -#define CKM_CAST128_CBC (0x322) -#define CKM_CAST5_MAC (0x323) -#define CKM_CAST128_MAC (0x323) -#define CKM_CAST5_MAC_GENERAL (0x324) -#define CKM_CAST128_MAC_GENERAL (0x324) -#define CKM_CAST5_CBC_PAD (0x325) -#define CKM_CAST128_CBC_PAD (0x325) -#define CKM_RC5_KEY_GEN (0x330) -#define CKM_RC5_ECB (0x331) -#define CKM_RC5_CBC (0x332) -#define CKM_RC5_MAC (0x333) -#define CKM_RC5_MAC_GENERAL (0x334) -#define CKM_RC5_CBC_PAD (0x335) -#define CKM_IDEA_KEY_GEN (0x340) -#define CKM_IDEA_ECB (0x341) -#define CKM_IDEA_CBC (0x342) -#define CKM_IDEA_MAC (0x343) -#define CKM_IDEA_MAC_GENERAL (0x344) -#define CKM_IDEA_CBC_PAD (0x345) -#define CKM_GENERIC_SECRET_KEY_GEN (0x350) -#define CKM_CONCATENATE_BASE_AND_KEY (0x360) -#define CKM_CONCATENATE_BASE_AND_DATA (0x362) -#define CKM_CONCATENATE_DATA_AND_BASE (0x363) -#define CKM_XOR_BASE_AND_DATA (0x364) -#define CKM_EXTRACT_KEY_FROM_KEY (0x365) -#define CKM_SSL3_PRE_MASTER_KEY_GEN (0x370) -#define CKM_SSL3_MASTER_KEY_DERIVE (0x371) -#define CKM_SSL3_KEY_AND_MAC_DERIVE (0x372) -#define CKM_SSL3_MASTER_KEY_DERIVE_DH (0x373) -#define CKM_TLS_PRE_MASTER_KEY_GEN (0x374) -#define CKM_TLS_MASTER_KEY_DERIVE (0x375) -#define CKM_TLS_KEY_AND_MAC_DERIVE (0x376) -#define CKM_TLS_MASTER_KEY_DERIVE_DH (0x377) -#define CKM_SSL3_MD5_MAC (0x380) -#define CKM_SSL3_SHA1_MAC (0x381) -#define CKM_MD5_KEY_DERIVATION (0x390) -#define CKM_MD2_KEY_DERIVATION (0x391) -#define CKM_SHA1_KEY_DERIVATION (0x392) -#define CKM_PBE_MD2_DES_CBC (0x3a0) -#define CKM_PBE_MD5_DES_CBC (0x3a1) -#define CKM_PBE_MD5_CAST_CBC (0x3a2) -#define CKM_PBE_MD5_CAST3_CBC (0x3a3) -#define CKM_PBE_MD5_CAST5_CBC (0x3a4) -#define CKM_PBE_MD5_CAST128_CBC (0x3a4) -#define CKM_PBE_SHA1_CAST5_CBC (0x3a5) -#define CKM_PBE_SHA1_CAST128_CBC (0x3a5) -#define CKM_PBE_SHA1_RC4_128 (0x3a6) -#define CKM_PBE_SHA1_RC4_40 (0x3a7) -#define CKM_PBE_SHA1_DES3_EDE_CBC (0x3a8) -#define CKM_PBE_SHA1_DES2_EDE_CBC (0x3a9) -#define CKM_PBE_SHA1_RC2_128_CBC (0x3aa) -#define CKM_PBE_SHA1_RC2_40_CBC (0x3ab) -#define CKM_PKCS5_PBKD2 (0x3b0) -#define CKM_PBA_SHA1_WITH_SHA1_HMAC (0x3c0) -#define CKM_KEY_WRAP_LYNKS (0x400) -#define CKM_KEY_WRAP_SET_OAEP (0x401) -#define CKM_SKIPJACK_KEY_GEN (0x1000) -#define CKM_SKIPJACK_ECB64 (0x1001) -#define CKM_SKIPJACK_CBC64 (0x1002) -#define CKM_SKIPJACK_OFB64 (0x1003) -#define CKM_SKIPJACK_CFB64 (0x1004) -#define CKM_SKIPJACK_CFB32 (0x1005) -#define CKM_SKIPJACK_CFB16 (0x1006) -#define CKM_SKIPJACK_CFB8 (0x1007) -#define CKM_SKIPJACK_WRAP (0x1008) -#define CKM_SKIPJACK_PRIVATE_WRAP (0x1009) -#define CKM_SKIPJACK_RELAYX (0x100a) -#define CKM_KEA_KEY_PAIR_GEN (0x1010) -#define CKM_KEA_KEY_DERIVE (0x1011) -#define CKM_FORTEZZA_TIMESTAMP (0x1020) -#define CKM_BATON_KEY_GEN (0x1030) -#define CKM_BATON_ECB128 (0x1031) -#define CKM_BATON_ECB96 (0x1032) -#define CKM_BATON_CBC128 (0x1033) -#define CKM_BATON_COUNTER (0x1034) -#define CKM_BATON_SHUFFLE (0x1035) -#define CKM_BATON_WRAP (0x1036) -#define CKM_ECDSA_KEY_PAIR_GEN (0x1040) -#define CKM_EC_KEY_PAIR_GEN (0x1040) -#define CKM_ECDSA (0x1041) -#define CKM_ECDSA_SHA1 (0x1042) -#define CKM_ECDH1_DERIVE (0x1050) -#define CKM_ECDH1_COFACTOR_DERIVE (0x1051) -#define CKM_ECMQV_DERIVE (0x1052) -#define CKM_JUNIPER_KEY_GEN (0x1060) -#define CKM_JUNIPER_ECB128 (0x1061) -#define CKM_JUNIPER_CBC128 (0x1062) -#define CKM_JUNIPER_COUNTER (0x1063) -#define CKM_JUNIPER_SHUFFLE (0x1064) -#define CKM_JUNIPER_WRAP (0x1065) -#define CKM_FASTHASH (0x1070) -#define CKM_AES_KEY_GEN (0x1080) -#define CKM_AES_ECB (0x1081) -#define CKM_AES_CBC (0x1082) -#define CKM_AES_MAC (0x1083) -#define CKM_AES_MAC_GENERAL (0x1084) -#define CKM_AES_CBC_PAD (0x1085) -#define CKM_DSA_PARAMETER_GEN (0x2000) -#define CKM_DH_PKCS_PARAMETER_GEN (0x2001) -#define CKM_X9_42_DH_PARAMETER_GEN (0x2002) -#define CKM_VENDOR_DEFINED (1U << 31) - +#define CKM_RSA_PKCS_KEY_PAIR_GEN (0UL) +#define CKM_RSA_PKCS (1UL) +#define CKM_RSA_9796 (2UL) +#define CKM_RSA_X_509 (3UL) +#define CKM_MD2_RSA_PKCS (4UL) +#define CKM_MD5_RSA_PKCS (5UL) +#define CKM_SHA1_RSA_PKCS (6UL) +#define CKM_RIPEMD128_RSA_PKCS (7UL) +#define CKM_RIPEMD160_RSA_PKCS (8UL) +#define CKM_RSA_PKCS_OAEP (9UL) +#define CKM_RSA_X9_31_KEY_PAIR_GEN (0xaUL) +#define CKM_RSA_X9_31 (0xbUL) +#define CKM_SHA1_RSA_X9_31 (0xcUL) +#define CKM_RSA_PKCS_PSS (0xdUL) +#define CKM_SHA1_RSA_PKCS_PSS (0xeUL) +#define CKM_DSA_KEY_PAIR_GEN (0x10UL) +#define CKM_DSA (0x11UL) +#define CKM_DSA_SHA1 (0x12UL) +#define CKM_DSA_SHA224 (0x13UL) +#define CKM_DSA_SHA256 (0x14UL) +#define CKM_DSA_SHA384 (0x15UL) +#define CKM_DSA_SHA512 (0x16UL) +#define CKM_DH_PKCS_KEY_PAIR_GEN (0x20UL) +#define CKM_DH_PKCS_DERIVE (0x21UL) +#define CKM_X9_42_DH_KEY_PAIR_GEN (0x30UL) +#define CKM_X9_42_DH_DERIVE (0x31UL) +#define CKM_X9_42_DH_HYBRID_DERIVE (0x32UL) +#define CKM_X9_42_MQV_DERIVE (0x33UL) +#define CKM_SHA256_RSA_PKCS (0x40UL) +#define CKM_SHA384_RSA_PKCS (0x41UL) +#define CKM_SHA512_RSA_PKCS (0x42UL) +#define CKM_SHA256_RSA_PKCS_PSS (0x43UL) +#define CKM_SHA384_RSA_PKCS_PSS (0x44UL) +#define CKM_SHA512_RSA_PKCS_PSS (0x45UL) +#define CKM_SHA224_RSA_PKCS (0x46UL) +#define CKM_SHA224_RSA_PKCS_PSS (0x47UL) +#define CKM_SHA3_256_RSA_PKCS (0x60UL) +#define CKM_SHA3_384_RSA_PKCS (0x61UL) +#define CKM_SHA3_512_RSA_PKCS (0x62UL) +#define CKM_SHA3_256_RSA_PKCS_PSS (0x63UL) +#define CKM_SHA3_384_RSA_PKCS_PSS (0x64UL) +#define CKM_SHA3_512_RSA_PKCS_PSS (0x65UL) +#define CKM_SHA3_224_RSA_PKCS (0x66UL) +#define CKM_SHA3_224_RSA_PKCS_PSS (0x67UL) +#define CKM_RC2_KEY_GEN (0x100UL) +#define CKM_RC2_ECB (0x101UL) +#define CKM_RC2_CBC (0x102UL) +#define CKM_RC2_MAC (0x103UL) +#define CKM_RC2_MAC_GENERAL (0x104UL) +#define CKM_RC2_CBC_PAD (0x105UL) +#define CKM_RC4_KEY_GEN (0x110UL) +#define CKM_RC4 (0x111UL) +#define CKM_DES_KEY_GEN (0x120UL) +#define CKM_DES_ECB (0x121UL) +#define CKM_DES_CBC (0x122UL) +#define CKM_DES_MAC (0x123UL) +#define CKM_DES_MAC_GENERAL (0x124UL) +#define CKM_DES_CBC_PAD (0x125UL) +#define CKM_DES2_KEY_GEN (0x130UL) +#define CKM_DES3_KEY_GEN (0x131UL) +#define CKM_DES3_ECB (0x132UL) +#define CKM_DES3_CBC (0x133UL) +#define CKM_DES3_MAC (0x134UL) +#define CKM_DES3_MAC_GENERAL (0x135UL) +#define CKM_DES3_CBC_PAD (0x136UL) +#define CKM_DES3_CMAC_GENERAL (0x137UL) +#define CKM_DES3_CMAC (0x138UL) +#define CKM_CDMF_KEY_GEN (0x140UL) +#define CKM_CDMF_ECB (0x141UL) +#define CKM_CDMF_CBC (0x142UL) +#define CKM_CDMF_MAC (0x143UL) +#define CKM_CDMF_MAC_GENERAL (0x144UL) +#define CKM_CDMF_CBC_PAD (0x145UL) +#define CKM_MD2 (0x200UL) +#define CKM_MD2_HMAC (0x201UL) +#define CKM_MD2_HMAC_GENERAL (0x202UL) +#define CKM_MD5 (0x210UL) +#define CKM_MD5_HMAC (0x211UL) +#define CKM_MD5_HMAC_GENERAL (0x212UL) +#define CKM_SHA_1 (0x220UL) +#define CKM_SHA_1_HMAC (0x221UL) +#define CKM_SHA_1_HMAC_GENERAL (0x222UL) +#define CKM_RIPEMD128 (0x230UL) +#define CKM_RIPEMD128_HMAC (0x231UL) +#define CKM_RIPEMD128_HMAC_GENERAL (0x232UL) +#define CKM_RIPEMD160 (0x240UL) +#define CKM_RIPEMD160_HMAC (0x241UL) +#define CKM_RIPEMD160_HMAC_GENERAL (0x242UL) +#define CKM_SHA256 (0x250UL) +#define CKM_SHA256_HMAC (0x251UL) +#define CKM_SHA256_HMAC_GENERAL (0x252UL) +#define CKM_SHA224 (0x255UL) +#define CKM_SHA224_HMAC (0x256UL) +#define CKM_SHA224_HMAC_GENERAL (0x257UL) +#define CKM_SHA384 (0x260UL) +#define CKM_SHA384_HMAC (0x261UL) +#define CKM_SHA384_HMAC_GENERAL (0x262UL) +#define CKM_SHA512 (0x270UL) +#define CKM_SHA512_HMAC (0x271UL) +#define CKM_SHA512_HMAC_GENERAL (0x272UL) +#define CKM_SHA3_256 (0x2B0UL) +#define CKM_SHA3_256_HMAC (0x2B1UL) +#define CKM_SHA3_256_HMAC_GENERAL (0x2B2UL) +#define CKM_SHA3_256_KEY_GEN (0x2B3UL) +#define CKM_SHA3_224 (0x2B5UL) +#define CKM_SHA3_224_HMAC (0x2B6UL) +#define CKM_SHA3_224_HMAC_GENERAL (0x2B7UL) +#define CKM_SHA3_224_KEY_GEN (0x2B8UL) +#define CKM_SHA3_384 (0x2C0UL) +#define CKM_SHA3_384_HMAC (0x2C1UL) +#define CKM_SHA3_384_HMAC_GENERAL (0x2C2UL) +#define CKM_SHA3_384_KEY_GEN (0x2C3UL) +#define CKM_SHA3_512 (0x2D0UL) +#define CKM_SHA3_512_HMAC (0x2D1UL) +#define CKM_SHA3_512_HMAC_GENERAL (0x2D2UL) +#define CKM_SHA3_512_KEY_GEN (0x2D3UL) +#define CKM_CAST_KEY_GEN (0x300UL) +#define CKM_CAST_ECB (0x301UL) +#define CKM_CAST_CBC (0x302UL) +#define CKM_CAST_MAC (0x303UL) +#define CKM_CAST_MAC_GENERAL (0x304UL) +#define CKM_CAST_CBC_PAD (0x305UL) +#define CKM_CAST3_KEY_GEN (0x310UL) +#define CKM_CAST3_ECB (0x311UL) +#define CKM_CAST3_CBC (0x312UL) +#define CKM_CAST3_MAC (0x313UL) +#define CKM_CAST3_MAC_GENERAL (0x314UL) +#define CKM_CAST3_CBC_PAD (0x315UL) +#define CKM_CAST5_KEY_GEN (0x320UL) +#define CKM_CAST128_KEY_GEN (0x320UL) +#define CKM_CAST5_ECB (0x321UL) +#define CKM_CAST128_ECB (0x321UL) +#define CKM_CAST5_CBC (0x322UL) +#define CKM_CAST128_CBC (0x322UL) +#define CKM_CAST5_MAC (0x323UL) +#define CKM_CAST128_MAC (0x323UL) +#define CKM_CAST5_MAC_GENERAL (0x324UL) +#define CKM_CAST128_MAC_GENERAL (0x324UL) +#define CKM_CAST5_CBC_PAD (0x325UL) +#define CKM_CAST128_CBC_PAD (0x325UL) +#define CKM_RC5_KEY_GEN (0x330UL) +#define CKM_RC5_ECB (0x331UL) +#define CKM_RC5_CBC (0x332UL) +#define CKM_RC5_MAC (0x333UL) +#define CKM_RC5_MAC_GENERAL (0x334UL) +#define CKM_RC5_CBC_PAD (0x335UL) +#define CKM_IDEA_KEY_GEN (0x340UL) +#define CKM_IDEA_ECB (0x341UL) +#define CKM_IDEA_CBC (0x342UL) +#define CKM_IDEA_MAC (0x343UL) +#define CKM_IDEA_MAC_GENERAL (0x344UL) +#define CKM_IDEA_CBC_PAD (0x345UL) +#define CKM_GENERIC_SECRET_KEY_GEN (0x350UL) +#define CKM_CONCATENATE_BASE_AND_KEY (0x360UL) +#define CKM_CONCATENATE_BASE_AND_DATA (0x362UL) +#define CKM_CONCATENATE_DATA_AND_BASE (0x363UL) +#define CKM_XOR_BASE_AND_DATA (0x364UL) +#define CKM_EXTRACT_KEY_FROM_KEY (0x365UL) +#define CKM_SSL3_PRE_MASTER_KEY_GEN (0x370UL) +#define CKM_SSL3_MASTER_KEY_DERIVE (0x371UL) +#define CKM_SSL3_KEY_AND_MAC_DERIVE (0x372UL) +#define CKM_SSL3_MASTER_KEY_DERIVE_DH (0x373UL) +#define CKM_TLS_PRE_MASTER_KEY_GEN (0x374UL) +#define CKM_TLS_MASTER_KEY_DERIVE (0x375UL) +#define CKM_TLS_KEY_AND_MAC_DERIVE (0x376UL) +#define CKM_TLS_MASTER_KEY_DERIVE_DH (0x377UL) +#define CKM_SSL3_MD5_MAC (0x380UL) +#define CKM_SSL3_SHA1_MAC (0x381UL) +#define CKM_MD5_KEY_DERIVATION (0x390UL) +#define CKM_MD2_KEY_DERIVATION (0x391UL) +#define CKM_SHA1_KEY_DERIVATION (0x392UL) +#define CKM_PBE_MD2_DES_CBC (0x3a0UL) +#define CKM_PBE_MD5_DES_CBC (0x3a1UL) +#define CKM_PBE_MD5_CAST_CBC (0x3a2UL) +#define CKM_PBE_MD5_CAST3_CBC (0x3a3UL) +#define CKM_PBE_MD5_CAST5_CBC (0x3a4UL) +#define CKM_PBE_MD5_CAST128_CBC (0x3a4UL) +#define CKM_PBE_SHA1_CAST5_CBC (0x3a5UL) +#define CKM_PBE_SHA1_CAST128_CBC (0x3a5UL) +#define CKM_PBE_SHA1_RC4_128 (0x3a6UL) +#define CKM_PBE_SHA1_RC4_40 (0x3a7UL) +#define CKM_PBE_SHA1_DES3_EDE_CBC (0x3a8UL) +#define CKM_PBE_SHA1_DES2_EDE_CBC (0x3a9UL) +#define CKM_PBE_SHA1_RC2_128_CBC (0x3aaUL) +#define CKM_PBE_SHA1_RC2_40_CBC (0x3abUL) +#define CKM_PKCS5_PBKD2 (0x3b0UL) +#define CKM_PBA_SHA1_WITH_SHA1_HMAC (0x3c0UL) +#define CKM_KEY_WRAP_LYNKS (0x400UL) +#define CKM_KEY_WRAP_SET_OAEP (0x401UL) +#define CKM_SKIPJACK_KEY_GEN (0x1000UL) +#define CKM_SKIPJACK_ECB64 (0x1001UL) +#define CKM_SKIPJACK_CBC64 (0x1002UL) +#define CKM_SKIPJACK_OFB64 (0x1003UL) +#define CKM_SKIPJACK_CFB64 (0x1004UL) +#define CKM_SKIPJACK_CFB32 (0x1005UL) +#define CKM_SKIPJACK_CFB16 (0x1006UL) +#define CKM_SKIPJACK_CFB8 (0x1007UL) +#define CKM_SKIPJACK_WRAP (0x1008UL) +#define CKM_SKIPJACK_PRIVATE_WRAP (0x1009UL) +#define CKM_SKIPJACK_RELAYX (0x100aUL) +#define CKM_KEA_KEY_PAIR_GEN (0x1010UL) +#define CKM_KEA_KEY_DERIVE (0x1011UL) +#define CKM_FORTEZZA_TIMESTAMP (0x1020UL) +#define CKM_BATON_KEY_GEN (0x1030UL) +#define CKM_BATON_ECB128 (0x1031UL) +#define CKM_BATON_ECB96 (0x1032UL) +#define CKM_BATON_CBC128 (0x1033UL) +#define CKM_BATON_COUNTER (0x1034UL) +#define CKM_BATON_SHUFFLE (0x1035UL) +#define CKM_BATON_WRAP (0x1036UL) +#define CKM_ECDSA_KEY_PAIR_GEN (0x1040UL) +#define CKM_EC_KEY_PAIR_GEN (0x1040UL) +#define CKM_ECDSA (0x1041UL) +#define CKM_ECDSA_SHA1 (0x1042UL) +#define CKM_ECDSA_SHA224 (0x1043UL) +#define CKM_ECDSA_SHA256 (0x1044UL) +#define CKM_ECDSA_SHA384 (0x1045UL) +#define CKM_ECDSA_SHA512 (0x1046UL) +#define CKM_ECDSA_SHA3_224 (0x1047UL) +#define CKM_ECDSA_SHA3_256 (0x1048UL) +#define CKM_ECDSA_SHA3_384 (0x1049UL) +#define CKM_ECDSA_SHA3_512 (0x104AUL) +#define CKM_ECDH1_DERIVE (0x1050UL) +#define CKM_ECDH1_COFACTOR_DERIVE (0x1051UL) +#define CKM_ECMQV_DERIVE (0x1052UL) +#define CKM_EC_EDWARDS_KEY_PAIR_GEN (0x1055UL) +#define CKM_EC_MONTGOMERY_KEY_PAIR_GEN (0x1056UL) +#define CKM_EDDSA (0x1057UL) +#define CKM_JUNIPER_KEY_GEN (0x1060UL) +#define CKM_JUNIPER_ECB128 (0x1061UL) +#define CKM_JUNIPER_CBC128 (0x1062UL) +#define CKM_JUNIPER_COUNTER (0x1063UL) +#define CKM_JUNIPER_SHUFFLE (0x1064UL) +#define CKM_JUNIPER_WRAP (0x1065UL) +#define CKM_FASTHASH (0x1070UL) +#define CKM_AES_KEY_GEN (0x1080UL) +#define CKM_AES_ECB (0x1081UL) +#define CKM_AES_CBC (0x1082UL) +#define CKM_AES_MAC (0x1083UL) +#define CKM_AES_MAC_GENERAL (0x1084UL) +#define CKM_AES_CBC_PAD (0x1085UL) +#define CKM_AES_CTR (0x1086UL) +#define CKM_AES_GCM (0x1087UL) +#define CKM_AES_CCM (0x1088UL) +#define CKM_AES_CTS (0x1089UL) +#define CKM_AES_CMAC (0x108AUL) +#define CKM_AES_CMAC_GENERAL (0x108BUL) +#define CKM_AES_XCBC_MAC (0x108CUL) +#define CKM_AES_XCBC_MAC_96 (0x108DUL) +#define CKM_AES_GMAC (0x108EUL) +#define CKM_BLOWFISH_KEY_GEN (0x1090UL) +#define CKM_BLOWFISH_CBC (0x1091UL) +#define CKM_TWOFISH_KEY_GEN (0x1092UL) +#define CKM_TWOFISH_CBC (0x1093UL) +#define CKM_DES_ECB_ENCRYPT_DATA (0x1100UL) +#define CKM_DES_CBC_ENCRYPT_DATA (0x1101UL) +#define CKM_DES3_ECB_ENCRYPT_DATA (0x1102UL) +#define CKM_DES3_CBC_ENCRYPT_DATA (0x1103UL) +#define CKM_AES_ECB_ENCRYPT_DATA (0x1104UL) +#define CKM_AES_CBC_ENCRYPT_DATA (0x1105UL) +#define CKM_GOSTR3410_KEY_PAIR_GEN (0x1200UL) +#define CKM_GOSTR3410 (0x1201UL) +#define CKM_GOSTR3410_WITH_GOSTR3411 (0x1202UL) +#define CKM_GOSTR3410_KEY_WRAP (0x1203UL) +#define CKM_GOSTR3410_DERIVE (0x1204UL) +#define CKM_GOSTR3410_512_KEY_PAIR_GEN (CK_VENDOR_PKCS11_RU_TEAM_TK26 | 0x005) +#define CKM_GOSTR3410_512 (CK_VENDOR_PKCS11_RU_TEAM_TK26 | 0x006) +#define CKM_GOSTR3410_12_DERIVE (CK_VENDOR_PKCS11_RU_TEAM_TK26 | 0x007) +#define CKM_GOSTR3410_WITH_GOSTR3411_12_256 (CK_VENDOR_PKCS11_RU_TEAM_TK26 | 0x008) +#define CKM_GOSTR3410_WITH_GOSTR3411_12_512 (CK_VENDOR_PKCS11_RU_TEAM_TK26 | 0x009) +#define CKM_GOSTR3411 (0x1210UL) +#define CKM_GOSTR3411_HMAC (0x1211UL) +#define CKM_GOSTR3411_12_256 (CK_VENDOR_PKCS11_RU_TEAM_TK26 | 0x012) +#define CKM_GOSTR3411_12_512 (CK_VENDOR_PKCS11_RU_TEAM_TK26 | 0x013) +#define CKM_GOSTR3411_12_256_HMAC (CK_VENDOR_PKCS11_RU_TEAM_TK26 | 0x014) +#define CKM_GOSTR3411_12_512_HMAC (CK_VENDOR_PKCS11_RU_TEAM_TK26 | 0x015) +#define CKM_GOST28147_KEY_GEN (0x1220UL) +#define CKM_GOST28147_ECB (0x1221UL) +#define CKM_GOST28147 (0x1222UL) +#define CKM_GOST28147_MAC (0x1223UL) +#define CKM_GOST28147_KEY_WRAP (0x1224UL) + +#define CKM_DSA_PARAMETER_GEN (0x2000UL) +#define CKM_DH_PKCS_PARAMETER_GEN (0x2001UL) +#define CKM_X9_42_DH_PARAMETER_GEN (0x2002UL) +#define CKM_AES_OFB (0x2104UL) +#define CKM_AES_CFB64 (0x2105UL) +#define CKM_AES_CFB8 (0x2106UL) +#define CKM_AES_CFB128 (0x2107UL) +#define CKM_AES_CFB1 (0x2108UL) +#define CKM_AES_KEY_WRAP (0x2109UL) +#define CKM_AES_KEY_WRAP_PAD (0x210AUL) +#define CKM_XEDDSA (0x4029UL) +#define CKM_HKDF_DERIVE (0x402AUL) +#define CKM_HKDF_DATA (0x402BUL) +#define CKM_HKDF_KEY_GEN (0x402CUL) + +#define CKM_VENDOR_DEFINED (1UL << 31) struct ck_mechanism { @@ -690,25 +836,143 @@ struct ck_mechanism_info ck_flags_t flags; }; -#define CKF_HW (1 << 0) -#define CKF_ENCRYPT (1 << 8) -#define CKF_DECRYPT (1 << 9) -#define CKF_DIGEST (1 << 10) -#define CKF_SIGN (1 << 11) -#define CKF_SIGN_RECOVER (1 << 12) -#define CKF_VERIFY (1 << 13) -#define CKF_VERIFY_RECOVER (1 << 14) -#define CKF_GENERATE (1 << 15) -#define CKF_GENERATE_KEY_PAIR (1 << 16) -#define CKF_WRAP (1 << 17) -#define CKF_UNWRAP (1 << 18) -#define CKF_DERIVE (1 << 19) -#define CKF_EXTENSION (1U << 31) - +#define CKF_HW (1UL << 0) + +#define CKF_MESSAGE_ENCRYPT (1UL << 1) +#define CKF_MESSAGE_DECRYPT (1UL << 2) +#define CKF_MESSAGE_SIGN (1UL << 3) +#define CKF_MESSAGE_VERIFY (1UL << 4) +#define CKF_MULTI_MESSAGE (1UL << 5) +#define CKF_FIND_OBJECTS (1UL << 6) + +#define CKF_ENCRYPT (1UL << 8) +#define CKF_DECRYPT (1UL << 9) +#define CKF_DIGEST (1UL << 10) +#define CKF_SIGN (1UL << 11) +#define CKF_SIGN_RECOVER (1UL << 12) +#define CKF_VERIFY (1UL << 13) +#define CKF_VERIFY_RECOVER (1UL << 14) +#define CKF_GENERATE (1UL << 15) +#define CKF_GENERATE_KEY_PAIR (1UL << 16) +#define CKF_WRAP (1UL << 17) +#define CKF_UNWRAP (1UL << 18) +#define CKF_DERIVE (1UL << 19) +#define CKF_EXTENSION (1UL << 31) + +#define CKF_EC_F_P (1UL << 20) +#define CKF_EC_F_2M (1UL << 21) +#define CKF_EC_ECPARAMETERS (1UL << 22) +#define CKF_EC_OID (1UL << 23) +#define CKF_EC_NAMEDCURVE CKF_EC_OID +#define CKF_EC_UNCOMPRESS (1UL << 24) +#define CKF_EC_COMPRESS (1UL << 25) +#define CKF_EC_CURVENAME (1UL << 26) /* Flags for C_WaitForSlotEvent. */ -#define CKF_DONT_BLOCK (1) - +#define CKF_DONT_BLOCK (1UL) + +/* Flags for Key derivation */ +#define CKD_NULL (0x1UL) +#define CKD_SHA1_KDF (0x2UL) +#define CKD_SHA224_KDF (0x5UL) +#define CKD_SHA256_KDF (0x6UL) +#define CKD_SHA384_KDF (0x7UL) +#define CKD_SHA512_KDF (0x8UL) + +typedef struct CK_ECDH1_DERIVE_PARAMS { + unsigned long kdf; + unsigned long ulSharedDataLen; + unsigned char * pSharedData; + unsigned long ulPublicDataLen; + unsigned char * pPublicData; +} CK_ECDH1_DERIVE_PARAMS; + +typedef struct CK_ECMQV_DERIVE_PARAMS { + unsigned long kdf; + unsigned long ulSharedDataLen; + unsigned char * pSharedData; + unsigned long ulPublicDataLen; + unsigned char * pPublicData; + unsigned long ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + unsigned long ulPublicDataLen2; + unsigned char * pPublicData2; + CK_OBJECT_HANDLE publicKey; +} CK_ECMQV_DERIVE_PARAMS; + +typedef unsigned long ck_rsa_pkcs_mgf_type_t; +typedef unsigned long CK_RSA_PKCS_OAEP_SOURCE_TYPE; + +typedef struct CK_RSA_PKCS_OAEP_PARAMS { + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + CK_RSA_PKCS_OAEP_SOURCE_TYPE source; + void *pSourceData; + unsigned long ulSourceDataLen; +} CK_RSA_PKCS_OAEP_PARAMS; + +typedef struct CK_RSA_PKCS_PSS_PARAMS { + ck_mechanism_type_t hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + unsigned long sLen; +} CK_RSA_PKCS_PSS_PARAMS; + +#define CKG_MGF1_SHA1 (0x00000001UL) +#define CKG_MGF1_SHA224 (0x00000005UL) +#define CKG_MGF1_SHA256 (0x00000002UL) +#define CKG_MGF1_SHA384 (0x00000003UL) +#define CKG_MGF1_SHA512 (0x00000004UL) +#define CKG_MGF1_SHA3_224 (0x00000006UL) +#define CKG_MGF1_SHA3_256 (0x00000007UL) +#define CKG_MGF1_SHA3_384 (0x00000008UL) +#define CKG_MGF1_SHA3_512 (0x00000009UL) + +#define CKZ_DATA_SPECIFIED (0x00000001UL) + +typedef struct CK_GCM_PARAMS { + void * pIv; + unsigned long ulIvLen; + unsigned long ulIvBits; + void * pAAD; + unsigned long ulAADLen; + unsigned long ulTagBits; +} CK_GCM_PARAMS; + +typedef struct CK_CCM_PARAMS { + unsigned long ulDataLen; + unsigned char *pNonce; + unsigned long ulNonceLen; + unsigned char *pAAD; + unsigned long ulAADLen; + unsigned long ulMACLen; +} CK_CCM_PARAMS; + +/* EDDSA */ +typedef struct CK_EDDSA_PARAMS { + unsigned char phFlag; + unsigned long ulContextDataLen; + unsigned char *pContextData; +} CK_EDDSA_PARAMS; + +typedef CK_EDDSA_PARAMS *CK_EDDSA_PARAMS_PTR; + +/* XEDDSA */ +typedef struct CK_XEDDSA_PARAMS { + unsigned long hash; +} CK_XEDDSA_PARAMS; + +typedef CK_XEDDSA_PARAMS *CK_XEDDSA_PARAMS_PTR; + +typedef struct CK_AES_CTR_PARAMS { + unsigned long ulCounterBits; + unsigned char cb[16]; +} CK_AES_CTR_PARAMS; + +typedef CK_AES_CTR_PARAMS *CK_AES_CTR_PARAMS_PTR; + +typedef unsigned long CK_MAC_GENERAL_PARAMS; + +typedef CK_MAC_GENERAL_PARAMS *CK_MAC_GENERAL_PARAMS_PTR; typedef unsigned long ck_rv_t; @@ -716,8 +980,17 @@ typedef unsigned long ck_rv_t; typedef ck_rv_t (*ck_notify_t) (ck_session_handle_t session, ck_notification_t event, void *application); +struct ck_interface { + char * pInterfaceName; + void * pFunctionList; + ck_flags_t flags; +}; + +#define CKF_INTERFACE_FORK_SAFE (0x00000001UL) + /* Forward reference. */ struct ck_function_list; +struct ck_function_list_3_0; #define _CK_DECLARE_FUNCTION(name, args) \ typedef ck_rv_t (*CK_ ## name) args; \ @@ -774,7 +1047,7 @@ _CK_DECLARE_FUNCTION (C_SetOperationState, unsigned char *operation_state, unsigned long operation_state_len, ck_object_handle_t encryption_key, - ck_object_handle_t authentiation_key)); + ck_object_handle_t authentication_key)); _CK_DECLARE_FUNCTION (C_Login, (ck_session_handle_t session, ck_user_type_t user_type, unsigned char *pin, unsigned long pin_len)); @@ -999,6 +1272,147 @@ _CK_DECLARE_FUNCTION (C_GenerateRandom, _CK_DECLARE_FUNCTION (C_GetFunctionStatus, (ck_session_handle_t session)); _CK_DECLARE_FUNCTION (C_CancelFunction, (ck_session_handle_t session)); +_CK_DECLARE_FUNCTION (C_GetInterfaceList, + (struct ck_interface *interfaces_list, + unsigned long *count)); +_CK_DECLARE_FUNCTION (C_GetInterface, + (unsigned char *interface_name, + struct ck_version *version, + struct ck_interface **interface_ptr, + ck_flags_t flags)); + +_CK_DECLARE_FUNCTION (C_LoginUser, + (ck_session_handle_t session, + ck_user_type_t user_type, + unsigned char *pin, + unsigned long pin_len, + unsigned char *username, + unsigned long username_len)); + +_CK_DECLARE_FUNCTION (C_SessionCancel, + (ck_session_handle_t session, + ck_flags_t flags)); + +_CK_DECLARE_FUNCTION (C_MessageEncryptInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_EncryptMessage, + (ck_session_handle_t session, + void *parameter, + unsigned long parameter_len, + unsigned char *associated_data, + unsigned long associated_data_len, + unsigned char *plaintext, + unsigned long plaintext_len, + unsigned char *ciphertext, + unsigned long *ciphertext_len)); +_CK_DECLARE_FUNCTION (C_EncryptMessageBegin, + (ck_session_handle_t session, + void *parameter, + unsigned long parameter_len, + unsigned char *associated_data, + unsigned long associated_data_len)); +_CK_DECLARE_FUNCTION (C_EncryptMessageNext, + (ck_session_handle_t session, + void *parameter, + unsigned long parameter_len, + unsigned char *plaintext_part, + unsigned long plaintext_part_len, + unsigned char *ciphertext_part, + unsigned long *ciphertext_part_len, + ck_flags_t flags)); +_CK_DECLARE_FUNCTION (C_MessageEncryptFinal, + (ck_session_handle_t session)); + +_CK_DECLARE_FUNCTION (C_MessageDecryptInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_DecryptMessage, + (ck_session_handle_t session, + void *parameter, + unsigned long parameter_len, + unsigned char *associated_data, + unsigned long associated_data_len, + unsigned char *ciphertext, + unsigned long ciphertext_len, + unsigned char *plaintext, + unsigned long *plaintext_len)); +_CK_DECLARE_FUNCTION (C_DecryptMessageBegin, + (ck_session_handle_t session, + void *parameter, + unsigned long parameter_len, + unsigned char *associated_data, + unsigned long associated_data_len)); +_CK_DECLARE_FUNCTION (C_DecryptMessageNext, + (ck_session_handle_t session, + void *parameter, + unsigned long parameter_len, + unsigned char *ciphertext_part, + unsigned long ciphertext_part_len, + unsigned char *plaintext_part, + unsigned long *plaintext_part_len, + ck_flags_t flags)); +_CK_DECLARE_FUNCTION (C_MessageDecryptFinal, + (ck_session_handle_t session)); + +_CK_DECLARE_FUNCTION (C_MessageSignInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_SignMessage, + (ck_session_handle_t session, + void *parameter, + unsigned long parameter_len, + unsigned char *data, + unsigned long data_len, + unsigned char *signature, + unsigned long *signature_len)); +_CK_DECLARE_FUNCTION (C_SignMessageBegin, + (ck_session_handle_t session, + void *parameter, + unsigned long parameter_len)); +_CK_DECLARE_FUNCTION (C_SignMessageNext, + (ck_session_handle_t session, + void *parameter, + unsigned long parameter_len, + unsigned char *data, + unsigned long data_len, + unsigned char *signature, + unsigned long *signature_len)); +_CK_DECLARE_FUNCTION (C_MessageSignFinal, + (ck_session_handle_t session)); + +_CK_DECLARE_FUNCTION (C_MessageVerifyInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_VerifyMessage, + (ck_session_handle_t session, + void *parameter, + unsigned long parameter_len, + unsigned char *data, + unsigned long data_len, + unsigned char *signature, + unsigned long signature_len)); +_CK_DECLARE_FUNCTION (C_VerifyMessageBegin, + (ck_session_handle_t session, + void *parameter, + unsigned long parameter_len)); +_CK_DECLARE_FUNCTION (C_VerifyMessageNext, + (ck_session_handle_t session, + void *parameter, + unsigned long parameter_len, + unsigned char *data, + unsigned long data_len, + unsigned char *signature, + unsigned long signature_len)); +_CK_DECLARE_FUNCTION (C_MessageVerifyFinal, + (ck_session_handle_t session)); + +/* Flags in Message-based encryption/decryption API */ +#define CKF_END_OF_MESSAGE (0x00000001UL) struct ck_function_list { @@ -1073,6 +1487,105 @@ struct ck_function_list CK_C_WaitForSlotEvent C_WaitForSlotEvent; }; +struct ck_function_list_3_0 +{ + struct ck_version version; + CK_C_Initialize C_Initialize; + CK_C_Finalize C_Finalize; + CK_C_GetInfo C_GetInfo; + CK_C_GetFunctionList C_GetFunctionList; + CK_C_GetSlotList C_GetSlotList; + CK_C_GetSlotInfo C_GetSlotInfo; + CK_C_GetTokenInfo C_GetTokenInfo; + CK_C_GetMechanismList C_GetMechanismList; + CK_C_GetMechanismInfo C_GetMechanismInfo; + CK_C_InitToken C_InitToken; + CK_C_InitPIN C_InitPIN; + CK_C_SetPIN C_SetPIN; + CK_C_OpenSession C_OpenSession; + CK_C_CloseSession C_CloseSession; + CK_C_CloseAllSessions C_CloseAllSessions; + CK_C_GetSessionInfo C_GetSessionInfo; + CK_C_GetOperationState C_GetOperationState; + CK_C_SetOperationState C_SetOperationState; + CK_C_Login C_Login; + CK_C_Logout C_Logout; + CK_C_CreateObject C_CreateObject; + CK_C_CopyObject C_CopyObject; + CK_C_DestroyObject C_DestroyObject; + CK_C_GetObjectSize C_GetObjectSize; + CK_C_GetAttributeValue C_GetAttributeValue; + CK_C_SetAttributeValue C_SetAttributeValue; + CK_C_FindObjectsInit C_FindObjectsInit; + CK_C_FindObjects C_FindObjects; + CK_C_FindObjectsFinal C_FindObjectsFinal; + CK_C_EncryptInit C_EncryptInit; + CK_C_Encrypt C_Encrypt; + CK_C_EncryptUpdate C_EncryptUpdate; + CK_C_EncryptFinal C_EncryptFinal; + CK_C_DecryptInit C_DecryptInit; + CK_C_Decrypt C_Decrypt; + CK_C_DecryptUpdate C_DecryptUpdate; + CK_C_DecryptFinal C_DecryptFinal; + CK_C_DigestInit C_DigestInit; + CK_C_Digest C_Digest; + CK_C_DigestUpdate C_DigestUpdate; + CK_C_DigestKey C_DigestKey; + CK_C_DigestFinal C_DigestFinal; + CK_C_SignInit C_SignInit; + CK_C_Sign C_Sign; + CK_C_SignUpdate C_SignUpdate; + CK_C_SignFinal C_SignFinal; + CK_C_SignRecoverInit C_SignRecoverInit; + CK_C_SignRecover C_SignRecover; + CK_C_VerifyInit C_VerifyInit; + CK_C_Verify C_Verify; + CK_C_VerifyUpdate C_VerifyUpdate; + CK_C_VerifyFinal C_VerifyFinal; + CK_C_VerifyRecoverInit C_VerifyRecoverInit; + CK_C_VerifyRecover C_VerifyRecover; + CK_C_DigestEncryptUpdate C_DigestEncryptUpdate; + CK_C_DecryptDigestUpdate C_DecryptDigestUpdate; + CK_C_SignEncryptUpdate C_SignEncryptUpdate; + CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate; + CK_C_GenerateKey C_GenerateKey; + CK_C_GenerateKeyPair C_GenerateKeyPair; + CK_C_WrapKey C_WrapKey; + CK_C_UnwrapKey C_UnwrapKey; + CK_C_DeriveKey C_DeriveKey; + CK_C_SeedRandom C_SeedRandom; + CK_C_GenerateRandom C_GenerateRandom; + CK_C_GetFunctionStatus C_GetFunctionStatus; + CK_C_CancelFunction C_CancelFunction; + CK_C_WaitForSlotEvent C_WaitForSlotEvent; + /* PKCS #11 3.0 functions */ + CK_C_GetInterfaceList C_GetInterfaceList; + CK_C_GetInterface C_GetInterface; + CK_C_LoginUser C_LoginUser; + CK_C_SessionCancel C_SessionCancel; + CK_C_MessageEncryptInit C_MessageEncryptInit; + CK_C_EncryptMessage C_EncryptMessage; + CK_C_EncryptMessageBegin C_EncryptMessageBegin; + CK_C_EncryptMessageNext C_EncryptMessageNext; + CK_C_MessageEncryptFinal C_MessageEncryptFinal; + CK_C_MessageDecryptInit C_MessageDecryptInit; + CK_C_DecryptMessage C_DecryptMessage; + CK_C_DecryptMessageBegin C_DecryptMessageBegin; + CK_C_DecryptMessageNext C_DecryptMessageNext; + CK_C_MessageDecryptFinal C_MessageDecryptFinal; + CK_C_MessageSignInit C_MessageSignInit; + CK_C_SignMessage C_SignMessage; + CK_C_SignMessageBegin C_SignMessageBegin; + CK_C_SignMessageNext C_SignMessageNext; + CK_C_MessageSignFinal C_MessageSignFinal; + CK_C_MessageVerifyInit C_MessageVerifyInit; + CK_C_VerifyMessage C_VerifyMessage; + CK_C_VerifyMessageBegin C_VerifyMessageBegin; + CK_C_VerifyMessageNext C_VerifyMessageNext; + CK_C_MessageVerifyFinal C_MessageVerifyFinal; +}; + + typedef ck_rv_t (*ck_createmutex_t) (void **mutex); typedef ck_rv_t (*ck_destroymutex_t) (void *mutex); @@ -1091,96 +1604,97 @@ struct ck_c_initialize_args }; -#define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1 << 0) -#define CKF_OS_LOCKING_OK (1 << 1) - -#define CKR_OK (0) -#define CKR_CANCEL (1) -#define CKR_HOST_MEMORY (2) -#define CKR_SLOT_ID_INVALID (3) -#define CKR_GENERAL_ERROR (5) -#define CKR_FUNCTION_FAILED (6) -#define CKR_ARGUMENTS_BAD (7) -#define CKR_NO_EVENT (8) -#define CKR_NEED_TO_CREATE_THREADS (9) -#define CKR_CANT_LOCK (0xa) -#define CKR_ATTRIBUTE_READ_ONLY (0x10) -#define CKR_ATTRIBUTE_SENSITIVE (0x11) -#define CKR_ATTRIBUTE_TYPE_INVALID (0x12) -#define CKR_ATTRIBUTE_VALUE_INVALID (0x13) -#define CKR_DATA_INVALID (0x20) -#define CKR_DATA_LEN_RANGE (0x21) -#define CKR_DEVICE_ERROR (0x30) -#define CKR_DEVICE_MEMORY (0x31) -#define CKR_DEVICE_REMOVED (0x32) -#define CKR_ENCRYPTED_DATA_INVALID (0x40) -#define CKR_ENCRYPTED_DATA_LEN_RANGE (0x41) -#define CKR_FUNCTION_CANCELED (0x50) -#define CKR_FUNCTION_NOT_PARALLEL (0x51) -#define CKR_FUNCTION_NOT_SUPPORTED (0x54) -#define CKR_KEY_HANDLE_INVALID (0x60) -#define CKR_KEY_SIZE_RANGE (0x62) -#define CKR_KEY_TYPE_INCONSISTENT (0x63) -#define CKR_KEY_NOT_NEEDED (0x64) -#define CKR_KEY_CHANGED (0x65) -#define CKR_KEY_NEEDED (0x66) -#define CKR_KEY_INDIGESTIBLE (0x67) -#define CKR_KEY_FUNCTION_NOT_PERMITTED (0x68) -#define CKR_KEY_NOT_WRAPPABLE (0x69) -#define CKR_KEY_UNEXTRACTABLE (0x6a) -#define CKR_MECHANISM_INVALID (0x70) -#define CKR_MECHANISM_PARAM_INVALID (0x71) -#define CKR_OBJECT_HANDLE_INVALID (0x82) -#define CKR_OPERATION_ACTIVE (0x90) -#define CKR_OPERATION_NOT_INITIALIZED (0x91) -#define CKR_PIN_INCORRECT (0xa0) -#define CKR_PIN_INVALID (0xa1) -#define CKR_PIN_LEN_RANGE (0xa2) -#define CKR_PIN_EXPIRED (0xa3) -#define CKR_PIN_LOCKED (0xa4) -#define CKR_SESSION_CLOSED (0xb0) -#define CKR_SESSION_COUNT (0xb1) -#define CKR_SESSION_HANDLE_INVALID (0xb3) -#define CKR_SESSION_PARALLEL_NOT_SUPPORTED (0xb4) -#define CKR_SESSION_READ_ONLY (0xb5) -#define CKR_SESSION_EXISTS (0xb6) -#define CKR_SESSION_READ_ONLY_EXISTS (0xb7) -#define CKR_SESSION_READ_WRITE_SO_EXISTS (0xb8) -#define CKR_SIGNATURE_INVALID (0xc0) -#define CKR_SIGNATURE_LEN_RANGE (0xc1) -#define CKR_TEMPLATE_INCOMPLETE (0xd0) -#define CKR_TEMPLATE_INCONSISTENT (0xd1) -#define CKR_TOKEN_NOT_PRESENT (0xe0) -#define CKR_TOKEN_NOT_RECOGNIZED (0xe1) -#define CKR_TOKEN_WRITE_PROTECTED (0xe2) -#define CKR_UNWRAPPING_KEY_HANDLE_INVALID (0xf0) -#define CKR_UNWRAPPING_KEY_SIZE_RANGE (0xf1) -#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT (0xf2) -#define CKR_USER_ALREADY_LOGGED_IN (0x100) -#define CKR_USER_NOT_LOGGED_IN (0x101) -#define CKR_USER_PIN_NOT_INITIALIZED (0x102) -#define CKR_USER_TYPE_INVALID (0x103) -#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN (0x104) -#define CKR_USER_TOO_MANY_TYPES (0x105) -#define CKR_WRAPPED_KEY_INVALID (0x110) -#define CKR_WRAPPED_KEY_LEN_RANGE (0x112) -#define CKR_WRAPPING_KEY_HANDLE_INVALID (0x113) -#define CKR_WRAPPING_KEY_SIZE_RANGE (0x114) -#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT (0x115) -#define CKR_RANDOM_SEED_NOT_SUPPORTED (0x120) -#define CKR_RANDOM_NO_RNG (0x121) -#define CKR_DOMAIN_PARAMS_INVALID (0x130) -#define CKR_BUFFER_TOO_SMALL (0x150) -#define CKR_SAVED_STATE_INVALID (0x160) -#define CKR_INFORMATION_SENSITIVE (0x170) -#define CKR_STATE_UNSAVEABLE (0x180) -#define CKR_CRYPTOKI_NOT_INITIALIZED (0x190) -#define CKR_CRYPTOKI_ALREADY_INITIALIZED (0x191) -#define CKR_MUTEX_BAD (0x1a0) -#define CKR_MUTEX_NOT_LOCKED (0x1a1) -#define CKR_FUNCTION_REJECTED (0x200) -#define CKR_VENDOR_DEFINED (1U << 31) - +#define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1UL << 0) +#define CKF_OS_LOCKING_OK (1UL << 1) + +#define CKR_OK (0UL) +#define CKR_CANCEL (1UL) +#define CKR_HOST_MEMORY (2UL) +#define CKR_SLOT_ID_INVALID (3UL) +#define CKR_GENERAL_ERROR (5UL) +#define CKR_FUNCTION_FAILED (6UL) +#define CKR_ARGUMENTS_BAD (7UL) +#define CKR_NO_EVENT (8UL) +#define CKR_NEED_TO_CREATE_THREADS (9UL) +#define CKR_CANT_LOCK (0xaUL) +#define CKR_ATTRIBUTE_READ_ONLY (0x10UL) +#define CKR_ATTRIBUTE_SENSITIVE (0x11UL) +#define CKR_ATTRIBUTE_TYPE_INVALID (0x12UL) +#define CKR_ATTRIBUTE_VALUE_INVALID (0x13UL) +#define CKR_ACTION_PROHIBITED (0x1BUL) +#define CKR_DATA_INVALID (0x20UL) +#define CKR_DATA_LEN_RANGE (0x21UL) +#define CKR_DEVICE_ERROR (0x30UL) +#define CKR_DEVICE_MEMORY (0x31UL) +#define CKR_DEVICE_REMOVED (0x32UL) +#define CKR_ENCRYPTED_DATA_INVALID (0x40UL) +#define CKR_ENCRYPTED_DATA_LEN_RANGE (0x41UL) +#define CKR_FUNCTION_CANCELED (0x50UL) +#define CKR_FUNCTION_NOT_PARALLEL (0x51UL) +#define CKR_FUNCTION_NOT_SUPPORTED (0x54UL) +#define CKR_KEY_HANDLE_INVALID (0x60UL) +#define CKR_KEY_SIZE_RANGE (0x62UL) +#define CKR_KEY_TYPE_INCONSISTENT (0x63UL) +#define CKR_KEY_NOT_NEEDED (0x64UL) +#define CKR_KEY_CHANGED (0x65UL) +#define CKR_KEY_NEEDED (0x66UL) +#define CKR_KEY_INDIGESTIBLE (0x67UL) +#define CKR_KEY_FUNCTION_NOT_PERMITTED (0x68UL) +#define CKR_KEY_NOT_WRAPPABLE (0x69UL) +#define CKR_KEY_UNEXTRACTABLE (0x6aUL) +#define CKR_MECHANISM_INVALID (0x70UL) +#define CKR_MECHANISM_PARAM_INVALID (0x71UL) +#define CKR_OBJECT_HANDLE_INVALID (0x82UL) +#define CKR_OPERATION_ACTIVE (0x90UL) +#define CKR_OPERATION_NOT_INITIALIZED (0x91UL) +#define CKR_PIN_INCORRECT (0xa0UL) +#define CKR_PIN_INVALID (0xa1UL) +#define CKR_PIN_LEN_RANGE (0xa2UL) +#define CKR_PIN_EXPIRED (0xa3UL) +#define CKR_PIN_LOCKED (0xa4UL) +#define CKR_SESSION_CLOSED (0xb0UL) +#define CKR_SESSION_COUNT (0xb1UL) +#define CKR_SESSION_HANDLE_INVALID (0xb3UL) +#define CKR_SESSION_PARALLEL_NOT_SUPPORTED (0xb4UL) +#define CKR_SESSION_READ_ONLY (0xb5UL) +#define CKR_SESSION_EXISTS (0xb6UL) +#define CKR_SESSION_READ_ONLY_EXISTS (0xb7UL) +#define CKR_SESSION_READ_WRITE_SO_EXISTS (0xb8UL) +#define CKR_SIGNATURE_INVALID (0xc0UL) +#define CKR_SIGNATURE_LEN_RANGE (0xc1UL) +#define CKR_TEMPLATE_INCOMPLETE (0xd0UL) +#define CKR_TEMPLATE_INCONSISTENT (0xd1UL) +#define CKR_TOKEN_NOT_PRESENT (0xe0UL) +#define CKR_TOKEN_NOT_RECOGNIZED (0xe1UL) +#define CKR_TOKEN_WRITE_PROTECTED (0xe2UL) +#define CKR_UNWRAPPING_KEY_HANDLE_INVALID (0xf0UL) +#define CKR_UNWRAPPING_KEY_SIZE_RANGE (0xf1UL) +#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT (0xf2UL) +#define CKR_USER_ALREADY_LOGGED_IN (0x100UL) +#define CKR_USER_NOT_LOGGED_IN (0x101UL) +#define CKR_USER_PIN_NOT_INITIALIZED (0x102UL) +#define CKR_USER_TYPE_INVALID (0x103UL) +#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN (0x104UL) +#define CKR_USER_TOO_MANY_TYPES (0x105UL) +#define CKR_WRAPPED_KEY_INVALID (0x110UL) +#define CKR_WRAPPED_KEY_LEN_RANGE (0x112UL) +#define CKR_WRAPPING_KEY_HANDLE_INVALID (0x113UL) +#define CKR_WRAPPING_KEY_SIZE_RANGE (0x114UL) +#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT (0x115UL) +#define CKR_RANDOM_SEED_NOT_SUPPORTED (0x120UL) +#define CKR_RANDOM_NO_RNG (0x121UL) +#define CKR_DOMAIN_PARAMS_INVALID (0x130UL) +#define CKR_CURVE_NOT_SUPPORTED (0x140UL) +#define CKR_BUFFER_TOO_SMALL (0x150UL) +#define CKR_SAVED_STATE_INVALID (0x160UL) +#define CKR_INFORMATION_SENSITIVE (0x170UL) +#define CKR_STATE_UNSAVEABLE (0x180UL) +#define CKR_CRYPTOKI_NOT_INITIALIZED (0x190UL) +#define CKR_CRYPTOKI_ALREADY_INITIALIZED (0x191UL) +#define CKR_MUTEX_BAD (0x1a0UL) +#define CKR_MUTEX_NOT_LOCKED (0x1a1UL) +#define CKR_FUNCTION_REJECTED (0x200UL) +#define CKR_VENDOR_DEFINED (1UL << 31) /* Compatibility layer. */ @@ -1216,6 +1730,22 @@ typedef void **CK_VOID_PTR_PTR; #endif #endif +typedef struct CK_HKDF_PARAMS { + CK_BBOOL bExtract; + CK_BBOOL bExpand; + CK_MECHANISM_TYPE prfHashMechanism; + CK_ULONG ulSaltType; + CK_BYTE_PTR pSalt; + CK_ULONG ulSaltLen; + CK_OBJECT_HANDLE hSaltKey; + CK_BYTE_PTR pInfo; + CK_ULONG ulInfoLen; +} CK_HKDF_PARAMS; + +#define CKF_HKDF_SALT_NULL 0x00000001UL +#define CKF_HKDF_SALT_DATA 0x00000002UL +#define CKF_HKDF_SALT_KEY 0x00000004UL + typedef struct ck_version CK_VERSION; typedef struct ck_version *CK_VERSION_PTR; @@ -1247,16 +1777,26 @@ typedef struct ck_date *CK_DATE_PTR; typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR; +typedef ck_rsa_pkcs_mgf_type_t *CK_RSA_PKCS_MGF_TYPE_PTR; + typedef struct ck_mechanism CK_MECHANISM; typedef struct ck_mechanism *CK_MECHANISM_PTR; typedef struct ck_mechanism_info CK_MECHANISM_INFO; typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR; +typedef struct ck_interface CK_INTERFACE; +typedef struct ck_interface *CK_INTERFACE_PTR; +typedef struct ck_interface **CK_INTERFACE_PTR_PTR; + typedef struct ck_function_list CK_FUNCTION_LIST; typedef struct ck_function_list *CK_FUNCTION_LIST_PTR; typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR; +typedef struct ck_function_list_3_0 CK_FUNCTION_LIST_3_0; +typedef struct ck_function_list_3_0 *CK_FUNCTION_LIST_3_0_PTR; +typedef struct ck_function_list_3_0 **CK_FUNCTION_LIST_3_0_PTR_PTR; + typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS; typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR; @@ -1317,6 +1857,8 @@ typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR; #undef ck_mechanism_type_t +#undef ck_rsa_pkcs_mgf_type_t + #undef ck_mechanism #undef parameter #undef parameter_len @@ -1328,7 +1870,10 @@ typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR; #undef ck_rv_t #undef ck_notify_t +#undef ck_interface + #undef ck_function_list +#undef ck_function_list_3_0 #undef ck_createmutex_t #undef ck_destroymutex_t @@ -1344,7 +1889,6 @@ typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR; #endif /* CRYPTOKI_COMPAT */ - /* System dependencies. */ #if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) #pragma pack(pop, cryptoki) diff --git a/platform.c b/platform.c index 143528f8970c..0e1c40997741 100644 --- a/platform.c +++ b/platform.c @@ -183,17 +183,26 @@ platform_locked_account(struct passwd *pw) /* check for locked account */ if (passwd && *passwd) { #ifdef LOCKED_PASSWD_STRING - if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0) + if (strcmp(passwd, LOCKED_PASSWD_STRING) == 0) { + debug3_f("password matches locked string '%s'", + LOCKED_PASSWD_STRING); locked = 1; + } #endif #ifdef LOCKED_PASSWD_PREFIX if (strncmp(passwd, LOCKED_PASSWD_PREFIX, - strlen(LOCKED_PASSWD_PREFIX)) == 0) + strlen(LOCKED_PASSWD_PREFIX)) == 0) { + debug3_f("password matches locked prefix '%s'", + LOCKED_PASSWD_PREFIX); locked = 1; + } #endif #ifdef LOCKED_PASSWD_SUBSTR - if (strstr(passwd, LOCKED_PASSWD_SUBSTR)) + if (strstr(passwd, LOCKED_PASSWD_SUBSTR)) { + debug3_f("password matches locked substring '%s'", + LOCKED_PASSWD_SUBSTR); locked = 1; + } #endif } #ifdef USE_LIBIAF diff --git a/poly1305.c b/poly1305.c index de4d8877025d..c6747161c97f 100644 --- a/poly1305.c +++ b/poly1305.c @@ -7,9 +7,7 @@ #include "includes.h" #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include "poly1305.h" diff --git a/progressmeter.c b/progressmeter.c index 04e75a363c95..b156444e3455 100644 --- a/progressmeter.c +++ b/progressmeter.c @@ -1,4 +1,4 @@ -/* $OpenBSD: progressmeter.c,v 1.54 2024/09/22 12:56:21 jsg Exp $ */ +/* $OpenBSD: progressmeter.c,v 1.56 2025/06/11 13:27:11 dtucker Exp $ */ /* * Copyright (c) 2003 Nils Nordman. All rights reserved. * @@ -98,15 +98,15 @@ format_rate(off_t bytes) bytes *= 100; for (i = 0; bytes >= 100*1000 && unit[i] != 'T'; i++) bytes = (bytes + 512) / 1024; + /* Display at least KB, even when rate is low or zero. */ if (i == 0) { i++; bytes = (bytes + 512) / 1024; } - snprintf(buf, sizeof(buf), "%3lld.%1lld%c%s", + snprintf(buf, sizeof(buf), "%3lld.%1lld%cB", (long long) (bytes + 5) / 100, (long long) (bytes + 5) / 10 % 10, - unit[i], - i ? "B" : " "); + unit[i]); return buf; } @@ -137,7 +137,8 @@ refresh_progress_meter(int force_update) int hours, minutes, seconds; int file_len, cols; - if ((!force_update && !alarm_fired && !win_resized) || !can_output()) + if (file == NULL || (!force_update && !alarm_fired && !win_resized) || + !can_output()) return; alarm_fired = 0; @@ -281,6 +282,7 @@ stop_progress_meter(void) refresh_progress_meter(1); atomicio(vwrite, STDOUT_FILENO, "\n", 1); + file = NULL; } static void diff --git a/readconf.c b/readconf.c index 3605a50e4e5b..e273dab00e27 100644 --- a/readconf.c +++ b/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.398 2025/03/18 04:53:14 djm Exp $ */ +/* $OpenBSD: readconf.c,v 1.406 2025/08/29 03:50:38 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -30,12 +30,12 @@ #include #include #ifdef HAVE_IFADDRS_H -# include +#include #endif #include #include #ifdef HAVE_PATHS_H -# include +#include #endif #include #include @@ -181,7 +181,7 @@ typedef enum { oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump, oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize, oEnableEscapeCommandline, oObscureKeystrokeTiming, oChannelTimeout, - oVersionAddendum, + oVersionAddendum, oRefuseConnection, oWarnWeakCrypto, oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported } OpCodes; @@ -333,6 +333,8 @@ static struct { { "obscurekeystroketiming", oObscureKeystrokeTiming }, { "channeltimeout", oChannelTimeout }, { "versionaddendum", oVersionAddendum }, + { "refuseconnection", oRefuseConnection }, + { "warnweakcrypto", oWarnWeakCrypto }, { NULL, oBadOption } }; @@ -775,12 +777,13 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp, 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 the config requests "Match final" without + * negation then remember this so we can perform a + * second pass later. */ if (strcasecmp(attrib, "final") == 0 && want_final_pass != NULL) - *want_final_pass = 1; + *want_final_pass |= !negate; r = !!final_pass; /* force bitmask member to boolean */ if (r == (negate ? 1 : 0)) this_result = result = 0; @@ -1106,6 +1109,15 @@ static const struct multistate multistate_compression[] = { { "no", COMP_NONE }, { NULL, -1 } }; +/* XXX this will need to be replaced with a bitmask if we add more flags */ +static const struct multistate multistate_warnweakcrypto[] = { + { "true", 1 }, + { "false", 0 }, + { "yes", 1 }, + { "no", 0 }, + { "no-pq-kex", 0 }, + { NULL, -1 } +}; static int parse_multistate_value(const char *arg, const char *filename, int linenum, @@ -2169,6 +2181,12 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, filename, linenum, arg); goto out; } + if (value == INT_MIN) { + debug("%s line %d: Deprecated IPQoS value \"%s\" " + "ignored - using system default instead. Consider" + " using DSCP values.", filename, linenum, arg); + value = INT_MAX; + } arg = argv_next(&ac, &av); if (arg == NULL) value2 = value; @@ -2177,6 +2195,12 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, filename, linenum, arg); goto out; } + if (value2 == INT_MIN) { + debug("%s line %d: Deprecated IPQoS value \"%s\" " + "ignored - using system default instead. Consider" + " using DSCP values.", filename, linenum, arg); + value2 = INT_MAX; + } if (*activep && options->ip_qos_interactive == -1) { options->ip_qos_interactive = value; options->ip_qos_bulk = value2; @@ -2424,6 +2448,11 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, intptr = &options->required_rsa_size; goto parse_int; + case oWarnWeakCrypto: + intptr = &options->warn_weak_crypto; + multistate_ptr = multistate_warnweakcrypto; + goto parse_multistate; + case oObscureKeystrokeTiming: value = -1; while ((arg = argv_next(&ac, &av)) != NULL) { @@ -2519,6 +2548,19 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, argv_consume(&ac); break; + case oRefuseConnection: + arg = argv_next(&ac, &av); + if (!arg || *arg == '\0') { + error("%.200s line %d: Missing argument.", + filename, linenum); + goto out; + } + if (*activep) { + fatal("%.200s line %d: RefuseConnection: %s", + filename, linenum, arg); + } + break; + case oDeprecated: debug("%s line %d: Deprecated option \"%s\"", filename, linenum, keyword); @@ -2781,6 +2823,7 @@ initialize_options(Options * options) options->pubkey_accepted_algos = NULL; options->known_hosts_command = NULL; options->required_rsa_size = -1; + options->warn_weak_crypto = -1; options->enable_escape_commandline = -1; options->obscure_keystroke_timing_interval = -1; options->tag = NULL; @@ -2890,10 +2933,6 @@ fill_default_options(Options * 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); -#ifdef WITH_DSA - add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0); -#endif } if (options->escape_char == -1) options->escape_char = '~'; @@ -2957,9 +2996,9 @@ fill_default_options(Options * options) if (options->visual_host_key == -1) options->visual_host_key = 0; if (options->ip_qos_interactive == -1) - options->ip_qos_interactive = IPTOS_DSCP_AF21; + options->ip_qos_interactive = IPTOS_DSCP_EF; if (options->ip_qos_bulk == -1) - options->ip_qos_bulk = IPTOS_DSCP_CS1; + options->ip_qos_bulk = IPTOS_DSCP_CS0; if (options->request_tty == -1) options->request_tty = REQUEST_TTY_AUTO; if (options->session_type == -1) @@ -2987,6 +3026,8 @@ fill_default_options(Options * options) #endif if (options->required_rsa_size == -1) options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; + if (options->warn_weak_crypto == -1) + options->warn_weak_crypto = 1; if (options->enable_escape_commandline == -1) options->enable_escape_commandline = 0; if (options->obscure_keystroke_timing_interval == -1) { @@ -3018,6 +3059,7 @@ fill_default_options(Options * options) goto fail; \ } \ } while (0) + options->kex_algorithms_set = options->kex_algorithms != NULL; ASSEMBLE(ciphers, def_cipher, all_cipher); ASSEMBLE(macs, def_mac, all_mac); ASSEMBLE(kex_algorithms, def_kex, all_kex); @@ -3705,6 +3747,7 @@ dump_client_config(Options *o, const char *host) dump_cfg_fmtint(oVisualHostKey, o->visual_host_key); dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys); dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline); + dump_cfg_fmtint(oWarnWeakCrypto, o->warn_weak_crypto); /* Integer options */ dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots); diff --git a/readconf.h b/readconf.h index cd49139b13c0..942149f9ae3f 100644 --- a/readconf.h +++ b/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.159 2025/02/15 01:48:30 djm Exp $ */ +/* $OpenBSD: readconf.h,v 1.161 2025/08/11 10:55:38 djm Exp $ */ /* * Author: Tatu Ylonen @@ -49,8 +49,8 @@ typedef struct { 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 */ + int ip_qos_interactive; /* DSCP value for interactive */ + int ip_qos_bulk; /* DSCP value for bulk traffic */ SyslogFacility log_facility; /* Facility for system logging. */ LogLevel log_level; /* Level for logging. */ u_int num_log_verbose; /* Verbose log overrides */ @@ -67,6 +67,7 @@ typedef struct { 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. */ + int kex_algorithms_set; /* KexAlgorithms was set by the user */ char *ca_sign_algorithms; /* Allowed CA signature algorithms */ char *hostname; /* Real host to connect. */ char *tag; /* Configuration tag name. */ @@ -180,6 +181,7 @@ typedef struct { int required_rsa_size; /* minimum size of RSA keys */ int enable_escape_commandline; /* ~C commandline */ int obscure_keystroke_timing_interval; + int warn_weak_crypto; char **channel_timeouts; /* inactivity timeout by channel type */ u_int num_channel_timeouts; diff --git a/readpass.c b/readpass.c index 46a7716e9792..4ef761ad626e 100644 --- a/readpass.c +++ b/readpass.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readpass.c,v 1.71 2024/03/30 04:27:44 djm Exp $ */ +/* $OpenBSD: readpass.c,v 1.72 2025/06/11 13:24:05 dtucker Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -122,7 +122,7 @@ ssh_askpass(char *askpass, const char *msg, const char *env_hint) if (r <= 0) break; len += r; - } while (sizeof(buf) - 1 - len > 0); + } while (len < sizeof(buf) - 1); buf[len] = '\0'; close(p[0]); diff --git a/regress/Makefile b/regress/Makefile index 7e7f95b58a2c..ece093a2ba87 100644 --- a/regress/Makefile +++ b/regress/Makefile @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.136 2025/03/11 07:50:20 dtucker Exp $ +# $OpenBSD: Makefile,v 1.140 2025/07/04 07:52:17 djm Exp $ tests: prep file-tests t-exec unit -REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 +REGRESS_TARGETS= t1 t2 t3 t4 t5 t7 t9 t10 t11 t12 # File based tests file-tests: $(REGRESS_TARGETS) @@ -106,16 +106,18 @@ LTESTS= connect \ knownhosts-command \ agent-restrict \ hostbased \ + password \ channel-timeout \ connection-timeout \ match-subsystem \ agent-pkcs11-restrict \ agent-pkcs11-cert \ penalty \ - penalty-expire + penalty-expire \ + connect-bigconf INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers -INTEROP_TESTS+= dropbear-ciphers dropbear-kex +INTEROP_TESTS+= dropbear-ciphers dropbear-kex dropbear-server #INTEROP_TESTS+=ssh-com ssh-com-client ssh-com-keygen ssh-com-sftp EXTRA_TESTS= agent-pkcs11 @@ -130,9 +132,9 @@ CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \ 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.ecdsa-sha2-nistp521 host.ssh-ed25519 \ host.ssh-rsa host_ca_key* host_krl_* host_revoked_* key.* \ - key.dsa-* key.ecdsa-* key.ed25519-512 \ + 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 \ @@ -191,36 +193,18 @@ t5: ${TEST_SSH_SSHKEYGEN} -Bf ${.CURDIR}/rsa_openssh.pub |\ awk '{print $$2}' | diff - ${.CURDIR}/t5.ok ; \ fi -t6: - set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-dss" ; then \ - ${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 ; \ - fi $(OBJ)/t7.out: - set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-dss" ; then \ + set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-rsa" ; then \ ${TEST_SSH_SSHKEYGEN} -q -t rsa -N '' -f $@ ; \ fi t7: $(OBJ)/t7.out - set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-dss" ; then \ + set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-rsa" ; then \ ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t7.out > /dev/null ; \ ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t7.out > /dev/null ; \ fi -$(OBJ)/t8.out: - set -xe ; if ssh -Q key | grep -q "^ssh-dss" ; then \ - ${TEST_SSH_SSHKEYGEN} -q -t dsa -N '' -f $@ ; \ - fi - -t8: $(OBJ)/t8.out - set -xe ; if ssh -Q key | grep -q "^ssh-dss" ; then \ - ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t8.out > /dev/null ; \ - ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t8.out > /dev/null ; \ - fi - $(OBJ)/t9.out: ! ${TEST_SSH_SSH} -Q key-plain | grep ecdsa >/dev/null || \ ${TEST_SSH_SSHKEYGEN} -q -t ecdsa -N '' -f $@ @@ -240,7 +224,7 @@ t10: $(OBJ)/t10.out ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t10.out > /dev/null t11: - set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-dss" ; then \ + set -xe ; if ${TEST_SSH_SSH} -Q key | grep -q "^ssh-rsa" ; then \ ${TEST_SSH_SSHKEYGEN} -E sha256 -lf ${.CURDIR}/rsa_openssh.pub |\ awk '{print $$2}' | diff - ${.CURDIR}/t11.ok ; \ fi @@ -292,26 +276,33 @@ t-extra: ${EXTRA_TESTS:=.sh} interop: ${INTEROP_TARGETS} # Unit tests, built by top-level Makefile -unit: +unit unit-bench: 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 ; \ + ARGS=""; \ + test "x$@" = "xunit-bench" && ARGS="-b"; \ + test "x${UNITTEST_FAST}" = "x" || ARGS="$$ARGS -f"; \ + test "x${UNITTEST_SLOW}" = "x" || ARGS="$$ARGS -F"; \ + test "x${UNITTEST_VERBOSE}" = "x" || ARGS="$$ARGS -v"; \ + test "x${UNITTEST_BENCH_DETAIL}" = "x" || ARGS="$$ARGS -B"; \ + test "x${UNITTEST_BENCH_ONLY}" = "x" || ARGS="$$ARGS -O ${UNITTEST_BENCH_ONLY}"; \ + $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf $${ARGS}; \ $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ - -d ${.CURDIR}/unittests/sshkey/testdata ; \ + -d ${.CURDIR}/unittests/sshkey/testdata $${ARGS}; \ $$V ${.OBJDIR}/unittests/sshsig/test_sshsig \ - -d ${.CURDIR}/unittests/sshsig/testdata ; \ + -d ${.CURDIR}/unittests/sshsig/testdata $${ARGS}; \ $$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 ; \ + -d ${.CURDIR}/unittests/authopt/testdata $${ARGS}; \ + $$V ${.OBJDIR}/unittests/bitmap/test_bitmap $${ARGS}; \ + $$V ${.OBJDIR}/unittests/conversion/test_conversion $${ARGS}; \ + $$V ${.OBJDIR}/unittests/kex/test_kex $${ARGS}; \ $$V ${.OBJDIR}/unittests/hostkeys/test_hostkeys \ - -d ${.CURDIR}/unittests/hostkeys/testdata ; \ - $$V ${.OBJDIR}/unittests/match/test_match ; \ - $$V ${.OBJDIR}/unittests/misc/test_misc ; \ + -d ${.CURDIR}/unittests/hostkeys/testdata $${ARGS}; \ + $$V ${.OBJDIR}/unittests/match/test_match $${ARGS}; \ + $$V ${.OBJDIR}/unittests/misc/test_misc $${ARGS}; \ if test "x${TEST_SSH_UTF8}" = "xyes" ; then \ - $$V ${.OBJDIR}/unittests/utf8/test_utf8 ; \ + $$V ${.OBJDIR}/unittests/utf8/test_utf8 $${ARGS}; \ fi \ fi diff --git a/regress/agent-pkcs11-cert.sh b/regress/agent-pkcs11-cert.sh index 4e8f748465a3..551067d23f5f 100644 --- a/regress/agent-pkcs11-cert.sh +++ b/regress/agent-pkcs11-cert.sh @@ -1,15 +1,12 @@ -# $OpenBSD: agent-pkcs11-cert.sh,v 1.1 2023/12/18 14:50:08 djm Exp $ +# $OpenBSD: agent-pkcs11-cert.sh,v 1.3 2025/07/26 01:53:31 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* @@ -19,74 +16,80 @@ $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 || +$SSHKEYGEN -qs $OBJ/ca -I "ed25519_key" -n $USER -z 3 \ + ${SSH_SOFTHSM_DIR}/ED25519.pub || + fatal "certify ed25519 key failed" +$SSHKEYGEN -qs $OBJ/ca -I "ca_ca" -n $USER -z 4 $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 +start_ssh_agent -trace "load pkcs11 keys and certs" +verbose "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}/ED25519.pub \ + ${SSH_SOFTHSM_DIR}/ED25519-cert.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 +verbose "verify presence" cut -d' ' -f1-2 \ + ${SSH_SOFTHSM_DIR}/ED25519.pub \ ${SSH_SOFTHSM_DIR}/EC.pub \ ${SSH_SOFTHSM_DIR}/RSA.pub \ + ${SSH_SOFTHSM_DIR}/ED25519-cert.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. +verbose "check 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 + ${SSH_SOFTHSM_DIR}/EC-cert.pub ${SSH_SOFTHSM_DIR}/RSA-cert.pub \ + ${SSH_SOFTHSM_DIR}/ED25519.pub ${SSH_SOFTHSM_DIR}/ED25519-cert.pub ; do $SSHADD -T $x || fail "Signing failed for $x" done # Delete plain keys. +verbose "delete plain keys" $SSHADD -qd ${SSH_SOFTHSM_DIR}/EC.pub ${SSH_SOFTHSM_DIR}/RSA.pub +$SSHADD -qd ${SSH_SOFTHSM_DIR}/ED25519.pub # Verify that certs can still perform signatures. -for x in ${SSH_SOFTHSM_DIR}/EC-cert.pub ${SSH_SOFTHSM_DIR}/RSA-cert.pub ; do +verbose "reverify certificate signatures" +for x in ${SSH_SOFTHSM_DIR}/EC-cert.pub ${SSH_SOFTHSM_DIR}/RSA-cert.pub \ + ${SSH_SOFTHSM_DIR}/ED25519-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" +verbose "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 || + ${SSH_SOFTHSM_DIR}/RSA-cert.pub \ + ${SSH_SOFTHSM_DIR}/ED25519.pub \ + ${SSH_SOFTHSM_DIR}/ED25519-cert.pub || fatal "failed to add keys" # Verify their presence +verbose "verify presence" cut -d' ' -f1-2 \ ${SSH_SOFTHSM_DIR}/EC-cert.pub \ - ${SSH_SOFTHSM_DIR}/RSA-cert.pub | sort > $OBJ/expect_list + ${SSH_SOFTHSM_DIR}/RSA-cert.pub \ + ${SSH_SOFTHSM_DIR}/ED25519-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 +verbose "check signatures" +for x in ${SSH_SOFTHSM_DIR}/EC-cert.pub ${SSH_SOFTHSM_DIR}/RSA-cert.pub \ + ${SSH_SOFTHSM_DIR}/ED25519-cert.pub ; do $SSHADD -T $x || fail "Signing failed for $x" done diff --git a/regress/agent-pkcs11-restrict.sh b/regress/agent-pkcs11-restrict.sh index 867253211714..9fc5e1c69f50 100644 --- a/regress/agent-pkcs11-restrict.sh +++ b/regress/agent-pkcs11-restrict.sh @@ -1,11 +1,11 @@ -# $OpenBSD: agent-pkcs11-restrict.sh,v 1.1 2023/12/18 14:49:39 djm Exp $ +# $OpenBSD: agent-pkcs11-restrict.sh,v 1.3 2025/07/26 01:53:31 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/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_* @@ -16,6 +16,7 @@ for h in a b x ca ; do done # XXX test CA hostcerts too. +# XXX test ed25519 keys key_for() { case $h in @@ -26,23 +27,7 @@ key_for() { 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 +start_ssh_agent # 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 @@ -118,7 +103,7 @@ for h in a b ; do cat $K) >> $OBJ/authorized_keys_$USER done -trace "unrestricted keys" +verbose "unrestricted keys" $SSHADD -qD >/dev/null || fatal "clear agent failed" p11_ssh_add -qs ${TEST_SSH_PKCS11} || fatal "failed to add keys" @@ -134,7 +119,7 @@ for h in a b ; do cmp $OBJ/expect_$h $OBJ/ssh_output || fatal "unexpected output" done -trace "restricted to different host" +verbose "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" @@ -144,7 +129,7 @@ for h in a b ; do host_$h true > $OBJ/ssh_output && fatal "test ssh $h succeeded" done -trace "restricted to destination host" +verbose "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" @@ -160,7 +145,7 @@ for h in a b ; do cmp $OBJ/expect_$h $OBJ/ssh_output || fatal "unexpected output" done -trace "restricted multihop" +verbose "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" diff --git a/regress/agent-pkcs11.sh b/regress/agent-pkcs11.sh index 304734f4b484..491466659211 100644 --- a/regress/agent-pkcs11.sh +++ b/regress/agent-pkcs11.sh @@ -1,54 +1,46 @@ -# $OpenBSD: agent-pkcs11.sh,v 1.13 2023/10/30 23:00:25 djm Exp $ +# $OpenBSD: agent-pkcs11.sh,v 1.15 2025/07/26 01:53:31 djm Exp $ # Placed in the Public Domain. tid="pkcs11 agent test" p11_setup || skip "No PKCS#11 library found" -trace "start agent" -eval `${SSHAGENT} ${EXTRA_AGENT_ARGS} -s` > /dev/null +start_ssh_agent + +trace "add pkcs11 key to agent" +p11_ssh_add -s ${TEST_SSH_PKCS11} > /dev/null 2>&1 r=$? if [ $r -ne 0 ]; then - fail "could not start ssh-agent: exit code $r" -else - trace "add pkcs11 key to agent" - 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 + fail "ssh-add -s failed: exit code $r" +fi - trace "pkcs11 list via agent" - ${SSHADD} -l > /dev/null 2>&1 - r=$? - if [ $r -ne 0 ]; then - fail "ssh-add -l failed: exit code $r" - fi +trace "pkcs11 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" - pub=$(cat $k.pub) - ${SSHADD} -L | grep -q "$pub" || \ - fail "key $k missing in ssh-add -L" - ${SSHADD} -T $k.pub || fail "ssh-add -T with $k failed" - - # add to authorized keys - cat $k.pub > $OBJ/authorized_keys_$USER - trace "pkcs11 connect via agent ($k)" - ${SSH} -F $OBJ/ssh_proxy somehost exit 5 - r=$? - if [ $r -ne 5 ]; then - fail "ssh connect failed (exit code $r)" - fi - done - - trace "remove pkcs11 keys" - p11_ssh_add -e ${TEST_SSH_PKCS11} > /dev/null 2>&1 +for k in $ED25519 $RSA $EC; do + trace "testing $k" + pub=$(cat $k.pub) + ${SSHADD} -L | grep -q "$pub" || \ + fail "key $k missing in ssh-add -L" + ${SSHADD} -T $k.pub || fail "ssh-add -T with $k failed" + + # add to authorized keys + cat $k.pub > $OBJ/authorized_keys_$USER + trace "pkcs11 connect via agent ($k)" + ${SSH} -F $OBJ/ssh_proxy somehost exit 5 r=$? - if [ $r -ne 0 ]; then - fail "ssh-add -e failed: exit code $r" + if [ $r -ne 5 ]; then + fail "ssh connect failed (exit code $r)" fi +done - trace "kill agent" - ${SSHAGENT} -k > /dev/null +trace "remove pkcs11 keys" +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 diff --git a/regress/agent-restrict.sh b/regress/agent-restrict.sh index cd10a618d28a..a1ea511eb365 100644 --- a/regress/agent-restrict.sh +++ b/regress/agent-restrict.sh @@ -1,4 +1,4 @@ -# $OpenBSD: agent-restrict.sh,v 1.7 2025/03/28 21:45:55 dtucker Exp $ +# $OpenBSD: agent-restrict.sh,v 1.8 2025/05/23 08:40:13 dtucker Exp $ # Placed in the Public Domain. tid="agent restrictions" @@ -58,10 +58,6 @@ 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 - verbose "prepare known_hosts" rm -f $OBJ/known_hosts for h in a b c x ; do @@ -90,7 +86,8 @@ reset_keys() { _command="" case "$_whichcmd" in authinfo) _command="cat \$SSH_USER_AUTH" ;; - keylist) _command="$SSHADD -L | cut -d' ' -f-2 | sort" ;; + keylist) _command="$SSHADD -L | cut -d' ' -f-2 | \ + env LC_ALL=C sort" ;; *) fatal "unsupported command $_whichcmd" ;; esac trace "reset keys" @@ -233,7 +230,7 @@ rm -f $OBJ/expect_list.pre for u in a b c d e x; do cut -d " " -f-2 $OBJ/user_${u}.pub >> $OBJ/expect_list.pre done -sort $OBJ/expect_list.pre > $OBJ/expect_list +env LC_ALL=C sort $OBJ/expect_list.pre > $OBJ/expect_list for h in a b c d e; do cp $OBJ/expect_list $OBJ/expect_$h expect_succeed $h "unrestricted keylist" @@ -338,7 +335,7 @@ if test ! -z "\$me" ; then cat \$SSH_USER_AUTH fi echo AGENT -$SSHADD -L | egrep "^ssh" | cut -d" " -f-2 | sort +$SSHADD -L | egrep "^ssh" | cut -d" " -f-2 | env LC_ALL=C sort if test -z "\$next" ; then touch $OBJ/done echo "FINISH" @@ -375,7 +372,7 @@ prepare_multihop_expected() { done rm -f $OBJ/expect_a echo "AGENT" >> $OBJ/expect_a - test "x$_keys" = "xnone" || sort $OBJ/expect_keys >> $OBJ/expect_a + test "x$_keys" = "xnone" || env LC_ALL=C sort $OBJ/expect_keys >> $OBJ/expect_a echo "NEXT" >> $OBJ/expect_a for h in $_hops ; do echo "HOSTNAME host_$h" >> $OBJ/expect_a @@ -383,7 +380,7 @@ prepare_multihop_expected() { (printf "publickey " ; cut -d" " -f-2 $OBJ/user_a.pub) >> $OBJ/expect_a echo "AGENT" >> $OBJ/expect_a if test "x$_keys" = "xall" ; then - sort $OBJ/expect_keys >> $OBJ/expect_a + env LC_ALL=C sort $OBJ/expect_keys >> $OBJ/expect_a fi if test "x$h" != "x$_lasthop" ; then if test "x$_keys" = "xfiltered" ; then diff --git a/regress/agent.sh b/regress/agent.sh index 2c98b700d77a..31676e75b062 100644 --- a/regress/agent.sh +++ b/regress/agent.sh @@ -1,4 +1,4 @@ -# $OpenBSD: agent.sh,v 1.22 2024/10/24 03:28:34 djm Exp $ +# $OpenBSD: agent.sh,v 1.23 2025/05/06 06:05:48 djm Exp $ # Placed in the Public Domain. tid="simple agent test" @@ -92,10 +92,6 @@ fi for t in ${SSH_KEYTYPES}; do trace "connect via agent using $t key" - if [ "$t" = "ssh-dss" ]; then - echo "PubkeyAcceptedAlgorithms +ssh-dss" >> $OBJ/ssh_proxy - echo "PubkeyAcceptedAlgorithms +ssh-dss" >> $OBJ/sshd_proxy - fi ${SSH} -F $OBJ/ssh_proxy -i $OBJ/$t-agent.pub -oIdentitiesOnly=yes \ somehost exit 52 r=$? @@ -149,7 +145,6 @@ fi (printf 'cert-authority,principals="estragon" '; cat $OBJ/user_ca_key.pub) \ > $OBJ/authorized_keys_$USER for t in ${SSH_KEYTYPES}; do - if [ "$t" != "ssh-dss" ]; then trace "connect via agent using $t key" ${SSH} -F $OBJ/ssh_proxy -i $OBJ/$t-agent.pub \ -oCertificateFile=$OBJ/$t-agent-cert.pub \ @@ -158,7 +153,6 @@ for t in ${SSH_KEYTYPES}; do if [ $r -ne 52 ]; then fail "ssh connect with failed (exit code $r)" fi - fi done ## Deletion tests. diff --git a/regress/cert-hostkey.sh b/regress/cert-hostkey.sh index f66d493c181c..b45dc88b51b7 100644 --- a/regress/cert-hostkey.sh +++ b/regress/cert-hostkey.sh @@ -1,4 +1,4 @@ -# $OpenBSD: cert-hostkey.sh,v 1.27 2021/09/30 05:26:26 dtucker Exp $ +# $OpenBSD: cert-hostkey.sh,v 1.28 2025/05/06 06:05:48 djm Exp $ # Placed in the Public Domain. tid="certified host keys" @@ -73,7 +73,7 @@ touch $OBJ/host_revoked_plain touch $OBJ/host_revoked_cert cat $OBJ/host_ca_key.pub $OBJ/host_ca_key2.pub > $OBJ/host_revoked_ca -PLAIN_TYPES=`echo "$SSH_KEYTYPES" | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'` +PLAIN_TYPES=`echo "$SSH_KEYTYPES" | sed 's/^ssh-//'` if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then PLAIN_TYPES="$PLAIN_TYPES rsa-sha2-256 rsa-sha2-512" diff --git a/regress/cert-userkey.sh b/regress/cert-userkey.sh index 4dac8c307baa..aa64b2ee62a2 100644 --- a/regress/cert-userkey.sh +++ b/regress/cert-userkey.sh @@ -1,4 +1,4 @@ -# $OpenBSD: cert-userkey.sh,v 1.29 2024/12/06 16:25:58 djm Exp $ +# $OpenBSD: cert-userkey.sh,v 1.30 2025/05/06 06:05:48 djm Exp $ # Placed in the Public Domain. tid="certified user keys" @@ -16,7 +16,7 @@ fi grep -v AuthorizedKeysFile $OBJ/sshd_proxy > $OBJ/sshd_proxy_bak echo "AuthorizedKeysFile $OBJ/authorized_keys_%u_*" >> $OBJ/sshd_proxy_bak -PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` +PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | sed 's/^ssh-//'` EXTRA_TYPES="" rsa="" @@ -31,7 +31,7 @@ kname() { sk-ecdsa-*) n="sk-ecdsa" ;; sk-ssh-ed25519*) n="sk-ssh-ed25519" ;; # subshell because some seds will add a newline - *) n=$(echo $1 | sed 's/^dsa/ssh-dss/;s/^rsa/ssh-rsa/;s/^ed/ssh-ed/') ;; + *) n=$(echo $1 | sed 's/^rsa/ssh-rsa/;s/^ed/ssh-ed/') ;; esac if [ -z "$rsa" ]; then echo "$n*,ssh-ed25519*" diff --git a/regress/cfgmatch.sh b/regress/cfgmatch.sh index 0c5d27c23c86..a04588c11782 100644 --- a/regress/cfgmatch.sh +++ b/regress/cfgmatch.sh @@ -1,4 +1,4 @@ -# $OpenBSD: cfgmatch.sh,v 1.14 2024/09/27 01:05:54 djm Exp $ +# $OpenBSD: cfgmatch.sh,v 1.15 2025/07/11 23:26:59 djm Exp $ # Placed in the Public Domain. tid="sshd_config match" @@ -128,6 +128,8 @@ cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy echo "PermitOpen 127.0.0.1:1 127.0.0.1:$PORT 127.0.0.2:2" >>$OBJ/sshd_proxy echo "Match User NoSuchUser" >>$OBJ/sshd_proxy echo "PermitOpen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy +echo "Match Group NoSuchGroup" >>$OBJ/sshd_proxy +echo "PermitOpen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy # Test that a rule that doesn't match doesn't override, plus test a # PermitOpen entry that's not at the start of the list diff --git a/regress/cfgparse.sh b/regress/cfgparse.sh index 060116fb7dee..6cad2dde889b 100644 --- a/regress/cfgparse.sh +++ b/regress/cfgparse.sh @@ -1,4 +1,4 @@ -# $OpenBSD: cfgparse.sh,v 1.7 2018/05/11 03:51:06 dtucker Exp $ +# $OpenBSD: cfgparse.sh,v 1.9 2025/09/26 04:40:45 dtucker Exp $ # Placed in the Public Domain. tid="sshd config parse" @@ -52,12 +52,12 @@ EOD if [ "$os" == "windows" ]; then # Ignore the CR (carriage return) during diff ($SUDO ${SSHD} -T -f $OBJ/sshd_config.1 | \ - grep 'listenaddress ' >$OBJ/sshd_config.2 && + grep '^listenaddress ' >$OBJ/sshd_config.2 && diff --strip-trailing-cr $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \ fail "listenaddress order 1" else ($SUDO ${SSHD} -T -f $OBJ/sshd_config.1 | \ - grep 'listenaddress ' >$OBJ/sshd_config.2 && + grep '^listenaddress ' >$OBJ/sshd_config.2 && diff $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \ fail "listenaddress order 1" fi @@ -75,15 +75,36 @@ EOD if [ "$os" == "windows" ]; then # Ignore the CR (carriage return) during diff ($SUDO ${SSHD} -T -f $OBJ/sshd_config.1 | \ - grep 'listenaddress ' >$OBJ/sshd_config.2 && + grep '^listenaddress ' >$OBJ/sshd_config.2 && diff --strip-trailing-cr $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \ fail "listenaddress order 2" else ($SUDO ${SSHD} -T -f $OBJ/sshd_config.1 | \ - grep 'listenaddress ' >$OBJ/sshd_config.2 && + grep '^listenaddress ' >$OBJ/sshd_config.2 && diff $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \ fail "listenaddress order 2" fi +# Check idempotence of MaxStartups +verbose "maxstartups idempotent" +echo "maxstartups 1:2:3" > $OBJ/sshd_config.0 +cat > $OBJ/sshd_config.1 <$OBJ/sshd_config.2 && + diff --strip-trailing-cr $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \ + fail "maxstartups idempotence" +else + ($SUDO ${SSHD} -T -f $OBJ/sshd_config.1 | \ + grep '^maxstartups ' >$OBJ/sshd_config.2 && + diff $OBJ/sshd_config.0 $OBJ/sshd_config.2) || \ + fail "maxstartups idempotence" +fi + # cleanup rm -f $OBJ/sshd_config.[012] diff --git a/regress/connect-bigconf.sh b/regress/connect-bigconf.sh new file mode 100644 index 000000000000..ca2c11918dc0 --- /dev/null +++ b/regress/connect-bigconf.sh @@ -0,0 +1,17 @@ +# $OpenBSD: connect-bigconf.sh,v 1.1 2025/07/04 07:52:17 djm Exp $ +# Placed in the Public Domain. + +tid="simple connect" + +for x in `jot 10000 1` ; do + echo "Match version NONEXIST" >> $OBJ/sshd_config + echo "ChrootDirectory /some/path/for/group/NONEXIST" >> $OBJ/sshd_config +done +#cat $OBJ/sshd_config +start_sshd + +trace "direct connect with large sshd_config" +${SSH} -F $OBJ/ssh_config somehost true +if [ $? -ne 0 ]; then + fail "ssh direct connect with large sshd_config failed" +fi diff --git a/regress/dropbear-server.sh b/regress/dropbear-server.sh new file mode 100644 index 000000000000..c72c86bfd39e --- /dev/null +++ b/regress/dropbear-server.sh @@ -0,0 +1,76 @@ +# $OpenBSD: dropbear-server.sh,v 1.2 2025/06/29 05:35:00 dtucker Exp $ +# Placed in the Public Domain. + +tid="dropbear server" + +if test "x$REGRESS_INTEROP_DROPBEAR" != "xyes" ; then + skip "dropbear interop tests not enabled" +fi + +ver="`$DROPBEAR -V 2>&1 | sed 's/Dropbear v//'`" +if [ -z "$ver" ]; then + skip "can't determine dropbear version" +fi + +major=`echo $ver | cut -f1 -d.` +minor=`echo $ver | cut -f2 -d.` + +if [ "$major" -lt "2025" ] || [ "$minor" -lt "87" ]; then + skip "dropbear version $ver (${major}.${minor}) does not support '-D'" +else + trace "dropbear version $ver (${major}.${minor}) ok" +fi + +if [ -z "$SUDO" -a ! -w /var/run ]; then + skip "need SUDO to create dir in /var/run, test won't work without" +fi +authkeydir=/var/run/dropbear-regress + +ciphers=`$DBCLIENT -c help hst 2>&1 | awk '/ ciphers: /{print $4}' | tr ',' ' '` +macs=`$DBCLIENT -m help hst 2>&1 | awk '/ MACs: /{print $4}' | tr ',' ' '` +if [ -z "$macs" ] || [ -z "$ciphers" ]; then + skip "dbclient query ciphers '$ciphers' or macs '$macs' failed" +fi + +# Set up authorized_keys for dropbear. +umask 077 +$SUDO mkdir -p $authkeydir +$SUDO chown -R $USER $authkeydir +cp $OBJ/authorized_keys_$USER $authkeydir/authorized_keys + +for i in `$SUDO $SSHD -f $OBJ/sshd_config -T | grep -v sk- | \ + awk '$1=="hostkey" {print $2}'`; do + file=`basename "$i"` + file=`echo "$file" | sed s/^host\./db\./g` + if $SUDO $DROPBEARCONVERT openssh dropbear "$i" "$OBJ/$file" \ + >/dev/null 2>&1; then + $SUDO chown $USER $OBJ/$file + hkeys="-r $OBJ/$file" + fi +done + +rm -f $OBJ/dropbear.pid +$DROPBEAR -D $authkeydir -p $PORT -P $OBJ/dropbear.pid $hkeys -E \ + 2>$OBJ/sshd.log +if [ $? -ne 0 ]; then + fatal "starting dropbear server failed" +fi +while [ ! -f $OBJ/dropbear.pid ]; do + sleep 1 +done + +pid=`cat $OBJ/dropbear.pid` +trap "kill $pid; $SUDO rm -rf $authkeydir" 0 + +for c in $ciphers; do + for m in $macs; do + trace "$tid: cipher $c mac $m hk $hk" + rm -f ${COPY} + ${SSH} -F $OBJ/ssh_config -oCiphers=$c -oMacs=$m \ + somehost cat ${DATA} > ${COPY} + if [ $? -ne 0 ]; then + fail "connect dropbear server failed" + fi + cmp ${DATA} ${COPY} || fail "corrupted copy" + done +done diff --git a/regress/dsa_ssh2.prv b/regress/dsa_ssh2.prv deleted file mode 100644 index c93b4037194c..000000000000 --- a/regress/dsa_ssh2.prv +++ /dev/null @@ -1,14 +0,0 @@ ----- BEGIN SSH2 ENCRYPTED PRIVATE KEY ---- -Subject: ssh-keygen test -Comment: "1024-bit dsa, Tue Jan 08 2002 22:00:23 +0100" -P2/56wAAAgIAAAAmZGwtbW9kcHtzaWdue2RzYS1uaXN0LXNoYTF9LGRoe3BsYWlufX0AAA -AEbm9uZQAAAcQAAAHAAAAAAAAABACwUfm3AxZTut3icBmwCcD48nY64HzuELlQ+vEqjIcR -Lo49es/DQTeLNQ+kdKRCfouosGNv0WqxRtF0tUsWdXxS37oHGa4QPugBdHRd7YlZGZv8kg -x7FsoepY7v7E683/97dv2zxL3AGagTEzWr7fl0yPexAaZoDvtQrrjX44BLmwAABACWQkvv -MxnD8eFkS1konFfMJ1CkuRfTN34CBZ6dY7VTSGemy4QwtFdMKmoufD0eKgy3p5WOeWCYKt -F4FhjHKZk/aaxFjjIbtkrnlvXg64QI11dSZyBN6/ViQkHPSkUDF+A6AAEhrNbQbAFSvao1 -kTvNtPCtL0AkUIduEMzGQfLCTAAAAKDeC043YVo9Zo0zAEeIA4uZh4LBCQAAA/9aj7Y5ik -ehygJ4qTDSlVypsPuV+n59tMS0e2pfrSG87yf5r94AKBmJeho5OO6wYaXCxsVB7AFbSUD6 -75AK8mHF4v1/+7SWKk5f8xlMCMSPZ9K0+j/W1d/q2qkhnnDZolOHDomLA+U00i5ya/jnTV -zyDPWLFpWK8u3xGBPAYX324gAAAKDHFvooRnaXdZbeWGTTqmgHB1GU9A== ----- END SSH2 ENCRYPTED PRIVATE KEY ---- diff --git a/regress/dsa_ssh2.pub b/regress/dsa_ssh2.pub deleted file mode 100644 index 215d73baef31..000000000000 --- a/regress/dsa_ssh2.pub +++ /dev/null @@ -1,13 +0,0 @@ ----- BEGIN SSH2 PUBLIC KEY ---- -Subject: ssh-keygen test -Comment: "1024-bit dsa, Tue Jan 08 2002 22:00:23 +0100" -AAAAB3NzaC1kc3MAAACBALBR+bcDFlO63eJwGbAJwPjydjrgfO4QuVD68SqMhxEujj16z8 -NBN4s1D6R0pEJ+i6iwY2/RarFG0XS1SxZ1fFLfugcZrhA+6AF0dF3tiVkZm/ySDHsWyh6l -ju/sTrzf/3t2/bPEvcAZqBMTNavt+XTI97EBpmgO+1CuuNfjgEubAAAAFQDeC043YVo9Zo -0zAEeIA4uZh4LBCQAAAIEAlkJL7zMZw/HhZEtZKJxXzCdQpLkX0zd+AgWenWO1U0hnpsuE -MLRXTCpqLnw9HioMt6eVjnlgmCrReBYYxymZP2msRY4yG7ZK55b14OuECNdXUmcgTev1Yk -JBz0pFAxfgOgABIazW0GwBUr2qNZE7zbTwrS9AJFCHbhDMxkHywkwAAACAWo+2OYpHocoC -eKkw0pVcqbD7lfp+fbTEtHtqX60hvO8n+a/eACgZiXoaOTjusGGlwsbFQewBW0lA+u+QCv -JhxeL9f/u0lipOX/MZTAjEj2fStPo/1tXf6tqpIZ5w2aJThw6JiwPlNNIucmv4501c8gz1 -ixaVivLt8RgTwGF99uI= ----- END SSH2 PUBLIC KEY ---- diff --git a/regress/dynamic-forward.sh b/regress/dynamic-forward.sh index 4413d7c8cd00..f086ce11ecf5 100644 --- a/regress/dynamic-forward.sh +++ b/regress/dynamic-forward.sh @@ -1,4 +1,4 @@ -# $OpenBSD: dynamic-forward.sh,v 1.17 2024/03/08 11:34:10 dtucker Exp $ +# $OpenBSD: dynamic-forward.sh,v 1.18 2025/05/21 08:41:52 djm Exp $ # Placed in the Public Domain. tid="dynamic forwarding" @@ -60,7 +60,7 @@ stop_ssh() { check_socks() { direction=$1 expect_success=$2 - for s in 4 5; do + for s in 4A 4 5; do for h in 127.0.0.1 localhost; do trace "testing ssh socks version $s host $h (-$direction)" ${REAL_SSH} -q -F $OBJ/ssh_config -o \ diff --git a/regress/hostbased.sh b/regress/hostbased.sh index eb9cf2727d33..5de176b18bf7 100644 --- a/regress/hostbased.sh +++ b/regress/hostbased.sh @@ -1,4 +1,4 @@ -# $OpenBSD: hostbased.sh,v 1.4 2022/12/07 11:45:43 dtucker Exp $ +# $OpenBSD: hostbased.sh,v 1.5 2025/05/06 06:05:48 djm Exp $ # Placed in the Public Domain. # This test requires external setup and thus is skipped unless @@ -43,7 +43,6 @@ for key in `${SUDO} ${SSHD} -T | awk '$1=="hostkey"{print $2}'`; do 521*ECDSA*) algos="$algos ecdsa-sha2-nistp521" ;; *RSA*) algos="$algos ssh-rsa rsa-sha2-256 rsa-sha2-512" ;; *ED25519*) algos="$algos ssh-ed25519" ;; - *DSA*) algos="$algos ssh-dss" ;; *) verbose "unknown host key type $key" ;; esac done diff --git a/regress/keygen-comment.sh b/regress/keygen-comment.sh index 57c2c10caec7..bd3cfc8c1954 100644 --- a/regress/keygen-comment.sh +++ b/regress/keygen-comment.sh @@ -1,4 +1,5 @@ -#    Placed in the Public Domain. +# $OpenBSD: keygen-comment.sh,v 1.3 2025/10/01 00:30:19 dtucker Exp $ +# Placed in the Public Domain. tid="Comment extraction from private key" diff --git a/regress/keytype.sh b/regress/keytype.sh index f1c045183bd3..11ef7d0cb270 100644 --- a/regress/keytype.sh +++ b/regress/keytype.sh @@ -1,4 +1,4 @@ -# $OpenBSD: keytype.sh,v 1.11 2021/02/25 03:27:34 djm Exp $ +# $OpenBSD: keytype.sh,v 1.12 2025/05/06 06:05:48 djm Exp $ # Placed in the Public Domain. tid="login with different key types" @@ -10,7 +10,6 @@ cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak ktypes="" for i in ${SSH_KEYTYPES}; do case "$i" in - ssh-dss) ktypes="$ktypes dsa-1024" ;; ssh-rsa) ktypes="$ktypes rsa-2048 rsa-3072" ;; ssh-ed25519) ktypes="$ktypes ed25519-512" ;; ecdsa-sha2-nistp256) ktypes="$ktypes ecdsa-256" ;; @@ -36,7 +35,6 @@ done kname_to_ktype() { case $1 in - dsa-1024) echo ssh-dss;; ecdsa-256) echo ecdsa-sha2-nistp256;; ecdsa-384) echo ecdsa-sha2-nistp384;; ecdsa-521) echo ecdsa-sha2-nistp521;; diff --git a/regress/knownhosts-command.sh b/regress/knownhosts-command.sh index 1eeeca521543..6db87a754b91 100644 --- a/regress/knownhosts-command.sh +++ b/regress/knownhosts-command.sh @@ -1,4 +1,4 @@ -# $OpenBSD: knownhosts-command.sh,v 1.3 2021/08/30 01:15:45 djm Exp $ +# $OpenBSD: knownhosts-command.sh,v 1.4 2025/05/06 06:05:48 djm Exp $ # Placed in the Public Domain. tid="known hosts command " @@ -48,7 +48,6 @@ echo "expected_username: $expected_username" for keytype in ${SSH_HOSTKEY_TYPES} ; do algs=$keytype - test "x$keytype" = "xssh-dss" && continue test "x$keytype" = "xssh-rsa" && algs=ssh-rsa,rsa-sha2-256,rsa-sha2-512 verbose "keytype $keytype" cat > $OBJ/knownhosts_command << _EOF diff --git a/regress/krl.sh b/regress/krl.sh index a42684ec5592..93efadeb6665 100644 --- a/regress/krl.sh +++ b/regress/krl.sh @@ -1,4 +1,4 @@ -# $OpenBSD: krl.sh,v 1.12 2023/01/16 04:11:29 djm Exp $ +# $OpenBSD: krl.sh,v 1.13 2025/05/06 06:05:48 djm Exp $ # Placed in the Public Domain. tid="key revocation lists" @@ -11,7 +11,6 @@ for t in $SSH_KEYTYPES; do case "$t" in ecdsa*) ktype2=ecdsa ;; ssh-rsa) ktype3=rsa ;; - ssh-dss) ktype4=dsa ;; sk-ssh-ed25519@openssh.com) ktype5=ed25519-sk ;; sk-ecdsa-sha2-nistp256@openssh.com) ktype6=ecdsa-sk ;; esac diff --git a/regress/limit-keytype.sh b/regress/limit-keytype.sh index e333de9a7883..01c4874481fb 100644 --- a/regress/limit-keytype.sh +++ b/regress/limit-keytype.sh @@ -1,4 +1,4 @@ -# $OpenBSD: limit-keytype.sh,v 1.10 2021/02/25 03:27:34 djm Exp $ +# $OpenBSD: limit-keytype.sh,v 1.11 2025/05/06 06:05:48 djm Exp $ # Placed in the Public Domain. tid="restrict pubkey type" @@ -17,7 +17,6 @@ for t in $SSH_KEYTYPES ; do case "$t" in ssh-rsa) ktype2=rsa ;; ecdsa*) ktype3=ecdsa ;; # unused - ssh-dss) ktype4=dsa ;; sk-ssh-ed25519@openssh.com) ktype5=ed25519-sk ;; sk-ecdsa-sha2-nistp256@openssh.com) ktype6=ecdsa-sk ;; esac @@ -75,7 +74,6 @@ keytype() { case "$1" in ecdsa) printf "ecdsa-sha2-*" ;; ed25519) printf "ssh-ed25519" ;; - dsa) printf "ssh-dss" ;; rsa) printf "rsa-sha2-256,rsa-sha2-512,ssh-rsa" ;; sk-ecdsa) printf "sk-ecdsa-*" ;; sk-ssh-ed25519) printf "sk-ssh-ed25519-*" ;; @@ -123,7 +121,7 @@ if [ "$ktype1" != "$ktype2" ]; then fi ${SSH} $opts -i $OBJ/user_key2 proxy true || fatal "key2 failed" -# Allow only DSA in main config, Ed25519 for user. +# Allow only Ed25519 in main config, Ed25519 for user. verbose "match w/ matching" if [ "$os" == "windows" ]; then # If User is domainuser then it will be in "domain/user" so convert it to "domain\user" diff --git a/regress/misc/fuzz-harness/Makefile b/regress/misc/fuzz-harness/Makefile index 55dcc17175c4..2963ba6824e8 100644 --- a/regress/misc/fuzz-harness/Makefile +++ b/regress/misc/fuzz-harness/Makefile @@ -1,15 +1,16 @@ # NB. libssh and libopenbsd-compat should be built with the same sanitizer opts. -CC=clang-16 -CXX=clang++-16 +CC=clang-19 +CXX=clang++-19 FUZZ_FLAGS=-fsanitize=address,fuzzer -fno-omit-frame-pointer -FUZZ_LIBS=-L/usr/lib/llvm-16/lib -lFuzzer +FUZZ_LIBS=-L/usr/lib/llvm-19/lib -lFuzzer CFLAGS=-D_GNU_SOURCE=1 -O2 -g -Wall -Wextra -Wno-unused-parameter -Wno-exceptions -Wno-deprecated -I ../../.. CXXFLAGS=$(CFLAGS) $(FUZZ_FLAGS) LDFLAGS=-L ../../.. -L ../../../openbsd-compat -g -LIBS=-lssh -lopenbsd-compat -lmd -lcrypto -lfido2 -lcbor $(FUZZ_LIBS) +COMMON_OBJS=../../../ssh-pkcs11-client.o +LIBS=$(COMMON_OBJS) -lssh -lopenbsd-compat -lmd -lcrypto -lfido2 -lcbor $(FUZZ_LIBS) SK_NULL_OBJS=ssh-sk-null.o -COMMON_DEPS=../../../libssh.a +COMMON_DEPS=../../../libssh.a $(COMMON_OBJS) TARGETS=pubkey_fuzz sig_fuzz authopt_fuzz authkeys_fuzz sshsig_fuzz \ sshsigopt_fuzz privkey_fuzz kex_fuzz agent_fuzz \ diff --git a/regress/misc/fuzz-harness/agent_fuzz_helper.c b/regress/misc/fuzz-harness/agent_fuzz_helper.c index 2750221154e6..400b63156b7a 100644 --- a/regress/misc/fuzz-harness/agent_fuzz_helper.c +++ b/regress/misc/fuzz-harness/agent_fuzz_helper.c @@ -175,10 +175,3 @@ test_one(const uint8_t* s, size_t slen) cleanup_idtab(); cleanup_sockettab(); } - -int -pkcs11_make_cert(const struct sshkey *priv, - const struct sshkey *certpub, struct sshkey **certprivp) -{ - return -1; /* XXX */ -} diff --git a/regress/misc/fuzz-harness/fixed-keys.h b/regress/misc/fuzz-harness/fixed-keys.h index c6e7c6cc1828..61afa876a0fa 100644 --- a/regress/misc/fuzz-harness/fixed-keys.h +++ b/regress/misc/fuzz-harness/fixed-keys.h @@ -34,32 +34,6 @@ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdT" #define CERT_RSA \ "ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg89JX6OBMYDSxER8fnU5y8xxeMCHR/hI0uVqdEhNyCpcAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAAAAA+0AAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQGCDA6PWw4x9bHQl0w7NqifHepumqD3dmyMx+hZGuPRon+TsyCjfytu7hWmV7l9XUF0fPQNFQ7FGat5e+7YUNgE= id_rsa.pub" -#define PRIV_DSA \ -"-----BEGIN OPENSSH PRIVATE KEY-----\n"\ -"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH\n"\ -"NzAAAAgQCsGTfjpQ465EOkfQXJM9BOvfRQE0fqlykAls+ncz+T7hrbeScRu8xpwzsznJNm\n"\ -"xlW8o6cUDiHmBJ5OHgamUC9N7YJeU/6fnOAZifgN8mqK6k8pKHuje8ANOiYgHLl0yiASQA\n"\ -"3//qMyzZ+W/hemoLSmLAbEqlfWVeyYx+wta1Vm+QAAABUAvWyehvUvdHvQxavYgS5p0t5Q\n"\ -"d7UAAACBAIRA9Yy+f4Kzqpv/qICPO3zk42UuP7WAhSW2nCbQdLlCiSTxcjKgcvXNRckwJP\n"\ -"44JjSHOtJy/AMtJrPIbLYG6KuWTdBlEHFiG6DafvLG+qPMSL2bPjXTOhuOMbCHIZ+5WBkW\n"\ -"THeG/Nv11iI01Of9V6tXkig23K370flkRkXFi9MdAAAAgCt6YUcQkNwG7B/e5M1FZsLP9O\n"\ -"kVB3BwLAOjmWdHpyhu3HpwSJa3XLEvhXN0i6IVI2KgPo/2GtYA6rHt14L+6u1pmhh8sAvQ\n"\ -"ksp3qZB+xh/NP+hBqf0sbHX0yYbzKOvI5SCc/kKK6yagcBZOsubM/KC8TxyVgmD5c6WzYs\n"\ -"h5TEpvAAAB2PHjRbbx40W2AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FAT\n"\ -"R+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4B\n"\ -"mJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1r\n"\ -"VWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS\n"\ -"4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIb\n"\ -"oNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRc\n"\ -"WL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SL\n"\ -"ohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJ\n"\ -"z+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAUUA+OGldMi76ClO/sstpdbBUE\n"\ -"lq8AAAAAAQI=\n"\ -"-----END OPENSSH PRIVATE KEY-----\n" -#define PUB_DSA \ -"ssh-dss AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8=" -#define CERT_DSA \ -"ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAguF716Yub+vVKNlONKLsfxGYWkRe/PyjfYdGRTsFaDvAAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAAAAAD6AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAjMQEZcbdUYJBjIC4GxByFDOb8tv71vDZdx7irHwaqIjx5rzpJUuOV1r8ZO4kY+Yaiun1yrWj2QYkfJrHBvD1DA== id_dsa.pub" #define PRIV_ECDSA \ "-----BEGIN OPENSSH PRIVATE KEY-----\n"\ "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS\n"\ diff --git a/regress/misc/fuzz-harness/testdata/create-agent-corpus.sh b/regress/misc/fuzz-harness/testdata/create-agent-corpus.sh index 1043b9ff47d7..842b8c48d9dd 100755 --- a/regress/misc/fuzz-harness/testdata/create-agent-corpus.sh +++ b/regress/misc/fuzz-harness/testdata/create-agent-corpus.sh @@ -14,7 +14,7 @@ sleep 1 AGENT_PID=$! trap "kill $AGENT_PID" EXIT -PRIV="id_dsa id_ecdsa id_ecdsa_sk id_ed25519 id_ed25519_sk id_rsa" +PRIV="id_ecdsa id_ecdsa_sk id_ed25519 id_ed25519_sk id_rsa" # add keys ssh-add $PRIV diff --git a/regress/misc/sk-dummy/sk-dummy.c b/regress/misc/sk-dummy/sk-dummy.c index 347b212271ec..4c96e8827c50 100644 --- a/regress/misc/sk-dummy/sk-dummy.c +++ b/regress/misc/sk-dummy/sk-dummy.c @@ -1,3 +1,4 @@ +/* $OpenBSD: sk-dummy.c,v 1.16 2025/06/17 01:24:32 djm Exp $ */ /* * Copyright (c) 2019 Markus Friedl * @@ -16,9 +17,7 @@ #include "includes.h" -#ifdef HAVE_STDINT_H #include -#endif #include #include #include @@ -263,7 +262,7 @@ sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, break; default: skdebug(__func__, "unsupported key type %d", alg); - return -1; + goto out; } /* Have to return something here */ if ((response->signature = calloc(1, 1)) == NULL) { @@ -520,7 +519,7 @@ sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, break; default: skdebug(__func__, "unsupported key type %d", alg); - return -1; + goto out; } *sign_response = response; response = NULL; diff --git a/regress/misc/ssh-verify-attestation/Makefile b/regress/misc/ssh-verify-attestation/Makefile index 2a797aecae46..06fb8aac4e98 100644 --- a/regress/misc/ssh-verify-attestation/Makefile +++ b/regress/misc/ssh-verify-attestation/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.1 2024/12/04 16:42:49 djm Exp $ +# $OpenBSD: Makefile,v 1.2 2025/05/06 06:05:48 djm Exp $ .include .include @@ -13,7 +13,7 @@ SRCS=ssh-verify-attestation.c # From usr.bin/ssh SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c -SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c +SRCS+=ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c SRCS+=addr.c addrmatch.c bitmap.c SRCS+=ed25519.c hash.c diff --git a/regress/misc/ssh-verify-attestation/ssh-verify-attestation.c b/regress/misc/ssh-verify-attestation/ssh-verify-attestation.c index 4d82a0390587..da7f5a23366c 100644 --- a/regress/misc/ssh-verify-attestation/ssh-verify-attestation.c +++ b/regress/misc/ssh-verify-attestation/ssh-verify-attestation.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-verify-attestation.c,v 1.2 2024/12/06 10:37:42 djm Exp $ */ +/* $OpenBSD: ssh-verify-attestation.c,v 1.3 2025/05/12 05:42:02 tb Exp $ */ /* * Copyright (c) 2022-2024 Damien Miller * @@ -70,6 +70,7 @@ #include #include #include +#include "openbsd-compat/openssl-compat.h" extern char *__progname; @@ -164,8 +165,8 @@ get_pubkey_from_cred_ecdsa(const fido_cred_t *cred, size_t *pubkey_len) error_f("BN_bin2bn failed"); goto out; } - if (EC_POINT_set_affine_coordinates_GFp(g, q, x, y, NULL) != 1) { - error_f("EC_POINT_set_affine_coordinates_GFp failed"); + if (EC_POINT_set_affine_coordinates(g, q, x, y, NULL) != 1) { + error_f("EC_POINT_set_affine_coordinates failed"); goto out; } *pubkey_len = EC_POINT_point2oct(g, q, diff --git a/regress/modpipe.c b/regress/modpipe.c index 5f4824b51d02..5ef2f12ed1f6 100644 --- a/regress/modpipe.c +++ b/regress/modpipe.c @@ -14,7 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $OpenBSD: modpipe.c,v 1.6 2013/11/21 03:16:47 djm Exp $ */ +/* $OpenBSD: modpipe.c,v 1.7 2025/10/03 01:03:45 dtucker Exp $ */ #include "includes.h" @@ -127,7 +127,7 @@ main(int argc, char **argv) } } for (o = 0; o < s; o += r) { - r = write(STDOUT_FILENO, buf, s - o); + r = write(STDOUT_FILENO, buf + o, s - o); if (r == 0) break; if (r < 0) { diff --git a/regress/netcat.c b/regress/netcat.c index 20ec3f5954fa..c62111780636 100644 --- a/regress/netcat.c +++ b/regress/netcat.c @@ -55,13 +55,7 @@ #include #include "atomicio.h" -#ifdef HAVE_POLL_H #include -#else -# ifdef HAVE_SYS_POLL_H -# include -# endif -#endif #ifdef HAVE_ERR_H # include #endif @@ -185,6 +179,8 @@ main(int argc, char *argv[]) socksv = -1; /* HTTP proxy CONNECT */ else if (strcmp(optarg, "4") == 0) socksv = 4; /* SOCKS v.4 */ + else if (strcasecmp(optarg, "4A") == 0) + socksv = 44; /* SOCKS v.4A */ else if (strcmp(optarg, "5") == 0) socksv = 5; /* SOCKS v.5 */ else @@ -1138,7 +1134,7 @@ build_ports(char *p) char *c; for (x = 0; x <= (hi - lo); x++) { - y = (arc4random() & 0xFFFF) % (hi - lo); + y = arc4random_uniform(hi - lo); c = portlist[x]; portlist[x] = portlist[y]; portlist[y] = c; @@ -1586,19 +1582,33 @@ socks_connect(const char *host, const char *port, default: errx(1, "connection failed, unsupported address type"); } - } else if (socksv == 4) { - /* This will exit on lookup failure */ - decode_addrport(host, port, (struct sockaddr *)&addr, - sizeof(addr), 1, 0); + } else if (socksv == 4 || socksv == 44) { + if (socksv == 4) { + /* This will exit on lookup failure */ + decode_addrport(host, port, (struct sockaddr *)&addr, + sizeof(addr), 1, 0); + } /* Version 4 */ buf[0] = SOCKS_V4; buf[1] = SOCKS_CONNECT; /* connect */ memcpy(buf + 2, &in4->sin_port, sizeof in4->sin_port); - memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr); + if (socksv == 4) { + memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr); + } else { + /* SOCKS4A uses addr of 0.0.0.x, and hostname later */ + buf[4] = buf[5] = buf[6] = 0; + buf[7] = 1; + } buf[8] = 0; /* empty username */ wlen = 9; - + if (socksv == 44) { + /* SOCKS4A has nul-terminated hostname after user */ + if (strlcpy(buf + 9, host, + sizeof(buf) - 9) >= sizeof(buf) - 9) + errx(1, "hostname too big"); + wlen = 9 + strlen(host) + 1; + } cnt = atomicio(vwrite, proxyfd, buf, wlen); if (cnt != wlen) err(1, "write failed (%zu/%zu)", cnt, wlen); diff --git a/regress/password.sh b/regress/password.sh new file mode 100644 index 000000000000..10f507e4472c --- /dev/null +++ b/regress/password.sh @@ -0,0 +1,60 @@ +# $OpenBSD: password.sh,v 1.2 2025/06/29 08:20:21 dtucker Exp $ +# Placed in the Public Domain. +# +# This tests standard "password" authentication. It does not run by default, +# and needs to be enabled by putting the password of the user running the tests +# into ${OBJ}/password. Since this obviously puts the password at risk it is +# recommended to do this on a throwaway VM by setting a random password +# (and randomizing it again after the test, if you can't immediately dispose +# of the VM). + +tid="password" + +if [ -z "$SUDO" -o ! -f ${OBJ}/password ]; then + skip "Password auth requires SUDO and password file." +fi + +# Enable password auth +echo "PasswordAuthentication yes" >>sshd_proxy + +# Create askpass script to replay a series of password responses. +# Keep a counter of the number of times it has been called and +# reply with the next line of the replypass file. +cat >${OBJ}/replypass.sh <${OBJ}/replypass.N +EOD +chmod 700 ${OBJ}/replypass.sh + +SSH_ASKPASS=${OBJ}/replypass.sh +SSH_ASKPASS_REQUIRE=force +export SSH_ASKPASS SSH_ASKPASS_REQUIRE + +opts="-oPasswordAuthentication=yes -oPreferredAuthentications=password" +opts="-oBatchMode=no $opts" + +trace plain password +cat ${OBJ}/password >${OBJ}/replypass +echo 1 >${OBJ}/replypass.N +${SSH} $opts -F $OBJ/ssh_proxy somehost true +if [ $? -ne 0 ]; then + fail "ssh password failed" +fi + +trace 2-round password +(echo; cat ${OBJ}/password) >${OBJ}/replypass +echo 1 >${OBJ}/replypass.N +${SSH} $opts -F $OBJ/ssh_proxy somehost true +if [ $? -ne 0 ]; then + fail "ssh 2-round password failed" +fi + +trace empty password +echo >${OBJ}/replypass +echo 1 >${OBJ}/replypass.N +${SSH} $opts -F $OBJ/ssh_proxy somehost true +if [ $? -eq 0 ]; then + fail "ssh password failed" +fi diff --git a/regress/penalty-expire.sh b/regress/penalty-expire.sh index 4f0bbe638f63..27e36e3eefbf 100644 --- a/regress/penalty-expire.sh +++ b/regress/penalty-expire.sh @@ -1,4 +1,4 @@ -# $OpenBSD +# $OpenBSD: penalty-expire.sh,v 1.3 2025/05/22 04:34:18 bluhm Exp $ # Placed in the Public Domain. tid="penalties" diff --git a/regress/penalty.sh b/regress/penalty.sh index 8b8353238111..bf719dc0aab2 100644 --- a/regress/penalty.sh +++ b/regress/penalty.sh @@ -1,4 +1,4 @@ -# $OpenBSD +# $OpenBSD: penalty.sh,v 1.7 2025/05/22 04:34:18 bluhm Exp $ # Placed in the Public Domain. tid="penalties" diff --git a/regress/percent.sh b/regress/percent.sh index 7ce9e8a1dc30..c607c8d23aa0 100644 --- a/regress/percent.sh +++ b/regress/percent.sh @@ -1,4 +1,4 @@ -# $OpenBSD: percent.sh,v 1.21 2025/04/08 23:10:46 djm Exp $ +# $OpenBSD: percent.sh,v 1.22 2025/09/04 03:04:44 djm Exp $ # Placed in the Public Domain. tid="percent expansions" @@ -33,14 +33,14 @@ trial() if [ "$arg" = '%r' ] || [ "$arg" = '%C' ]; then # User does not support %r, ie itself or %C. Skip test. got="$expect" - elif [ "$i" = "user" ]; then + elif [ "$opt" = "user" ]; then got=`${SSH} -F $OBJ/ssh_proxy -o $opt="$arg" -G \ remuser@somehost | awk '$1=="'$opt'"{print $2}'` - elif [ "$i" = "user-l" ]; then + elif [ "$opt" = "user-l" ]; then # Also test ssh -l got=`${SSH} -F $OBJ/ssh_proxy -l "$arg" -G \ somehost | awk '$1=="'user'"{print $2}'` - elif [ "$i" = "user-at" ]; then + elif [ "$opt" = "user-at" ]; then # Also test user@host got=`${SSH} -F $OBJ/ssh_proxy -G "$arg@somehost" | \ awk '$1=="'user'"{print $2}'` @@ -91,7 +91,7 @@ trial() for i in matchexec localcommand remotecommand controlpath identityagent \ forwardagent localforward remoteforward revokedhostkeys \ - user user-l user-at setenv userknownhostsfile; do + user setenv userknownhostsfile; do verbose $tid $i percent case "$i" in localcommand|userknownhostsfile) @@ -137,11 +137,11 @@ done # Subset of above since we don't expand shell-style variables on anything that # runs a command because the shell will expand those. +FOO=bar +export FOO for i in controlpath identityagent forwardagent localforward remoteforward \ - user user-l user-at setenv userknownhostsfile; do + user setenv userknownhostsfile; do verbose $tid $i dollar - FOO=bar - export FOO trial $i '${FOO}' $FOO done @@ -152,3 +152,32 @@ for i in controlpath identityagent forwardagent; do trial $i '~' $HOME/ trial $i '~/.ssh' $HOME/.ssh done + +for i in user-l user-at; do + verbose $tid $i noexpand + trial $i '%u' '%u' +done + +# These should be not be expanded but rejected for containing shell characters. +verbose $tid user-l noenv +${SSH} -F $OBJ/ssh_proxy -l '${FOO}' -G somehost && fail "user-l expanded env" +verbose $tid user-at noenv +${SSH} -F $OBJ/ssh_proxy -G '${FOO}@somehost' && fail "user-at expanded env" + +FOO=`printf 'x\ay'` +export FOO + +# These should be rejected as containing control characters. +verbose $tid user-l badchar +${SSH} -F $OBJ/ssh_proxy -l "${FOO}" -G somehost && fail "user-l expanded env" +verbose $tid user-at badchar +${SSH} -F $OBJ/ssh_proxy -G "${FOO}@somehost" && fail "user-at expanded env" + +# Literal control characters in config is acceptable +verbose $tid user control-literal +trial user "$FOO" "$FOO" + +# Control characters expanded from config aren't. +${SSH} -F $OBJ/ssh_proxy -G '-oUser=${FOO}' somehost && \ + fail "user expanded ctrl" + diff --git a/regress/rekey.sh b/regress/rekey.sh index 828e6d0826e1..fbf4cab4cf56 100644 --- a/regress/rekey.sh +++ b/regress/rekey.sh @@ -11,7 +11,7 @@ cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak echo "Compression no" >> $OBJ/ssh_proxy echo "RekeyLimit 256k" >> $OBJ/ssh_proxy -echo "KexAlgorithms curve25519-sha256" >> ssh_proxy +echo "KexAlgorithms curve25519-sha256" >> $OBJ/ssh_proxy # Test rekeying based on data volume only. # Arguments: rekeylimit, kex method, optional remaining opts are passed to ssh. diff --git a/regress/ssh-com-client.sh b/regress/ssh-com-client.sh index e4f80cf0aadf..97b36b564f4a 100644 --- a/regress/ssh-com-client.sh +++ b/regress/ssh-com-client.sh @@ -1,4 +1,4 @@ -# $OpenBSD: ssh-com-client.sh,v 1.7 2013/05/17 04:29:14 dtucker Exp $ +# $OpenBSD: ssh-com-client.sh,v 1.8 2025/05/06 06:05:48 djm Exp $ # Placed in the Public Domain. tid="connect with ssh.com client" @@ -28,7 +28,7 @@ VERSIONS=" # setup authorized keys SRC=`dirname ${SCRIPT}` -cp ${SRC}/dsa_ssh2.prv ${OBJ}/id.com +cp ${SRC}/rsa_ssh2.prv ${OBJ}/id.com chmod 600 ${OBJ}/id.com ${SSHKEYGEN} -i -f ${OBJ}/id.com > $OBJ/id.openssh chmod 600 ${OBJ}/id.openssh @@ -36,8 +36,8 @@ ${SSHKEYGEN} -y -f ${OBJ}/id.openssh > $OBJ/authorized_keys_$USER ${SSHKEYGEN} -e -f ${OBJ}/id.openssh > $OBJ/id.com.pub echo IdKey ${OBJ}/id.com > ${OBJ}/id.list -# we need a DSA host key -t=dsa +# we need a RSA host key +t=rsa rm -f ${OBJ}/$t ${OBJ}/$t.pub ${SSHKEYGEN} -q -N '' -t $t -f ${OBJ}/$t $SUDO cp $OBJ/$t $OBJ/host.$t @@ -47,7 +47,6 @@ echo HostKey $OBJ/host.$t >> $OBJ/sshd_config mkdir -p ${OBJ}/${USER}/hostkeys HK=${OBJ}/${USER}/hostkeys/key_${PORT}_127.0.0.1 ${SSHKEYGEN} -e -f ${OBJ}/rsa.pub > ${HK}.ssh-rsa.pub -${SSHKEYGEN} -e -f ${OBJ}/dsa.pub > ${HK}.ssh-dss.pub cat > ${OBJ}/ssh2_config << EOF *: @@ -74,7 +73,7 @@ for v in ${VERSIONS}; do continue fi verbose "ssh2 ${v}" - key=ssh-dss + key=ssh-rsa skipcat=0 case $v in 2.1.*|2.3.0) @@ -124,7 +123,6 @@ for v in ${VERSIONS}; do done rm -rf ${OBJ}/${USER} -for i in ssh2_config random_seed dsa.pub dsa host.dsa \ - id.list id.com id.com.pub id.openssh; do +for i in ssh2_config random_seed id.list id.com id.com.pub id.openssh; do rm -f ${OBJ}/$i done diff --git a/regress/ssh-com.sh b/regress/ssh-com.sh index b1a2505d1135..bb833380eb57 100644 --- a/regress/ssh-com.sh +++ b/regress/ssh-com.sh @@ -1,4 +1,4 @@ -# $OpenBSD: ssh-com.sh,v 1.10 2017/05/08 01:52:49 djm Exp $ +# $OpenBSD: ssh-com.sh,v 1.11 2025/05/06 06:05:48 djm Exp $ # Placed in the Public Domain. tid="connect to ssh.com server" @@ -41,8 +41,8 @@ cat << EOF > $OBJ/sshd2_config PubKeyAuthentication yes #AllowedAuthentications publickey AuthorizationFile authorization - HostKeyFile ${SRC}/dsa_ssh2.prv - PublicHostKeyFile ${SRC}/dsa_ssh2.pub + HostKeyFile ${SRC}/rsa_ssh2.prv + PublicHostKeyFile ${SRC}/rsa_ssh2.pub RandomSeedFile ${OBJ}/random_seed MaxConnections 0 PermitRootLogin yes @@ -55,23 +55,21 @@ EOF sed "s/HostKeyAlias.*/HostKeyAlias ssh2-localhost-with-alias/" \ < $OBJ/ssh_config > $OBJ/ssh_config_com -# we need a DSA key for -rm -f ${OBJ}/dsa ${OBJ}/dsa.pub -${SSHKEYGEN} -q -N '' -t dsa -f ${OBJ}/dsa +# we need a RSA key for +rm -f ${OBJ}/rsa ${OBJ}/rsa.pub +${SSHKEYGEN} -q -N '' -t rsa -f ${OBJ}/rsa # setup userdir, try rsa first mkdir -p ${OBJ}/${USER} cp /dev/null ${OBJ}/${USER}/authorization -for t in rsa dsa; do - ${SSHKEYGEN} -e -f ${OBJ}/$t.pub > ${OBJ}/${USER}/$t.com - echo Key $t.com >> ${OBJ}/${USER}/authorization - echo IdentityFile ${OBJ}/$t >> ${OBJ}/ssh_config_com -done +${SSHKEYGEN} -e -f ${OBJ}/rsa.pub > ${OBJ}/${USER}/rsa.com +echo Key rsa.com >> ${OBJ}/${USER}/authorization +echo IdentityFile ${OBJ}/rsa >> ${OBJ}/ssh_config_com -# convert and append DSA hostkey +# convert and append RSA hostkey ( printf 'ssh2-localhost-with-alias,127.0.0.1,::1 ' - ${SSHKEYGEN} -if ${SRC}/dsa_ssh2.pub + ${SSHKEYGEN} -if ${SRC}/rsa_ssh2.pub ) >> $OBJ/known_hosts # go for it @@ -114,6 +112,6 @@ done rm -rf ${OBJ}/${USER} for i in sshd_config_proxy ssh_config_proxy random_seed \ - sshd2_config dsa.pub dsa ssh_config_com; do + sshd2_config rsa.pub rsa ssh_config_com; do rm -f ${OBJ}/$i done diff --git a/regress/ssh2putty.sh b/regress/ssh2putty.sh index 9b08310391ca..bd291313f6c3 100755 --- a/regress/ssh2putty.sh +++ b/regress/ssh2putty.sh @@ -1,5 +1,5 @@ #!/bin/sh -# $OpenBSD: ssh2putty.sh,v 1.9 2021/07/25 12:13:03 dtucker Exp $ +# $OpenBSD: ssh2putty.sh,v 1.10 2025/05/06 06:05:48 djm Exp $ if test "x$1" = "x" -o "x$2" = "x" -o "x$3" = "x" ; then echo "Usage: ssh2putty hostname port ssh-private-key" @@ -12,7 +12,6 @@ KEYFILE=$3 OPENSSL_BIN="${OPENSSL_BIN:-openssl}" -# XXX - support DSA keys too if grep "BEGIN RSA PRIVATE KEY" $KEYFILE >/dev/null 2>&1 ; then : else diff --git a/regress/sshcfgparse.sh b/regress/sshcfgparse.sh index bf6971ebe18b..7d418090f2aa 100644 --- a/regress/sshcfgparse.sh +++ b/regress/sshcfgparse.sh @@ -1,15 +1,8 @@ -# $OpenBSD: sshcfgparse.sh,v 1.9 2021/06/08 07:05:27 dtucker Exp $ +# $OpenBSD: sshcfgparse.sh,v 1.10 2025/05/06 06:05:48 djm Exp $ # Placed in the Public Domain. tid="ssh config parse" -dsa=0 -for t in $SSH_KEYTYPES; do - case "$t" in - ssh-dss) dsa=1 ;; - esac -done - expect_result_present() { _str="$1" ; shift for _expect in "$@" ; do @@ -99,7 +92,6 @@ if [ "$os" == "windows" ]; then f=${f/$'\r'/} # remove CR (carriage return) fi expect_result_present "$f" "ssh-ed25519" "ssh-ed25519-cert-v01.*" -expect_result_absent "$f" "ssh-dss" # Explicit override f=`${SSH} -GF none -opubkeyacceptedalgorithms=ssh-ed25519 host | \ awk '/^pubkeyacceptedalgorithms /{print $2}'` @@ -107,7 +99,7 @@ if [ "$os" == "windows" ]; then f=${f/$'\r'/} # remove CR (carriage return) fi expect_result_present "$f" "ssh-ed25519" -expect_result_absent "$f" "ssh-ed25519-cert-v01.*" "ssh-dss" +expect_result_absent "$f" "ssh-ed25519-cert-v01.*" # Removal from default set f=`${SSH} -GF none -opubkeyacceptedalgorithms=-ssh-ed25519-cert* host | \ awk '/^pubkeyacceptedalgorithms /{print $2}'` @@ -115,32 +107,17 @@ if [ "$os" == "windows" ]; then f=${f/$'\r'/} # remove CR (carriage return) fi expect_result_present "$f" "ssh-ed25519" -expect_result_absent "$f" "ssh-ed25519-cert-v01.*" "ssh-dss" +expect_result_absent "$f" "ssh-ed25519-cert-v01.*" f=`${SSH} -GF none -opubkeyacceptedalgorithms=-ssh-ed25519 host | \ awk '/^pubkeyacceptedalgorithms /{print $2}'` if [ "$os" == "windows" ]; then f=${f/$'\r'/} # remove CR (carriage return) fi expect_result_present "$f" "ssh-ed25519-cert-v01.*" -expect_result_absent "$f" "ssh-ed25519" "ssh-dss" +expect_result_absent "$f" "ssh-ed25519" # Append to default set. # This is not tested when built !WITH_OPENSSL -if [ "$dsa" = "1" ]; then - f=`${SSH} -GF none -opubkeyacceptedalgorithms=+ssh-dss-cert* host | \ - awk '/^pubkeyacceptedalgorithms /{print $2}'` - if [ "$os" == "windows" ]; then - f=${f/$'\r'/} # remove CR (carriage return) - fi - expect_result_present "$f" "ssh-ed25519" "ssh-dss-cert-v01.*" - expect_result_absent "$f" "ssh-dss" - f=`${SSH} -GF none -opubkeyacceptedalgorithms=+ssh-dss host | \ - awk '/^pubkeyacceptedalgorithms /{print $2}'` - if [ "$os" == "windows" ]; then - f=${f/$'\r'/} # remove CR (carriage return) - fi - expect_result_present "$f" "ssh-ed25519" "ssh-ed25519-cert-v01.*" "ssh-dss" - expect_result_absent "$f" "ssh-dss-cert-v01.*" -fi +# XXX need a test for this verbose "agentforwarding" f=`${SSH} -GF none host | awk '/^forwardagent /{print$2}'` diff --git a/regress/sshsig.sh b/regress/sshsig.sh index f0858281c33b..a01021aa2da5 100644 --- a/regress/sshsig.sh +++ b/regress/sshsig.sh @@ -1,4 +1,4 @@ -# $OpenBSD: sshsig.sh,v 1.15 2023/10/12 03:51:08 djm Exp $ +# $OpenBSD: sshsig.sh,v 1.16 2025/09/11 07:23:32 djm Exp $ # Placed in the Public Domain. tid="sshsig" @@ -255,7 +255,7 @@ for t in $SIGNKEYS; do # 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" + ${SSHADD} -N ${privkey} > /dev/null 2>&1 || fail "ssh-add failed" # Move private key to ensure agent key is used mv ${privkey} ${privkey}.tmp diff --git a/regress/test-exec.sh b/regress/test-exec.sh index 3335f8941bdf..42419d580c3b 100644 --- a/regress/test-exec.sh +++ b/regress/test-exec.sh @@ -1,4 +1,4 @@ -# $OpenBSD: test-exec.sh,v 1.127 2025/03/28 05:41:15 dtucker Exp $ +# $OpenBSD: test-exec.sh,v 1.131 2025/07/26 01:53:31 djm Exp $ # Placed in the Public Domain. #SUDO=sudo @@ -113,7 +113,7 @@ SSH_REGRESS_TMP= PLINK=/usr/local/bin/plink PUTTYGEN=/usr/local/bin/puttygen CONCH=/usr/local/bin/conch -DROPBEAR=/usr/local/bin/dropbear +DROPBEAR=/usr/local/sbin/dropbear DBCLIENT=/usr/local/bin/dbclient DROPBEARKEY=/usr/local/bin/dropbearkey DROPBEARCONVERT=/usr/local/bin/dropbearconvert @@ -591,6 +591,7 @@ save_debug_log () $SUDO chown -R $USER $logfile fi done + test -z "$SUDO" || $SUDO chmod ug+rw $TEST_SSHD_LOGFILE echo $@ >>$TEST_REGRESS_LOGFILE echo $@ >>$TEST_SSH_LOGFILE echo $@ >>$TEST_SSHD_LOGFILE @@ -598,19 +599,6 @@ save_debug_log () (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 () @@ -1040,7 +1028,7 @@ p11_setup() { /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" + trace "using token library $TEST_SSH_PKCS11" TEST_SSH_PIN=1234 TEST_SSH_SOPIN=12345678 if [ "x$TEST_SSH_SSHPKCS11HELPER" != "x" ]; then @@ -1092,6 +1080,18 @@ EOF --import $ECP8 >/dev/null || fatal "softhsm import EC fail" chmod 600 $EC ssh-keygen -y -f $EC > ${EC}.pub + # Ed25519 key + ED25519=${SSH_SOFTHSM_DIR}/ED25519 + ED25519P8=${SSH_SOFTHSM_DIR}/ED25519P8 + $OPENSSL_BIN genpkey -algorithm ed25519 > $ED25519 || \ + fatal "genpkey Ed25519 fail" + $OPENSSL_BIN pkcs8 -nocrypt -in $ED25519 > $ED25519P8 || \ + fatal "pkcs8 Ed25519 fail" + softhsm2-util --slot "$slot" --label 03 --id 03 --pin "$TEST_SSH_PIN" \ + --import $ED25519P8 >/dev/null || \ + fatal "softhsm import ed25519 fail" + chmod 600 $ED25519 + ssh-keygen -y -f $ED25519 > ${ED25519}.pub # Prepare askpass script to load PIN. PIN_SH=$SSH_SOFTHSM_DIR/pin.sh cat > $PIN_SH << EOF @@ -1108,6 +1108,28 @@ p11_ssh_add() { env SSH_ASKPASS="$PIN_SH" SSH_ASKPASS_REQUIRE=force ${SSHADD} "$@" } +start_ssh_agent() { + EXTRA_AGENT_ARGS="$1" + SSH_AUTH_SOCK="$OBJ/agent.sock" + export SSH_AUTH_SOCK + rm -f $SSH_AUTH_SOCK $OBJ/agent.log + 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 +} + # source test body . $SCRIPT diff --git a/regress/unittests/Makefile.inc b/regress/unittests/Makefile.inc index 98e280486ab1..5fcf7a950a39 100644 --- a/regress/unittests/Makefile.inc +++ b/regress/unittests/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.16 2024/01/11 01:45:58 djm Exp $ +# $OpenBSD: Makefile.inc,v 1.18 2025/05/06 06:05:48 djm Exp $ .include .include @@ -7,6 +7,9 @@ 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). +UNITTEST_BENCHMARK?= no # Run unit tests in benchmarking mode. +UNITTEST_BENCH_DETAIL?=no # Detailed benchmark statistics. +UNITTEST_BENCH_ONLY?= # Run only these benchmarks MALLOC_OPTIONS?= CFGJRSUX TEST_ENV?= MALLOC_OPTIONS=${MALLOC_OPTIONS} @@ -15,10 +18,6 @@ TEST_ENV?= MALLOC_OPTIONS=${MALLOC_OPTIONS} OPENSSL?= yes DSAKEY?= yes -.if (${DSAKEY:L} == "yes") -CFLAGS+= -DWITH_DSA -.endif - .if (${OPENSSL:L} == "yes") CFLAGS+= -DWITH_OPENSSL .endif @@ -69,8 +68,8 @@ DPADD+=${.CURDIR}/../test_helper/libtest_helper.a .PATH: ${.CURDIR}/${SSHREL} -LDADD+= -lutil -DPADD+= ${LIBUTIL} +LDADD+= -lutil -lm +DPADD+= ${LIBUTIL} ${LIBM} .if (${OPENSSL:L} == "yes") LDADD+= -lcrypto @@ -82,11 +81,21 @@ DPADD+= ${LIBFIDO2} ${LIBCBOR} ${LIBUSBHID} UNITTEST_ARGS?= -.if (${UNITTEST_VERBOSE:L} != "no") +.if (${UNITTEST_VERBOSE:L:R} != "no") UNITTEST_ARGS+= -v .endif -.if (${UNITTEST_FAST:L} != "no") +.if (${UNITTEST_FAST:L:R} != "no") UNITTEST_ARGS+= -f -.elif (${UNITTEST_SLOW:L} != "no") +.elif (${UNITTEST_SLOW:L:R} != "no") UNITTEST_ARGS+= -F .endif + +.if (${UNITTEST_BENCHMARK:L:R} != "no") +UNITTEST_ARGS+= -b +.endif +.if (${UNITTEST_BENCH_DETAIL:L:R} != "no") +UNITTEST_ARGS+= -B +.endif +.if (${UNITTEST_BENCH_ONLY:L} != "") +UNITTEST_ARGS+= -O "${UNITTEST_BENCH_ONLY}" +.endif diff --git a/regress/unittests/authopt/Makefile b/regress/unittests/authopt/Makefile index 3045ec708165..1ecaa30ce343 100644 --- a/regress/unittests/authopt/Makefile +++ b/regress/unittests/authopt/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.7 2023/01/15 23:35:10 djm Exp $ +# $OpenBSD: Makefile,v 1.10 2025/07/24 06:04:47 djm Exp $ PROG=test_authopt SRCS=tests.c @@ -8,12 +8,12 @@ SRCS+=auth-options.c # From usr.bin/ssh SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c -SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c +SRCS+=ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c SRCS+=addr.c addrmatch.c bitmap.c SRCS+=ed25519.c hash.c SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c -SRCS+=ssh-ed25519-sk.c sk-usbhid.c +SRCS+=ssh-ed25519-sk.c sk-usbhid.c ssh-pkcs11-client.c SRCS+=digest-openssl.c #SRCS+=digest-libc.c @@ -22,6 +22,6 @@ SRCS+=utf8.c REGRESS_TARGETS=run-regress-${PROG} run-regress-${PROG}: ${PROG} - env ${TEST_ENV} ./${PROG} -d ${.CURDIR}/testdata + env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} -d ${.CURDIR}/testdata .include diff --git a/regress/unittests/authopt/tests.c b/regress/unittests/authopt/tests.c index d9e190305e76..a81dffbf7ba3 100644 --- a/regress/unittests/authopt/tests.c +++ b/regress/unittests/authopt/tests.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tests.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ +/* $OpenBSD: tests.c,v 1.4 2025/04/15 04:00:42 djm Exp $ */ /* * Regress test for keys options functions. @@ -10,9 +10,7 @@ #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include @@ -576,3 +574,9 @@ tests(void) test_cert_parse(); test_merge(); } + +void +benchmarks(void) +{ + printf("no benchmarks\n"); +} diff --git a/regress/unittests/bitmap/Makefile b/regress/unittests/bitmap/Makefile index fe30acc77394..c38cc7918cc1 100644 --- a/regress/unittests/bitmap/Makefile +++ b/regress/unittests/bitmap/Makefile @@ -1,14 +1,15 @@ -# $OpenBSD: Makefile,v 1.4 2017/12/21 00:41:22 djm Exp $ +# $OpenBSD: Makefile,v 1.5 2025/04/15 04:00:42 djm Exp $ PROG=test_bitmap SRCS=tests.c # From usr.sbin/ssh -SRCS+=bitmap.c atomicio.c +SRCS+=bitmap.c atomicio.c misc.c xmalloc.c fatal.c log.c cleanup.c match.c +SRCS+=sshbuf.c sshbuf-getput-basic.c sshbuf-misc.c ssherr.c addr.c addrmatch.c REGRESS_TARGETS=run-regress-${PROG} run-regress-${PROG}: ${PROG} - env ${TEST_ENV} ./${PROG} + env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} .include diff --git a/regress/unittests/bitmap/tests.c b/regress/unittests/bitmap/tests.c index 576b863f4066..6470f983d447 100644 --- a/regress/unittests/bitmap/tests.c +++ b/regress/unittests/bitmap/tests.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tests.c,v 1.2 2021/12/14 21:25:27 deraadt Exp $ */ +/* $OpenBSD: tests.c,v 1.3 2025/04/15 04:00:42 djm Exp $ */ /* * Regress test for bitmap.h bitmap API * @@ -9,9 +9,7 @@ #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include @@ -23,7 +21,7 @@ #include "bitmap.h" -#define NTESTS 131 +#define DEFAULT_NTESTS 131 void tests(void) @@ -32,10 +30,15 @@ tests(void) struct bitmap *b; BIGNUM *bn; size_t len; - int i, j, k, n; + int i, j, k, n, ntests = DEFAULT_NTESTS; u_char bbuf[1024], bnbuf[1024]; int r; + if (test_is_fast()) + ntests /= 4; + else if (test_is_slow()) + ntests *= 2; + TEST_START("bitmap_new"); b = bitmap_new(); ASSERT_PTR_NE(b, NULL); @@ -44,9 +47,9 @@ tests(void) TEST_DONE(); TEST_START("bitmap_set_bit / bitmap_test_bit"); - for (i = -1; i < NTESTS; i++) { - for (j = -1; j < NTESTS; j++) { - for (k = -1; k < NTESTS; k++) { + for (i = -1; i < ntests; i++) { + for (j = -1; j < ntests; j++) { + for (k = -1; k < ntests; k++) { bitmap_zero(b); BN_clear(bn); @@ -67,7 +70,7 @@ tests(void) /* Check perfect match between bitmap and bn */ test_subtest_info("match %d/%d/%d", i, j, k); - for (n = 0; n < NTESTS; n++) { + for (n = 0; n < ntests; n++) { ASSERT_INT_EQ(BN_is_bit_set(bn, n), bitmap_test_bit(b, n)); } @@ -99,7 +102,7 @@ tests(void) bitmap_zero(b); ASSERT_INT_EQ(bitmap_from_string(b, bnbuf, len), 0); - for (n = 0; n < NTESTS; n++) { + for (n = 0; n < ntests; n++) { ASSERT_INT_EQ(BN_is_bit_set(bn, n), bitmap_test_bit(b, n)); } @@ -107,7 +110,7 @@ tests(void) /* Test clearing bits */ test_subtest_info("clear %d/%d/%d", i, j, k); - for (n = 0; n < NTESTS; n++) { + for (n = 0; n < ntests; n++) { ASSERT_INT_EQ(bitmap_set_bit(b, n), 0); ASSERT_INT_EQ(BN_set_bit(bn, n), 1); } @@ -123,7 +126,7 @@ tests(void) bitmap_clear_bit(b, k); BN_clear_bit(bn, k); } - for (n = 0; n < NTESTS; n++) { + for (n = 0; n < ntests; n++) { ASSERT_INT_EQ(BN_is_bit_set(bn, n), bitmap_test_bit(b, n)); } @@ -135,4 +138,9 @@ tests(void) TEST_DONE(); #endif } +void +benchmarks(void) +{ + printf("no benchmarks\n"); +} diff --git a/regress/unittests/conversion/Makefile b/regress/unittests/conversion/Makefile index 5793c4934845..f9f5859ac5e8 100644 --- a/regress/unittests/conversion/Makefile +++ b/regress/unittests/conversion/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.4 2021/01/09 12:24:30 dtucker Exp $ +# $OpenBSD: Makefile,v 1.5 2025/04/15 04:00:42 djm Exp $ PROG=test_conversion SRCS=tests.c @@ -11,6 +11,6 @@ SRCS+=match.c addr.c addrmatch.c REGRESS_TARGETS=run-regress-${PROG} run-regress-${PROG}: ${PROG} - env ${TEST_ENV} ./${PROG} + env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} .include diff --git a/regress/unittests/conversion/tests.c b/regress/unittests/conversion/tests.c index 5b526f7afa07..fce4d1ca7001 100644 --- a/regress/unittests/conversion/tests.c +++ b/regress/unittests/conversion/tests.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tests.c,v 1.4 2021/12/14 21:25:27 deraadt Exp $ */ +/* $OpenBSD: tests.c,v 1.5 2025/04/15 04:00:42 djm Exp $ */ /* * Regress test for conversions * @@ -9,9 +9,7 @@ #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include @@ -50,3 +48,9 @@ tests(void) ASSERT_INT_EQ(convtime("1000000000000000000000w"), -1); TEST_DONE(); } + +void +benchmarks(void) +{ + printf("no benchmarks\n"); +} diff --git a/regress/unittests/hostkeys/Makefile b/regress/unittests/hostkeys/Makefile index 04d93359acaa..76c8e67f8aa1 100644 --- a/regress/unittests/hostkeys/Makefile +++ b/regress/unittests/hostkeys/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.10 2023/01/15 23:35:10 djm Exp $ +# $OpenBSD: Makefile,v 1.13 2025/07/24 06:04:47 djm Exp $ PROG=test_hostkeys SRCS=tests.c test_iterate.c @@ -6,12 +6,12 @@ SRCS=tests.c test_iterate.c # From usr.bin/ssh SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c -SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c +SRCS+=ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c SRCS+=addr.c addrmatch.c bitmap.c hostfile.c SRCS+=ed25519.c hash.c SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c -SRCS+=ssh-ed25519-sk.c sk-usbhid.c +SRCS+=ssh-ed25519-sk.c sk-usbhid.c ssh-pkcs11-client.c SRCS+=digest-openssl.c #SRCS+=digest-libc.c @@ -20,6 +20,6 @@ SRCS+=utf8.c REGRESS_TARGETS=run-regress-${PROG} run-regress-${PROG}: ${PROG} - env ${TEST_ENV} ./${PROG} -d ${.CURDIR}/testdata + env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} -d ${.CURDIR}/testdata .include diff --git a/regress/unittests/hostkeys/mktestdata.sh b/regress/unittests/hostkeys/mktestdata.sh index 5a46de990dca..5fec5829853a 100644 --- a/regress/unittests/hostkeys/mktestdata.sh +++ b/regress/unittests/hostkeys/mktestdata.sh @@ -1,11 +1,11 @@ #!/bin/sh -# $OpenBSD: mktestdata.sh,v 1.2 2017/04/30 23:33:48 djm Exp $ +# $OpenBSD: mktestdata.sh,v 1.3 2025/05/06 06:05:48 djm Exp $ set -ex cd testdata -rm -f rsa* dsa* ecdsa* ed25519* +rm -f rsa* ecdsa* ed25519* rm -f known_hosts* gen_all() { @@ -14,11 +14,10 @@ gen_all() { test "x$_n" = "x1" && _ecdsa_bits=384 test "x$_n" = "x2" && _ecdsa_bits=521 ssh-keygen -qt rsa -b 1024 -C "RSA #$_n" -N "" -f rsa_$_n - ssh-keygen -qt dsa -b 1024 -C "DSA #$_n" -N "" -f dsa_$_n ssh-keygen -qt ecdsa -b $_ecdsa_bits -C "ECDSA #$_n" -N "" -f ecdsa_$_n ssh-keygen -qt ed25519 -C "ED25519 #$_n" -N "" -f ed25519_$_n # Don't need private keys - rm -f rsa_$_n dsa_$_n ecdsa_$_n ed25519_$_n + rm -f rsa_$_n ecdsa_$_n ed25519_$_n } hentries() { @@ -65,18 +64,18 @@ rm -f known_hosts_hash_frag.old echo "# Revoked and CA keys" printf "@revoked sisyphus.example.com " ; cat ed25519_4.pub printf "@cert-authority prometheus.example.com " ; cat ecdsa_4.pub - printf "@cert-authority *.example.com " ; cat dsa_4.pub + printf "@cert-authority *.example.com " ; cat rsa_4.pub printf "\n" echo "# Some invalid lines" # Invalid marker - printf "@what sisyphus.example.com " ; cat dsa_1.pub + printf "@what sisyphus.example.com " ; cat rsa_1.pub # Key missing echo "sisyphus.example.com " # Key blob missing echo "prometheus.example.com ssh-ed25519 " # Key blob truncated - echo "sisyphus.example.com ssh-dsa AAAATgAAAAdz" + echo "sisyphus.example.com ssh-rsa AAAATgAAAAdz" # Invalid type echo "sisyphus.example.com ssh-XXX AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg==" # Type mismatch with blob diff --git a/regress/unittests/hostkeys/test_iterate.c b/regress/unittests/hostkeys/test_iterate.c index 7efb8e1b9cc6..65d6d1f43557 100644 --- a/regress/unittests/hostkeys/test_iterate.c +++ b/regress/unittests/hostkeys/test_iterate.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_iterate.c,v 1.9 2024/01/11 01:45:58 djm Exp $ */ +/* $OpenBSD: test_iterate.c,v 1.10 2025/05/06 06:05:48 djm Exp $ */ /* * Regress test for hostfile.h hostkeys_foreach() * @@ -9,9 +9,7 @@ #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include @@ -94,15 +92,8 @@ check(struct hostkey_foreach_line *l, void *_ctx) expected->no_parse_keytype == KEY_ECDSA) skip = 1; #endif /* OPENSSL_HAS_ECC */ -#ifndef WITH_DSA - if (expected->l.keytype == KEY_DSA || - expected->no_parse_keytype == KEY_DSA) - skip = 1; -#endif #ifndef WITH_OPENSSL - if (expected->l.keytype == KEY_DSA || - expected->no_parse_keytype == KEY_DSA || - expected->l.keytype == KEY_RSA || + if (expected->l.keytype == KEY_RSA || expected->no_parse_keytype == KEY_RSA || expected->l.keytype == KEY_ECDSA || expected->no_parse_keytype == KEY_ECDSA) @@ -160,14 +151,9 @@ prepare_expected(struct expected *expected, size_t n) if (expected[i].l.keytype == KEY_ECDSA) continue; #endif /* OPENSSL_HAS_ECC */ -#ifndef WITH_DSA - if (expected[i].l.keytype == KEY_DSA) - continue; -#endif #ifndef WITH_OPENSSL switch (expected[i].l.keytype) { case KEY_RSA: - case KEY_DSA: case KEY_ECDSA: continue; } @@ -204,23 +190,9 @@ struct expected expected_full[] = { NULL, /* comment */ 0, /* note */ } }, - { "dsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { - NULL, - 2, - HKF_STATUS_OK, - 0, - NULL, - MRK_NONE, - "sisyphus.example.com", - NULL, - KEY_DSA, - NULL, /* filled at runtime */ - "DSA #1", - 0, - } }, { "ecdsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, - 3, + 2, HKF_STATUS_OK, 0, NULL, @@ -234,7 +206,7 @@ struct expected expected_full[] = { } }, { "ed25519_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, - 4, + 3, HKF_STATUS_OK, 0, NULL, @@ -248,7 +220,7 @@ struct expected expected_full[] = { } }, { "rsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, - 5, + 4, HKF_STATUS_OK, 0, NULL, @@ -262,7 +234,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 6, + 5, HKF_STATUS_COMMENT, 0, "", @@ -276,7 +248,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 7, + 6, HKF_STATUS_COMMENT, 0, "# Plain host keys, hostnames + addresses", @@ -288,23 +260,9 @@ struct expected expected_full[] = { NULL, 0, } }, - { "dsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { - NULL, - 8, - HKF_STATUS_OK, - 0, - NULL, - MRK_NONE, - "prometheus.example.com,192.0.2.1,2001:db8::1", - NULL, - KEY_DSA, - NULL, /* filled at runtime */ - "DSA #2", - 0, - } }, { "ecdsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, - 9, + 7, HKF_STATUS_OK, 0, NULL, @@ -318,7 +276,7 @@ struct expected expected_full[] = { } }, { "ed25519_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, - 10, + 8, HKF_STATUS_OK, 0, NULL, @@ -332,7 +290,7 @@ struct expected expected_full[] = { } }, { "rsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, - 11, + 9, HKF_STATUS_OK, 0, NULL, @@ -346,7 +304,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 12, + 10, HKF_STATUS_COMMENT, 0, "", @@ -360,7 +318,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 13, + 11, HKF_STATUS_COMMENT, 0, "# Some hosts with wildcard names / IPs", @@ -372,23 +330,9 @@ struct expected expected_full[] = { NULL, 0, } }, - { "dsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { - NULL, - 14, - HKF_STATUS_OK, - 0, - NULL, - MRK_NONE, - "*.example.com,192.0.2.*,2001:*", - NULL, - KEY_DSA, - NULL, /* filled at runtime */ - "DSA #3", - 0, - } }, { "ecdsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, - 15, + 12, HKF_STATUS_OK, 0, NULL, @@ -402,7 +346,7 @@ struct expected expected_full[] = { } }, { "ed25519_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, - 16, + 13, HKF_STATUS_OK, 0, NULL, @@ -416,7 +360,7 @@ struct expected expected_full[] = { } }, { "rsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, { NULL, - 17, + 14, HKF_STATUS_OK, 0, NULL, @@ -430,7 +374,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 18, + 15, HKF_STATUS_COMMENT, 0, "", @@ -444,7 +388,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 19, + 16, HKF_STATUS_COMMENT, 0, "# Hashed hostname and address entries", @@ -456,23 +400,9 @@ struct expected expected_full[] = { NULL, 0, } }, - { "dsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { - NULL, - 20, - HKF_STATUS_OK, - 0, - NULL, - MRK_NONE, - NULL, - NULL, - KEY_DSA, - NULL, /* filled at runtime */ - "DSA #5", - 0, - } }, { "ecdsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { NULL, - 21, + 17, HKF_STATUS_OK, 0, NULL, @@ -486,7 +416,7 @@ struct expected expected_full[] = { } }, { "ed25519_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { NULL, - 22, + 18, HKF_STATUS_OK, 0, NULL, @@ -500,7 +430,7 @@ struct expected expected_full[] = { } }, { "rsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, { NULL, - 23, + 19, HKF_STATUS_OK, 0, NULL, @@ -514,7 +444,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 24, + 20, HKF_STATUS_COMMENT, 0, "", @@ -531,51 +461,9 @@ struct expected expected_full[] = { * hostname and addresses in the pre-hashed known_hosts are split * to separate lines. */ - { "dsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { - NULL, - 25, - HKF_STATUS_OK, - 0, - NULL, - MRK_NONE, - NULL, - NULL, - KEY_DSA, - NULL, /* filled at runtime */ - "DSA #6", - 0, - } }, - { "dsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { - NULL, - 26, - HKF_STATUS_OK, - 0, - NULL, - MRK_NONE, - NULL, - NULL, - KEY_DSA, - NULL, /* filled at runtime */ - "DSA #6", - 0, - } }, - { "dsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { - NULL, - 27, - HKF_STATUS_OK, - 0, - NULL, - MRK_NONE, - NULL, - NULL, - KEY_DSA, - NULL, /* filled at runtime */ - "DSA #6", - 0, - } }, { "ecdsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { NULL, - 28, + 21, HKF_STATUS_OK, 0, NULL, @@ -589,7 +477,7 @@ struct expected expected_full[] = { } }, { "ecdsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { NULL, - 29, + 22, HKF_STATUS_OK, 0, NULL, @@ -603,7 +491,7 @@ struct expected expected_full[] = { } }, { "ecdsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { NULL, - 30, + 23, HKF_STATUS_OK, 0, NULL, @@ -617,7 +505,7 @@ struct expected expected_full[] = { } }, { "ed25519_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { NULL, - 31, + 24, HKF_STATUS_OK, 0, NULL, @@ -631,7 +519,7 @@ struct expected expected_full[] = { } }, { "ed25519_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { NULL, - 32, + 25, HKF_STATUS_OK, 0, NULL, @@ -645,7 +533,7 @@ struct expected expected_full[] = { } }, { "ed25519_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { NULL, - 33, + 26, HKF_STATUS_OK, 0, NULL, @@ -659,7 +547,7 @@ struct expected expected_full[] = { } }, { "rsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, { NULL, - 34, + 27, HKF_STATUS_OK, 0, NULL, @@ -673,7 +561,7 @@ struct expected expected_full[] = { } }, { "rsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, { NULL, - 35, + 28, HKF_STATUS_OK, 0, NULL, @@ -687,7 +575,7 @@ struct expected expected_full[] = { } }, { "rsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, { NULL, - 36, + 29, HKF_STATUS_OK, 0, NULL, @@ -701,7 +589,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 37, + 30, HKF_STATUS_COMMENT, 0, "", @@ -715,7 +603,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 38, + 31, HKF_STATUS_COMMENT, 0, "", @@ -729,7 +617,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 39, + 32, HKF_STATUS_COMMENT, 0, "# Revoked and CA keys", @@ -743,7 +631,7 @@ struct expected expected_full[] = { } }, { "ed25519_4.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, - 40, + 33, HKF_STATUS_OK, 0, NULL, @@ -757,7 +645,7 @@ struct expected expected_full[] = { } }, { "ecdsa_4.pub" , -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, { NULL, - 41, + 34, HKF_STATUS_OK, 0, NULL, @@ -769,23 +657,9 @@ struct expected expected_full[] = { "ECDSA #4", 0, } }, - { "dsa_4.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, 0, 0, -1, { - NULL, - 42, - HKF_STATUS_OK, - 0, - NULL, - MRK_CA, - "*.example.com", - NULL, - KEY_DSA, - NULL, /* filled at runtime */ - "DSA #4", - 0, - } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 43, + 35, HKF_STATUS_COMMENT, 0, "", @@ -799,7 +673,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 44, + 36, HKF_STATUS_COMMENT, 0, "# Some invalid lines", @@ -813,7 +687,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, 0, 0, 0, -1, { NULL, - 45, + 37, HKF_STATUS_INVALID, 0, NULL, @@ -827,7 +701,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, - 46, + 38, HKF_STATUS_INVALID, 0, NULL, @@ -841,7 +715,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, { NULL, - 47, + 39, HKF_STATUS_INVALID, 0, NULL, @@ -853,9 +727,9 @@ struct expected expected_full[] = { NULL, 0, } }, - { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { + { NULL, HKF_STATUS_OK, KEY_ED25519, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, - 48, + 40, HKF_STATUS_INVALID, /* Would be ok if key not parsed */ 0, NULL, @@ -869,7 +743,7 @@ struct expected expected_full[] = { } }, { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, { NULL, - 49, + 41, HKF_STATUS_INVALID, 0, NULL, @@ -883,7 +757,7 @@ struct expected expected_full[] = { } }, { NULL, HKF_STATUS_OK, KEY_RSA, HKF_MATCH_HOST, 0, 0, 0, -1, { NULL, - 50, + 42, HKF_STATUS_INVALID, /* Would be ok if key not parsed */ 0, NULL, diff --git a/regress/unittests/hostkeys/testdata/dsa_1.pub b/regress/unittests/hostkeys/testdata/dsa_1.pub deleted file mode 100644 index 56e1e3714625..000000000000 --- a/regress/unittests/hostkeys/testdata/dsa_1.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1 diff --git a/regress/unittests/hostkeys/testdata/dsa_2.pub b/regress/unittests/hostkeys/testdata/dsa_2.pub deleted file mode 100644 index 394e0bf00255..000000000000 --- a/regress/unittests/hostkeys/testdata/dsa_2.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBAI38Hy/61/O5Bp6yUG8J5XQCeNjRS0xvjlCdzKLyXCueMa+L+X2L/u9PWUsy5SVbTjGgpB8sF6UkCNsV+va7S8zCCHas2MZ7GPlxP6GZBkRPTIFR0N/Pu7wfBzDQz0t0iL4VmxBfTBQv/SxkGWZg+yHihIQP9fwdSAwD/7aVh6ItAAAAFQDSyihIUlINlswM0PJ8wXSti3yIMwAAAIB+oqzaB6ozqs8YxpN5oQOBa/9HEBQEsp8RSIlQmVubXRNgktp42n+Ii1waU9UUk8DX5ahhIeR6B7ojWkqmDAji4SKpoHf4kmr6HvYo85ZSTSx0W4YK/gJHSpDJwhlT52tAfb1JCbWSObjl09B4STv7KedCHcR5oXQvvrV+XoKOSAAAAIAue/EXrs2INw1RfaKNHC0oqOMxmRitv0BFMuNVPo1VDj39CE5kA7AHjwvS1TNeaHtK5Hhgeb6vsmLmNPTOc8xCob0ilyQbt9O0GbONeF2Ge7D2UJyULA/hxql+tCYFIC6yUrmo35fF9XiNisXLoaflk9fjp7ROWWVwnki/jstaQw== DSA #2 diff --git a/regress/unittests/hostkeys/testdata/dsa_3.pub b/regress/unittests/hostkeys/testdata/dsa_3.pub deleted file mode 100644 index e506ea42253a..000000000000 --- a/regress/unittests/hostkeys/testdata/dsa_3.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBAI6lz2Ip9bzE7TGuDD4SjO9S4Ac90gq0h6ai1O06eI8t/Ot2uJ5Jk2QyVr2jvIZHDl/5bwBx7+5oyjlwRoUrAPPD814wf5tU2tSnmdu1Wbf0cBswif5q0r4tevzmopp/AtgH11QHo3u0/pfyJd10qBDLV2FaYSKMmZvyPfZJ0s9pAAAAFQD5Eqjl6Rx2qVePodD9OwAPT0bU6wAAAIAfnDm6csZF0sFaJR3NIJvaYgSGr8s7cqlsk2gLltB/1wOOO2yX+NeEC+B0H93hlMfaUsPa08bwgmYxnavSMqEBpmtPceefJiEd68zwYqXd38f88wyWZ9Z5iwaI/6OVZPHzCbDxOa4ewVTevRNYUKP1xUTZNT8/gSMfZLYPk4T2AQAAAIAUKroozRMyV+3V/rxt0gFnNxRXBKk+9cl3vgsQ7ktkI9cYg7V1T2K0XF21AVMK9gODszy6PBJjV6ruXBV6TRiqIbQauivp3bHHKYsG6wiJNqwdbVwIjfvv8nn1qFoZQLXG3sdONr9NwN8KzrX89OV0BlR2dVM5qqp+YxOXymP9yg== DSA #3 diff --git a/regress/unittests/hostkeys/testdata/dsa_4.pub b/regress/unittests/hostkeys/testdata/dsa_4.pub deleted file mode 100644 index 8552c3819287..000000000000 --- a/regress/unittests/hostkeys/testdata/dsa_4.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBAKvjnFHm0VvMr5h2Zu3nURsxQKGoxm+DCzYDxRYcilK07Cm5c4XTrFbA2X86+9sGs++W7QRMcTJUYIg0a+UtIMtAjwORd6ZPXM2K5dBW+gh1oHyvKi767tWX7I2c+1ZPJDY95mUUfZQUEfdy9eGDSBmw/pSsveQ1ur6XNUh/MtP/AAAAFQDHnXk/9jBJAdce1pHtLWnbdPSGdQAAAIEAm2OLy8tZBfiEO3c3X1yyB/GTcDwrQCqRMDkhnsmrliec3dWkOfNTzu+MrdvF8ymTWLEqPpbMheYtvNyZ3TF0HO5W7aVBpdGZbOdOAIfB+6skqGbI8A5Up1d7dak/bSsqL2r5NjwbDOdq+1hBzzvbl/qjh+sQarV2zHrpKoQaV28AAACANtkBVedBbqIAdphCrN/LbUi9WlyuF9UZz+tlpVLYrj8GJVwnplV2tvOmUw6yP5/pzCimTsao8dpL5PWxm7fKxLWVxA+lEsA4WeC885CiZn8xhdaJOCN+NyJ2bqkz+4VPI7oDGBm0aFwUqJn+M1PiSgvI50XdF2dBsFRTRNY0wzA= DSA #4 diff --git a/regress/unittests/hostkeys/testdata/dsa_5.pub b/regress/unittests/hostkeys/testdata/dsa_5.pub deleted file mode 100644 index 149e1efd166b..000000000000 --- a/regress/unittests/hostkeys/testdata/dsa_5.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBALrFy7w5ihlaOG+qR+6fj+vm5EQaO3qwxgACLcgH+VfShuOG4mkx8qFJmf+OZ3fh5iKngjNZfKtfcqI7zHWdk6378TQfQC52/kbZukjNXOLCpyNkogahcjA00onIoTK1RUDuMW28edAHwPFbpttXDTaqis+8JPMY8hZwsZGENCzTAAAAFQD6+It5vozwGgaN9ROYPMlByhi6jwAAAIBz2mcAC694vNzz9b6614gkX9d9E99PzJYfU1MPkXDziKg7MrjBw7Opd5y1jL09S3iL6lSTlHkKwVKvQ3pOwWRwXXRrKVus4I0STveoApm526jmp6mY0YEtqR98vMJ0v97h1ydt8FikKlihefCsnXVicb8887PXs2Y8C6GuFT3tfQAAAIBbmHtV5tPcrMRDkULhaQ/Whap2VKvT2DUhIHA7lx6oy/KpkltOpxDZOIGUHKqffGbiR7Jh01/y090AY5L2eCf0S2Ytx93+eADwVVpJbFJo6zSwfeey2Gm6L2oA+rCz9zTdmtZoekpD3/RAOQjnJIAPwbs7mXwabZTw4xRtiYIRrw== DSA #5 diff --git a/regress/unittests/hostkeys/testdata/dsa_6.pub b/regress/unittests/hostkeys/testdata/dsa_6.pub deleted file mode 100644 index edbb97643d26..000000000000 --- a/regress/unittests/hostkeys/testdata/dsa_6.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 diff --git a/regress/unittests/hostkeys/testdata/known_hosts b/regress/unittests/hostkeys/testdata/known_hosts index 4446f45dffe8..5298e3eebb3d 100644 --- a/regress/unittests/hostkeys/testdata/known_hosts +++ b/regress/unittests/hostkeys/testdata/known_hosts @@ -1,30 +1,23 @@ # Plain host keys, plain host names -sisyphus.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1 sisyphus.example.com ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF6yQEtD9yBw9gmDRf477WBBzvWhAa0ioBI3nbA4emKykj0RbuQd5C4XdQAEOZGzE7v//FcCjwB2wi+JH5eKkxCtN6CjohDASZ1huoIV2UVyYIicZJEEOg1IWjjphvaxtw== ECDSA #1 sisyphus.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9ks7jkua5YWIwByRnnnc6UPJQWI75O0e/UJdPYU1JI ED25519 #1 sisyphus.example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDg4hB4vAZHJ0PVRiJajOv/GlytFWNpv5/9xgB9+5BIbvp8LOrFZ5D9K0Gsmwpd4G4rfaAz8j896DhMArg0vtkilIPPGt/6VzWMERgvaIQPJ/IE99X3+fjcAG56oAWwy29JX10lQMzBPU6XJIaN/zqpkb6qUBiAHBdLpxrFBBU0/w== RSA #1 # Plain host keys, hostnames + addresses -prometheus.example.com,192.0.2.1,2001:db8::1 ssh-dss AAAAB3NzaC1kc3MAAACBAI38Hy/61/O5Bp6yUG8J5XQCeNjRS0xvjlCdzKLyXCueMa+L+X2L/u9PWUsy5SVbTjGgpB8sF6UkCNsV+va7S8zCCHas2MZ7GPlxP6GZBkRPTIFR0N/Pu7wfBzDQz0t0iL4VmxBfTBQv/SxkGWZg+yHihIQP9fwdSAwD/7aVh6ItAAAAFQDSyihIUlINlswM0PJ8wXSti3yIMwAAAIB+oqzaB6ozqs8YxpN5oQOBa/9HEBQEsp8RSIlQmVubXRNgktp42n+Ii1waU9UUk8DX5ahhIeR6B7ojWkqmDAji4SKpoHf4kmr6HvYo85ZSTSx0W4YK/gJHSpDJwhlT52tAfb1JCbWSObjl09B4STv7KedCHcR5oXQvvrV+XoKOSAAAAIAue/EXrs2INw1RfaKNHC0oqOMxmRitv0BFMuNVPo1VDj39CE5kA7AHjwvS1TNeaHtK5Hhgeb6vsmLmNPTOc8xCob0ilyQbt9O0GbONeF2Ge7D2UJyULA/hxql+tCYFIC6yUrmo35fF9XiNisXLoaflk9fjp7ROWWVwnki/jstaQw== DSA #2 prometheus.example.com,192.0.2.1,2001:db8::1 ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAB8qVcXwgBM92NCmReQlPrZAoui4Bz/mW0VUBFOpHXXW1n+15b/Y7Pc6UBd/ITTZmaBciXY+PWaSBGdwc5GdqGdLgFyJ/QAGrFMPNpVutm/82gNQzlxpNwjbMcKyiZEXzSgnjS6DzMQ0WuSMdzIBXq8OW/Kafxg4ZkU6YqALUXxlQMZuQ== ECDSA #2 prometheus.example.com,192.0.2.1,2001:db8::1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBp6PVW0z2o9C4Ukv/JOgmK7QMFe1pD1s3ADFF7IQob ED25519 #2 prometheus.example.com,192.0.2.1,2001:db8::1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDmbUhNabB5AmBDX6GNHZ3lbn7pRxqfpW+f53QqNGlK0sLV+0gkMIrOfUp1kdE2ZLE6tfzdicatj/RlH6/wuo4yyYb+Pyx3G0vxdmAIiA4aANq38XweDucBC0TZkRWVHK+Gs5V/uV0z7N0axJvkkJujMLvST3CRiiWwlficBc6yVQ== RSA #2 # Some hosts with wildcard names / IPs -*.example.com,192.0.2.*,2001:* ssh-dss AAAAB3NzaC1kc3MAAACBAI6lz2Ip9bzE7TGuDD4SjO9S4Ac90gq0h6ai1O06eI8t/Ot2uJ5Jk2QyVr2jvIZHDl/5bwBx7+5oyjlwRoUrAPPD814wf5tU2tSnmdu1Wbf0cBswif5q0r4tevzmopp/AtgH11QHo3u0/pfyJd10qBDLV2FaYSKMmZvyPfZJ0s9pAAAAFQD5Eqjl6Rx2qVePodD9OwAPT0bU6wAAAIAfnDm6csZF0sFaJR3NIJvaYgSGr8s7cqlsk2gLltB/1wOOO2yX+NeEC+B0H93hlMfaUsPa08bwgmYxnavSMqEBpmtPceefJiEd68zwYqXd38f88wyWZ9Z5iwaI/6OVZPHzCbDxOa4ewVTevRNYUKP1xUTZNT8/gSMfZLYPk4T2AQAAAIAUKroozRMyV+3V/rxt0gFnNxRXBKk+9cl3vgsQ7ktkI9cYg7V1T2K0XF21AVMK9gODszy6PBJjV6ruXBV6TRiqIbQauivp3bHHKYsG6wiJNqwdbVwIjfvv8nn1qFoZQLXG3sdONr9NwN8KzrX89OV0BlR2dVM5qqp+YxOXymP9yg== DSA #3 *.example.com,192.0.2.*,2001:* ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIb3BhJZk+vUQPg5TQc1koIzuGqloCq7wjr9LjlhG24IBeiFHLsdWw74HDlH4DrOmlxToVYk2lTdnjARleRByjk= ECDSA #3 *.example.com,192.0.2.*,2001:* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBlYfExtYZAPqYvYdrlpGlSWhh/XNHcH3v3c2JzsVNbB ED25519 #3 *.example.com,192.0.2.*,2001:* ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDX8F93W3SH4ZSus4XUQ2cw9dqcuyUETTlKEeGv3zlknV3YCoe2Mp04naDhiuwj8sOsytrZSESzLY1ZEyzrjxE6ZFVv8NKgck/AbRjcwlRFOcx9oKUxOrXRa0IoXlTq0kyjKCJfaHBKnGitZThknCPTbVmpATkm5xx6J0WEDozfoQ== RSA #3 # Hashed hostname and address entries -|1|z3xOIdT5ue3Vuf3MzT67kaioqjw=|GZhhe5uwDOBQrC9N4cCjpbLpSn4= ssh-dss AAAAB3NzaC1kc3MAAACBALrFy7w5ihlaOG+qR+6fj+vm5EQaO3qwxgACLcgH+VfShuOG4mkx8qFJmf+OZ3fh5iKngjNZfKtfcqI7zHWdk6378TQfQC52/kbZukjNXOLCpyNkogahcjA00onIoTK1RUDuMW28edAHwPFbpttXDTaqis+8JPMY8hZwsZGENCzTAAAAFQD6+It5vozwGgaN9ROYPMlByhi6jwAAAIBz2mcAC694vNzz9b6614gkX9d9E99PzJYfU1MPkXDziKg7MrjBw7Opd5y1jL09S3iL6lSTlHkKwVKvQ3pOwWRwXXRrKVus4I0STveoApm526jmp6mY0YEtqR98vMJ0v97h1ydt8FikKlihefCsnXVicb8887PXs2Y8C6GuFT3tfQAAAIBbmHtV5tPcrMRDkULhaQ/Whap2VKvT2DUhIHA7lx6oy/KpkltOpxDZOIGUHKqffGbiR7Jh01/y090AY5L2eCf0S2Ytx93+eADwVVpJbFJo6zSwfeey2Gm6L2oA+rCz9zTdmtZoekpD3/RAOQjnJIAPwbs7mXwabZTw4xRtiYIRrw== DSA #5 |1|B7t/AYabn8zgwU47Cb4A/Nqt3eI=|arQPZyRphkzisr7w6wwikvhaOyE= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIudcagzq4QPtP1jkpje34+0POLB0jwT64hqrbCqhTH2T800KDZ0h2vwlJYa3OP3Oqru9AB5pnuHsKw7mAhUGY= ECDSA #5 |1|JR81WxEocTP5d7goIRkl8fHBbno=|l6sj6FOsoXxgEZMzn/BnOfPKN68= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINf63qSV8rD57N+digID8t28WVhd3Yf2K2UhaoG8TsWQ ED25519 #5 |1|W7x4zY6KtTZJgsopyOusJqvVPag=|QauLt7hKezBZFZi2i4Xopho7Nsk= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/C15Q4sfnk7BZff1er8bscay+5s51oD4eWArlHWMK/ZfYeeTAccTy+7B7Jv+MS4nKCpflrvJI2RQz4kS8vF0ATdBbi4jeWefStlHNg0HLhnCY7NAfDIlRdaN9lm3Pqm2vmr+CkqwcJaSpycDg8nPN9yNAuD6pv7NDuUnECezojQ== RSA #5 -|1|mxnU8luzqWLvfVi5qBm5xVIyCRM=|9Epopft7LBd80Bf6RmWPIpwa8yU= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 -|1|klvLmvh2vCpkNMDEjVvrE8SJWTg=|e/dqEEBLnbgqmwEesl4cDRu/7TM= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 -|1|wsk3ddB3UjuxEsoeNCeZjZ6NvZs=|O3O/q2Z/u7DrxoTiIq6kzCevQT0= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6 |1|B8epmkLSni+vGZDijr/EwxeR2k4=|7ct8yzNOVJhKm3ZD2w0XIT7df8E= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 |1|JojD885UhYhbCu571rgyM/5PpYU=|BJaU2aE1FebQZy3B5tzTDRWFRG0= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 |1|5t7UDHDybVrDZVQPCpwdnr6nk4k=|EqJ73W/veIL3H2x+YWHcJxI5ETA= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6 @@ -39,12 +32,11 @@ prometheus.example.com,192.0.2.1,2001:db8::1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAA # Revoked and CA keys @revoked sisyphus.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFP8L9REfN/iYy1KIRtFqSCn3V2+vOCpoZYENFGLdOF ED25519 #4 @cert-authority prometheus.example.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHZd0OXHIWwK3xnjAdMZ1tojxWycdu38pORO/UX5cqsKMgGCKQVBWWO3TFk1ePkGIE9VMWT1hCGqWRRwYlH+dSE= ECDSA #4 -@cert-authority *.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAKvjnFHm0VvMr5h2Zu3nURsxQKGoxm+DCzYDxRYcilK07Cm5c4XTrFbA2X86+9sGs++W7QRMcTJUYIg0a+UtIMtAjwORd6ZPXM2K5dBW+gh1oHyvKi767tWX7I2c+1ZPJDY95mUUfZQUEfdy9eGDSBmw/pSsveQ1ur6XNUh/MtP/AAAAFQDHnXk/9jBJAdce1pHtLWnbdPSGdQAAAIEAm2OLy8tZBfiEO3c3X1yyB/GTcDwrQCqRMDkhnsmrliec3dWkOfNTzu+MrdvF8ymTWLEqPpbMheYtvNyZ3TF0HO5W7aVBpdGZbOdOAIfB+6skqGbI8A5Up1d7dak/bSsqL2r5NjwbDOdq+1hBzzvbl/qjh+sQarV2zHrpKoQaV28AAACANtkBVedBbqIAdphCrN/LbUi9WlyuF9UZz+tlpVLYrj8GJVwnplV2tvOmUw6yP5/pzCimTsao8dpL5PWxm7fKxLWVxA+lEsA4WeC885CiZn8xhdaJOCN+NyJ2bqkz+4VPI7oDGBm0aFwUqJn+M1PiSgvI50XdF2dBsFRTRNY0wzA= DSA #4 # Some invalid lines -@what sisyphus.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1 +@what ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDg4hB4vAZHJ0PVRiJajOv/GlytFWNpv5/9xgB9+5BIbvp8LOrFZ5D9K0Gsmwpd4G4rfaAz8j896DhMArg0vtkilIPPGt/6VzWMERgvaIQPJ/IE99X3+fjcAG56oAWwy29JX10lQMzBPU6XJIaN/zqpkb6qUBiAHBdLpxrFBBU0/w== RSA #1 sisyphus.example.com prometheus.example.com ssh-ed25519 -sisyphus.example.com ssh-dsa AAAATgAAAAdz +sisyphus.example.com ssh-ed25519 AAAATgAAAAdz sisyphus.example.com ssh-XXX AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg== prometheus.example.com ssh-rsa AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg== diff --git a/regress/unittests/hostkeys/tests.c b/regress/unittests/hostkeys/tests.c index 92c7646ad164..c6e17fad09cb 100644 --- a/regress/unittests/hostkeys/tests.c +++ b/regress/unittests/hostkeys/tests.c @@ -1,10 +1,16 @@ -/* $OpenBSD: tests.c,v 1.1 2015/02/16 22:18:34 djm Exp $ */ +/* $OpenBSD: tests.c,v 1.2 2025/04/15 04:00:42 djm Exp $ */ /* * Regress test for known_hosts-related API. * * Placed in the public domain */ +#include "includes.h" + +#include + +#include "../test_helper/test_helper.h" + void tests(void); void test_iterate(void); /* test_iterate.c */ @@ -14,3 +20,8 @@ tests(void) test_iterate(); } +void +benchmarks(void) +{ + printf("no benchmarks\n"); +} diff --git a/regress/unittests/kex/Makefile b/regress/unittests/kex/Makefile index ca4f0ee38639..5201a35df5bc 100644 --- a/regress/unittests/kex/Makefile +++ b/regress/unittests/kex/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.16 2024/09/09 03:13:39 djm Exp $ +# $OpenBSD: Makefile,v 1.19 2025/07/24 06:04:47 djm Exp $ PROG=test_kex SRCS=tests.c test_kex.c test_proposal.c @@ -6,12 +6,12 @@ SRCS=tests.c test_kex.c test_proposal.c # From usr.bin/ssh SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c -SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c +SRCS+=ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c SRCS+=addr.c addrmatch.c bitmap.c packet.c dispatch.c canohost.c ssh_api.c SRCS+=compat.c ed25519.c hash.c SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c -SRCS+=ssh-ed25519-sk.c sk-usbhid.c +SRCS+=ssh-ed25519-sk.c sk-usbhid.c ssh-pkcs11-client.c SRCS+= kex.c SRCS+= kex-names.c @@ -35,7 +35,7 @@ SRCS+=digest-openssl.c REGRESS_TARGETS=run-regress-${PROG} run-regress-${PROG}: ${PROG} - env ${TEST_ENV} ./${PROG} + env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} .include diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c index caf8f57f75d6..16c2f2dff975 100644 --- a/regress/unittests/kex/test_kex.c +++ b/regress/unittests/kex/test_kex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_kex.c,v 1.9 2024/09/09 03:13:39 djm Exp $ */ +/* $OpenBSD: test_kex.c,v 1.12 2025/08/21 05:55:30 djm Exp $ */ /* * Regress test KEX * @@ -8,10 +8,9 @@ #include "includes.h" #include +#include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include @@ -76,7 +75,8 @@ run_kex(struct ssh *client, struct ssh *server) } static void -do_kex_with_key(char *kex, int keytype, int bits) +do_kex_with_key(char *kex, char *cipher, char *mac, + struct sshkey *key, int keytype, int bits) { struct ssh *client = NULL, *server = NULL, *server2 = NULL; struct sshkey *private, *public; @@ -85,9 +85,14 @@ do_kex_with_key(char *kex, int keytype, int bits) char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; char *keyname = NULL; - TEST_START("sshkey_generate"); - ASSERT_INT_EQ(sshkey_generate(keytype, bits, &private), 0); - TEST_DONE(); + if (key != NULL) { + private = key; + keytype = key->type; + } else { + TEST_START("sshkey_generate"); + ASSERT_INT_EQ(sshkey_generate(keytype, bits, &private), 0); + TEST_DONE(); + } TEST_START("sshkey_from_private"); ASSERT_INT_EQ(sshkey_from_private(private, &public), 0); @@ -97,6 +102,14 @@ do_kex_with_key(char *kex, int keytype, int bits) memcpy(kex_params.proposal, myproposal, sizeof(myproposal)); if (kex != NULL) kex_params.proposal[PROPOSAL_KEX_ALGS] = kex; + if (cipher != NULL) { + kex_params.proposal[PROPOSAL_ENC_ALGS_CTOS] = cipher; + kex_params.proposal[PROPOSAL_ENC_ALGS_STOC] = cipher; + } + if (mac != NULL) { + kex_params.proposal[PROPOSAL_MAC_ALGS_CTOS] = mac; + kex_params.proposal[PROPOSAL_MAC_ALGS_STOC] = mac; + } keyname = strdup(sshkey_ssh_name(private)); ASSERT_PTR_NE(keyname, NULL); kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname; @@ -147,6 +160,9 @@ do_kex_with_key(char *kex, int keytype, int bits) server2->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server; server2->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; server2->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; + server2->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server; + server2->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server; + server2->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server; #ifdef OPENSSL_HAS_ECC server2->kex->kex[KEX_ECDH_SHA2] = kex_gen_server; #endif /* OPENSSL_HAS_ECC */ @@ -167,7 +183,8 @@ do_kex_with_key(char *kex, int keytype, int bits) TEST_DONE(); TEST_START("cleanup"); - sshkey_free(private); + if (key == NULL) + sshkey_free(private); sshkey_free(public); ssh_free(client); ssh_free(server); @@ -179,25 +196,40 @@ do_kex_with_key(char *kex, int keytype, int bits) static void do_kex(char *kex) { -#if 0 - log_init("test_kex", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 1); -#endif + struct sshkey *key = NULL; + char name[256]; + + if (test_is_benchmark()) { + snprintf(name, sizeof(name), "generate %s", kex); + TEST_START(name); + ASSERT_INT_EQ(sshkey_generate(KEY_ED25519, 0, &key), 0); + TEST_DONE(); + snprintf(name, sizeof(name), "KEX %s", kex); + BENCH_START(name); + /* + * NB. use a cipher/MAC here that requires minimal bits from + * the KEX to avoid DH-GEX taking forever. + */ + do_kex_with_key(kex, "aes128-ctr", "hmac-sha2-256", key, + KEY_ED25519, 256); + BENCH_FINISH("kex"); + sshkey_free(key); + return; + } + #ifdef WITH_OPENSSL - do_kex_with_key(kex, KEY_RSA, 2048); -#ifdef WITH_DSA - do_kex_with_key(kex, KEY_DSA, 1024); -#endif -#ifdef OPENSSL_HAS_ECC - do_kex_with_key(kex, KEY_ECDSA, 256); -#endif /* OPENSSL_HAS_ECC */ + do_kex_with_key(kex, NULL, NULL, NULL, KEY_RSA, 2048); +# ifdef OPENSSL_HAS_ECC + do_kex_with_key(kex, NULL, NULL, NULL, KEY_ECDSA, 256); +# endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ - do_kex_with_key(kex, KEY_ED25519, 256); + do_kex_with_key(kex, NULL, NULL, NULL, KEY_ED25519, 256); } void kex_tests(void) { - do_kex("curve25519-sha256@libssh.org"); + do_kex("curve25519-sha256"); #ifdef WITH_OPENSSL #ifdef OPENSSL_HAS_ECC do_kex("ecdh-sha2-nistp256"); @@ -208,11 +240,16 @@ kex_tests(void) do_kex("diffie-hellman-group-exchange-sha1"); do_kex("diffie-hellman-group14-sha1"); do_kex("diffie-hellman-group1-sha1"); + if (test_is_benchmark()) { + do_kex("diffie-hellman-group14-sha256"); + do_kex("diffie-hellman-group16-sha512"); + do_kex("diffie-hellman-group18-sha512"); + } # ifdef USE_MLKEM768X25519 do_kex("mlkem768x25519-sha256"); # endif /* USE_MLKEM768X25519 */ # ifdef USE_SNTRUP761X25519 - do_kex("sntrup761x25519-sha512@openssh.com"); + do_kex("sntrup761x25519-sha512"); # endif /* USE_SNTRUP761X25519 */ #endif /* WITH_OPENSSL */ } diff --git a/regress/unittests/kex/test_proposal.c b/regress/unittests/kex/test_proposal.c index fa4192bb661c..01bf7e589f40 100644 --- a/regress/unittests/kex/test_proposal.c +++ b/regress/unittests/kex/test_proposal.c @@ -10,9 +10,7 @@ #include #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include diff --git a/regress/unittests/kex/tests.c b/regress/unittests/kex/tests.c index d3044f033767..a3ef19ef410a 100644 --- a/regress/unittests/kex/tests.c +++ b/regress/unittests/kex/tests.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tests.c,v 1.3 2023/03/06 12:15:47 dtucker Exp $ */ +/* $OpenBSD: tests.c,v 1.4 2025/04/15 04:00:42 djm Exp $ */ /* * Placed in the public domain */ @@ -16,3 +16,10 @@ tests(void) kex_proposal_tests(); kex_proposal_populate_tests(); } + +void +benchmarks(void) +{ + printf("\n"); + kex_tests(); +} diff --git a/regress/unittests/match/Makefile b/regress/unittests/match/Makefile index 939163d30ef5..7b17e5689344 100644 --- a/regress/unittests/match/Makefile +++ b/regress/unittests/match/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.5 2021/01/09 12:24:31 dtucker Exp $ +# $OpenBSD: Makefile,v 1.6 2025/04/15 04:00:42 djm Exp $ PROG=test_match SRCS=tests.c @@ -11,6 +11,6 @@ SRCS+=cleanup.c atomicio.c addr.c REGRESS_TARGETS=run-regress-${PROG} run-regress-${PROG}: ${PROG} - env ${TEST_ENV} ./${PROG} + env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} .include diff --git a/regress/unittests/match/tests.c b/regress/unittests/match/tests.c index f00d1f9348fc..163a3a25569d 100644 --- a/regress/unittests/match/tests.c +++ b/regress/unittests/match/tests.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tests.c,v 1.8 2021/12/14 21:25:27 deraadt Exp $ */ +/* $OpenBSD: tests.c,v 1.9 2025/04/15 04:00:42 djm Exp $ */ /* * Regress test for matching functions * @@ -9,9 +9,7 @@ #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include @@ -129,3 +127,9 @@ tests(void) * int addr_match_cidr_list(const char *, const char *); */ } + +void +benchmarks(void) +{ + printf("no benchmarks\n"); +} diff --git a/regress/unittests/misc/Makefile b/regress/unittests/misc/Makefile index d2be393ad703..77575061d456 100644 --- a/regress/unittests/misc/Makefile +++ b/regress/unittests/misc/Makefile @@ -1,7 +1,8 @@ -# $OpenBSD: Makefile,v 1.9 2023/01/06 02:59:50 djm Exp $ +# $OpenBSD: Makefile,v 1.12 2025/09/04 00:34:17 djm Exp $ PROG=test_misc SRCS=tests.c +SRCS+= test_misc.c SRCS+= test_convtime.c SRCS+= test_expand.c SRCS+= test_parse.c @@ -9,6 +10,7 @@ SRCS+= test_argv.c SRCS+= test_strdelim.c SRCS+= test_hpdelim.c SRCS+= test_ptimeout.c +SRCS+= test_xextendf.c # From usr.bin/ssh/Makefile.inc SRCS+= sshbuf.c @@ -28,6 +30,6 @@ SRCS+= atomicio.c cleanup.c fatal.c REGRESS_TARGETS=run-regress-${PROG} run-regress-${PROG}: ${PROG} - env ${TEST_ENV} ./${PROG} + env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} .include diff --git a/regress/unittests/misc/test_argv.c b/regress/unittests/misc/test_argv.c index 682863e73ba9..a20a9e78fcc4 100644 --- a/regress/unittests/misc/test_argv.c +++ b/regress/unittests/misc/test_argv.c @@ -9,9 +9,7 @@ #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include diff --git a/regress/unittests/misc/test_convtime.c b/regress/unittests/misc/test_convtime.c index 4794dbd9daae..4fdcf38127df 100644 --- a/regress/unittests/misc/test_convtime.c +++ b/regress/unittests/misc/test_convtime.c @@ -10,9 +10,7 @@ #include #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include diff --git a/regress/unittests/misc/test_expand.c b/regress/unittests/misc/test_expand.c index 6f2cd8adbedd..a8be8d9f488e 100644 --- a/regress/unittests/misc/test_expand.c +++ b/regress/unittests/misc/test_expand.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_expand.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ +/* $OpenBSD: test_expand.c,v 1.4 2025/09/15 03:00:22 djm Exp $ */ /* * Regress test for misc string expansion functions. * @@ -9,9 +9,7 @@ #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include @@ -73,17 +71,26 @@ test_expand(void) TEST_DONE(); TEST_START("percent_expand"); - ASSERT_STRING_EQ(percent_expand("%%", "%h", "foo", NULL), "%"); - ASSERT_STRING_EQ(percent_expand("%h", "h", "foo", NULL), "foo"); - ASSERT_STRING_EQ(percent_expand("%h ", "h", "foo", NULL), "foo "); - ASSERT_STRING_EQ(percent_expand(" %h", "h", "foo", NULL), " foo"); - ASSERT_STRING_EQ(percent_expand(" %h ", "h", "foo", NULL), " foo "); - ASSERT_STRING_EQ(percent_expand(" %a%b ", "a", "foo", "b", "bar", NULL), - " foobar "); +#define CHECK_ONE(val, expect) \ + ASSERT_STRING_EQ(val, expect); \ + free(val); + ret = percent_expand("%%", "%h", "foo", NULL); + CHECK_ONE(ret, "%"); + ret = percent_expand("%h", "h", "foo", NULL); + CHECK_ONE(ret, "foo"); + ret = percent_expand("%h ", "h", "foo", NULL); + CHECK_ONE(ret, "foo "); + ret = percent_expand(" %h", "h", "foo", NULL); + CHECK_ONE(ret, " foo"); + ret = percent_expand(" %h ", "h", "foo", NULL); + CHECK_ONE(ret, " foo "); + ret = percent_expand(" %a%b ", "a", "foo", "b", "bar", NULL); + CHECK_ONE(ret, " foobar "); TEST_DONE(); TEST_START("percent_dollar_expand"); - ASSERT_STRING_EQ(percent_dollar_expand("%h${FOO}", "h", "foo", NULL), - "foobar"); + ret = percent_dollar_expand("%h${FOO}", "h", "foo", NULL); + CHECK_ONE(ret, "foobar"); +#undef CHECK_ONE TEST_DONE(); } diff --git a/regress/unittests/misc/test_hpdelim.c b/regress/unittests/misc/test_hpdelim.c index d423023dc3d2..626f1856444d 100644 --- a/regress/unittests/misc/test_hpdelim.c +++ b/regress/unittests/misc/test_hpdelim.c @@ -9,9 +9,7 @@ #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include diff --git a/regress/unittests/misc/test_misc.c b/regress/unittests/misc/test_misc.c new file mode 100644 index 000000000000..d175196b7d47 --- /dev/null +++ b/regress/unittests/misc/test_misc.c @@ -0,0 +1,436 @@ +/* + * Regress test for misc helper functions. + * + * Placed in the public domain. + */ + +#include "includes.h" + +#include +#include +#include +#include +#include + +#include "../test_helper/test_helper.h" + +#include "log.h" +#include "misc.h" +#include "xmalloc.h" + +void test_misc(void); + +static void +test_chop(void) +{ + char *s; + + TEST_START("chop newline"); + s = xstrdup("hello\n"); + ASSERT_STRING_EQ(chop(s), "hello"); + free(s); + TEST_DONE(); + + TEST_START("chop carriage return"); + s = xstrdup("hello\r"); + ASSERT_STRING_EQ(chop(s), "hello"); + free(s); + TEST_DONE(); + + TEST_START("chop CRLF"); + s = xstrdup("hello\r\n"); + ASSERT_STRING_EQ(chop(s), "hello"); + free(s); + TEST_DONE(); + + TEST_START("chop newline in middle"); + s = xstrdup("he\nllo"); + ASSERT_STRING_EQ(chop(s), "he"); + free(s); + TEST_DONE(); + + TEST_START("chop no newline"); + s = xstrdup("hello"); + ASSERT_STRING_EQ(chop(s), "hello"); + free(s); + TEST_DONE(); + + TEST_START("chop empty string"); + s = xstrdup(""); + ASSERT_STRING_EQ(chop(s), ""); + free(s); + TEST_DONE(); + + TEST_START("chop only newline"); + s = xstrdup("\n"); + ASSERT_STRING_EQ(chop(s), ""); + free(s); + TEST_DONE(); + + TEST_START("chop only CR"); + s = xstrdup("\r"); + ASSERT_STRING_EQ(chop(s), ""); + free(s); + TEST_DONE(); + + TEST_START("chop only CRLF"); + s = xstrdup("\r\n"); + ASSERT_STRING_EQ(chop(s), ""); + free(s); + TEST_DONE(); +} + +static void +test_rtrim(void) +{ + char *s; + + TEST_START("rtrim trailing space"); + s = xstrdup("hello "); + rtrim(s); + ASSERT_STRING_EQ(s, "hello"); + free(s); + TEST_DONE(); + + TEST_START("rtrim trailing tab"); + s = xstrdup("hello\t\t"); + rtrim(s); + ASSERT_STRING_EQ(s, "hello"); + free(s); + TEST_DONE(); + + TEST_START("rtrim trailing mixed whitespace"); + s = xstrdup("hello \t "); + rtrim(s); + ASSERT_STRING_EQ(s, "hello"); + free(s); + TEST_DONE(); + + TEST_START("rtrim no trailing whitespace"); + s = xstrdup("hello"); + rtrim(s); + ASSERT_STRING_EQ(s, "hello"); + free(s); + TEST_DONE(); + + TEST_START("rtrim whitespace in middle"); + s = xstrdup("he llo"); + rtrim(s); + ASSERT_STRING_EQ(s, "he llo"); + free(s); + TEST_DONE(); + + TEST_START("rtrim empty string"); + s = xstrdup(""); + rtrim(s); + ASSERT_STRING_EQ(s, ""); + free(s); + TEST_DONE(); + + TEST_START("rtrim only whitespace"); + s = xstrdup(" \t"); + rtrim(s); + ASSERT_STRING_EQ(s, ""); + free(s); + TEST_DONE(); +} + +static void +test_strprefix(void) +{ + const char *s; + + TEST_START("strprefix basic match"); + s = strprefix("hello world", "hello", 0); + ASSERT_PTR_NE(s, NULL); + ASSERT_STRING_EQ(s, " world"); + TEST_DONE(); + + TEST_START("strprefix no match"); + s = strprefix("hello world", "world", 0); + ASSERT_PTR_EQ(s, NULL); + TEST_DONE(); + + TEST_START("strprefix full match"); + s = strprefix("hello", "hello", 0); + ASSERT_PTR_NE(s, NULL); + ASSERT_STRING_EQ(s, ""); + TEST_DONE(); + + TEST_START("strprefix empty string"); + s = strprefix("", "hello", 0); + ASSERT_PTR_EQ(s, NULL); + TEST_DONE(); + + TEST_START("strprefix empty prefix"); + s = strprefix("hello", "", 0); + ASSERT_PTR_NE(s, NULL); + ASSERT_STRING_EQ(s, "hello"); + TEST_DONE(); + + TEST_START("strprefix case sensitive no match"); + s = strprefix("Hello world", "hello", 0); + ASSERT_PTR_EQ(s, NULL); + TEST_DONE(); + + TEST_START("strprefix case insensitive match"); + s = strprefix("Hello world", "hello", 1); + ASSERT_PTR_NE(s, NULL); + ASSERT_STRING_EQ(s, " world"); + TEST_DONE(); + + TEST_START("strprefix case insensitive full match"); + s = strprefix("HELLO", "hello", 1); + ASSERT_PTR_NE(s, NULL); + ASSERT_STRING_EQ(s, ""); + TEST_DONE(); +} + +static void +test_fmt_timeframe(void) +{ + TEST_START("fmt_timeframe seconds"); + ASSERT_STRING_EQ(fmt_timeframe(0), "00:00:00"); + ASSERT_STRING_EQ(fmt_timeframe(59), "00:00:59"); + ASSERT_STRING_EQ(fmt_timeframe(60), "00:01:00"); + ASSERT_STRING_EQ(fmt_timeframe(3599), "00:59:59"); + ASSERT_STRING_EQ(fmt_timeframe(3600), "01:00:00"); + ASSERT_STRING_EQ(fmt_timeframe(86399), "23:59:59"); + TEST_DONE(); + + TEST_START("fmt_timeframe days"); + ASSERT_STRING_EQ(fmt_timeframe(86400), "1d00h00m"); + ASSERT_STRING_EQ(fmt_timeframe(90061), "1d01h01m"); + ASSERT_STRING_EQ(fmt_timeframe(604799), "6d23h59m"); + TEST_DONE(); + + TEST_START("fmt_timeframe weeks"); + ASSERT_STRING_EQ(fmt_timeframe(604800), "01w0d00h"); + ASSERT_STRING_EQ(fmt_timeframe(694861), "01w1d01h"); + TEST_DONE(); +} + +static void +test_arglist(void) +{ + arglist args; + u_int i; + + memset(&args, 0, sizeof(args)); + + TEST_START("addargs initial"); + addargs(&args, "one"); + ASSERT_U_INT_EQ(args.num, 1); + ASSERT_U_INT_EQ(args.nalloc, 32); + ASSERT_PTR_NE(args.list, NULL); + ASSERT_STRING_EQ(args.list[0], "one"); + ASSERT_PTR_EQ(args.list[1], NULL); + TEST_DONE(); + + TEST_START("addargs second"); + addargs(&args, "two"); + ASSERT_U_INT_EQ(args.num, 2); + ASSERT_U_INT_EQ(args.nalloc, 32); + ASSERT_PTR_NE(args.list, NULL); + ASSERT_STRING_EQ(args.list[0], "one"); + ASSERT_STRING_EQ(args.list[1], "two"); + ASSERT_PTR_EQ(args.list[2], NULL); + TEST_DONE(); + + TEST_START("addargs with format"); + addargs(&args, "three=%d", 3); + ASSERT_U_INT_EQ(args.num, 3); + ASSERT_U_INT_EQ(args.nalloc, 32); + ASSERT_PTR_NE(args.list, NULL); + ASSERT_STRING_EQ(args.list[0], "one"); + ASSERT_STRING_EQ(args.list[1], "two"); + ASSERT_STRING_EQ(args.list[2], "three=3"); + ASSERT_PTR_EQ(args.list[3], NULL); + TEST_DONE(); + + TEST_START("replacearg middle"); + replacearg(&args, 1, "TWO!"); + ASSERT_U_INT_EQ(args.num, 3); + ASSERT_STRING_EQ(args.list[0], "one"); + ASSERT_STRING_EQ(args.list[1], "TWO!"); + ASSERT_STRING_EQ(args.list[2], "three=3"); + ASSERT_PTR_EQ(args.list[3], NULL); + TEST_DONE(); + + TEST_START("replacearg first"); + replacearg(&args, 0, "ONE!"); + ASSERT_U_INT_EQ(args.num, 3); + ASSERT_STRING_EQ(args.list[0], "ONE!"); + ASSERT_STRING_EQ(args.list[1], "TWO!"); + ASSERT_STRING_EQ(args.list[2], "three=3"); + ASSERT_PTR_EQ(args.list[3], NULL); + TEST_DONE(); + + TEST_START("replacearg last"); + replacearg(&args, 2, "THREE=3!"); + ASSERT_U_INT_EQ(args.num, 3); + ASSERT_STRING_EQ(args.list[0], "ONE!"); + ASSERT_STRING_EQ(args.list[1], "TWO!"); + ASSERT_STRING_EQ(args.list[2], "THREE=3!"); + ASSERT_PTR_EQ(args.list[3], NULL); + TEST_DONE(); + + TEST_START("replacearg with format"); + replacearg(&args, 1, "two=%d", 2); + ASSERT_U_INT_EQ(args.num, 3); + ASSERT_STRING_EQ(args.list[0], "ONE!"); + ASSERT_STRING_EQ(args.list[1], "two=2"); + ASSERT_STRING_EQ(args.list[2], "THREE=3!"); + ASSERT_PTR_EQ(args.list[3], NULL); + TEST_DONE(); + + TEST_START("addargs reallocation"); + for (i = args.num; i < 33; i++) + addargs(&args, "pad-%d", i); + ASSERT_U_INT_EQ(args.num, 33); + ASSERT_U_INT_GE(args.nalloc, 33); + ASSERT_STRING_EQ(args.list[32], "pad-32"); + ASSERT_PTR_EQ(args.list[33], NULL); + TEST_DONE(); + + TEST_START("freeargs"); + freeargs(&args); + ASSERT_U_INT_EQ(args.num, 0); + ASSERT_U_INT_EQ(args.nalloc, 0); + ASSERT_PTR_EQ(args.list, NULL); + TEST_DONE(); + + TEST_START("freeargs on NULL"); + freeargs(NULL); + TEST_DONE(); + + TEST_START("freeargs on empty"); + memset(&args, 0, sizeof(args)); + freeargs(&args); + ASSERT_U_INT_EQ(args.num, 0); + ASSERT_U_INT_EQ(args.nalloc, 0); + ASSERT_PTR_EQ(args.list, NULL); + TEST_DONE(); +} + +static void +test_tohex(void) +{ + char *hex; + + TEST_START("tohex simple"); + hex = tohex("foo", 3); + ASSERT_STRING_EQ(hex, "666f6f"); + free(hex); + TEST_DONE(); + + TEST_START("tohex with null"); + hex = tohex("a\0b", 3); + ASSERT_STRING_EQ(hex, "610062"); + free(hex); + TEST_DONE(); + + TEST_START("tohex empty"); + hex = tohex("", 0); + ASSERT_STRING_EQ(hex, ""); + free(hex); + TEST_DONE(); +} + +static void +test_lowercase(void) +{ + char *s; + + TEST_START("lowercase mixed"); + s = xstrdup("HeLlO WoRlD 123"); + lowercase(s); + ASSERT_STRING_EQ(s, "hello world 123"); + free(s); + TEST_DONE(); + + TEST_START("lowercase empty"); + s = xstrdup(""); + lowercase(s); + ASSERT_STRING_EQ(s, ""); + free(s); + TEST_DONE(); +} + +static void +test_path_absolute(void) +{ + TEST_START("path_absolute absolute"); + ASSERT_INT_EQ(path_absolute("/foo/bar"), 1); + TEST_DONE(); + + TEST_START("path_absolute relative"); + ASSERT_INT_EQ(path_absolute("foo/bar"), 0); + TEST_DONE(); + + TEST_START("path_absolute empty"); + ASSERT_INT_EQ(path_absolute(""), 0); + TEST_DONE(); +} + +static void +test_skip_space(void) +{ + char *s, *p; + + TEST_START("skip_space leading spaces"); + s = p = xstrdup(" hello"); + skip_space(&p); + ASSERT_STRING_EQ(p, "hello"); + free(s); + TEST_DONE(); + + TEST_START("skip_space leading tabs"); + s = p = xstrdup("\t\thello"); + skip_space(&p); + ASSERT_STRING_EQ(p, "hello"); + free(s); + TEST_DONE(); + + TEST_START("skip_space leading mixed whitespace"); + s = p = xstrdup(" \t hello"); + skip_space(&p); + ASSERT_STRING_EQ(p, "hello"); + free(s); + TEST_DONE(); + + TEST_START("skip_space no leading whitespace"); + s = p = xstrdup("hello"); + skip_space(&p); + ASSERT_STRING_EQ(p, "hello"); + free(s); + TEST_DONE(); + + TEST_START("skip_space empty string"); + s = p = xstrdup(""); + skip_space(&p); + ASSERT_STRING_EQ(p, ""); + free(s); + TEST_DONE(); + + TEST_START("skip_space only whitespace"); + s = p = xstrdup(" \t "); + skip_space(&p); + ASSERT_STRING_EQ(p, ""); + free(s); + TEST_DONE(); +} + +void +test_misc(void) +{ + test_chop(); + test_rtrim(); + test_strprefix(); + test_fmt_timeframe(); + test_arglist(); + test_tohex(); + test_lowercase(); + test_path_absolute(); + test_skip_space(); +} diff --git a/regress/unittests/misc/test_parse.c b/regress/unittests/misc/test_parse.c index 1f1ea31d149c..cbffbe0fdb9f 100644 --- a/regress/unittests/misc/test_parse.c +++ b/regress/unittests/misc/test_parse.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_parse.c,v 1.2 2021/12/14 21:25:27 deraadt Exp $ */ +/* $OpenBSD: test_parse.c,v 1.3 2025/06/12 10:09:39 dtucker Exp $ */ /* * Regress test for misc user/host/URI parsing functions. * @@ -9,9 +9,7 @@ #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include @@ -29,6 +27,7 @@ test_parse(void) char *user, *host, *path; TEST_START("misc_parse_user_host_path"); + user = host = path = NULL; ASSERT_INT_EQ(parse_user_host_path("someuser@some.host:some/path", &user, &host, &path), 0); ASSERT_STRING_EQ(user, "someuser"); @@ -38,6 +37,7 @@ test_parse(void) TEST_DONE(); TEST_START("misc_parse_user_ipv4_path"); + user = host = path = NULL; ASSERT_INT_EQ(parse_user_host_path("someuser@1.22.33.144:some/path", &user, &host, &path), 0); ASSERT_STRING_EQ(user, "someuser"); @@ -47,6 +47,7 @@ test_parse(void) TEST_DONE(); TEST_START("misc_parse_user_[ipv4]_path"); + user = host = path = NULL; ASSERT_INT_EQ(parse_user_host_path("someuser@[1.22.33.144]:some/path", &user, &host, &path), 0); ASSERT_STRING_EQ(user, "someuser"); @@ -56,6 +57,7 @@ test_parse(void) TEST_DONE(); TEST_START("misc_parse_user_[ipv4]_nopath"); + user = host = path = NULL; ASSERT_INT_EQ(parse_user_host_path("someuser@[1.22.33.144]:", &user, &host, &path), 0); ASSERT_STRING_EQ(user, "someuser"); @@ -65,6 +67,7 @@ test_parse(void) TEST_DONE(); TEST_START("misc_parse_user_ipv6_path"); + user = host = path = NULL; ASSERT_INT_EQ(parse_user_host_path("someuser@[::1]:some/path", &user, &host, &path), 0); ASSERT_STRING_EQ(user, "someuser"); @@ -74,6 +77,7 @@ test_parse(void) TEST_DONE(); TEST_START("misc_parse_uri"); + user = host = path = NULL; ASSERT_INT_EQ(parse_uri("ssh", "ssh://someuser@some.host:22/some/path", &user, &host, &port, &path), 0); ASSERT_STRING_EQ(user, "someuser"); diff --git a/regress/unittests/misc/test_ptimeout.c b/regress/unittests/misc/test_ptimeout.c index cc58ee8547c3..f56e88996ceb 100644 --- a/regress/unittests/misc/test_ptimeout.c +++ b/regress/unittests/misc/test_ptimeout.c @@ -9,14 +9,10 @@ #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include -#ifdef HAVE_POLL_H -# include -#endif +#include #include #include "../test_helper/test_helper.h" diff --git a/regress/unittests/misc/test_strdelim.c b/regress/unittests/misc/test_strdelim.c index f7bea4bfe8f7..ae0f71556d07 100644 --- a/regress/unittests/misc/test_strdelim.c +++ b/regress/unittests/misc/test_strdelim.c @@ -9,9 +9,7 @@ #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include diff --git a/regress/unittests/misc/test_xextendf.c b/regress/unittests/misc/test_xextendf.c new file mode 100644 index 000000000000..3c1ee8b8b65c --- /dev/null +++ b/regress/unittests/misc/test_xextendf.c @@ -0,0 +1,89 @@ +/* $OpenBSD: test_xextendf.c,v 1.1 2025/09/02 11:04:58 djm Exp $ */ +/* + * Regress test for misc xextendf() function. + * + * Placed in the public domain. + */ + +#include "includes.h" + +#include +#include +#include +#include +#include + +#include "../test_helper/test_helper.h" + +#include "log.h" +#include "misc.h" +#include "xmalloc.h" + +void test_xextendf(void); + +void +test_xextendf(void) +{ + char *s = NULL; + + TEST_START("xextendf NULL string"); + xextendf(&s, ",", "hello"); + ASSERT_STRING_EQ(s, "hello"); + free(s); + s = NULL; + TEST_DONE(); + + TEST_START("xextendf empty string"); + s = xstrdup(""); + xextendf(&s, ",", "world"); + ASSERT_STRING_EQ(s, "world"); + free(s); + s = NULL; + TEST_DONE(); + + TEST_START("xextendf append to string"); + s = xstrdup("foo"); + xextendf(&s, ",", "bar"); + ASSERT_STRING_EQ(s, "foo,bar"); + free(s); + s = NULL; + TEST_DONE(); + + TEST_START("xextendf append with NULL separator"); + s = xstrdup("foo"); + xextendf(&s, NULL, "bar"); + ASSERT_STRING_EQ(s, "foobar"); + free(s); + s = NULL; + TEST_DONE(); + + TEST_START("xextendf append with empty separator"); + s = xstrdup("foo"); + xextendf(&s, "", "bar"); + ASSERT_STRING_EQ(s, "foobar"); + free(s); + s = NULL; + TEST_DONE(); + + TEST_START("xextendf with format string"); + s = xstrdup("start"); + xextendf(&s, ":", "s=%s,d=%d", "string", 123); + ASSERT_STRING_EQ(s, "start:s=string,d=123"); + free(s); + s = NULL; + TEST_DONE(); + + TEST_START("xextendf multiple appends"); + s = NULL; + xextendf(&s, ",", "one"); + ASSERT_STRING_EQ(s, "one"); + xextendf(&s, ",", "two"); + ASSERT_STRING_EQ(s, "one,two"); + xextendf(&s, ":", "three=%d", 3); + ASSERT_STRING_EQ(s, "one,two:three=3"); + xextendf(&s, NULL, "four"); + ASSERT_STRING_EQ(s, "one,two:three=3four"); + free(s); + s = NULL; + TEST_DONE(); +} diff --git a/regress/unittests/misc/tests.c b/regress/unittests/misc/tests.c index 32699541413e..a71dde727a5b 100644 --- a/regress/unittests/misc/tests.c +++ b/regress/unittests/misc/tests.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tests.c,v 1.10 2023/01/06 02:59:50 djm Exp $ */ +/* $OpenBSD: tests.c,v 1.13 2025/09/04 00:34:17 djm Exp $ */ /* * Regress test for misc helper functions. * @@ -9,9 +9,7 @@ #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include @@ -27,6 +25,8 @@ void test_argv(void); void test_strdelim(void); void test_hpdelim(void); void test_ptimeout(void); +void test_xextendf(void); +void test_misc(void); void tests(void) @@ -38,4 +38,12 @@ tests(void) test_strdelim(); test_hpdelim(); test_ptimeout(); + test_xextendf(); + test_misc(); +} + +void +benchmarks(void) +{ + printf("no benchmarks\n"); } diff --git a/regress/unittests/sshbuf/test_sshbuf.c b/regress/unittests/sshbuf/test_sshbuf.c index e22b390fe33d..dc021ba9087b 100644 --- a/regress/unittests/sshbuf/test_sshbuf.c +++ b/regress/unittests/sshbuf/test_sshbuf.c @@ -10,9 +10,7 @@ #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include diff --git a/regress/unittests/sshbuf/test_sshbuf_fixed.c b/regress/unittests/sshbuf/test_sshbuf_fixed.c index dff77f042152..cc05025a82af 100644 --- a/regress/unittests/sshbuf/test_sshbuf_fixed.c +++ b/regress/unittests/sshbuf/test_sshbuf_fixed.c @@ -10,9 +10,7 @@ #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include diff --git a/regress/unittests/sshbuf/test_sshbuf_fuzz.c b/regress/unittests/sshbuf/test_sshbuf_fuzz.c index c0b809dcde1b..51838ee724dd 100644 --- a/regress/unittests/sshbuf/test_sshbuf_fuzz.c +++ b/regress/unittests/sshbuf/test_sshbuf_fuzz.c @@ -9,9 +9,7 @@ #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_basic.c b/regress/unittests/sshbuf/test_sshbuf_getput_basic.c index 3da413edd35c..bfe61a8773bc 100644 --- a/regress/unittests/sshbuf/test_sshbuf_getput_basic.c +++ b/regress/unittests/sshbuf/test_sshbuf_getput_basic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_sshbuf_getput_basic.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ +/* $OpenBSD: test_sshbuf_getput_basic.c,v 1.5 2025/09/15 03:00:22 djm Exp $ */ /* * Regress test for sshbuf.h buffer API * @@ -9,9 +9,7 @@ #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include @@ -576,6 +574,7 @@ sshbuf_getput_basic_tests(void) ASSERT_PTR_NE(s2, NULL); ASSERT_STRING_EQ(s2, "00000000000000000000"); sshbuf_free(p1); + free(s2); TEST_DONE(); TEST_START("sshbuf_poke_u32"); @@ -610,6 +609,7 @@ sshbuf_getput_basic_tests(void) ASSERT_PTR_NE(s2, NULL); ASSERT_STRING_EQ(s2, "00000000000000000000"); sshbuf_free(p1); + free(s2); TEST_DONE(); TEST_START("sshbuf_poke_u16"); @@ -644,6 +644,7 @@ sshbuf_getput_basic_tests(void) ASSERT_PTR_NE(s2, NULL); ASSERT_STRING_EQ(s2, "00000000000000000000"); sshbuf_free(p1); + free(s2); TEST_DONE(); TEST_START("sshbuf_poke_u8"); @@ -674,6 +675,7 @@ sshbuf_getput_basic_tests(void) ASSERT_PTR_NE(s2, NULL); ASSERT_STRING_EQ(s2, "00000000000000000000"); sshbuf_free(p1); + free(s2); TEST_DONE(); TEST_START("sshbuf_poke"); @@ -708,5 +710,6 @@ sshbuf_getput_basic_tests(void) ASSERT_PTR_NE(s2, NULL); ASSERT_STRING_EQ(s2, "00000000000000000000"); sshbuf_free(p1); + free(s2); TEST_DONE(); } diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c b/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c index e3620e97fe99..97ee853d8875 100644 --- a/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c +++ b/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_sshbuf_getput_crypto.c,v 1.3 2021/12/14 21:25:27 deraadt Exp $ */ +/* $OpenBSD: test_sshbuf_getput_crypto.c,v 1.4 2025/05/12 05:42:02 tb Exp $ */ /* * Regress test for sshbuf.h buffer API * @@ -11,9 +11,7 @@ #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include @@ -22,6 +20,7 @@ #ifdef OPENSSL_HAS_NISTP256 # include #endif +#include "openbsd-compat/openssl-compat.h" #include "../test_helper/test_helper.h" #include "ssherr.h" @@ -230,7 +229,7 @@ sshbuf_getput_crypto_tests(void) ASSERT_PTR_NE(ecp, NULL); MKBN(ec256_x, bn_x); MKBN(ec256_y, bn_y); - ASSERT_INT_EQ(EC_POINT_set_affine_coordinates_GFp( + ASSERT_INT_EQ(EC_POINT_set_affine_coordinates( EC_KEY_get0_group(eck), ecp, bn_x, bn_y, NULL), 1); ASSERT_INT_EQ(EC_KEY_set_public_key(eck, ecp), 1); BN_free(bn_x); @@ -259,7 +258,7 @@ sshbuf_getput_crypto_tests(void) bn_y = BN_new(); ASSERT_PTR_NE(bn_x, NULL); ASSERT_PTR_NE(bn_y, NULL); - ASSERT_INT_EQ(EC_POINT_get_affine_coordinates_GFp( + ASSERT_INT_EQ(EC_POINT_get_affine_coordinates( EC_KEY_get0_group(eck), EC_KEY_get0_public_key(eck), bn_x, bn_y, NULL), 1); MKBN(ec256_x, bn); diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c b/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c index 3b4895895ef1..cd712c62be29 100644 --- a/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c +++ b/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_sshbuf_getput_fuzz.c,v 1.5 2021/12/14 21:25:27 deraadt Exp $ */ +/* $OpenBSD: test_sshbuf_getput_fuzz.c,v 1.6 2025/09/25 22:17:29 dtucker Exp $ */ /* * Regress test for sshbuf.h buffer API * @@ -9,9 +9,7 @@ #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include @@ -49,22 +47,22 @@ attempt_parse_blob(u_char *blob, size_t len) p1 = sshbuf_new(); ASSERT_PTR_NE(p1, NULL); ASSERT_INT_EQ(sshbuf_put(p1, blob, len), 0); - sshbuf_get_u8(p1, &u8); - sshbuf_get_u16(p1, &u16); - sshbuf_get_u32(p1, &u32); - sshbuf_get_u64(p1, &u64); + ASSERT_INT_EQ(sshbuf_get_u8(p1, &u8), 0); + ASSERT_INT_EQ(sshbuf_get_u16(p1, &u16), 0); + ASSERT_INT_EQ(sshbuf_get_u32(p1, &u32), 0); + ASSERT_INT_EQ(sshbuf_get_u64(p1, &u64), 0); if (sshbuf_get_string(p1, &s, &l) == 0) { bzero(s, l); free(s); } #ifdef WITH_OPENSSL bn = NULL; - sshbuf_get_bignum2(p1, &bn); + ASSERT_INT_EQ(sshbuf_get_bignum2(p1, &bn), 0); BN_clear_free(bn); #if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); ASSERT_PTR_NE(eck, NULL); - sshbuf_get_eckey(p1, eck); + ASSERT_INT_EQ(sshbuf_get_eckey(p1, eck), 0); EC_KEY_free(eck); #endif /* defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) */ #endif /* WITH_OPENSSL */ diff --git a/regress/unittests/sshbuf/test_sshbuf_misc.c b/regress/unittests/sshbuf/test_sshbuf_misc.c index 249ecf235764..6b5b380d8524 100644 --- a/regress/unittests/sshbuf/test_sshbuf_misc.c +++ b/regress/unittests/sshbuf/test_sshbuf_misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_sshbuf_misc.c,v 1.5 2021/12/14 21:25:27 deraadt Exp $ */ +/* $OpenBSD: test_sshbuf_misc.c,v 1.7 2025/09/15 03:00:22 djm Exp $ */ /* * Regress test for sshbuf.h buffer API * @@ -9,9 +9,7 @@ #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include @@ -22,11 +20,11 @@ void sshbuf_misc_tests(void); -void -sshbuf_misc_tests(void) +static void +test_sshbuf_dump(void) { struct sshbuf *p1; - char tmp[512], msg[] = "imploring ping silence ping over", *p; + char tmp[512]; FILE *out; size_t sz; @@ -48,6 +46,13 @@ sshbuf_misc_tests(void) fclose(out); sshbuf_free(p1); TEST_DONE(); +} + +static void +test_sshbuf_dtob16(void) +{ + struct sshbuf *p1; + char *p; TEST_START("sshbuf_dtob16"); p1 = sshbuf_new(); @@ -59,6 +64,13 @@ sshbuf_misc_tests(void) free(p); sshbuf_free(p1); TEST_DONE(); +} + +static void +test_sshbuf_dtob64_string(void) +{ + struct sshbuf *p1; + char *p; TEST_START("sshbuf_dtob64_string len 1"); p1 = sshbuf_new(); @@ -107,6 +119,12 @@ sshbuf_misc_tests(void) free(p); sshbuf_free(p1); TEST_DONE(); +} + +static void +test_sshbuf_b64tod(void) +{ + struct sshbuf *p1; TEST_START("sshbuf_b64tod len 1"); p1 = sshbuf_new(); @@ -134,6 +152,13 @@ sshbuf_misc_tests(void) ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), 0xd00fd00f); sshbuf_free(p1); TEST_DONE(); +} + +static void +test_sshbuf_dup_string(void) +{ + struct sshbuf *p1; + char *p; TEST_START("sshbuf_dup_string"); p1 = sshbuf_new(); @@ -163,6 +188,13 @@ sshbuf_misc_tests(void) ASSERT_PTR_EQ(p, NULL); sshbuf_free(p1); TEST_DONE(); +} + +static void +test_sshbuf_cmp(void) +{ + struct sshbuf *p1; + char msg[] = "imploring ping silence ping over"; TEST_START("sshbuf_cmp"); p1 = sshbuf_from(msg, sizeof(msg) - 1); @@ -182,7 +214,16 @@ sshbuf_misc_tests(void) ASSERT_INT_EQ(sshbuf_cmp(p1, 1000, "silence", 7), SSH_ERR_MESSAGE_INCOMPLETE); ASSERT_INT_EQ(sshbuf_cmp(p1, 0, msg, sizeof(msg) - 1), 0); + sshbuf_free(p1); TEST_DONE(); +} + +static void +test_sshbuf_find(void) +{ + struct sshbuf *p1; + char msg[] = "imploring ping silence ping over"; + size_t sz; TEST_START("sshbuf_find"); p1 = sshbuf_from(msg, sizeof(msg) - 1); @@ -212,6 +253,174 @@ sshbuf_misc_tests(void) SSH_ERR_MESSAGE_INCOMPLETE); ASSERT_INT_EQ(sshbuf_find(p1, 0, msg + 1, sizeof(msg) - 2, &sz), 0); ASSERT_SIZE_T_EQ(sz, 1); + sshbuf_free(p1); + TEST_DONE(); +} + +static void +test_sshbuf_equals(void) +{ + struct sshbuf *b1, *b2; + + TEST_START("sshbuf_equals identical"); + b1 = sshbuf_new(); + b2 = sshbuf_new(); + ASSERT_PTR_NE(b1, NULL); + ASSERT_PTR_NE(b2, NULL); + ASSERT_INT_EQ(sshbuf_put(b1, "hello", 5), 0); + ASSERT_INT_EQ(sshbuf_put(b2, "hello", 5), 0); + ASSERT_INT_EQ(sshbuf_equals(b1, b2), 0); + sshbuf_free(b1); + sshbuf_free(b2); + TEST_DONE(); + + TEST_START("sshbuf_equals different content"); + b1 = sshbuf_new(); + b2 = sshbuf_new(); + ASSERT_PTR_NE(b1, NULL); + ASSERT_PTR_NE(b2, NULL); + ASSERT_INT_EQ(sshbuf_put(b1, "hello", 5), 0); + ASSERT_INT_EQ(sshbuf_put(b2, "world", 5), 0); + ASSERT_INT_EQ(sshbuf_equals(b1, b2), SSH_ERR_INVALID_FORMAT); + sshbuf_free(b1); + sshbuf_free(b2); + TEST_DONE(); + + TEST_START("sshbuf_equals different length"); + b1 = sshbuf_new(); + b2 = sshbuf_new(); + ASSERT_PTR_NE(b1, NULL); + ASSERT_PTR_NE(b2, NULL); + ASSERT_INT_EQ(sshbuf_put(b1, "hello", 5), 0); + ASSERT_INT_EQ(sshbuf_put(b2, "hell", 4), 0); + ASSERT_INT_EQ(sshbuf_equals(b1, b2), SSH_ERR_MESSAGE_INCOMPLETE); + sshbuf_free(b1); + sshbuf_free(b2); + TEST_DONE(); + + TEST_START("sshbuf_equals empty buffers"); + b1 = sshbuf_new(); + b2 = sshbuf_new(); + ASSERT_PTR_NE(b1, NULL); + ASSERT_PTR_NE(b2, NULL); + ASSERT_INT_EQ(sshbuf_equals(b1, b2), 0); + sshbuf_free(b1); + sshbuf_free(b2); + TEST_DONE(); + + TEST_START("sshbuf_equals one empty buffer"); + b1 = sshbuf_new(); + b2 = sshbuf_new(); + ASSERT_PTR_NE(b1, NULL); + ASSERT_PTR_NE(b2, NULL); + ASSERT_INT_EQ(sshbuf_put(b1, "hello", 5), 0); + ASSERT_INT_EQ(sshbuf_equals(b1, b2), SSH_ERR_MESSAGE_INCOMPLETE); + sshbuf_free(b1); + sshbuf_free(b2); + TEST_DONE(); + + TEST_START("sshbuf_equals buffer to self"); + b1 = sshbuf_new(); + ASSERT_PTR_NE(b1, NULL); + ASSERT_INT_EQ(sshbuf_put(b1, "hello", 5), 0); + ASSERT_INT_EQ(sshbuf_equals(b1, b1), 0); + sshbuf_free(b1); TEST_DONE(); } +static void +test_sshbuf_dtourlb64(void) +{ + struct sshbuf *b, *b64; + char *s; + /* From RFC4648 */ + const u_char test_vec1[] = {0x14, 0xfb, 0x9c, 0x03, 0xd9, 0x7e}; + const u_char test_vec2[] = {0xff, 0xff, 0xff}; + const u_char test_vec3[] = {0xfb}; + + TEST_START("sshbuf_dtourlb64 empty"); + b = sshbuf_new(); + b64 = sshbuf_new(); + ASSERT_PTR_NE(b, NULL); + ASSERT_PTR_NE(b64, NULL); + ASSERT_INT_EQ(sshbuf_dtourlb64(b, b64, 0), 0); + ASSERT_SIZE_T_EQ(sshbuf_len(b64), 0); + sshbuf_free(b); + sshbuf_free(b64); + TEST_DONE(); + + TEST_START("sshbuf_dtourlb64 no special chars"); + b = sshbuf_new(); + b64 = sshbuf_new(); + ASSERT_PTR_NE(b, NULL); + ASSERT_PTR_NE(b64, NULL); + ASSERT_INT_EQ(sshbuf_put(b, "hello", 5), 0); + ASSERT_INT_EQ(sshbuf_dtourlb64(b, b64, 0), 0); + s = sshbuf_dup_string(b64); + ASSERT_PTR_NE(s, NULL); + ASSERT_STRING_EQ(s, "aGVsbG8"); + free(s); + sshbuf_free(b); + sshbuf_free(b64); + TEST_DONE(); + + TEST_START("sshbuf_dtourlb64 with '+' char"); + b = sshbuf_new(); + b64 = sshbuf_new(); + ASSERT_PTR_NE(b, NULL); + ASSERT_PTR_NE(b64, NULL); + ASSERT_INT_EQ(sshbuf_put(b, test_vec1, sizeof(test_vec1)), 0); + ASSERT_INT_EQ(sshbuf_dtourlb64(b, b64, 0), 0); + s = sshbuf_dup_string(b64); + ASSERT_PTR_NE(s, NULL); + ASSERT_STRING_EQ(s, "FPucA9l-"); + free(s); + sshbuf_free(b); + sshbuf_free(b64); + TEST_DONE(); + + TEST_START("sshbuf_dtourlb64 with '/' char"); + b = sshbuf_new(); + b64 = sshbuf_new(); + ASSERT_PTR_NE(b, NULL); + ASSERT_PTR_NE(b64, NULL); + ASSERT_INT_EQ(sshbuf_put(b, test_vec2, sizeof(test_vec2)), 0); + ASSERT_INT_EQ(sshbuf_dtourlb64(b, b64, 0), 0); + s = sshbuf_dup_string(b64); + ASSERT_PTR_NE(s, NULL); + ASSERT_STRING_EQ(s, "____"); + free(s); + sshbuf_free(b); + sshbuf_free(b64); + TEST_DONE(); + + TEST_START("sshbuf_dtourlb64 with padding removed"); + b = sshbuf_new(); + b64 = sshbuf_new(); + ASSERT_PTR_NE(b, NULL); + ASSERT_PTR_NE(b64, NULL); + ASSERT_INT_EQ(sshbuf_put(b, test_vec3, sizeof(test_vec3)), 0); + ASSERT_INT_EQ(sshbuf_dtourlb64(b, b64, 0), 0); + s = sshbuf_dup_string(b64); + ASSERT_PTR_NE(s, NULL); + ASSERT_STRING_EQ(s, "-w"); + free(s); + sshbuf_free(b); + sshbuf_free(b64); + TEST_DONE(); +} + +void +sshbuf_misc_tests(void) +{ + test_sshbuf_dump(); + test_sshbuf_dtob16(); + test_sshbuf_dtob64_string(); + test_sshbuf_b64tod(); + test_sshbuf_dup_string(); + test_sshbuf_cmp(); + test_sshbuf_find(); + test_sshbuf_equals(); + test_sshbuf_dtourlb64(); +} + diff --git a/regress/unittests/sshbuf/tests.c b/regress/unittests/sshbuf/tests.c index 29916a10bc5b..95a34a8c8e97 100644 --- a/regress/unittests/sshbuf/tests.c +++ b/regress/unittests/sshbuf/tests.c @@ -1,10 +1,14 @@ -/* $OpenBSD: tests.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */ +/* $OpenBSD: tests.c,v 1.2 2025/04/15 04:00:42 djm Exp $ */ /* * Regress test for sshbuf.h buffer API * * Placed in the public domain */ +#include "includes.h" + +#include + #include "../test_helper/test_helper.h" void sshbuf_tests(void); @@ -28,3 +32,9 @@ tests(void) sshbuf_getput_fuzz_tests(); sshbuf_fixed(); } + +void +benchmarks(void) +{ + printf("no benchmarks\n"); +} diff --git a/regress/unittests/sshkey/Makefile b/regress/unittests/sshkey/Makefile index cd0f44d13d24..77d07d1b550e 100644 --- a/regress/unittests/sshkey/Makefile +++ b/regress/unittests/sshkey/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.12 2023/01/15 23:35:10 djm Exp $ +# $OpenBSD: Makefile,v 1.14 2025/07/24 06:04:47 djm Exp $ PROG=test_sshkey SRCS=tests.c test_sshkey.c test_file.c test_fuzz.c common.c @@ -6,12 +6,12 @@ SRCS=tests.c test_sshkey.c test_file.c test_fuzz.c common.c # From usr.bin/ssh SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c -SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c +SRCS+=ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c SRCS+=addr.c addrmatch.c bitmap.c SRCS+=ed25519.c hash.c SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c -SRCS+=ssh-ed25519-sk.c sk-usbhid.c +SRCS+=ssh-ed25519-sk.c sk-usbhid.c ssh-pkcs11-client.c SRCS+=digest-openssl.c #SRCS+=digest-libc.c diff --git a/regress/unittests/sshkey/common.c b/regress/unittests/sshkey/common.c index f325c2ac2025..fa68e6d5b3ff 100644 --- a/regress/unittests/sshkey/common.c +++ b/regress/unittests/sshkey/common.c @@ -1,4 +1,4 @@ -/* $OpenBSD: common.c,v 1.6 2024/08/15 00:52:23 djm Exp $ */ +/* $OpenBSD: common.c,v 1.8 2025/06/16 08:49:27 dtucker Exp $ */ /* * Helpers for key API tests * @@ -11,9 +11,7 @@ #include #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include #include @@ -21,7 +19,6 @@ #ifdef WITH_OPENSSL #include #include -#include #include #ifdef OPENSSL_HAS_NISTP256 # include @@ -54,13 +51,13 @@ load_text_file(const char *name) { struct sshbuf *ret = load_file(name); const u_char *p; + size_t len; /* Trim whitespace at EOL */ - for (p = sshbuf_ptr(ret); sshbuf_len(ret) > 0;) { - if (p[sshbuf_len(ret) - 1] == '\r' || - p[sshbuf_len(ret) - 1] == '\t' || - p[sshbuf_len(ret) - 1] == ' ' || - p[sshbuf_len(ret) - 1] == '\n') + for (p = sshbuf_ptr(ret); (len = sshbuf_len(ret)) > 0;) { + len--; + if (p[len] == '\r' || p[len] == '\t' || + p[len] == ' ' || p[len] == '\n') ASSERT_INT_EQ(sshbuf_consume_end(ret, 1), 0); else break; @@ -126,38 +123,4 @@ rsa_q(struct sshkey *k) RSA_get0_factors(EVP_PKEY_get0_RSA(k->pkey), NULL, &q); return q; } - -const BIGNUM * -dsa_g(struct sshkey *k) -{ - const BIGNUM *g = NULL; - - ASSERT_PTR_NE(k, NULL); - ASSERT_PTR_NE(k->dsa, NULL); - DSA_get0_pqg(k->dsa, NULL, NULL, &g); - return g; -} - -const BIGNUM * -dsa_pub_key(struct sshkey *k) -{ - const BIGNUM *pub_key = NULL; - - ASSERT_PTR_NE(k, NULL); - ASSERT_PTR_NE(k->dsa, NULL); - DSA_get0_key(k->dsa, &pub_key, NULL); - return pub_key; -} - -const BIGNUM * -dsa_priv_key(struct sshkey *k) -{ - const BIGNUM *priv_key = NULL; - - ASSERT_PTR_NE(k, NULL); - ASSERT_PTR_NE(k->dsa, NULL); - DSA_get0_key(k->dsa, NULL, &priv_key); - return priv_key; -} #endif /* WITH_OPENSSL */ - diff --git a/regress/unittests/sshkey/common.h b/regress/unittests/sshkey/common.h index 7a514fdc8fe6..6127116da3d4 100644 --- a/regress/unittests/sshkey/common.h +++ b/regress/unittests/sshkey/common.h @@ -1,4 +1,4 @@ -/* $OpenBSD: common.h,v 1.2 2018/09/13 09:03:20 djm Exp $ */ +/* $OpenBSD: common.h,v 1.3 2025/05/06 06:05:48 djm Exp $ */ /* * Helpers for key API tests * @@ -19,7 +19,4 @@ const BIGNUM *rsa_n(struct sshkey *k); const BIGNUM *rsa_e(struct sshkey *k); const BIGNUM *rsa_p(struct sshkey *k); const BIGNUM *rsa_q(struct sshkey *k); -const BIGNUM *dsa_g(struct sshkey *k); -const BIGNUM *dsa_pub_key(struct sshkey *k); -const BIGNUM *dsa_priv_key(struct sshkey *k); diff --git a/regress/unittests/sshkey/mktestdata.sh b/regress/unittests/sshkey/mktestdata.sh index fcd78e990e8b..97e5d79fd734 100755 --- a/regress/unittests/sshkey/mktestdata.sh +++ b/regress/unittests/sshkey/mktestdata.sh @@ -1,5 +1,5 @@ #!/bin/sh -# $OpenBSD: mktestdata.sh,v 1.11 2020/06/19 03:48:49 djm Exp $ +# $OpenBSD: mktestdata.sh,v 1.12 2025/05/06 06:05:48 djm Exp $ PW=mekmitasdigoat @@ -24,27 +24,6 @@ rsa_params() { done } -dsa_params() { - _in="$1" - _outbase="$2" - set -e - openssl dsa -noout -text -in $_in | \ - awk '/^priv:$/,/^pub:/' | \ - grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.priv - openssl dsa -noout -text -in $_in | \ - awk '/^pub:/,/^P:/' | #\ - grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.pub - openssl dsa -noout -text -in $_in | \ - awk '/^G:/,0' | \ - grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.g - for x in priv pub g ; do - echo "" >> ${_outbase}.$x - echo ============ ${_outbase}.$x - cat ${_outbase}.$x - echo ============ - done -} - ecdsa_params() { _in="$1" _outbase="$2" @@ -79,15 +58,14 @@ else exit 1 fi -rm -f rsa_1 dsa_1 ecdsa_1 ed25519_1 -rm -f rsa_2 dsa_2 ecdsa_2 ed25519_2 -rm -f rsa_n dsa_n ecdsa_n # new-format keys -rm -f rsa_1_pw dsa_1_pw ecdsa_1_pw ed25519_1_pw -rm -f rsa_n_pw dsa_n_pw ecdsa_n_pw +rm -f rsa_1 ecdsa_1 ed25519_1 +rm -f rsa_2 ecdsa_2 ed25519_2 +rm -f rsa_n ecdsa_n # new-format keys +rm -f rsa_1_pw ecdsa_1_pw ed25519_1_pw +rm -f rsa_n_pw ecdsa_n_pw rm -f pw *.pub *.bn.* *.param.* *.fp *.fp.bb ssh-keygen -t rsa -b 1024 -C "RSA test key #1" -N "" -f rsa_1 -m PEM -ssh-keygen -t dsa -b 1024 -C "DSA test key #1" -N "" -f dsa_1 -m PEM ssh-keygen -t ecdsa -b 256 -C "ECDSA test key #1" -N "" -f ecdsa_1 -m PEM ssh-keygen -t ed25519 -C "ED25519 test key #1" -N "" -f ed25519_1 ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key #1" \ @@ -97,7 +75,6 @@ ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key #1" \ ssh-keygen -t rsa -b 2048 -C "RSA test key #2" -N "" -f rsa_2 -m PEM -ssh-keygen -t dsa -b 1024 -C "DSA test key #2" -N "" -f dsa_2 -m PEM ssh-keygen -t ecdsa -b 521 -C "ECDSA test key #2" -N "" -f ecdsa_2 -m PEM ssh-keygen -t ed25519 -C "ED25519 test key #2" -N "" -f ed25519_2 ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key #2" \ @@ -106,37 +83,29 @@ ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key #2" \ -N "" -f ed25519_sk2 cp rsa_1 rsa_n -cp dsa_1 dsa_n cp ecdsa_1 ecdsa_n ssh-keygen -pf rsa_n -N "" -ssh-keygen -pf dsa_n -N "" ssh-keygen -pf ecdsa_n -N "" cp rsa_1 rsa_1_pw -cp dsa_1 dsa_1_pw cp ecdsa_1 ecdsa_1_pw cp ed25519_1 ed25519_1_pw cp ecdsa_sk1 ecdsa_sk1_pw cp ed25519_sk1 ed25519_sk1_pw cp rsa_1 rsa_n_pw -cp dsa_1 dsa_n_pw cp ecdsa_1 ecdsa_n_pw ssh-keygen -pf rsa_1_pw -m PEM -N "$PW" -ssh-keygen -pf dsa_1_pw -m PEM -N "$PW" ssh-keygen -pf ecdsa_1_pw -m PEM -N "$PW" ssh-keygen -pf ed25519_1_pw -N "$PW" ssh-keygen -pf ecdsa_sk1_pw -m PEM -N "$PW" ssh-keygen -pf ed25519_sk1_pw -N "$PW" ssh-keygen -pf rsa_n_pw -N "$PW" -ssh-keygen -pf dsa_n_pw -N "$PW" ssh-keygen -pf ecdsa_n_pw -N "$PW" rsa_params rsa_1 rsa_1.param rsa_params rsa_2 rsa_2.param -dsa_params dsa_1 dsa_1.param -dsa_params dsa_1 dsa_1.param ecdsa_params ecdsa_1 ecdsa_1.param ecdsa_params ecdsa_2 ecdsa_2.param # XXX ed25519, *sk params @@ -144,9 +113,6 @@ ecdsa_params ecdsa_2 ecdsa_2.param ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ -V 19990101:20110101 -z 1 rsa_1.pub -ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ - -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ - -V 19990101:20110101 -z 2 dsa_1.pub ssh-keygen -s rsa_2 -I hugo -n user1,user2 \ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \ -V 19990101:20110101 -z 3 ecdsa_1.pub @@ -175,8 +141,6 @@ ssh-keygen -s rsa_2 -I hugo -n user1,user2 -t rsa-sha2-512 \ ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ -V 19990101:20110101 -z 5 rsa_1.pub -ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ - -V 19990101:20110101 -z 6 dsa_1.pub ssh-keygen -s ecdsa_1 -I julius -n host1,host2 -h \ -V 19990101:20110101 -z 7 ecdsa_1.pub ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ @@ -187,33 +151,28 @@ ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \ -V 19990101:20110101 -z 8 ed25519_sk1.pub ssh-keygen -lf rsa_1 | awk '{print $2}' > rsa_1.fp -ssh-keygen -lf dsa_1 | awk '{print $2}' > dsa_1.fp ssh-keygen -lf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp ssh-keygen -lf ed25519_1 | awk '{print $2}' > ed25519_1.fp ssh-keygen -lf ecdsa_sk1 | awk '{print $2}' > ecdsa_sk1.fp ssh-keygen -lf ed25519_sk1 | awk '{print $2}' > ed25519_sk1.fp ssh-keygen -lf rsa_2 | awk '{print $2}' > rsa_2.fp -ssh-keygen -lf dsa_2 | awk '{print $2}' > dsa_2.fp ssh-keygen -lf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp ssh-keygen -lf ed25519_2 | awk '{print $2}' > ed25519_2.fp ssh-keygen -lf ecdsa_sk2 | awk '{print $2}' > ecdsa_sk2.fp ssh-keygen -lf ed25519_sk2 | awk '{print $2}' > ed25519_sk2.fp ssh-keygen -lf rsa_1-cert.pub | awk '{print $2}' > rsa_1-cert.fp -ssh-keygen -lf dsa_1-cert.pub | awk '{print $2}' > dsa_1-cert.fp ssh-keygen -lf ecdsa_1-cert.pub | awk '{print $2}' > ecdsa_1-cert.fp ssh-keygen -lf ed25519_1-cert.pub | awk '{print $2}' > ed25519_1-cert.fp ssh-keygen -lf ecdsa_sk1-cert.pub | awk '{print $2}' > ecdsa_sk1-cert.fp ssh-keygen -lf ed25519_sk1-cert.pub | awk '{print $2}' > ed25519_sk1-cert.fp ssh-keygen -Bf rsa_1 | awk '{print $2}' > rsa_1.fp.bb -ssh-keygen -Bf dsa_1 | awk '{print $2}' > dsa_1.fp.bb ssh-keygen -Bf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp.bb ssh-keygen -Bf ed25519_1 | awk '{print $2}' > ed25519_1.fp.bb ssh-keygen -Bf ecdsa_sk1 | awk '{print $2}' > ecdsa_sk1.fp.bb ssh-keygen -Bf ed25519_sk1 | awk '{print $2}' > ed25519_sk1.fp.bb ssh-keygen -Bf rsa_2 | awk '{print $2}' > rsa_2.fp.bb -ssh-keygen -Bf dsa_2 | awk '{print $2}' > dsa_2.fp.bb ssh-keygen -Bf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp.bb ssh-keygen -Bf ed25519_2 | awk '{print $2}' > ed25519_2.fp.bb ssh-keygen -Bf ecdsa_sk2 | awk '{print $2}' > ecdsa_sk2.fp.bb diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c index 25f73de79619..571cf574db36 100644 --- a/regress/unittests/sshkey/test_file.c +++ b/regress/unittests/sshkey/test_file.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_file.c,v 1.12 2024/08/15 00:52:23 djm Exp $ */ +/* $OpenBSD: test_file.c,v 1.13 2025/05/06 06:05:48 djm Exp $ */ /* * Regress test for sshkey.h key management API * @@ -11,9 +11,7 @@ #include #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include #include @@ -21,7 +19,6 @@ #ifdef WITH_OPENSSL #include #include -#include #include #ifdef OPENSSL_HAS_NISTP256 # include @@ -167,101 +164,6 @@ sshkey_file_tests(void) sshkey_free(k1); -#ifdef WITH_DSA - TEST_START("parse DSA from private"); - buf = load_file("dsa_1"); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); - sshbuf_free(buf); - ASSERT_PTR_NE(k1, NULL); - a = load_bignum("dsa_1.param.g"); - b = load_bignum("dsa_1.param.priv"); - c = load_bignum("dsa_1.param.pub"); - ASSERT_BIGNUM_EQ(dsa_g(k1), a); - ASSERT_BIGNUM_EQ(dsa_priv_key(k1), b); - ASSERT_BIGNUM_EQ(dsa_pub_key(k1), c); - BN_free(a); - BN_free(b); - BN_free(c); - TEST_DONE(); - -#ifndef WINDOWS /* TODO: test fails (atleast) on Windows as Licrypto is unable to parse legacy private key file with passphrase*/ - TEST_START("parse DSA from private w/ passphrase"); - buf = load_file("dsa_1_pw"); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, - (const char *)sshbuf_ptr(pw), &k2, NULL), 0); - sshbuf_free(buf); - ASSERT_PTR_NE(k2, NULL); - ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); - sshkey_free(k2); - TEST_DONE(); -#endif - - TEST_START("parse DSA from new-format"); - buf = load_file("dsa_n"); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k2, NULL), 0); - sshbuf_free(buf); - ASSERT_PTR_NE(k2, NULL); - ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); - sshkey_free(k2); - TEST_DONE(); - - TEST_START("parse DSA from new-format w/ passphrase"); - buf = load_file("dsa_n_pw"); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, - (const char *)sshbuf_ptr(pw), &k2, NULL), 0); - sshbuf_free(buf); - ASSERT_PTR_NE(k2, NULL); - ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); - sshkey_free(k2); - TEST_DONE(); - - TEST_START("load DSA from public"); - ASSERT_INT_EQ(sshkey_load_public(test_data_file("dsa_1.pub"), &k2, - NULL), 0); - ASSERT_PTR_NE(k2, NULL); - ASSERT_INT_EQ(sshkey_equal(k1, k2), 1); - sshkey_free(k2); - TEST_DONE(); - - TEST_START("load DSA cert"); - ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k2), 0); - ASSERT_PTR_NE(k2, NULL); - ASSERT_INT_EQ(k2->type, KEY_DSA_CERT); - ASSERT_INT_EQ(sshkey_equal(k1, k2), 0); - ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); - TEST_DONE(); - - TEST_START("DSA key hex fingerprint"); - buf = load_text_file("dsa_1.fp"); - cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64); - ASSERT_PTR_NE(cp, NULL); - ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); - sshbuf_free(buf); - free(cp); - TEST_DONE(); - - TEST_START("DSA cert hex fingerprint"); - buf = load_text_file("dsa_1-cert.fp"); - cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64); - ASSERT_PTR_NE(cp, NULL); - ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); - sshbuf_free(buf); - free(cp); - sshkey_free(k2); - TEST_DONE(); - - TEST_START("DSA key bubblebabble fingerprint"); - buf = load_text_file("dsa_1.fp.bb"); - cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE); - ASSERT_PTR_NE(cp, NULL); - ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); - sshbuf_free(buf); - free(cp); - TEST_DONE(); - - sshkey_free(k1); -#endif - #ifdef OPENSSL_HAS_ECC TEST_START("parse ECDSA from private"); buf = load_file("ecdsa_1"); diff --git a/regress/unittests/sshkey/test_fuzz.c b/regress/unittests/sshkey/test_fuzz.c index 0aff7c9bf4e4..d0f47d7cfd1d 100644 --- a/regress/unittests/sshkey/test_fuzz.c +++ b/regress/unittests/sshkey/test_fuzz.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_fuzz.c,v 1.14 2024/01/11 01:45:58 djm Exp $ */ +/* $OpenBSD: test_fuzz.c,v 1.15 2025/05/06 06:05:48 djm Exp $ */ /* * Fuzz tests for key parsing * @@ -11,9 +11,7 @@ #include #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include #include @@ -21,7 +19,6 @@ #ifdef WITH_OPENSSL #include #include -#include #include #ifdef OPENSSL_HAS_NISTP256 # include @@ -160,52 +157,6 @@ sshkey_fuzz_tests(void) fuzz_cleanup(fuzz); TEST_DONE(); -#ifdef WITH_DSA - TEST_START("fuzz DSA private"); - buf = load_file("dsa_1"); - fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), - sshbuf_len(buf)); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); - sshkey_free(k1); - sshbuf_free(buf); - ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); - TEST_ONERROR(onerror, fuzz); - for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) { - r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); - ASSERT_INT_EQ(r, 0); - if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) - sshkey_free(k1); - sshbuf_reset(fuzzed); - if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS) - break; - } - sshbuf_free(fuzzed); - fuzz_cleanup(fuzz); - TEST_DONE(); - - TEST_START("fuzz DSA new-format private"); - buf = load_file("dsa_n"); - fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf), - sshbuf_len(buf)); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); - sshkey_free(k1); - sshbuf_free(buf); - ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL); - TEST_ONERROR(onerror, fuzz); - for(i = 0; !fuzz_done(fuzz); i++, fuzz_next(fuzz)) { - r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz)); - ASSERT_INT_EQ(r, 0); - if (sshkey_parse_private_fileblob(fuzzed, "", &k1, NULL) == 0) - sshkey_free(k1); - sshbuf_reset(fuzzed); - if (test_is_fast() && i >= NUM_FAST_BASE64_TESTS) - break; - } - sshbuf_free(fuzzed); - fuzz_cleanup(fuzz); - TEST_DONE(); -#endif - #ifdef OPENSSL_HAS_ECC TEST_START("fuzz ECDSA private"); buf = load_file("ecdsa_1"); @@ -290,22 +241,6 @@ sshkey_fuzz_tests(void) sshkey_free(k1); TEST_DONE(); -#ifdef WITH_DSA - TEST_START("fuzz DSA public"); - buf = load_file("dsa_1"); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); - sshbuf_free(buf); - public_fuzz(k1); - sshkey_free(k1); - TEST_DONE(); - - TEST_START("fuzz DSA cert"); - ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k1), 0); - public_fuzz(k1); - sshkey_free(k1); - TEST_DONE(); -#endif - #ifdef OPENSSL_HAS_ECC TEST_START("fuzz ECDSA public"); buf = load_file("ecdsa_1"); @@ -362,16 +297,6 @@ sshkey_fuzz_tests(void) sshkey_free(k1); TEST_DONE(); -#ifdef WITH_DSA - TEST_START("fuzz DSA sig"); - buf = load_file("dsa_1"); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); - sshbuf_free(buf); - sig_fuzz(k1, NULL); - sshkey_free(k1); - TEST_DONE(); -#endif - #ifdef OPENSSL_HAS_ECC TEST_START("fuzz ECDSA sig"); buf = load_file("ecdsa_1"); diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c index 5bf4b65cc055..d0c46a90beb7 100644 --- a/regress/unittests/sshkey/test_sshkey.c +++ b/regress/unittests/sshkey/test_sshkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_sshkey.c,v 1.25 2024/08/15 00:52:23 djm Exp $ */ +/* $OpenBSD: test_sshkey.c,v 1.32 2025/10/01 00:33:37 dtucker Exp $ */ /* * Regress test for sshkey.h key management API * @@ -9,16 +9,13 @@ #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include #ifdef WITH_OPENSSL #include #include -#include #if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256) # include #endif @@ -36,6 +33,7 @@ #include "ssh2.h" void sshkey_tests(void); +void sshkey_benchmarks(void); static void put_opt(struct sshbuf *b, const char *name, const char *value) @@ -133,6 +131,55 @@ signature_test(struct sshkey *k, struct sshkey *bad, const char *sig_alg, free(sig); } +static void +signature_bench(const char *name, int ktype, int bits, const char *sig_alg, + const u_char *d, size_t l) +{ + struct sshkey *k; + size_t len; + u_char *sig; + char testname[256]; + + snprintf(testname, sizeof(testname), "sign %s", name); + TEST_START(testname); + ASSERT_INT_EQ(sshkey_generate(ktype, bits, &k), 0); + ASSERT_PTR_NE(k, NULL); + + BENCH_START(testname); + ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg, + NULL, NULL, 0), 0); + free(sig); + BENCH_FINISH("sign"); + + sshkey_free(k); + TEST_DONE(); +} + +static void +verify_bench(const char *name, int ktype, int bits, const char *sig_alg, + const u_char *d, size_t l) +{ + struct sshkey *k; + size_t len; + u_char *sig; + char testname[256]; + + snprintf(testname, sizeof(testname), "verify %s", name); + TEST_START(testname); + ASSERT_INT_EQ(sshkey_generate(ktype, bits, &k), 0); + ASSERT_PTR_NE(k, NULL); + + ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg, + NULL, NULL, 0), 0); + BENCH_START(testname); + ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); + BENCH_FINISH("verify"); + + free(sig); + sshkey_free(k); + TEST_DONE(); +} + static void banana(u_char *s, size_t l) { @@ -165,6 +212,19 @@ signature_tests(struct sshkey *k, struct sshkey *bad, const char *sig_alg) } } +static void +signature_benchmark(const char *name, int ktype, int bits, + const char *sig_alg, int bench_verify) +{ + u_char buf[256]; + + banana(buf, sizeof(buf)); + if (bench_verify) + verify_bench(name, ktype, bits, sig_alg, buf, sizeof(buf)); + else + signature_bench(name, ktype, bits, sig_alg, buf, sizeof(buf)); +} + static struct sshkey * get_private(const char *n) { @@ -198,6 +258,7 @@ sshkey_tests(void) k1 = sshkey_new(KEY_UNSPEC); ASSERT_PTR_NE(k1, NULL); sshkey_free(k1); + k1 = NULL; TEST_DONE(); #ifdef WITH_OPENSSL @@ -206,16 +267,9 @@ sshkey_tests(void) ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_NE(k1->pkey, NULL); sshkey_free(k1); + k1 = NULL; TEST_DONE(); -#ifdef WITH_DSA - TEST_START("new/free KEY_DSA"); - k1 = sshkey_new(KEY_DSA); - ASSERT_PTR_NE(k1, NULL); - ASSERT_PTR_NE(k1->dsa, NULL); - sshkey_free(k1); - TEST_DONE(); -#endif #ifdef OPENSSL_HAS_ECC TEST_START("new/free KEY_ECDSA"); @@ -223,6 +277,7 @@ sshkey_tests(void) ASSERT_PTR_NE(k1, NULL); ASSERT_PTR_EQ(k1->pkey, NULL); /* Can't allocate without NID */ sshkey_free(k1); + k1 = NULL; TEST_DONE(); #endif @@ -233,6 +288,7 @@ sshkey_tests(void) ASSERT_PTR_EQ(k1->ed25519_sk, NULL); ASSERT_PTR_EQ(k1->ed25519_pk, NULL); sshkey_free(k1); + k1 = NULL; TEST_DONE(); TEST_START("generate KEY_RSA too small modulus"); @@ -247,14 +303,6 @@ sshkey_tests(void) ASSERT_PTR_EQ(k1, NULL); TEST_DONE(); -#ifdef WITH_DSA - TEST_START("generate KEY_DSA wrong bits"); - ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 2048, &k1), - SSH_ERR_KEY_LENGTH); - ASSERT_PTR_EQ(k1, NULL); - sshkey_free(k1); - TEST_DONE(); -#endif #ifdef OPENSSL_HAS_ECC TEST_START("generate KEY_ECDSA wrong bits"); @@ -262,6 +310,7 @@ sshkey_tests(void) SSH_ERR_KEY_LENGTH); ASSERT_PTR_EQ(k1, NULL); sshkey_free(k1); + k1 = NULL; TEST_DONE(); #endif @@ -277,15 +326,6 @@ sshkey_tests(void) ASSERT_INT_EQ(BN_num_bits(rsa_n(kr)), 1024); TEST_DONE(); -#ifdef WITH_DSA - TEST_START("generate KEY_DSA"); - ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &kd), 0); - ASSERT_PTR_NE(kd, NULL); - ASSERT_PTR_NE(kd->dsa, NULL); - ASSERT_PTR_NE(dsa_g(kd), NULL); - ASSERT_PTR_NE(dsa_priv_key(kd), NULL); - TEST_DONE(); -#endif #ifdef OPENSSL_HAS_ECC TEST_START("generate KEY_ECDSA"); @@ -323,24 +363,9 @@ sshkey_tests(void) TEST_START("equal KEY_RSA/demoted KEY_RSA"); ASSERT_INT_EQ(sshkey_equal(kr, k1), 1); sshkey_free(k1); + k1 = NULL; TEST_DONE(); -#ifdef WITH_DSA - TEST_START("demote KEY_DSA"); - ASSERT_INT_EQ(sshkey_from_private(kd, &k1), 0); - ASSERT_PTR_NE(k1, NULL); - ASSERT_PTR_NE(kd, k1); - ASSERT_INT_EQ(k1->type, KEY_DSA); - ASSERT_PTR_NE(k1->dsa, NULL); - ASSERT_PTR_NE(dsa_g(k1), NULL); - ASSERT_PTR_EQ(dsa_priv_key(k1), NULL); - TEST_DONE(); - - TEST_START("equal KEY_DSA/demoted KEY_DSA"); - ASSERT_INT_EQ(sshkey_equal(kd, k1), 1); - sshkey_free(k1); - TEST_DONE(); -#endif #ifdef OPENSSL_HAS_ECC TEST_START("demote KEY_ECDSA"); @@ -359,6 +384,7 @@ sshkey_tests(void) TEST_START("equal KEY_ECDSA/demoted KEY_ECDSA"); ASSERT_INT_EQ(sshkey_equal(ke, k1), 1); sshkey_free(k1); + k1 = NULL; TEST_DONE(); #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ @@ -375,6 +401,7 @@ sshkey_tests(void) TEST_START("equal KEY_ED25519/demoted KEY_ED25519"); ASSERT_INT_EQ(sshkey_equal(kf, k1), 1); sshkey_free(k1); + k1 = NULL; TEST_DONE(); #ifdef WITH_OPENSSL @@ -394,15 +421,18 @@ sshkey_tests(void) ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1024, &k1), 0); ASSERT_INT_EQ(sshkey_equal(kr, k1), 0); sshkey_free(k1); + k1 = NULL; #ifdef OPENSSL_HAS_ECC ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 256, &k1), 0); ASSERT_INT_EQ(sshkey_equal(ke, k1), 0); sshkey_free(k1); + k1 = NULL; #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ ASSERT_INT_EQ(sshkey_generate(KEY_ED25519, 256, &k1), 0); ASSERT_INT_EQ(sshkey_equal(kf, k1), 0); sshkey_free(k1); + k1 = NULL; TEST_DONE(); #ifdef WITH_OPENSSL @@ -457,6 +487,7 @@ sshkey_tests(void) sshkey_free(k1); sshkey_free(k2); sshkey_free(k3); + k1 = k2 = k3 = NULL; sshbuf_reset(b); TEST_DONE(); @@ -468,6 +499,7 @@ sshkey_tests(void) signature_tests(k1, k2, "ssh-rsa"); sshkey_free(k1); sshkey_free(k2); + k1 = k2 = NULL; TEST_DONE(); TEST_START("sign and verify RSA-SHA256"); @@ -477,6 +509,7 @@ sshkey_tests(void) signature_tests(k1, k2, "rsa-sha2-256"); sshkey_free(k1); sshkey_free(k2); + k1 = k2 = NULL; TEST_DONE(); TEST_START("sign and verify RSA-SHA512"); @@ -486,18 +519,9 @@ sshkey_tests(void) signature_tests(k1, k2, "rsa-sha2-512"); sshkey_free(k1); sshkey_free(k2); + k1 = k2 = NULL; TEST_DONE(); -#ifdef WITH_DSA - TEST_START("sign and verify DSA"); - k1 = get_private("dsa_1"); - ASSERT_INT_EQ(sshkey_load_public(test_data_file("dsa_2.pub"), &k2, - NULL), 0); - signature_tests(k1, k2, NULL); - sshkey_free(k1); - sshkey_free(k2); - TEST_DONE(); -#endif #ifdef OPENSSL_HAS_ECC TEST_START("sign and verify ECDSA"); @@ -507,6 +531,7 @@ sshkey_tests(void) signature_tests(k1, k2, NULL); sshkey_free(k1); sshkey_free(k2); + k1 = k2 = NULL; TEST_DONE(); #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ @@ -518,6 +543,7 @@ sshkey_tests(void) signature_tests(k1, k2, NULL); sshkey_free(k1); sshkey_free(k2); + k1 = k2 = NULL; TEST_DONE(); #ifdef WITH_OPENSSL @@ -533,7 +559,96 @@ sshkey_tests(void) sshkey_free(k1); sshkey_free(k2); sshkey_free(k3); + k1 = k2 = k3 = NULL; sshbuf_free(b); TEST_DONE(); #endif /* WITH_OPENSSL */ } + +void +sshkey_benchmarks(void) +{ + struct sshkey *k = NULL; + +#ifdef WITH_OPENSSL + BENCH_START("generate RSA-1024"); + TEST_START("generate KEY_RSA"); + ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1024, &k), 0); + ASSERT_PTR_NE(k, NULL); + sshkey_free(k); + k = NULL; + TEST_DONE(); + BENCH_FINISH("keys"); + + BENCH_START("generate RSA-2048"); + TEST_START("generate KEY_RSA"); + ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 2048, &k), 0); + ASSERT_PTR_NE(k, NULL); + sshkey_free(k); + k = NULL; + TEST_DONE(); + BENCH_FINISH("keys"); + + BENCH_START("generate ECDSA-256"); + TEST_START("generate KEY_ECDSA"); + ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 256, &k), 0); + ASSERT_PTR_NE(k, NULL); + sshkey_free(k); + k = NULL; + TEST_DONE(); + BENCH_FINISH("keys"); + + BENCH_START("generate ECDSA-384"); + TEST_START("generate KEY_ECDSA"); + ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 384, &k), 0); + ASSERT_PTR_NE(k, NULL); + sshkey_free(k); + k = NULL; + TEST_DONE(); + BENCH_FINISH("keys"); + + BENCH_START("generate ECDSA-521"); + TEST_START("generate KEY_ECDSA"); + ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 521, &k), 0); + ASSERT_PTR_NE(k, NULL); + sshkey_free(k); + k = NULL; + TEST_DONE(); + BENCH_FINISH("keys"); +#endif /* WITH_OPENSSL */ + + BENCH_START("generate ED25519"); + TEST_START("generate KEY_ED25519"); + ASSERT_INT_EQ(sshkey_generate(KEY_ED25519, 256, &k), 0); + ASSERT_PTR_NE(k, NULL); + sshkey_free(k); + k = NULL; + TEST_DONE(); + BENCH_FINISH("keys"); + +#ifdef WITH_OPENSSL + /* sign */ + signature_benchmark("RSA-1024/SHA1", KEY_RSA, 1024, "ssh-rsa", 0); + signature_benchmark("RSA-1024/SHA256", KEY_RSA, 1024, "rsa-sha2-256", 0); + signature_benchmark("RSA-1024/SHA512", KEY_RSA, 1024, "rsa-sha2-512", 0); + signature_benchmark("RSA-2048/SHA1", KEY_RSA, 2048, "ssh-rsa", 0); + signature_benchmark("RSA-2048/SHA256", KEY_RSA, 2048, "rsa-sha2-256", 0); + signature_benchmark("RSA-2048/SHA512", KEY_RSA, 2048, "rsa-sha2-512", 0); + signature_benchmark("ECDSA-256", KEY_ECDSA, 256, NULL, 0); + signature_benchmark("ECDSA-384", KEY_ECDSA, 384, NULL, 0); + signature_benchmark("ECDSA-521", KEY_ECDSA, 521, NULL, 0); + signature_benchmark("ED25519", KEY_ED25519, 0, NULL, 0); + + /* verify */ + signature_benchmark("RSA-1024/SHA1", KEY_RSA, 1024, "ssh-rsa", 1); + signature_benchmark("RSA-1024/SHA256", KEY_RSA, 1024, "rsa-sha2-256", 1); + signature_benchmark("RSA-1024/SHA512", KEY_RSA, 1024, "rsa-sha2-512", 1); + signature_benchmark("RSA-2048/SHA1", KEY_RSA, 2048, "ssh-rsa", 1); + signature_benchmark("RSA-2048/SHA256", KEY_RSA, 2048, "rsa-sha2-256", 1); + signature_benchmark("RSA-2048/SHA512", KEY_RSA, 2048, "rsa-sha2-512", 1); + signature_benchmark("ECDSA-256", KEY_ECDSA, 256, NULL, 1); + signature_benchmark("ECDSA-384", KEY_ECDSA, 384, NULL, 1); + signature_benchmark("ECDSA-521", KEY_ECDSA, 521, NULL, 1); +#endif /* WITH_OPENSSL */ + signature_benchmark("ED25519", KEY_ED25519, 0, NULL, 1); +} diff --git a/regress/unittests/sshkey/testdata/dsa_1 b/regress/unittests/sshkey/testdata/dsa_1 deleted file mode 100644 index d3f24824f8d5..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_1 +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIIBvAIBAAKBgQD6kutNFRsHTwEAv6d39Lhsqy1apdHBZ9c2HfyRr7WmypyGIy2m -Ka43vzXI8CNwmRSYs+A6d0vJC7Pl+f9QzJ/04NWOA+MiwfurwrR3CRe61QRYb8Py -mcHOxueHs95IcjrbIPNn86cjnPP5qvv/guUzCjuww4zBdJOXpligrGt2XwIVAKMD -/50qQy7j8JaMk+1+Xtg1pK01AoGBAO7l9QVVbSSoy5lq6cOtvpf8UlwOa6+zBwbl -o4gmFd1RwX1yWkA8kQ7RrhCSg8Hc6mIGnKRgKRli/3LgbSfZ0obFJehkRtEWtN4P -h8fVUeS74iQbIwFQeKlYHIlNTRoGtAbdi3nHdV+BBkEQc1V3rjqYqhjOoz/yNsgz -LND26HrdAoGBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxb -OXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joo -t+LK84ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQtAhRYIbQ5 -KfXsZuBPuWe5FJz3ldaEgw== ------END DSA PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/dsa_1-cert.fp b/regress/unittests/sshkey/testdata/dsa_1-cert.fp deleted file mode 100644 index 75ff0e9cd9f7..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_1-cert.fp +++ /dev/null @@ -1 +0,0 @@ -SHA256:kOLgXSoAT8O5T6r36n5NJUYigbux1d7gdH/rmWiJm6s diff --git a/regress/unittests/sshkey/testdata/dsa_1-cert.pub b/regress/unittests/sshkey/testdata/dsa_1-cert.pub deleted file mode 100644 index e768db1e7bad..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_1-cert.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgdTlbNU9Hn9Qng3FHxwH971bxCIoq1ern/QWFFDWXgmYAAACBAPqS600VGwdPAQC/p3f0uGyrLVql0cFn1zYd/JGvtabKnIYjLaYprje/NcjwI3CZFJiz4Dp3S8kLs+X5/1DMn/Tg1Y4D4yLB+6vCtHcJF7rVBFhvw/KZwc7G54ez3khyOtsg82fzpyOc8/mq+/+C5TMKO7DDjMF0k5emWKCsa3ZfAAAAFQCjA/+dKkMu4/CWjJPtfl7YNaStNQAAAIEA7uX1BVVtJKjLmWrpw62+l/xSXA5rr7MHBuWjiCYV3VHBfXJaQDyRDtGuEJKDwdzqYgacpGApGWL/cuBtJ9nShsUl6GRG0Ra03g+Hx9VR5LviJBsjAVB4qVgciU1NGga0Bt2Lecd1X4EGQRBzVXeuOpiqGM6jP/I2yDMs0Pboet0AAACBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxbOXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joot+LK84ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQtAAAAAAAAAAYAAAACAAAABmp1bGl1cwAAABIAAAAFaG9zdDEAAAAFaG9zdDIAAAAANowB8AAAAABNHmBwAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACBThupGO0X+FLQhbz8CoKPwc7V3JNsQuGtlsgN+F7SMGQAAAFMAAAALc3NoLWVkMjU1MTkAAABAh/z1LIdNL1b66tQ8t9DY9BTB3BQKpTKmc7ezyFKLwl96yaIniZwD9Ticdbe/8i/Li3uCFE3EAt8NAIv9zff8Bg== DSA test key #1 diff --git a/regress/unittests/sshkey/testdata/dsa_1.fp b/regress/unittests/sshkey/testdata/dsa_1.fp deleted file mode 100644 index 75ff0e9cd9f7..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_1.fp +++ /dev/null @@ -1 +0,0 @@ -SHA256:kOLgXSoAT8O5T6r36n5NJUYigbux1d7gdH/rmWiJm6s diff --git a/regress/unittests/sshkey/testdata/dsa_1.fp.bb b/regress/unittests/sshkey/testdata/dsa_1.fp.bb deleted file mode 100644 index ba37776ee30a..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_1.fp.bb +++ /dev/null @@ -1 +0,0 @@ -xetag-todiz-mifah-torec-mynyv-cyvit-gopon-pygag-rupic-cenav-bexax diff --git a/regress/unittests/sshkey/testdata/dsa_1.param.g b/regress/unittests/sshkey/testdata/dsa_1.param.g deleted file mode 100644 index e51c3f9fd1b4..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_1.param.g +++ /dev/null @@ -1 +0,0 @@ -00eee5f505556d24a8cb996ae9c3adbe97fc525c0e6bafb30706e5a3882615dd51c17d725a403c910ed1ae109283c1dcea62069ca460291962ff72e06d27d9d286c525e86446d116b4de0f87c7d551e4bbe2241b23015078a9581c894d4d1a06b406dd8b79c7755f81064110735577ae3a98aa18cea33ff236c8332cd0f6e87add diff --git a/regress/unittests/sshkey/testdata/dsa_1.param.priv b/regress/unittests/sshkey/testdata/dsa_1.param.priv deleted file mode 100644 index 4f743314c76e..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_1.param.priv +++ /dev/null @@ -1 +0,0 @@ -5821b43929f5ec66e04fb967b9149cf795d68483 diff --git a/regress/unittests/sshkey/testdata/dsa_1.param.pub b/regress/unittests/sshkey/testdata/dsa_1.param.pub deleted file mode 100644 index ba0313beec48..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_1.param.pub +++ /dev/null @@ -1 +0,0 @@ -00e757a727e6a1b10168ea9902ebe08f53f4ba18c6d8fdf551fbabbf6d8558f054dc0f6aae4c5b397c04d0bc2f8c2bebb1057f96b621273fed8b2b38d1579a86e956644e520073171887fde4b88b4a0697323928ee3a28b7e2caf3896d2f29b067840c9d88e765249c95fd54bb240c714b5bdf8f88d2ef58727ca1a7699216c42d diff --git a/regress/unittests/sshkey/testdata/dsa_1.pub b/regress/unittests/sshkey/testdata/dsa_1.pub deleted file mode 100644 index 41cae2f69f52..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_1.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBAPqS600VGwdPAQC/p3f0uGyrLVql0cFn1zYd/JGvtabKnIYjLaYprje/NcjwI3CZFJiz4Dp3S8kLs+X5/1DMn/Tg1Y4D4yLB+6vCtHcJF7rVBFhvw/KZwc7G54ez3khyOtsg82fzpyOc8/mq+/+C5TMKO7DDjMF0k5emWKCsa3ZfAAAAFQCjA/+dKkMu4/CWjJPtfl7YNaStNQAAAIEA7uX1BVVtJKjLmWrpw62+l/xSXA5rr7MHBuWjiCYV3VHBfXJaQDyRDtGuEJKDwdzqYgacpGApGWL/cuBtJ9nShsUl6GRG0Ra03g+Hx9VR5LviJBsjAVB4qVgciU1NGga0Bt2Lecd1X4EGQRBzVXeuOpiqGM6jP/I2yDMs0Pboet0AAACBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxbOXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joot+LK84ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQt DSA test key #1 diff --git a/regress/unittests/sshkey/testdata/dsa_1_pw b/regress/unittests/sshkey/testdata/dsa_1_pw deleted file mode 100644 index 24c73039fe1a..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_1_pw +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: AES-128-CBC,BC8386C373B22EB7F00ADC821D5D8BE9 - -+HDV2DQ09sxrIAeXTz9r3YFuPRa2hk1+NGcr3ETkXbC6KiZ14wpTnGTloKwaQjIW -eXTa9mpCOWAoohgvsVb+hOuOlP7AfeHu1IXV4EAS+GDpkiV5UxlCXXwqlD75Buu4 -wwDd/p4SWzILH3WGjDk5JIXoxWNY13LHwC7Q6gtGJx4AicUG7YBRTXMIBDa/Kh77 -6o2rFETKmp4VHBvHbakmiETfptdM8bbWxKWeY2vakThyESgeofsLoTOQCIwlEfJC -s2D/KYL65C8VbHYgIoSLTQnooO45DDyxIuhCqP+H23mhv9vB1Od3nc2atgHj/XFs -dcOPFkF/msDRYqxY3V0AS6+jpKwFodZ7g/hyGcyPxOkzlJVuKoKuH6P5PyQ69Gx0 -iqri0xEPyABr7kGlXNrjjctojX+B4WwSnjg/2euXXWFXCRalIdA7ErATTiQbGOx7 -Vd6Gn8PZbSy1MkqEDrZRip0pfAFJYI/8GXPC75BpnRsrVlfhtrngbW+kBP35LzaN -l2K+RQ3gSB3iFoqNb1Kuu6T5MZlyVl5H2dVlJSeb1euQ2OycXdDoFTyJ4AiyWS7w -Vlh8zeJnso5QRDjMwx99pZilbbuFGSLsahiGEveFc6o= ------END DSA PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/dsa_2 b/regress/unittests/sshkey/testdata/dsa_2 deleted file mode 100644 index 3cc9631afa0f..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_2 +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIIBvQIBAAKBgQCbyPXNdHeLsjpobPVCMkfagBkt15Zsltqf/PGNP1y1cuz7rsTX -ZekQwUkSTNm5coqXe+ZOw2O4tjobJDd60I1/VPgaB0NYlQR9Hn87M284WD4f6VY+ -aunHmP134a8ybG5G4NqVNF3ihvxAR2pVITqb7kE46r2uYZNcNlHI8voRCwIVAMcP -bwqFNsQbH5pJyZW30wj4KVZ3AoGBAIK98BVeKQVf8qDFqx9ovMuNgVSxpd+N0Yta -5ZEy1OI2ziu5RhjueIM2K7Gq2Mnp38ob1AM53BUxqlcBJaHEDa6rj6yvuMgW9oCJ -dImBM8sIFxfBbXNbpJiMaDwa6WyT84OkpDE6uuAepTMnWOUWkUVkAiyokHDUGXkG -GyoQblbXAoGBAIsf7TaZ804sUWwRV0wI8DYx+hxD5QdrfYPYMtL2fHn3lICimGt0 -FTtUZ25jKg0E0DMBPdET6ZEHB3ZZkR8hFoUzZhdnyJMu3UjVtgaV88Ue3PrXxchk -0W2jHPaAgQU3JIWzo8HFIFqvC/HEL+EyW3rBTY2uXM3XGI+YcWSA4ZrZAhUAsY2f -bDFNzgZ4DaZ9wLRzTgOswPU= ------END DSA PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/dsa_2.fp b/regress/unittests/sshkey/testdata/dsa_2.fp deleted file mode 100644 index 51fbeb4d8ce1..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_2.fp +++ /dev/null @@ -1 +0,0 @@ -SHA256:ecwhWcXgpdBxZ2e+OjpRRY7dqXHHCD62BGtoVQQBwCk diff --git a/regress/unittests/sshkey/testdata/dsa_2.fp.bb b/regress/unittests/sshkey/testdata/dsa_2.fp.bb deleted file mode 100644 index 4d908ee30977..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_2.fp.bb +++ /dev/null @@ -1 +0,0 @@ -xeser-megad-pocan-rozit-belup-tapoh-fapif-kyvit-vonav-cehab-naxax diff --git a/regress/unittests/sshkey/testdata/dsa_2.pub b/regress/unittests/sshkey/testdata/dsa_2.pub deleted file mode 100644 index 77bb555d595f..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_2.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBAJvI9c10d4uyOmhs9UIyR9qAGS3XlmyW2p/88Y0/XLVy7PuuxNdl6RDBSRJM2blyipd75k7DY7i2OhskN3rQjX9U+BoHQ1iVBH0efzszbzhYPh/pVj5q6ceY/XfhrzJsbkbg2pU0XeKG/EBHalUhOpvuQTjqva5hk1w2Ucjy+hELAAAAFQDHD28KhTbEGx+aScmVt9MI+ClWdwAAAIEAgr3wFV4pBV/yoMWrH2i8y42BVLGl343Ri1rlkTLU4jbOK7lGGO54gzYrsarYyenfyhvUAzncFTGqVwElocQNrquPrK+4yBb2gIl0iYEzywgXF8Ftc1ukmIxoPBrpbJPzg6SkMTq64B6lMydY5RaRRWQCLKiQcNQZeQYbKhBuVtcAAACBAIsf7TaZ804sUWwRV0wI8DYx+hxD5QdrfYPYMtL2fHn3lICimGt0FTtUZ25jKg0E0DMBPdET6ZEHB3ZZkR8hFoUzZhdnyJMu3UjVtgaV88Ue3PrXxchk0W2jHPaAgQU3JIWzo8HFIFqvC/HEL+EyW3rBTY2uXM3XGI+YcWSA4ZrZ DSA test key #2 diff --git a/regress/unittests/sshkey/testdata/dsa_n b/regress/unittests/sshkey/testdata/dsa_n deleted file mode 100644 index 657624e0e72f..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_n +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABswAAAAdzc2gtZH -NzAAAAgQD6kutNFRsHTwEAv6d39Lhsqy1apdHBZ9c2HfyRr7WmypyGIy2mKa43vzXI8CNw -mRSYs+A6d0vJC7Pl+f9QzJ/04NWOA+MiwfurwrR3CRe61QRYb8PymcHOxueHs95IcjrbIP -Nn86cjnPP5qvv/guUzCjuww4zBdJOXpligrGt2XwAAABUAowP/nSpDLuPwloyT7X5e2DWk -rTUAAACBAO7l9QVVbSSoy5lq6cOtvpf8UlwOa6+zBwblo4gmFd1RwX1yWkA8kQ7RrhCSg8 -Hc6mIGnKRgKRli/3LgbSfZ0obFJehkRtEWtN4Ph8fVUeS74iQbIwFQeKlYHIlNTRoGtAbd -i3nHdV+BBkEQc1V3rjqYqhjOoz/yNsgzLND26HrdAAAAgQDnV6cn5qGxAWjqmQLr4I9T9L -oYxtj99VH7q79thVjwVNwPaq5MWzl8BNC8L4wr67EFf5a2ISc/7YsrONFXmobpVmROUgBz -FxiH/eS4i0oGlzI5KO46KLfiyvOJbS8psGeEDJ2I52UknJX9VLskDHFLW9+PiNLvWHJ8oa -dpkhbELQAAAdhWTOFbVkzhWwAAAAdzc2gtZHNzAAAAgQD6kutNFRsHTwEAv6d39Lhsqy1a -pdHBZ9c2HfyRr7WmypyGIy2mKa43vzXI8CNwmRSYs+A6d0vJC7Pl+f9QzJ/04NWOA+Miwf -urwrR3CRe61QRYb8PymcHOxueHs95IcjrbIPNn86cjnPP5qvv/guUzCjuww4zBdJOXplig -rGt2XwAAABUAowP/nSpDLuPwloyT7X5e2DWkrTUAAACBAO7l9QVVbSSoy5lq6cOtvpf8Ul -wOa6+zBwblo4gmFd1RwX1yWkA8kQ7RrhCSg8Hc6mIGnKRgKRli/3LgbSfZ0obFJehkRtEW -tN4Ph8fVUeS74iQbIwFQeKlYHIlNTRoGtAbdi3nHdV+BBkEQc1V3rjqYqhjOoz/yNsgzLN -D26HrdAAAAgQDnV6cn5qGxAWjqmQLr4I9T9LoYxtj99VH7q79thVjwVNwPaq5MWzl8BNC8 -L4wr67EFf5a2ISc/7YsrONFXmobpVmROUgBzFxiH/eS4i0oGlzI5KO46KLfiyvOJbS8psG -eEDJ2I52UknJX9VLskDHFLW9+PiNLvWHJ8oadpkhbELQAAABRYIbQ5KfXsZuBPuWe5FJz3 -ldaEgwAAAAAB ------END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/testdata/dsa_n_pw b/regress/unittests/sshkey/testdata/dsa_n_pw deleted file mode 100644 index 24ac299a482d..000000000000 --- a/regress/unittests/sshkey/testdata/dsa_n_pw +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABCVs+LsMJ -wnB5zM9U9pTXrGAAAAEAAAAAEAAAGzAAAAB3NzaC1kc3MAAACBAPqS600VGwdPAQC/p3f0 -uGyrLVql0cFn1zYd/JGvtabKnIYjLaYprje/NcjwI3CZFJiz4Dp3S8kLs+X5/1DMn/Tg1Y -4D4yLB+6vCtHcJF7rVBFhvw/KZwc7G54ez3khyOtsg82fzpyOc8/mq+/+C5TMKO7DDjMF0 -k5emWKCsa3ZfAAAAFQCjA/+dKkMu4/CWjJPtfl7YNaStNQAAAIEA7uX1BVVtJKjLmWrpw6 -2+l/xSXA5rr7MHBuWjiCYV3VHBfXJaQDyRDtGuEJKDwdzqYgacpGApGWL/cuBtJ9nShsUl -6GRG0Ra03g+Hx9VR5LviJBsjAVB4qVgciU1NGga0Bt2Lecd1X4EGQRBzVXeuOpiqGM6jP/ -I2yDMs0Pboet0AAACBAOdXpyfmobEBaOqZAuvgj1P0uhjG2P31Ufurv22FWPBU3A9qrkxb -OXwE0LwvjCvrsQV/lrYhJz/tiys40VeahulWZE5SAHMXGIf95LiLSgaXMjko7joot+LK84 -ltLymwZ4QMnYjnZSSclf1UuyQMcUtb34+I0u9Ycnyhp2mSFsQtAAAB4HiOcRW4w+sIqBL0 -TPVbf0glN1hUi0rcE63Pqxmvxb8LkldC4IxAUagPrjhNAEW2AY42+CvPrtGB1z7gDADAIW -xZX6wKwIcXP0Qh+xHE12F4u6mwfasssnAp4t1Ki8uCjMjnimgb3KdWpp0kiUV0oR062TXV -PAdfrWjaq4fw0KOqbHIAG/v36AqzuqjSTfDbqvLZM3y0gp2Q1RxaQVJA5ZIKKyqRyFX7sr -BaEIyCgeE3hM0EB7BycY1oIcS/eNxrACBWVJCENl5N7LtEYXNX7TANFniztfXzwaqGTT6A -fCfbW4gz1UKldLUBzbIrPwMWlirAstbHvOf/2Iay2pNAs/SHhI0aF2jsGfvv5/D6N+r9dG -B2SgDKBg7pywMH1DTvg6YT3P4GjCx0GUHqRCFLvD1rDdk4KSjvaRMpVq1PJ0/Wv6UGtsMS -TR0PaEHDRNZqAX4YxqujnWrGKuRJhuz0eUvp7fZvbWHtiAMKV7368kkeUmkOHanb+TS+zs -KINX8ev8zJZ6WVr8Vl+IQavpv0i2bXwS6QqbEuifpv/+uBb7pqRiU4u8en0eMdX1bZoTPM -R6xHCnGD/Jpb3zS91Ya57T6CiXZ12KCaL6nWGnCkZVpzkfJ2HjFklWSWBQ6uyaosDQ== ------END OPENSSH PRIVATE KEY----- diff --git a/regress/unittests/sshkey/tests.c b/regress/unittests/sshkey/tests.c index 78aa9223d42b..5511e7b8900d 100644 --- a/regress/unittests/sshkey/tests.c +++ b/regress/unittests/sshkey/tests.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tests.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */ +/* $OpenBSD: tests.c,v 1.2 2025/04/15 04:00:42 djm Exp $ */ /* * Regress test for sshbuf.h buffer API * @@ -12,6 +12,7 @@ void sshkey_tests(void); void sshkey_file_tests(void); void sshkey_fuzz_tests(void); +void sshkey_benchmarks(void); void tests(void) @@ -20,3 +21,10 @@ tests(void) sshkey_file_tests(); sshkey_fuzz_tests(); } + +void +benchmarks(void) +{ + printf("\n"); + sshkey_benchmarks(); +} diff --git a/regress/unittests/sshsig/Makefile b/regress/unittests/sshsig/Makefile index bc3c6c739d48..f2f03e843856 100644 --- a/regress/unittests/sshsig/Makefile +++ b/regress/unittests/sshsig/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.3 2023/01/15 23:35:10 djm Exp $ +# $OpenBSD: Makefile,v 1.5 2025/07/24 06:04:47 djm Exp $ PROG=test_sshsig SRCS=tests.c @@ -6,12 +6,12 @@ SRCS=tests.c # From usr.bin/ssh SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c -SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c +SRCS+=ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c SRCS+=addr.c addrmatch.c bitmap.c sshsig.c SRCS+=ed25519.c hash.c SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c -SRCS+=ssh-ed25519-sk.c sk-usbhid.c +SRCS+=ssh-ed25519-sk.c sk-usbhid.c ssh-pkcs11-client.c SRCS+=digest-openssl.c #SRCS+=digest-libc.c diff --git a/regress/unittests/sshsig/mktestdata.sh b/regress/unittests/sshsig/mktestdata.sh index d2300f9c6ee1..b7c60cc27767 100755 --- a/regress/unittests/sshsig/mktestdata.sh +++ b/regress/unittests/sshsig/mktestdata.sh @@ -1,5 +1,5 @@ #!/bin/sh -# $OpenBSD: mktestdata.sh,v 1.1 2020/06/19 04:32:09 djm Exp $ +# $OpenBSD: mktestdata.sh,v 1.2 2025/05/06 06:05:48 djm Exp $ NAMESPACE=unittest @@ -17,14 +17,13 @@ else fi rm -f signed-data namespace -rm -f rsa dsa ecdsa ed25519 ecdsa_sk ed25519_sk -rm -f rsa.sig dsa.sig ecdsa.sig ed25519.sig ecdsa_sk.sig ed25519_sk.sig +rm -f rsa ecdsa ed25519 ecdsa_sk ed25519_sk +rm -f rsa.sig ecdsa.sig ed25519.sig ecdsa_sk.sig ed25519_sk.sig printf "This is a test, this is only a test" > signed-data printf "$NAMESPACE" > namespace ssh-keygen -t rsa -C "RSA test" -N "" -f rsa -m PEM -ssh-keygen -t dsa -C "DSA test" -N "" -f dsa -m PEM ssh-keygen -t ecdsa -C "ECDSA test" -N "" -f ecdsa -m PEM ssh-keygen -t ed25519 -C "ED25519 test key" -N "" -f ed25519 ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key" \ @@ -33,7 +32,6 @@ ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key" \ -N "" -f ed25519_sk ssh-keygen -Y sign -f rsa -n $NAMESPACE - < signed-data > rsa.sig -ssh-keygen -Y sign -f dsa -n $NAMESPACE - < signed-data > dsa.sig ssh-keygen -Y sign -f ecdsa -n $NAMESPACE - < signed-data > ecdsa.sig ssh-keygen -Y sign -f ed25519 -n $NAMESPACE - < signed-data > ed25519.sig ssh-keygen -w "$SK_DUMMY" \ diff --git a/regress/unittests/sshsig/testdata/dsa b/regress/unittests/sshsig/testdata/dsa deleted file mode 100644 index 7c0063efcdf5..000000000000 --- a/regress/unittests/sshsig/testdata/dsa +++ /dev/null @@ -1,12 +0,0 @@ ------BEGIN DSA PRIVATE KEY----- -MIIBuwIBAAKBgQCXpndQdz2mQVnk+lYOF3nxDT+h6SiJmUvBFhnFWBv8tG4pTOkb -EwGufLEzGpzjTj+3bjVau7LFt37AFrqs4Num272BWNsYNIjOlGPgq7Xjv32FN00x -JYh1DoRs1cGGnvohlsWEamGGhTHD1a9ipctPEBV+NrxtZMrl+pO/ZZg8vQIVAKJB -P3iNYSpSuW74+q4WxLCuK8O3AoGAQldE+BIuxlvoG1IFiWesx0CU+H2KO0SEZc9A -SX/qjOabh0Fb78ofTlEf9gWHFfat8SvSJQIOPMVlb76Lio8AAMT8Eaa/qQKKYmQL -dNq4MLhhjxx5KLGt6J2JyFPExCv+qnHYHD59ngtLwKyqGjpSC8LPLktdXn8W/Aad -Ly1K7+MCgYBsMHBczhSeUh8w7i20CVg4OlNTmfJRVU2tO6OpMxZ/quitRm3hLKSN -u4xRkvHJwi4LhQtv1SXvLI5gs5P3gCG8tsIAiyCqLinHha63iBdJpqhnV/x/j7dB -yJr3xJbnmLdWLkkCtNk1Ir1/CuEz+ufAyLGdKWksEAu1UUlb501BkwIVAILIa3Rg -0h7J9lQpHJphvF3K0M1T ------END DSA PRIVATE KEY----- diff --git a/regress/unittests/sshsig/testdata/dsa.pub b/regress/unittests/sshsig/testdata/dsa.pub deleted file mode 100644 index e77aa7ef41a0..000000000000 --- a/regress/unittests/sshsig/testdata/dsa.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-dss AAAAB3NzaC1kc3MAAACBAJemd1B3PaZBWeT6Vg4XefENP6HpKImZS8EWGcVYG/y0bilM6RsTAa58sTManONOP7duNVq7ssW3fsAWuqzg26bbvYFY2xg0iM6UY+CrteO/fYU3TTEliHUOhGzVwYae+iGWxYRqYYaFMcPVr2Kly08QFX42vG1kyuX6k79lmDy9AAAAFQCiQT94jWEqUrlu+PquFsSwrivDtwAAAIBCV0T4Ei7GW+gbUgWJZ6zHQJT4fYo7RIRlz0BJf+qM5puHQVvvyh9OUR/2BYcV9q3xK9IlAg48xWVvvouKjwAAxPwRpr+pAopiZAt02rgwuGGPHHkosa3onYnIU8TEK/6qcdgcPn2eC0vArKoaOlILws8uS11efxb8Bp0vLUrv4wAAAIBsMHBczhSeUh8w7i20CVg4OlNTmfJRVU2tO6OpMxZ/quitRm3hLKSNu4xRkvHJwi4LhQtv1SXvLI5gs5P3gCG8tsIAiyCqLinHha63iBdJpqhnV/x/j7dByJr3xJbnmLdWLkkCtNk1Ir1/CuEz+ufAyLGdKWksEAu1UUlb501Bkw== DSA test diff --git a/regress/unittests/sshsig/testdata/dsa.sig b/regress/unittests/sshsig/testdata/dsa.sig deleted file mode 100644 index 0b14ad6b8a7b..000000000000 --- a/regress/unittests/sshsig/testdata/dsa.sig +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN SSH SIGNATURE----- -U1NIU0lHAAAAAQAAAbEAAAAHc3NoLWRzcwAAAIEAl6Z3UHc9pkFZ5PpWDhd58Q0/oekoiZ -lLwRYZxVgb/LRuKUzpGxMBrnyxMxqc404/t241Wruyxbd+wBa6rODbptu9gVjbGDSIzpRj -4Ku14799hTdNMSWIdQ6EbNXBhp76IZbFhGphhoUxw9WvYqXLTxAVfja8bWTK5fqTv2WYPL -0AAAAVAKJBP3iNYSpSuW74+q4WxLCuK8O3AAAAgEJXRPgSLsZb6BtSBYlnrMdAlPh9ijtE -hGXPQEl/6ozmm4dBW+/KH05RH/YFhxX2rfEr0iUCDjzFZW++i4qPAADE/BGmv6kCimJkC3 -TauDC4YY8ceSixreidichTxMQr/qpx2Bw+fZ4LS8Csqho6UgvCzy5LXV5/FvwGnS8tSu/j -AAAAgGwwcFzOFJ5SHzDuLbQJWDg6U1OZ8lFVTa07o6kzFn+q6K1GbeEspI27jFGS8cnCLg -uFC2/VJe8sjmCzk/eAIby2wgCLIKouKceFrreIF0mmqGdX/H+Pt0HImvfElueYt1YuSQK0 -2TUivX8K4TP658DIsZ0paSwQC7VRSVvnTUGTAAAACHVuaXR0ZXN0AAAAAAAAAAZzaGE1MT -IAAAA3AAAAB3NzaC1kc3MAAAAodi5lr0pqBpO76OY4N1CtfR85BCgZ95qfVjP/e9lToj0q -lwjSJJXUjw== ------END SSH SIGNATURE----- diff --git a/regress/unittests/sshsig/tests.c b/regress/unittests/sshsig/tests.c index 80966bdd2c27..670d06718955 100644 --- a/regress/unittests/sshsig/tests.c +++ b/regress/unittests/sshsig/tests.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tests.c,v 1.4 2024/01/11 01:45:59 djm Exp $ */ +/* $OpenBSD: tests.c,v 1.6 2025/05/06 06:05:48 djm Exp $ */ /* * Regress test for sshbuf.h buffer API * @@ -11,9 +11,7 @@ #include #include #include -#ifdef HAVE_STDINT_H #include -#endif #include #include #include @@ -103,11 +101,6 @@ tests(void) check_sig("rsa.pub", "rsa.sig", msg, namespace); TEST_DONE(); -#ifdef WITH_DSA - TEST_START("check DSA signature"); - check_sig("dsa.pub", "dsa.sig", msg, namespace); - TEST_DONE(); -#endif #ifdef OPENSSL_HAS_ECC TEST_START("check ECDSA signature"); @@ -142,3 +135,9 @@ tests(void) sshbuf_free(msg); free(namespace); } + +void +benchmarks(void) +{ + printf("no benchmarks\n"); +} diff --git a/regress/unittests/test_helper/fuzz.c b/regress/unittests/test_helper/fuzz.c index fedb53294c22..a07400310322 100644 --- a/regress/unittests/test_helper/fuzz.c +++ b/regress/unittests/test_helper/fuzz.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fuzz.c,v 1.8 2015/03/03 20:42:49 djm Exp $ */ +/* $OpenBSD: fuzz.c,v 1.9 2025/06/13 07:23:07 dtucker Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -25,9 +25,7 @@ #include #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include #include @@ -150,7 +148,6 @@ fuzz_fmt(struct fuzz *fuzz, char *s, size_t n) return 0; default: return -1; - abort(); } } diff --git a/regress/unittests/test_helper/test_helper.c b/regress/unittests/test_helper/test_helper.c index 8e10a7d45c1b..b94d1450b5c8 100644 --- a/regress/unittests/test_helper/test_helper.c +++ b/regress/unittests/test_helper/test_helper.c @@ -1,4 +1,4 @@ -/* $OpenBSD: test_helper.c,v 1.13 2021/12/14 21:25:27 deraadt Exp $ */ +/* $OpenBSD: test_helper.c,v 1.14 2025/04/15 04:00:42 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -21,18 +21,20 @@ #include #include - -#include +#include + +#include #include +#include +#include +#include +#include +#include #include -#ifdef HAVE_STDINT_H -# include -#endif #include #include -#include +#include #include -#include #ifdef WITH_OPENSSL #include @@ -43,12 +45,25 @@ # include #endif -#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) - #include "entropy.h" #include "test_helper.h" #include "atomicio.h" +#include "match.h" +#include "misc.h" +#include "xmalloc.h" + +#define BENCH_FAST_DEADLINE 1 +#define BENCH_NORMAL_DEADLINE 10 +#define BENCH_SLOW_DEADLINE 60 +#define BENCH_SAMPLES_ALLOC 8192 +#define BENCH_COLUMN_WIDTH 40 + +#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b)) +#ifndef CLOCK_REALTIME +# define CLOCK_REALTIME 0 +#endif + #define TEST_CHECK_INT(r, pred) do { \ switch (pred) { \ case TEST_EQ: \ @@ -123,6 +138,15 @@ static const char *data_dir = NULL; static char subtest_info[512]; static int fast = 0; static int slow = 0; +static int benchmark_detail_statistics = 0; + +static int benchmark = 0; +static const char *bench_name = NULL; +static char *benchmark_pattern = NULL; +static struct timespec bench_start_time, bench_finish_time; +static struct timespec *bench_samples; +static int bench_skip, bench_nruns, bench_nalloc; +double bench_accum_secs; int main(int argc, char **argv) @@ -169,8 +193,17 @@ main(int argc, char **argv) } } - while ((ch = getopt(argc, argv, "Ffvqd:")) != -1) { + while ((ch = getopt(argc, argv, "O:bBFfvqd:")) != -1) { switch (ch) { + case 'b': + benchmark = 1; + break; + case 'B': + benchmark = benchmark_detail_statistics = 1; + break; + case 'O': + benchmark_pattern = xstrdup(optarg); + break; case 'F': slow = 1; break; @@ -190,7 +223,8 @@ main(int argc, char **argv) break; default: fprintf(stderr, "Unrecognised command line option\n"); - fprintf(stderr, "Usage: %s [-v]\n", __progname); + fprintf(stderr, "Usage: %s [-vqfFbB] [-d data_dir] " + "[-O pattern]\n", __progname); exit(1); } } @@ -200,7 +234,10 @@ main(int argc, char **argv) if (verbose_mode) printf("\n"); - tests(); + if (benchmark) + benchmarks(); + else + tests(); #ifdef WINDOWS if (isModuliFileCopied) { @@ -208,7 +245,7 @@ main(int argc, char **argv) } #endif - if (!quiet_mode) + if (!quiet_mode && !benchmark) printf(" %u tests ok\n", test_number); return 0; } @@ -302,7 +339,7 @@ test_done(void) active_test_name = NULL; if (verbose_mode) printf("OK\n"); - else if (!quiet_mode) { + else if (!quiet_mode && !benchmark) { printf("."); fflush(stdout); } @@ -318,6 +355,12 @@ test_subtest_info(const char *fmt, ...) va_end(ap); } +int +test_is_benchmark(void) +{ + return benchmark; +} + void ssl_err_check(const char *file, int line) { @@ -621,3 +664,131 @@ assert_ptr(const char *file, int line, const char *a1, const char *a2, test_die(); } +static double +tstod(const struct timespec *ts) +{ + return (double)ts->tv_sec + ((double)ts->tv_nsec / 1000000000.0); +} + +void +bench_start(const char *file, int line, const char *name) +{ + char *cp; + + if (bench_name != NULL) { + fprintf(stderr, "\n%s:%d internal error: BENCH_START() called " + "while previous benchmark \"%s\" incomplete", + file, line, bench_name); + abort(); + } + cp = xstrdup(name); + lowercase(cp); + bench_skip = benchmark_pattern != NULL && + match_pattern_list(cp, benchmark_pattern, 1) != 1; + free(cp); + + bench_name = name; + bench_nruns = 0; + if (bench_skip) + return; + free(bench_samples); + bench_nalloc = BENCH_SAMPLES_ALLOC; + bench_samples = xcalloc(sizeof(*bench_samples), bench_nalloc); + bench_accum_secs = 0; +} + +int +bench_done(void) +{ + return bench_skip || bench_accum_secs >= (fast ? BENCH_FAST_DEADLINE : + (slow ? BENCH_SLOW_DEADLINE : BENCH_NORMAL_DEADLINE)); +} + +void +bench_case_start(const char *file, int line) +{ + clock_gettime(CLOCK_REALTIME, &bench_start_time); +} + +void +bench_case_finish(const char *file, int line) +{ + struct timespec ts; + + clock_gettime(CLOCK_REALTIME, &bench_finish_time); + timespecsub(&bench_finish_time, &bench_start_time, &ts); + if (bench_nruns >= bench_nalloc) { + if (bench_nalloc >= INT_MAX / 2) { + fprintf(stderr, "\n%s:%d benchmark %s too many samples", + __FILE__, __LINE__, bench_name); + abort(); + } + bench_samples = xrecallocarray(bench_samples, bench_nalloc, + bench_nalloc * 2, sizeof(*bench_samples)); + bench_nalloc *= 2; + } + bench_samples[bench_nruns++] = ts; + bench_accum_secs += tstod(&ts); +} + +static int +tscmp(const void *aa, const void *bb) +{ + const struct timespec *a = (const struct timespec *)aa; + const struct timespec *b = (const struct timespec *)bb; + + if (timespeccmp(a, b, ==)) + return 0; + return timespeccmp(a, b, <) ? -1 : 1; +} + +void +bench_finish(const char *file, int line, const char *unit) +{ + double std_dev = 0, mean_spr, mean_rps, med_spr, med_rps; + int i; + + if (bench_skip) + goto done; + + if (bench_nruns < 1) { + fprintf(stderr, "\n%s:%d benchmark %s never ran", file, line, + bench_name); + abort(); + } + /* median */ + qsort(bench_samples, bench_nruns, sizeof(*bench_samples), tscmp); + i = bench_nruns / 2; + med_spr = tstod(&bench_samples[i]); + if (bench_nruns > 1 && bench_nruns & 1) + med_spr = (med_spr + tstod(&bench_samples[i - 1])) / 2.0; + med_rps = (med_spr == 0.0) ? INFINITY : 1.0/med_spr; + /* mean */ + mean_spr = bench_accum_secs / (double)bench_nruns; + mean_rps = (mean_spr == 0.0) ? INFINITY : 1.0/mean_spr; + /* std. dev */ + std_dev = 0; + for (i = 0; i < bench_nruns; i++) { + std_dev = tstod(&bench_samples[i]) - mean_spr; + std_dev *= std_dev; + } + std_dev /= (double)bench_nruns; + std_dev = sqrt(std_dev); + if (benchmark_detail_statistics) { + printf("%s: %d runs in %0.3fs, %0.03f/%0.03f ms/%s " + "(mean/median), std.dev %0.03f ms, " + "%0.2f/%0.2f %s/s (mean/median)\n", + bench_name, bench_nruns, bench_accum_secs, + mean_spr * 1000, med_spr * 1000, unit, std_dev * 1000, + mean_rps, med_rps, unit); + } else { + printf("%-*s %0.2f %s/s\n", BENCH_COLUMN_WIDTH, + bench_name, med_rps, unit); + } + done: + bench_name = NULL; + bench_nruns = 0; + free(bench_samples); + bench_samples = NULL; + bench_skip = 0; +} diff --git a/regress/unittests/test_helper/test_helper.h b/regress/unittests/test_helper/test_helper.h index 66302201cec3..4f7e2c87f28d 100644 --- a/regress/unittests/test_helper/test_helper.h +++ b/regress/unittests/test_helper/test_helper.h @@ -1,4 +1,4 @@ -/* $OpenBSD: test_helper.h,v 1.9 2018/10/17 23:28:05 djm Exp $ */ +/* $OpenBSD: test_helper.h,v 1.10 2025/04/15 04:00:42 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -23,9 +23,7 @@ #include "includes.h" #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #ifdef WITH_OPENSSL #include @@ -39,6 +37,7 @@ typedef void (test_onerror_func_t)(void *); /* Supplied by test suite */ void tests(void); +void benchmarks(void); const char *test_data_file(const char *name); void test_start(const char *n); @@ -49,6 +48,7 @@ int test_is_verbose(void); int test_is_quiet(void); int test_is_fast(void); int test_is_slow(void); +int test_is_benchmark(void); void test_subtest_info(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void ssl_err_check(const char *file, int line); @@ -285,6 +285,26 @@ void assert_u64(const char *file, int line, #define ASSERT_U64_GE(a1, a2) \ assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +/* Benchmarking support */ +#define BENCH_START(name) \ + do { \ + bench_start(__FILE__, __LINE__, name); \ + while (!bench_done()) { \ + bench_case_start(__FILE__, __LINE__); \ + do { +#define BENCH_FINISH(unit) \ + } while (0); \ + bench_case_finish(__FILE__, __LINE__); \ + } \ + bench_finish(__FILE__, __LINE__, unit); \ + } while (0) + +void bench_start(const char *file, int line, const char *name); +void bench_case_start(const char *file, int line); +void bench_case_finish(const char *file, int line); +void bench_finish(const char *file, int line, const char *unit); +int bench_done(void); + /* Fuzzing support */ struct fuzz; diff --git a/regress/unittests/utf8/Makefile b/regress/unittests/utf8/Makefile index f8eec0484f8f..e89536500822 100644 --- a/regress/unittests/utf8/Makefile +++ b/regress/unittests/utf8/Makefile @@ -1,14 +1,15 @@ -# $OpenBSD: Makefile,v 1.5 2017/12/21 00:41:22 djm Exp $ +# $OpenBSD: Makefile,v 1.6 2025/04/15 04:00:42 djm Exp $ PROG=test_utf8 SRCS=tests.c # From usr.bin/ssh -SRCS+=utf8.c atomicio.c +SRCS+=utf8.c atomicio.c misc.c xmalloc.c match.c ssherr.c cleanup.c fatal.c +SRCS+=sshbuf.c sshbuf-getput-basic.c sshbuf-misc.c addr.c addrmatch.c log.c REGRESS_TARGETS=run-regress-${PROG} run-regress-${PROG}: ${PROG} - env ${TEST_ENV} ./${PROG} + env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} .include diff --git a/regress/unittests/utf8/tests.c b/regress/unittests/utf8/tests.c index 8cf524ddb210..3fb63415e1ad 100644 --- a/regress/unittests/utf8/tests.c +++ b/regress/unittests/utf8/tests.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tests.c,v 1.4 2017/02/19 00:11:29 djm Exp $ */ +/* $OpenBSD: tests.c,v 1.5 2025/04/15 04:00:42 djm Exp $ */ /* * Regress test for the utf8.h *mprintf() API * @@ -102,3 +102,9 @@ tests(void) one(0, "double_fit", "a\343\201\201", 7, 5, -1, "a\\343"); one(0, "double_spc", "a\343\201\201", 13, 13, 13, "a\\343\\201\\201"); } + +void +benchmarks(void) +{ + printf("no benchmarks\n"); +} diff --git a/regress/unittests/win32compat/tests.c b/regress/unittests/win32compat/tests.c index ae27730dc757..756d6b8b394c 100644 --- a/regress/unittests/win32compat/tests.c +++ b/regress/unittests/win32compat/tests.c @@ -27,6 +27,12 @@ tests() miscellaneous_tests(); } +void +benchmarks(void) +{ + tests(); +} + char * dup_str(char *inStr) { diff --git a/sandbox-capsicum.c b/sandbox-capsicum.c index 9c329aa2ec63..ec07a7da94ca 100644 --- a/sandbox-capsicum.c +++ b/sandbox-capsicum.c @@ -54,7 +54,7 @@ ssh_sandbox_init(struct monitor *monitor) { struct ssh_sandbox *box; - debug3("%s: preparing capsicum sandbox", __func__); + debug3_f("preparing capsicum sandbox"); box = xcalloc(1, sizeof(*box)); box->m_recvfd = monitor->m_recvfd; box->m_log_sendfd = monitor->m_log_sendfd; @@ -97,13 +97,13 @@ ssh_sandbox_child(struct ssh_sandbox *box) cap_rights_init(&rights, CAP_READ, CAP_WRITE); if (cap_rights_limit(box->m_recvfd, &rights) < 0 && errno != ENOSYS) - fatal("%s: failed to limit the network socket", __func__); + fatal_f("failed to limit the network socket"); cap_rights_init(&rights, CAP_WRITE); if (cap_rights_limit(box->m_log_sendfd, &rights) < 0 && errno != ENOSYS) - fatal("%s: failed to limit the logging socket", __func__); + fatal_f("failed to limit the logging socket"); if (cap_enter() < 0 && errno != ENOSYS) - fatal("%s: failed to enter capability mode", __func__); + fatal_f("failed to enter capability mode"); } diff --git a/sandbox-darwin.c b/sandbox-darwin.c index 08f4315b035c..98a339e58ef5 100644 --- a/sandbox-darwin.c +++ b/sandbox-darwin.c @@ -49,7 +49,7 @@ ssh_sandbox_init(struct monitor *monitor) * Strictly, we don't need to maintain any state here but we need * to return non-NULL to satisfy the API. */ - debug3("%s: preparing Darwin sandbox", __func__); + debug3_f("preparing Darwin sandbox"); box = xcalloc(1, sizeof(*box)); return box; } @@ -60,10 +60,10 @@ ssh_sandbox_child(struct ssh_sandbox *box) char *errmsg; struct rlimit rl_zero; - debug3("%s: starting Darwin sandbox", __func__); + debug3_f("starting Darwin sandbox"); if (sandbox_init(kSBXProfilePureComputation, SANDBOX_NAMED, &errmsg) == -1) - fatal("%s: sandbox_init: %s", __func__, errmsg); + fatal_f("sandbox_init: %s", errmsg); /* * The kSBXProfilePureComputation still allows sockets, so diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c index b31062c2b56c..a0692dd2f5bd 100644 --- a/sandbox-seccomp-filter.c +++ b/sandbox-seccomp-filter.c @@ -49,6 +49,8 @@ #include #include +#include + #include #include #include @@ -180,12 +182,12 @@ /* Use this for both __NR_futex and __NR_futex_time64 */ # define SC_FUTEX(_nr) \ - SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAIT), \ - SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAIT_BITSET), \ - SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAKE), \ - SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_WAKE_BITSET), \ - SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_REQUEUE), \ - SC_ALLOW_FUTEX_OP(__NR_futex, FUTEX_CMP_REQUEUE) + SC_ALLOW_FUTEX_OP(_nr, FUTEX_WAIT), \ + SC_ALLOW_FUTEX_OP(_nr, FUTEX_WAIT_BITSET), \ + SC_ALLOW_FUTEX_OP(_nr, FUTEX_WAKE), \ + SC_ALLOW_FUTEX_OP(_nr, FUTEX_WAKE_BITSET), \ + SC_ALLOW_FUTEX_OP(_nr, FUTEX_REQUEUE), \ + SC_ALLOW_FUTEX_OP(_nr, FUTEX_CMP_REQUEUE) #endif /* __NR_futex || __NR_futex_time64 */ #if defined(__NR_mmap) || defined(__NR_mmap2) @@ -200,6 +202,32 @@ SC_ALLOW_ARG_MASK(_nr, 2, PROT_READ|PROT_WRITE|PROT_NONE) #endif /* __NR_mmap || __NR_mmap2 */ +/* Special handling for setsockopt(2) */ +#define SC_ALLOW_SETSOCKOPT(_level, _optname) \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_setsockopt, 0, 10), \ + /* load and test level, low word */ \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ + offsetof(struct seccomp_data, args[1]) + ARG_LO_OFFSET), \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, \ + ((_level) & 0xFFFFFFFF), 0, 7), \ + /* load and test level high word is zero */ \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ + offsetof(struct seccomp_data, args[1]) + ARG_HI_OFFSET), \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 5), \ + /* load and test optname, low word */ \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ + offsetof(struct seccomp_data, args[2]) + ARG_LO_OFFSET), \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, \ + ((_optname) & 0xFFFFFFFF), 0, 3), \ + /* load and test level high word is zero */ \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ + offsetof(struct seccomp_data, args[2]) + ARG_HI_OFFSET), \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 1), \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), \ + /* reload syscall number; all rules expect it in accumulator */ \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ + offsetof(struct seccomp_data, nr)) + /* Syscall filtering set for preauth. */ static const struct sock_filter preauth_insns[] = { /* Ensure the syscall arch convention is as expected. */ @@ -398,7 +426,23 @@ static const struct sock_filter preauth_insns[] = { #ifdef __NR_writev SC_ALLOW(__NR_writev), #endif +#ifdef __NR_getsockopt + SC_ALLOW(__NR_getsockopt), +#endif +#ifdef __NR_getsockname + SC_ALLOW(__NR_getsockname), +#endif +#ifdef __NR_getpeername + SC_ALLOW(__NR_getpeername), +#endif +#ifdef __NR_setsockopt + SC_ALLOW_SETSOCKOPT(IPPROTO_IPV6, IPV6_TCLASS), + SC_ALLOW_SETSOCKOPT(IPPROTO_IP, IP_TOS), +#endif #ifdef __NR_socketcall + SC_ALLOW_ARG(__NR_socketcall, 0, SYS_GETPEERNAME), + SC_ALLOW_ARG(__NR_socketcall, 0, SYS_GETSOCKNAME), + SC_ALLOW_ARG(__NR_socketcall, 0, SYS_GETSOCKOPT), SC_ALLOW_ARG(__NR_socketcall, 0, SYS_SHUTDOWN), SC_DENY(__NR_socketcall, EACCES), #endif @@ -442,7 +486,7 @@ ssh_sandbox_init(struct monitor *monitor) * Strictly, we don't need to maintain any state here but we need * to return non-NULL to satisfy the API. */ - debug3("%s: preparing seccomp filter sandbox", __func__); + debug3_f("preparing seccomp filter sandbox"); box = xcalloc(1, sizeof(*box)); return box; } @@ -469,7 +513,7 @@ ssh_sandbox_child_debugging(void) struct sigaction act; sigset_t mask; - debug3("%s: installing SIGSYS handler", __func__); + debug3_f("installing SIGSYS handler"); memset(&act, 0, sizeof(act)); sigemptyset(&mask); sigaddset(&mask, SIGSYS); @@ -477,7 +521,7 @@ ssh_sandbox_child_debugging(void) act.sa_sigaction = &ssh_sandbox_violation; act.sa_flags = SA_SIGINFO; if (sigaction(SIGSYS, &act, NULL) == -1) - fatal("%s: sigaction(SIGSYS): %s", __func__, strerror(errno)); + fatal_f("sigaction(SIGSYS): %s", strerror(errno)); if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) fatal("%s: sigprocmask(SIGSYS): %s", __func__, strerror(errno)); @@ -510,13 +554,13 @@ ssh_sandbox_child(struct ssh_sandbox *box) ssh_sandbox_child_debugging(); #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ - debug3("%s: setting PR_SET_NO_NEW_PRIVS", __func__); + debug3_f("setting PR_SET_NO_NEW_PRIVS"); if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) { debug("%s: prctl(PR_SET_NO_NEW_PRIVS): %s", __func__, strerror(errno)); nnp_failed = 1; } - debug3("%s: attaching seccomp filter program", __func__); + debug3_f("attaching seccomp filter program"); if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &preauth_program) == -1) debug("%s: prctl(PR_SET_SECCOMP): %s", __func__, strerror(errno)); diff --git a/scp.0 b/scp.0 index aa16f2c5c073..43acd03c53bb 100644 --- a/scp.0 +++ b/scp.0 @@ -11,7 +11,7 @@ SYNOPSIS DESCRIPTION scp copies files between hosts on a network. - scp uses the SFTP protocol over a ssh(1) connection for data transfer, + scp uses the SFTP protocol over an ssh(1) connection for data transfer, and uses the same authentication and provides the same security as a login session. @@ -30,11 +30,11 @@ DESCRIPTION The options are as follows: -3 Copies between two remote hosts are transferred through the local - host. Without this option the data is copied directly between - the two remote hosts. Note that, when using the legacy SCP - protocol (via the -O flag), this option selects batch mode for - the second host as scp cannot ask for passwords or passphrases - for both hosts. This mode is the default. + host. This mode is the default, but see also the -R option for + copying data directly between two remote hosts. Note that when + using the legacy SCP protocol (via the -O flag), this option + selects batch mode for the second host as scp cannot ask for + passwords or passphrases for both hosts. -4 Forces scp to use IPv4 addresses only. @@ -203,10 +203,12 @@ DESCRIPTION -q Quiet mode: disables the progress meter as well as warning and diagnostic messages from ssh(1). - -R Copies between two remote hosts are performed by connecting to - the origin host and executing scp there. This requires that scp - running on the origin host can authenticate to the destination - host without requiring a password. + -R Copies between two remote hosts are transferred through the local + host by default. This option instead copies between two remote + hosts by connecting to the origin host and executing scp there. + This requires that scp running on the origin host can + authenticate to the destination host without requiring a + password. -r Recursively copy entire directories. Note that scp follows symbolic links encountered in the tree traversal. @@ -268,4 +270,4 @@ CAVEATS requires careful quoting of any characters that have special meaning to the remote shell, such as quote characters. -OpenBSD 7.6 December 6, 2024 OpenBSD 7.6 +OpenBSD 7.7 October 4, 2025 OpenBSD 7.7 diff --git a/scp.1 b/scp.1 index aa2e2d8b53f8..7bce0fe6f90a 100644 --- a/scp.1 +++ b/scp.1 @@ -8,9 +8,9 @@ .\" .\" Created: Sun May 7 00:14:37 1995 ylo .\" -.\" $OpenBSD: scp.1,v 1.113 2024/12/06 15:12:56 djm Exp $ +.\" $OpenBSD: scp.1,v 1.115 2025/10/04 21:41:35 naddy Exp $ .\" -.Dd $Mdocdate: December 6 2024 $ +.Dd $Mdocdate: October 4 2025 $ .Dt SCP 1 .Os .Sh NAME @@ -35,7 +35,7 @@ copies files between hosts on a network. .Pp .Nm -uses the SFTP protocol over a +uses the SFTP protocol over an .Xr ssh 1 connection for data transfer, and uses the same authentication and provides the same security as a login session. @@ -76,15 +76,16 @@ The options are as follows: .Bl -tag -width Ds .It Fl 3 Copies between two remote hosts are transferred through the local host. -Without this option the data is copied directly between the two remote -hosts. -Note that, when using the legacy SCP protocol (via the +This mode is the default, +but see also the +.Fl R +option for copying data directly between two remote hosts. +Note that when using the legacy SCP protocol (via the .Fl O flag), this option selects batch mode for the second host as .Nm cannot ask for passwords or passphrases for both hosts. -This mode is the default. .It Fl 4 Forces .Nm @@ -278,7 +279,9 @@ Quiet mode: disables the progress meter as well as warning and diagnostic messages from .Xr ssh 1 . .It Fl R -Copies between two remote hosts are performed by connecting to the origin +Copies between two remote hosts are transferred through the local host +by default. +This option instead copies between two remote hosts by connecting to the origin host and executing .Nm there. diff --git a/scp.c b/scp.c index 0ac05b92e80b..5e58863d2fad 100644 --- a/scp.c +++ b/scp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scp.c,v 1.263 2025/03/28 06:04:07 dtucker Exp $ */ +/* $OpenBSD: scp.c,v 1.268 2025/09/25 06:23:19 jsg Exp $ */ /* * scp - secure remote copy. This is basically patched BSD rcp which * uses ssh to do the data transfer (instead of using rcmd). @@ -74,19 +74,9 @@ #include "includes.h" #include -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef HAVE_POLL_H +#include #include -#else -# ifdef HAVE_SYS_POLL_H -# include -# endif -#endif -#ifdef HAVE_SYS_TIME_H -# include -#endif +#include #include #include @@ -102,20 +92,16 @@ #else # include "openbsd-compat/glob.h" #endif -#ifdef HAVE_LIBGEN_H #include -#endif #include #ifdef HAVE_UTIL_H -# include +#include #endif #include #include #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include #include @@ -173,7 +159,7 @@ 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) */ +/* This is the program to execute for the secure connection. ("ssh" or -S) */ char *ssh_program = _PATH_SSH_PROGRAM; /* This is used to store the pid of ssh_program */ @@ -1279,6 +1265,7 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) if (mode == MODE_SFTP) { if (remin == -1 || conn == NULL) { /* Connect to dest now */ + sftp_free(conn); conn = do_sftp_connect(thost, tuser, tport, sftp_direct, &remin, &remout, &do_cmd_pid); @@ -1296,6 +1283,7 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) * scp -3 hosta:/foo hosta:/bar hostb: */ /* Connect to origin now */ + sftp_free(conn2); conn2 = do_sftp_connect(host, suser, sport, sftp_direct, &remin2, &remout2, &do_cmd_pid2); @@ -1385,6 +1373,7 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) } if (remin == -1) { /* Connect to remote now */ + sftp_free(conn); conn = do_sftp_connect(thost, tuser, tport, sftp_direct, &remin, &remout, &do_cmd_pid); @@ -1413,14 +1402,15 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) } } out: - if (mode == MODE_SFTP) - free(conn); + freeargs(&alist); free(tuser); free(thost); free(targ); free(suser); free(host); free(src); + sftp_free(conn); + sftp_free(conn2); } void @@ -1509,6 +1499,7 @@ tolocal(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) } /* Remote to local. */ if (mode == MODE_SFTP) { + sftp_free(conn); conn = do_sftp_connect(host, suser, sport, sftp_direct, &remin, &remout, &do_cmd_pid); if (conn == NULL) { @@ -1520,7 +1511,6 @@ tolocal(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) /* The protocol */ sink_sftp(1, argv[argc - 1], src, conn); - free(conn); (void) close(remin); (void) close(remout); remin = remout = -1; @@ -1540,9 +1530,11 @@ tolocal(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) (void) close(remin); remin = remout = -1; } + freeargs(&alist); free(suser); free(host); free(src); + sftp_free(conn); } /* Prepare remote path, handling ~ by assuming cwd is the homedir */ @@ -1895,7 +1887,7 @@ sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn) } /* 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 (g.gl_matchc == 0 && g.gl_pathc == 1 && g.gl_pathv[0] != NULL) { /* * If nothing matched but a path returned, then it's probably * a GLOB_NOCHECK result. Check whether the unglobbed path @@ -2212,7 +2204,7 @@ bad: run_err("%s: %s", np, strerror(errno)); /* * 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. + * desynchronise us from the peer. Use note_err() instead. */ statbytes = 0; if (showprogress) @@ -2363,7 +2355,7 @@ throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to, } /* 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 (g.gl_matchc == 0 && g.gl_pathc == 1 && g.gl_pathv[0] != NULL) { /* * If nothing matched but a path returned, then it's probably * a GLOB_NOCHECK result. Check whether the unglobbed path @@ -2573,7 +2565,7 @@ allocbuf(BUF *bp, int fd, int blksize) if (fstat(fd, &stb) == -1) { run_err("fstat: %s", strerror(errno)); - return (0); + return (NULL); } size = ROUNDUP(stb.st_blksize, blksize); if (size == 0) diff --git a/servconf.c b/servconf.c index eeffe77ce36e..3e0ce1348d87 100644 --- a/servconf.c +++ b/servconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.c,v 1.425 2025/02/25 06:25:30 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.435 2025/09/25 06:31:42 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -320,10 +320,6 @@ fill_default_server_options(ServerOptions *options) #endif servconf_add_hostkey("[default]", 0, options, _PATH_HOST_ED25519_KEY_FILE, 0); -#ifdef WITH_XMSS - servconf_add_hostkey("[default]", 0, options, - _PATH_HOST_XMSS_KEY_FILE, 0); -#endif /* WITH_XMSS */ } /* No certificates by default */ if (options->num_ports == 0) @@ -478,9 +474,9 @@ fill_default_server_options(ServerOptions *options) if (options->permit_tun == -1) options->permit_tun = SSH_TUNMODE_NO; if (options->ip_qos_interactive == -1) - options->ip_qos_interactive = IPTOS_DSCP_AF21; + options->ip_qos_interactive = IPTOS_DSCP_EF; if (options->ip_qos_bulk == -1) - options->ip_qos_bulk = IPTOS_DSCP_CS1; + options->ip_qos_bulk = IPTOS_DSCP_CS0; if (options->version_addendum == NULL) options->version_addendum = xstrdup(""); if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) @@ -1298,8 +1294,8 @@ static const struct multistate multistate_addressfamily[] = { { NULL, -1 } }; static const struct multistate multistate_permitrootlogin[] = { - { "without-password", PERMIT_NO_PASSWD }, { "prohibit-password", PERMIT_NO_PASSWD }, + { "without-password", PERMIT_NO_PASSWD }, { "forced-commands-only", PERMIT_FORCED_ONLY }, { "yes", PERMIT_YES }, { "no", PERMIT_NO }, @@ -1335,7 +1331,7 @@ process_server_config_line_depth(ServerOptions *options, char *line, struct include_list *includes) { char *str, ***chararrayptr, **charptr, *arg, *arg2, *p, *keyword; - int cmdline = 0, *intptr, value, value2, n, port, oactive, r; + int cmdline = 0, *intptr, value, value2, value3, n, port, oactive, r; int ca_only = 0, found = 0; SyslogFacility *log_facility_ptr; LogLevel *log_level_ptr; @@ -2091,25 +2087,27 @@ process_server_config_line_depth(ServerOptions *options, char *line, if (!arg || *arg == '\0') fatal("%s line %d: %s missing argument.", filename, linenum, keyword); + /* begin:rate:max */ 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) + &value, &value2, &value3)) == 3) { + if (value > value3 || value2 > 100 || value2 < 1) fatal("%s line %d: Invalid %s spec.", filename, linenum, keyword); - } else if (n != 1) + } else if (n == 1) { + value3 = value; + value = value2 = -1; + } else { 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) + } + if (value3 <= 0 || (value2 != -1 && value <= 0)) fatal("%s line %d: Invalid %s spec.", filename, linenum, keyword); + if (*activep && options->max_startups == -1) { + options->max_startups_begin = value; + options->max_startups_rate = value2; + options->max_startups = value3; + } break; case sPerSourceNetBlockSize: @@ -2129,7 +2127,7 @@ process_server_config_line_depth(ServerOptions *options, char *line, if (n != 1 && n != 2) fatal("%s line %d: Invalid %s spec.", filename, linenum, keyword); - if (*activep) { + if (*activep && options->per_source_masklen_ipv4 == -1) { options->per_source_masklen_ipv4 = value; options->per_source_masklen_ipv6 = value2; } @@ -2168,10 +2166,11 @@ process_server_config_line_depth(ServerOptions *options, char *line, case sPerSourcePenalties: while ((arg = argv_next(&ac, &av)) != NULL) { + const char *q = NULL; + found = 1; value = -1; value2 = 0; - p = NULL; /* Allow no/yes only in first position */ if (strcasecmp(arg, "no") == 0 || (value2 = (strcasecmp(arg, "yes") == 0))) { @@ -2184,35 +2183,28 @@ process_server_config_line_depth(ServerOptions *options, char *line, options->per_source_penalty.enabled == -1) options->per_source_penalty.enabled = value2; continue; - } else if (strncmp(arg, "crash:", 6) == 0) { - p = arg + 6; + } else if ((q = strprefix(arg, "crash:", 0)) != NULL) { intptr = &options->per_source_penalty.penalty_crash; - } else if (strncmp(arg, "authfail:", 9) == 0) { - p = arg + 9; + } else if ((q = strprefix(arg, "authfail:", 0)) != NULL) { intptr = &options->per_source_penalty.penalty_authfail; - } else if (strncmp(arg, "noauth:", 7) == 0) { - p = arg + 7; + } else if ((q = strprefix(arg, "noauth:", 0)) != NULL) { intptr = &options->per_source_penalty.penalty_noauth; - } else if (strncmp(arg, "grace-exceeded:", 15) == 0) { - p = arg + 15; + } else if ((q = strprefix(arg, "grace-exceeded:", 0)) != NULL) { intptr = &options->per_source_penalty.penalty_grace; - } else if (strncmp(arg, "refuseconnection:", 17) == 0) { - p = arg + 17; + } else if ((q = strprefix(arg, "refuseconnection:", 0)) != NULL) { intptr = &options->per_source_penalty.penalty_refuseconnection; - } else if (strncmp(arg, "max:", 4) == 0) { - p = arg + 4; + } else if ((q = strprefix(arg, "max:", 0)) != NULL) { intptr = &options->per_source_penalty.penalty_max; - } else if (strncmp(arg, "min:", 4) == 0) { - p = arg + 4; + } else if ((q = strprefix(arg, "min:", 0)) != NULL) { intptr = &options->per_source_penalty.penalty_min; - } else if (strncmp(arg, "max-sources4:", 13) == 0) { + } else if ((q = strprefix(arg, "max-sources4:", 0)) != NULL) { intptr = &options->per_source_penalty.max_sources4; - if ((errstr = atoi_err(arg+13, &value)) != NULL) + if ((errstr = atoi_err(q, &value)) != NULL) fatal("%s line %d: %s value %s.", filename, linenum, keyword, errstr); - } else if (strncmp(arg, "max-sources6:", 13) == 0) { + } else if ((q = strprefix(arg, "max-sources6:", 0)) != NULL) { intptr = &options->per_source_penalty.max_sources6; - if ((errstr = atoi_err(arg+13, &value)) != NULL) + if ((errstr = atoi_err(q, &value)) != NULL) fatal("%s line %d: %s value %s.", filename, linenum, keyword, errstr); } else if (strcmp(arg, "overflow:deny-all") == 0) { @@ -2232,7 +2224,7 @@ process_server_config_line_depth(ServerOptions *options, char *line, filename, linenum, keyword, arg); } /* If no value was parsed above, assume it's a time */ - if (value == -1 && (value = convtime(p)) == -1) { + if (value == -1 && (value = convtime(q)) == -1) { fatal("%s line %d: invalid %s time value.", filename, linenum, keyword); } @@ -2609,12 +2601,24 @@ process_server_config_line_depth(ServerOptions *options, char *line, if ((value = parse_ipqos(arg)) == -1) fatal("%s line %d: Bad %s value: %s", filename, linenum, keyword, arg); + if (value == INT_MIN) { + debug("%s line %d: Deprecated IPQoS value \"%s\" " + "ignored - using system default instead. Consider" + " using DSCP values.", filename, linenum, arg); + value = INT_MAX; + } 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 (value2 == INT_MIN) { + debug("%s line %d: Deprecated IPQoS value \"%s\" " + "ignored - using system default instead. Consider" + " using DSCP values.", filename, linenum, arg); + value2 = INT_MAX; + } if (*activep) { options->ip_qos_interactive = value; options->ip_qos_bulk = value2; @@ -3059,7 +3063,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) #define M_CP_STROPT(n) do {\ if (src->n != NULL && dst->n != src->n) { \ free(dst->n); \ - dst->n = src->n; \ + dst->n = xstrdup(src->n); \ } \ } while(0) #define M_CP_STRARRAYOPT(s, num_s) do {\ @@ -3404,6 +3408,7 @@ dump_config(ServerOptions *o) #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); + dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); #endif dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, diff --git a/serverloop.c b/serverloop.c index 40ddfb042b49..5d3b194d128f 100644 --- a/serverloop.c +++ b/serverloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: serverloop.c,v 1.241 2024/11/26 22:01:37 djm Exp $ */ +/* $OpenBSD: serverloop.c,v 1.244 2025/09/25 06:23:19 jsg Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -40,9 +40,7 @@ #include #include #include -#ifdef HAVE_SYS_TIME_H -# include -#endif +#include #include @@ -50,9 +48,7 @@ #include #include #include -#ifdef HAVE_POLL_H #include -#endif #include #include #include @@ -89,7 +85,8 @@ extern struct sshauthopt *auth_opts; static int no_more_sessions = 0; /* Disallow further sessions. */ -static volatile sig_atomic_t child_terminated = 0; /* The child has terminated. */ +static volatile sig_atomic_t child_terminated = 0; /* set on SIGCHLD */ +static volatile sig_atomic_t siginfo_received = 0; /* prototypes */ static void server_init_dispatch(struct ssh *); @@ -103,6 +100,14 @@ sigchld_handler(int sig) child_terminated = 1; } +#ifdef SIGINFO +static void +siginfo_handler(int sig) +{ + siginfo_received = 1; +} +#endif + static void client_alive_check(struct ssh *ssh) { @@ -285,8 +290,15 @@ static void process_output(struct ssh *ssh, int connection_out) { int r; + static int interactive = -1; /* Send any buffered packet data to the client. */ + if (interactive != !channel_has_bulk(ssh)) { + interactive = !channel_has_bulk(ssh); + debug2_f("session QoS is now %s", interactive ? + "interactive" : "non-interactive"); + ssh_packet_set_interactive(ssh, interactive); + } if ((r = ssh_packet_write_poll(ssh)) != 0) { sshpkt_fatal(ssh, r, "%s: ssh_packet_write_poll", __func__); @@ -326,9 +338,15 @@ server_loop2(struct ssh *ssh, Authctxt *authctxt) debug("Entering interactive session for SSH2."); - if (sigemptyset(&bsigset) == -1 || sigaddset(&bsigset, SIGCHLD) == -1) + if (sigemptyset(&bsigset) == -1 || + sigaddset(&bsigset, SIGCHLD) == -1) error_f("bsigset setup: %s", strerror(errno)); ssh_signal(SIGCHLD, sigchld_handler); +#ifdef SIGINFO + if (sigaddset(&bsigset, SIGINFO) == -1) + error_f("bsigset setup: %s", strerror(errno)); + ssh_signal(SIGINFO, siginfo_handler); +#endif child_terminated = 0; connection_in = ssh_packet_get_connection_in(ssh); connection_out = ssh_packet_get_connection_out(ssh); @@ -350,6 +368,10 @@ server_loop2(struct ssh *ssh, Authctxt *authctxt) if (sigprocmask(SIG_BLOCK, &bsigset, &osigset) == -1) error_f("bsigset sigprocmask: %s", strerror(errno)); collect_children(ssh); + if (siginfo_received) { + siginfo_received = 0; + channel_report_open(ssh, SYSLOG_LEVEL_INFO); + } wait_until_can_do_something(ssh, connection_in, connection_out, &pfd, &npfd_alloc, &npfd_active, &osigset, &conn_in_ready, &conn_out_ready); @@ -650,7 +672,7 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) int r, ndx, success = 0; const u_char *blob; const char *sigalg, *kex_rsa_sigalg = NULL; - u_char *sig = 0; + u_char *sig = NULL; size_t blen, slen; if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL) diff --git a/session.c b/session.c index 0308f5bd7d8c..e375782f53e4 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.341 2025/04/09 07:00:03 djm Exp $ */ +/* $OpenBSD: session.c,v 1.344 2025/09/25 02:15:39 jsg Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -36,9 +36,7 @@ #include "includes.h" #include -#ifdef HAVE_SYS_STAT_H -# include -#endif +#include #include #include #include @@ -75,9 +73,7 @@ #include "channels.h" #include "sshkey.h" #include "cipher.h" -#ifdef GSSAPI -#include "ssh-gss.h" -#endif +#include "kex.h" #include "hostfile.h" #include "auth.h" #include "auth-options.h" @@ -90,7 +86,9 @@ #include "serverloop.h" #include "canohost.h" #include "session.h" -#include "kex.h" +#ifdef GSSAPI +#include "ssh-gss.h" +#endif #include "monitor_wrap.h" #include "sftp.h" #include "atomicio.h" @@ -146,9 +144,6 @@ static int session_pty_req(struct ssh *, Session *); extern ServerOptions options; extern char *__progname; extern int debug_flag; -extern u_int utmp_len; -extern int startup_pipe; -extern void destroy_sensitive_data(void); extern struct sshbuf *loginmsg; extern struct sshauthopt *auth_opts; extern char *tun_fwd_ifnames; /* serverloop.c */ @@ -178,7 +173,6 @@ static char *auth_info_file = NULL; /* Name and directory of socket for authentication agent forwarding. */ static char *auth_sock_name = NULL; -static char *auth_sock_dir = NULL; /* removes the agent forwarding socket */ @@ -188,7 +182,6 @@ auth_sock_cleanup_proc(struct passwd *pw) if (auth_sock_name != NULL) { temporarily_use_uid(pw); unlink(auth_sock_name); - rmdir(auth_sock_dir); auth_sock_name = NULL; restore_uid(); } @@ -208,32 +201,15 @@ auth_input_request_forwarding(struct ssh *ssh, struct passwd * pw) /* Temporarily drop privileged uid for mkdir/bind. */ temporarily_use_uid(pw); - /* Allocate a buffer for the socket name, and format the name. */ - auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX"); - - /* Create private directory for socket */ - if (mkdtemp(auth_sock_dir) == NULL) { + if (agent_listener(pw->pw_dir, "sshd", &sock, &auth_sock_name) != 0) { + /* a more detailed error is already logged */ ssh_packet_send_debug(ssh, "Agent forwarding disabled: " - "mkdtemp() failed: %.100s", strerror(errno)); + "couldn't create listener socket"); restore_uid(); - free(auth_sock_dir); - auth_sock_dir = NULL; goto authsock_err; } - - xasprintf(&auth_sock_name, "%s/agent.%ld", - auth_sock_dir, (long) getpid()); - - /* Start a Unix listener on auth_sock_name. */ - sock = unix_listener(auth_sock_name, SSH_LISTEN_BACKLOG, 0); - - /* Restore the privileged uid. */ restore_uid(); - /* Check for socket/bind/listen failure. */ - if (sock < 0) - goto authsock_err; - /* Allocate a channel for the authentication agent socket. */ nc = channel_new(ssh, "auth-listener", SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, @@ -244,16 +220,9 @@ auth_input_request_forwarding(struct ssh *ssh, struct passwd * pw) authsock_err: free(auth_sock_name); - if (auth_sock_dir != NULL) { - temporarily_use_uid(pw); - rmdir(auth_sock_dir); - restore_uid(); - free(auth_sock_dir); - } if (sock != -1) close(sock); auth_sock_name = NULL; - auth_sock_dir = NULL; return 0; } @@ -529,9 +498,6 @@ do_exec_no_pty(struct ssh *ssh, Session *s, const char *command) #endif s->pid = pid; - /* Set interactive/non-interactive mode. */ - ssh_packet_set_interactive(ssh, s->display != NULL, - options.ip_qos_interactive, options.ip_qos_bulk); /* * Clear loginmsg, since it's the child's responsibility to display @@ -659,8 +625,6 @@ do_exec_pty(struct ssh *ssh, Session *s, const char *command) /* Enter interactive session. */ s->ptymaster = ptymaster; - ssh_packet_set_interactive(ssh, 1, - options.ip_qos_interactive, options.ip_qos_bulk); session_set_fds(ssh, s, ptyfd, fdout, -1, 1, 1); return 0; } diff --git a/sftp-client.c b/sftp-client.c index 59507baa6583..9958b95c61e3 100644 --- a/sftp-client.c +++ b/sftp-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-client.c,v 1.177 2025/03/11 07:48:51 dtucker Exp $ */ +/* $OpenBSD: sftp-client.c,v 1.180 2025/09/30 00:10:42 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -27,23 +27,13 @@ #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 #include #include -#ifdef HAVE_POLL_H #include -#else -# ifdef HAVE_SYS_POLL_H -# include -# endif -#endif #include #include #include @@ -616,6 +606,14 @@ sftp_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, return ret; } +void +sftp_free(struct sftp_conn *conn) +{ + if (conn == NULL) + return; + freezero(conn, sizeof(*conn)); +} + u_int sftp_proto_version(struct sftp_conn *conn) { @@ -1143,7 +1141,7 @@ sftp_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) attr.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; if ((msg = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); + fatal_f("sshbuf_new failed"); attrib_clear(&junk); /* Send empty attributes */ @@ -1154,7 +1152,7 @@ sftp_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) (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)); + fatal_fr(r, "buffer error"); send_msg(conn, msg); debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, oldpath); @@ -1175,7 +1173,7 @@ sftp_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) (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)); + fatal_fr(r, "buffer error"); send_msg(conn, msg); debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, newpath); @@ -1199,7 +1197,7 @@ sftp_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath) (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)); + fatal_fr(r, "buffer error"); send_msg(conn, msg); debug3("Sent message copy-data \"%s\" 0 0 -> \"%s\" 0", oldpath, newpath); @@ -2044,7 +2042,7 @@ sftp_upload(struct sftp_conn *conn, const char *local_path, int fsync_flag, int inplace_flag) { int r, local_fd; - u_int openmode, id, status = SSH2_FX_OK, reordered = 0; + u_int openmode, id, status = SSH2_FX_OK, status2, reordered = 0; off_t offset, progress_counter; u_char type, *handle, *data; struct sshbuf *msg; @@ -2186,9 +2184,11 @@ sftp_upload(struct sftp_conn *conn, const char *local_path, fatal("Expected SSH2_FXP_STATUS(%d) packet, " "got %d", SSH2_FXP_STATUS, type); - if ((r = sshbuf_get_u32(msg, &status)) != 0) + if ((r = sshbuf_get_u32(msg, &status2)) != 0) fatal_fr(r, "parse status"); - debug3("SSH2_FXP_STATUS %u", status); + debug3("SSH2_FXP_STATUS %u", status2); + if (status2 != SSH2_FX_OK) + status = status2; /* remember errors */ /* Find the request in our queue */ if ((ack = request_find(&acks, rid)) == NULL) diff --git a/sftp-client.h b/sftp-client.h index 74cdae7dc687..873ad3849f5b 100644 --- a/sftp-client.h +++ b/sftp-client.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-client.h,v 1.39 2023/09/08 05:56:13 djm Exp $ */ +/* $OpenBSD: sftp-client.h,v 1.40 2025/09/15 05:17:37 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller @@ -71,6 +71,7 @@ struct sftp_limits { * a pointer to a initialized sftp_conn struct on success. */ struct sftp_conn *sftp_init(int, int, u_int, u_int, u_int64_t); +void sftp_free(struct sftp_conn *); u_int sftp_proto_version(struct sftp_conn *); diff --git a/sftp-glob.c b/sftp-glob.c index 1b82759b04d6..e054e75e80af 100644 --- a/sftp-glob.c +++ b/sftp-glob.c @@ -18,9 +18,7 @@ #include "includes.h" #include -#ifdef HAVE_SYS_STAT_H -# include -#endif +#include #include #include diff --git a/sftp-server.0 b/sftp-server.0 index f86aaf12914b..273b69908c66 100644 --- a/sftp-server.0 +++ b/sftp-server.0 @@ -95,4 +95,4 @@ HISTORY AUTHORS Markus Friedl -OpenBSD 7.6 July 27, 2021 OpenBSD 7.6 +OpenBSD 7.7 July 27, 2021 OpenBSD 7.7 diff --git a/sftp-server.c b/sftp-server.c index 845a274ce5aa..c8f3f1f4a549 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp-server.c,v 1.148 2024/04/30 06:23:51 djm Exp $ */ +/* $OpenBSD: sftp-server.c,v 1.149 2025/09/02 09:26:21 djm Exp $ */ /* * Copyright (c) 2000-2004 Markus Friedl. All rights reserved. * @@ -20,9 +20,7 @@ #include #include #include -#ifdef HAVE_SYS_TIME_H -# include -#endif +#include #ifdef HAVE_SYS_MOUNT_H #include #endif @@ -33,9 +31,7 @@ #include #include #include -#ifdef HAVE_POLL_H #include -#endif #include #include #include @@ -1644,7 +1640,7 @@ process_extended_copy_data(u_int32_t id) (r = sshbuf_get_u64(iqueue, &read_len)) != 0 || (r = get_handle(iqueue, &write_handle)) != 0 || (r = sshbuf_get_u64(iqueue, &write_off)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); debug("request %u: copy-data from \"%s\" (handle %d) off %llu len %llu " "to \"%s\" (handle %d) off %llu", @@ -1672,14 +1668,14 @@ process_extended_copy_data(u_int32_t id) if (lseek(read_fd, read_off, SEEK_SET) < 0) { status = errno_to_portable(errno); - error("%s: read_seek failed", __func__); + error_f("read_seek failed"); goto out; } if ((handle_to_flags(write_handle) & O_APPEND) == 0 && lseek(write_fd, write_off, SEEK_SET) < 0) { status = errno_to_portable(errno); - error("%s: write_seek failed", __func__); + error_f("write_seek failed"); goto out; } @@ -1694,7 +1690,7 @@ process_extended_copy_data(u_int32_t id) break; } else if (ret == 0) { status = errno_to_portable(errno); - error("%s: read failed: %s", __func__, strerror(errno)); + error_f("read failed: %s", strerror(errno)); break; } len = ret; diff --git a/sftp.0 b/sftp.0 index 04fda74de4dd..d6648ac26ab0 100644 --- a/sftp.0 +++ b/sftp.0 @@ -474,4 +474,4 @@ SEE ALSO T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh- filexfer-00.txt, January 2001, work in progress material. -OpenBSD 7.6 December 6, 2024 OpenBSD 7.6 +OpenBSD 7.7 December 6, 2024 OpenBSD 7.7 diff --git a/sftp.c b/sftp.c index 812a5da4bc4d..13aecb65e25d 100644 --- a/sftp.c +++ b/sftp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sftp.c,v 1.240 2025/03/28 06:04:07 dtucker Exp $ */ +/* $OpenBSD: sftp.c,v 1.245 2025/10/02 04:23:11 djm Exp $ */ /* * Copyright (c) 2001-2004 Damien Miller * @@ -19,9 +19,7 @@ #include #include -#ifdef HAVE_SYS_STAT_H -# include -#endif +#include #include #include #ifdef HAVE_SYS_STATVFS_H @@ -32,11 +30,9 @@ #include #ifdef HAVE_PATHS_H -# include +#include #endif -#ifdef HAVE_LIBGEN_H #include -#endif #ifdef HAVE_LOCALE_H # include #endif @@ -55,7 +51,7 @@ typedef void EditLine; #include #ifdef HAVE_UTIL_H -# include +#include #endif #include "xmalloc.h" @@ -1912,7 +1908,7 @@ complete_display(char **list, u_int len) /* * Given a "list" of words that begin with a common prefix of "word", - * attempt to find an autocompletion to extends "word" by the next + * attempt to find an autocompletion that extends "word" by the next * characters common to all entries in "list". */ static char * @@ -2404,6 +2400,8 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) free(conn); #ifdef USE_LIBEDIT + if (hl != NULL) + history_end(hl); if (el != NULL) el_end(el); #endif /* USE_LIBEDIT */ @@ -2742,7 +2740,7 @@ main(int argc, char **argv) } else { if ((r = argv_split(sftp_direct, &tmp, &cpp, 1)) != 0) fatal_r(r, "Parse -D arguments"); - if (cpp[0] == 0) + if (cpp[0] == NULL) fatal("No sftp server specified via -D"); connect_to_server(cpp[0], cpp, &in, &out); argv_free(cpp, tmp); diff --git a/sk-api.h b/sk-api.h index 08f567a9e271..32d0f118b9b1 100644 --- a/sk-api.h +++ b/sk-api.h @@ -19,9 +19,7 @@ #define _SK_API_H 1 #include -#ifdef HAVE_STDINT_H #include -#endif /* Flags */ #define SSH_SK_USER_PRESENCE_REQD 0x01 diff --git a/sk-usbhid.c b/sk-usbhid.c index 6662734e35d6..c39f7eaefa86 100644 --- a/sk-usbhid.c +++ b/sk-usbhid.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sk-usbhid.c,v 1.47 2024/12/03 08:31:49 djm Exp $ */ +/* $OpenBSD: sk-usbhid.c,v 1.48 2025/05/12 05:41:20 tb Exp $ */ /* * Copyright (c) 2019 Markus Friedl * Copyright (c) 2020 Pedro Martelletto @@ -20,9 +20,7 @@ #ifdef ENABLE_SK_INTERNAL -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include #include @@ -49,6 +47,7 @@ #include #include #include +#include "openbsd-compat/openssl-compat.h" #endif /* WITH_OPENSSL */ #include @@ -636,8 +635,8 @@ pack_public_key_ecdsa(const fido_cred_t *cred, skdebug(__func__, "BN_bin2bn failed"); goto out; } - if (EC_POINT_set_affine_coordinates_GFp(g, q, x, y, NULL) != 1) { - skdebug(__func__, "EC_POINT_set_affine_coordinates_GFp failed"); + if (EC_POINT_set_affine_coordinates(g, q, x, y, NULL) != 1) { + skdebug(__func__, "EC_POINT_set_affine_coordinates failed"); goto out; } response->public_key_len = EC_POINT_point2oct(g, q, diff --git a/srclimit.c b/srclimit.c index c63a462e2783..c62763724b53 100644 --- a/srclimit.c +++ b/srclimit.c @@ -119,7 +119,7 @@ srclimit_init(int max, int persource, int ipv4len, int ipv6len, debug("%s: max connections %d, per source %d, masks %d,%d", __func__, max, persource, ipv4len, ipv6len); if (max <= 0) - fatal("%s: invalid number of sockets: %d", __func__, max); + fatal_f("invalid number of sockets: %d", max); children = xcalloc(max_children, sizeof(*children)); for (i = 0; i < max_children; i++) children[i].id = -1; @@ -136,7 +136,7 @@ srclimit_check_allow(int sock, int id) if (max_persource == INT_MAX) /* no limit */ return 1; - debug("%s: sock %d id %d limit %d", __func__, sock, id, max_persource); + debug_f("sock %d id %d limit %d", sock, id, max_persource); if (srclimit_peer_addr(sock, &xa) != 0) return 1; bits = xa.af == AF_INET ? ipv4_masklen : ipv6_masklen; @@ -154,14 +154,14 @@ srclimit_check_allow(int sock, int id) } } if (addr_ntop(&xa, xas, sizeof(xas)) != 0) { - debug3("%s: addr ntop failed", __func__); + debug3_f("addr ntop failed"); return 1; } debug3("%s: new unauthenticated connection from %s/%d, at %d of %d", __func__, xas, bits, count, max_persource); if (first_unused == max_children) { /* no free slot found */ - debug3("%s: no free slot", __func__); + debug3_f("no free slot"); return 0; } if (first_unused < 0 || first_unused >= max_children) @@ -185,7 +185,7 @@ srclimit_done(int id) if (max_persource == INT_MAX) /* no limit */ return; - debug("%s: id %d", __func__, id); + debug_f("id %d", id); /* Clear corresponding state entry. */ for (i = 0; i < max_children; i++) { if (children[i].id == id) { @@ -427,7 +427,9 @@ srclimit_penalise(struct xaddr *addr, int penalty_type) penalty->active = 1; if (RB_INSERT(penalties_by_expiry, by_expiry, penalty) != NULL) fatal_f("internal error: %s penalty tables corrupt", t); - verbose_f("%s: new %s %s penalty of %d seconds for %s", t, + do_log2_f(penalty->active ? + SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_VERBOSE, + "%s: new %s %s penalty of %d seconds for %s", t, addrnetmask, penalty->active ? "active" : "deferred", penalty_secs, reason); if (++(*npenaltiesp) > (size_t)max_sources) @@ -446,7 +448,7 @@ srclimit_penalise(struct xaddr *addr, int penalty_type) existing->expiry = now + penalty_cfg.penalty_max; if (existing->expiry - now > penalty_cfg.penalty_min && !existing->active) { - verbose_f("%s: activating %s penalty of %lld seconds for %s", + logit_f("%s: activating %s penalty of %lld seconds for %s", addrnetmask, t, (long long)(existing->expiry - now), reason); existing->active = 1; diff --git a/ssh-add.0 b/ssh-add.0 index af9901186c7a..a6b655df728a 100644 --- a/ssh-add.0 +++ b/ssh-add.0 @@ -4,7 +4,7 @@ NAME ssh-add M-bM-^@M-^S adds private key identities to the OpenSSH authentication agent SYNOPSIS - ssh-add [-CcDdKkLlqvXx] [-E fingerprint_hash] [-H hostkey_file] + ssh-add [-CcDdKkLlNqvXx] [-E fingerprint_hash] [-H hostkey_file] [-h destination_constraint] [-S provider] [-t life] [file ...] ssh-add -s pkcs11 [-Cv] [certificate ...] ssh-add -e pkcs11 @@ -120,6 +120,12 @@ DESCRIPTION -l Lists fingerprints of all identities currently represented by the agent. + -N When adding certificates, by default ssh-add will request that + the agent automatically delete the certificate shortly after the + certificate's expiry date. This flag suppresses this behaviour + and does not specify a lifetime for certificates added to an + agent. + -q Be quiet after a successful operation. -S provider @@ -206,4 +212,4 @@ AUTHORS created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. -OpenBSD 7.6 June 17, 2024 OpenBSD 7.6 +OpenBSD 7.7 September 11, 2025 OpenBSD 7.7 diff --git a/ssh-add.1 b/ssh-add.1 index c31de4dd9daf..babe78040f3d 100644 --- a/ssh-add.1 +++ b/ssh-add.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-add.1,v 1.87 2024/06/17 08:30:29 djm Exp $ +.\" $OpenBSD: ssh-add.1,v 1.88 2025/09/11 02:54:42 djm Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -35,7 +35,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: June 17 2024 $ +.Dd $Mdocdate: September 11 2025 $ .Dt SSH-ADD 1 .Os .Sh NAME @@ -43,7 +43,7 @@ .Nd adds private key identities to the OpenSSH authentication agent .Sh SYNOPSIS .Nm ssh-add -.Op Fl CcDdKkLlqvXx +.Op Fl CcDdKkLlNqvXx .Op Fl E Ar fingerprint_hash .Op Fl H Ar hostkey_file .Op Fl h Ar destination_constraint @@ -223,6 +223,13 @@ 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 N +When adding certificates, by default +.Nm +will request that the agent automatically delete the certificate shortly +after the certificate's expiry date. +This flag suppresses this behaviour and does not specify a lifetime for +certificates added to an agent. .It Fl q Be quiet after a successful operation. .It Fl S Ar provider diff --git a/ssh-add.c b/ssh-add.c index b90ae87b8455..9d98d55ff652 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-add.c,v 1.173 2024/09/06 02:30:44 djm Exp $ */ +/* $OpenBSD: ssh-add.c,v 1.181 2025/09/29 03:17:54 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -54,6 +54,7 @@ #include #include #include +#include #include "xmalloc.h" #include "ssh.h" @@ -70,6 +71,8 @@ #include "sk-api.h" #include "hostfile.h" +#define CERT_EXPIRY_GRACE (5*60) + /* argv0 */ extern char *__progname; @@ -84,10 +87,6 @@ static char *default_files[] = { #endif /* WITH_OPENSSL */ _PATH_SSH_CLIENT_ID_ED25519, _PATH_SSH_CLIENT_ID_ED25519_SK, - _PATH_SSH_CLIENT_ID_XMSS, -#ifdef WITH_DSA - _PATH_SSH_CLIENT_ID_DSA, -#endif NULL }; @@ -99,10 +98,6 @@ 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 @@ -242,20 +237,37 @@ delete_all(int agent_fd, int qflag) return ret; } +static int +check_cert_lifetime(const struct sshkey *cert, int cert_lifetime) +{ + time_t now; + uint64_t n; + + if (cert == NULL || cert->cert == NULL || !sshkey_is_cert(cert) || + cert->cert->valid_before == 0xFFFFFFFFFFFFFFFFULL) + return cert_lifetime; + if ((now = time(NULL)) <= 0) + fatal_f("system time is at/before epoch"); + if ((uint64_t)now > (cert->cert->valid_before + CERT_EXPIRY_GRACE)) + return -1; /* certificate already expired */ + n = (CERT_EXPIRY_GRACE + cert->cert->valid_before) - (uint64_t)now; + n = MINIMUM(n, INT_MAX); + if (cert_lifetime <= 0) + return (int)n; + return MINIMUM(cert_lifetime, (int)n); +} + static int add_file(int agent_fd, const char *filename, int key_only, int cert_only, - int qflag, const char *skprovider, + int qflag, int Nflag, const char *skprovider, struct dest_constraint **dest_constraints, size_t ndest_constraints) { - struct sshkey *private, *cert; + struct sshkey *private = NULL, *cert = NULL; char *comment = NULL; char msg[1024], *certpath = NULL; - int r, fd, ret = -1; - size_t i; - u_int32_t left; + int cert_lifetime, r, fd, ret = -1; struct sshbuf *keyblob; - struct ssh_identitylist *idlist; if (strcmp(filename, "-") == 0) { fd = STDIN_FILENO; @@ -331,37 +343,6 @@ add_file(int agent_fd, const char *filename, int key_only, int cert_only, 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); - } #ifndef WINDOWS if (sshkey_is_sk(private)) { if (skprovider == NULL) { @@ -377,26 +358,28 @@ add_file(int agent_fd, const char *filename, int key_only, int cert_only, if (!sshkey_is_sk(private)) skprovider = NULL; #endif - 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"); + + if (!cert_only) { + if ((r = ssh_add_identity_constrained(agent_fd, private, + comment, lifetime, confirm, 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 %s\n", + fmt_timeframe((time_t)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)); } - } else { - fprintf(stderr, "Could not add identity \"%s\": %s\n", - filename, ssh_err(r)); } /* Skip trying to load the cert if requested */ @@ -415,25 +398,28 @@ add_file(int agent_fd, const char *filename, int key_only, int cert_only, if (!sshkey_equal_public(cert, private)) { error("Certificate %s does not match private key %s", certpath, filename); - sshkey_free(cert); + goto out; + } + + cert_lifetime = lifetime; + if (!Nflag && + (cert_lifetime = check_cert_lifetime(cert, cert_lifetime)) == -1) { + logit("Certificate %s has already expired; ignored", certpath); 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); - + /* send to agent */ if ((r = ssh_add_identity_constrained(agent_fd, private, comment, - lifetime, confirm, maxsign, skprovider, + cert_lifetime, confirm, skprovider, dest_constraints, ndest_constraints)) != 0) { error_r(r, "Certificate %s (%s) add failed", certpath, private->cert->key_id); @@ -443,9 +429,9 @@ add_file(int agent_fd, const char *filename, int key_only, int cert_only, 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 (cert_lifetime != 0) { + fprintf(stderr, "Lifetime set to %s\n", + fmt_timeframe((time_t)cert_lifetime)); } if (confirm != 0) { fprintf(stderr, "The user must confirm each use " @@ -456,6 +442,7 @@ add_file(int agent_fd, const char *filename, int key_only, int cert_only, out: free(certpath); free(comment); + sshkey_free(cert); sshkey_free(private); return ret; @@ -537,7 +524,6 @@ 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) { @@ -562,12 +548,7 @@ list_identities(int agent_fd, int do_fp) 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"); + fprintf(stdout, " %s\n", idlist->comments[i]); } } ssh_free_identitylist(idlist); @@ -626,7 +607,7 @@ load_resident_keys(int agent_fd, const char *skprovider, int qflag, fingerprint_hash, SSH_FP_DEFAULT)) == NULL) fatal_f("sshkey_fingerprint failed"); if ((r = ssh_add_identity_constrained(agent_fd, key, "", - lifetime, confirm, maxsign, skprovider, + lifetime, confirm, skprovider, dest_constraints, ndest_constraints)) != 0) { error("Unable to add key %s %s", sshkey_type(key), fp); @@ -658,7 +639,7 @@ load_resident_keys(int agent_fd, const char *skprovider, int qflag, static int do_file(int agent_fd, int deleting, int key_only, int cert_only, - char *file, int qflag, const char *skprovider, + char *file, int qflag, int Nflag, const char *skprovider, struct dest_constraint **dest_constraints, size_t ndest_constraints) { if (deleting) { @@ -666,7 +647,7 @@ do_file(int agent_fd, int deleting, int key_only, int cert_only, cert_only, qflag) == -1) return -1; } else { - if (add_file(agent_fd, file, key_only, cert_only, qflag, + if (add_file(agent_fd, file, key_only, cert_only, qflag, Nflag, skprovider, dest_constraints, ndest_constraints) == -1) return -1; } @@ -689,6 +670,47 @@ stringlist_append(char ***listp, const char *s) (*listp)[i] = xstrdup(s); } +static void +stringlist_free(char **list) +{ + size_t i = 0; + + if (list == NULL) + return; + for (i = 0; list[i] != NULL; i++) + free(list[i]); + free(list); +} + +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[i]); + } + free(dcs); +} + + static void parse_dest_constraint_hop(const char *s, struct dest_constraint_hop *dch, char **hostkey_files) @@ -802,9 +824,6 @@ usage(void) "usage: ssh-add [-CcDdKkLlqvXx] [-E fingerprint_hash] [-H hostkey_file]\n" " [-h destination_constraint] [-S provider] [-t life]\n" #endif -#ifdef WITH_XMSS -" [-M maxsign] [-m minleft]\n" -#endif " [file ...]\n" " ssh-add -s pkcs11 [-Cv] [certificate ...]\n" " ssh-add -e pkcs11\n" @@ -822,12 +841,12 @@ main(int argc, char **argv) char **dest_constraint_strings = NULL, **hostkey_files = NULL; 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; + int qflag = 0, Tflag = 0, Nflag = 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, ncerts = 0; + size_t n, ndest_constraints = 0, ncerts = 0; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); @@ -855,9 +874,9 @@ main(int argc, char **argv) skprovider = getenv("SSH_SK_PROVIDER"); #ifdef WINDOWS - while ((ch = getopt(argc, argv, "vkKlLcdDTxXE:e:M:m:qs:S:t:")) != -1) { + while ((ch = getopt(argc, argv, "vkKlLNcdDTxXE:e:M:m:qs:S:t:")) != -1) { #else - while ((ch = getopt(argc, argv, "vkKlLCcdDTxXE:e:h:H:M:m:qs:S:t:")) != -1) { + while ((ch = getopt(argc, argv, "vkKlLNCcdDTxXE:e:h:H:M:m:qs:S:t:")) != -1) { #endif switch (ch) { case 'v': @@ -866,6 +885,9 @@ main(int argc, char **argv) else if (log_level < SYSLOG_LEVEL_DEBUG3) log_level++; break; + case 'N': + Nflag = 1; + break; case 'E': fingerprint_hash = ssh_digest_alg_by_name(optarg); if (fingerprint_hash == -1) @@ -904,20 +926,8 @@ main(int argc, char **argv) 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; - } + /* deprecated */ break; case 'd': deleting = 1; @@ -1017,6 +1027,9 @@ main(int argc, char **argv) dest_constraints, ndest_constraints, certs, ncerts) == -1) ret = 1; + for (n = 0; n < ncerts; n++) + sshkey_free(certs[n]); + free(certs); goto done; } if (do_download) { @@ -1046,7 +1059,7 @@ main(int argc, char **argv) if (stat(buf, &st) == -1) continue; if (do_file(agent_fd, deleting, key_only, cert_only, - buf, qflag, skprovider, + buf, qflag, Nflag, skprovider, dest_constraints, ndest_constraints) == -1) ret = 1; else @@ -1057,13 +1070,16 @@ main(int argc, char **argv) } else { for (i = 0; i < argc; i++) { if (do_file(agent_fd, deleting, key_only, cert_only, - argv[i], qflag, skprovider, + argv[i], qflag, Nflag, skprovider, dest_constraints, ndest_constraints) == -1) ret = 1; } } done: clear_pass(); + stringlist_free(hostkey_files); + stringlist_free(dest_constraint_strings); + free_dest_constraints(dest_constraints, ndest_constraints); ssh_close_authentication_socket(agent_fd); return ret; } diff --git a/ssh-agent.0 b/ssh-agent.0 index 03006198f776..95d4da4bc406 100644 --- a/ssh-agent.0 +++ b/ssh-agent.0 @@ -4,11 +4,12 @@ NAME ssh-agent M-bM-^@M-^S OpenSSH authentication agent SYNOPSIS - ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash] + ssh-agent [-c | -s] [-DdTU] [-a bind_address] [-E fingerprint_hash] [-O option] [-P allowed_providers] [-t life] - ssh-agent [-a bind_address] [-E fingerprint_hash] [-O option] + ssh-agent [-TU] [-a bind_address] [-E fingerprint_hash] [-O option] [-P allowed_providers] [-t life] command [arg ...] ssh-agent [-c | -s] -k + ssh-agent -u DESCRIPTION ssh-agent is a program to hold private keys used for public key @@ -20,7 +21,8 @@ DESCRIPTION -a bind_address Bind the agent to the UNIX-domain socket bind_address. The - default is $TMPDIR/ssh-XXXXXXXXXX/agent.. + default is to create a socket at a random path matching + $HOME/.ssh/agent/s.*. -c Generate C-shell commands on standard output. This is the default if SHELL looks like it's a csh style of shell. @@ -54,8 +56,8 @@ DESCRIPTION signatures using FIDO keys that might be web authentication requests. By default, ssh-agent refuses signature requests for FIDO keys where the key application string does not start with - M-bM-^@M-^\ssh:M-bM-^@M-^] and when the data to be signed does not appear to be a - ssh(1) user authentication request or a ssh-keygen(1) signature. + M-bM-^@M-^\ssh:M-bM-^@M-^] and when the data to be signed does not appear to be an + ssh(1) user authentication request or an ssh-keygen(1) signature. The default behaviour prevents forwarded access to a FIDO key from also implicitly forwarding the ability to authenticate to websites. @@ -81,6 +83,11 @@ DESCRIPTION -s Generate Bourne shell commands on standard output. This is the default if SHELL does not look like it's a csh style of shell. + -T Bind the agent socket in a randomised subdirectory of the form + $TMPDIR/ssh-XXXXXXXXXX/agent., instead of the default + behaviour of using a randomised name matching + $HOME/.ssh/agent/s.*. + -t life Set a default value for the maximum lifetime of identities added to the agent. The lifetime may be specified in seconds or in a @@ -88,6 +95,14 @@ DESCRIPTION for an identity with ssh-add(1) overrides this value. Without this option the default maximum lifetime is forever. + -U Instructs ssh-agent not to clean up stale agent sockets under + $HOME/.ssh/agent/. + + -u Instructs ssh-agent to only clean up stale agent sockets under + $HOME/.ssh/agent/ and then exit immediately. If this option is + given twice, ssh-agent will delete stale agent sockets regardless + of the host name that created them. + command [arg ...] If a command (and optional arguments) is given, this is executed as a subprocess of the agent. The agent exits automatically when @@ -143,7 +158,7 @@ ENVIRONMENT another instance of the same user. FILES - $TMPDIR/ssh-XXXXXXXXXX/agent. + $HOME/.ssh/agent/s.* UNIX-domain sockets used to contain the connection to the authentication agent. These sockets should only be readable by the owner. The sockets should get automatically removed when the @@ -159,4 +174,4 @@ AUTHORS created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. -OpenBSD 7.6 February 9, 2025 OpenBSD 7.6 +OpenBSD 7.7 October 4, 2025 OpenBSD 7.7 diff --git a/ssh-agent.1 b/ssh-agent.1 index 533ad6d3a6d2..f77a6cdd58f0 100644 --- a/ssh-agent.1 +++ b/ssh-agent.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-agent.1,v 1.82 2025/02/09 18:24:08 schwarze Exp $ +.\" $OpenBSD: ssh-agent.1,v 1.86 2025/10/04 21:41:35 naddy Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -34,7 +34,7 @@ .\" (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 9 2025 $ +.Dd $Mdocdate: October 4 2025 $ .Dt SSH-AGENT 1 .Os .Sh NAME @@ -43,13 +43,14 @@ .Sh SYNOPSIS .Nm ssh-agent .Op Fl c | s -.Op Fl \&Dd +.Op Fl \&DdTU .Op Fl a Ar bind_address .Op Fl E Ar fingerprint_hash .Op Fl O Ar option .Op Fl P Ar allowed_providers .Op Fl t Ar life .Nm ssh-agent +.Op Fl TU .Op Fl a Ar bind_address .Op Fl E Ar fingerprint_hash .Op Fl O Ar option @@ -59,6 +60,8 @@ .Nm ssh-agent .Op Fl c | s .Fl k +.Nm ssh-agent +.Fl u .Sh DESCRIPTION .Nm is a program to hold private keys used for public key authentication. @@ -74,8 +77,8 @@ Bind the agent to the .Ux Ns -domain socket .Ar bind_address . -The default is -.Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt . +The default is to create a socket at a random path matching +.Pa $HOME/.ssh/agent/s.* . .It Fl c Generate C-shell commands on standard output. This is the default if @@ -136,9 +139,9 @@ By default, refuses signature requests for FIDO keys where the key application string does not start with .Dq ssh: -and when the data to be signed does not appear to be a +and when the data to be signed does not appear to be an .Xr ssh 1 -user authentication request or a +user authentication request or an .Xr ssh-keygen 1 signature. The default behaviour prevents forwarded access to a FIDO key from also @@ -173,6 +176,11 @@ Generate Bourne shell commands on standard output. This is the default if .Ev SHELL does not look like it's a csh style of shell. +.It Fl T +Bind the agent socket in a randomised subdirectory of the form +.Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt , +instead of the default behaviour of using a randomised name matching +.Pa $HOME/.ssh/agent/s.* . .It Fl t Ar life Set a default value for the maximum lifetime of identities added to the agent. The lifetime may be specified in seconds or in a time format specified in @@ -181,6 +189,20 @@ A lifetime specified for an identity with .Xr ssh-add 1 overrides this value. Without this option the default maximum lifetime is forever. +.It Fl U +Instructs +.Nm +not to clean up stale agent sockets under +.Pa $HOME/.ssh/agent/ . +.It Fl u +Instructs +.Nm +to only clean up stale agent sockets under +.Pa $HOME/.ssh/agent/ +and then exit immediately. +If this option is given twice, +.Nm +will delete stale agent sockets regardless of the host name that created them. .It Ar command Op Ar arg ... If a command (and optional arguments) is given, this is executed as a subprocess of the agent. @@ -286,7 +308,7 @@ but is easily abused by root or another instance of the same user. .El .Sh FILES .Bl -tag -width Ds -.It Pa $TMPDIR/ssh-XXXXXXXXXX/agent. +.It Pa $HOME/.ssh/agent/s.* .Ux Ns -domain sockets used to contain the connection to the authentication agent. These sockets should only be readable by the owner. diff --git a/ssh-agent.c b/ssh-agent.c index c27c5a956f2c..df241379c0b1 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-agent.c,v 1.310 2025/02/18 08:02:48 djm Exp $ */ +/* $OpenBSD: ssh-agent.c,v 1.313 2025/08/29 03:50:38 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -41,12 +41,8 @@ #include #include #include -#ifdef HAVE_SYS_TIME_H -# include -#endif -#ifdef HAVE_SYS_UN_H -# include -#endif +#include +#include #include "openbsd-compat/sys-queue.h" #ifdef WITH_OPENSSL @@ -57,12 +53,8 @@ #include #include #include -#ifdef HAVE_PATHS_H -# include -#endif -#ifdef HAVE_POLL_H -# include -#endif +#include +#include #include #include #include @@ -70,9 +62,7 @@ #include #include #include -#ifdef HAVE_UTIL_H -# include -#endif +#include #include "xmalloc.h" #include "ssh.h" @@ -644,8 +634,7 @@ process_request_identities(SocketEntry *e) /* 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 || + if ((r = sshkey_puts(id->key, keys)) != 0 || (r = sshbuf_put_cstring(keys, id->comment)) != 0) { error_fr(r, "compose key/comment"); continue; @@ -1292,7 +1281,7 @@ parse_key_constraints(struct sshbuf *m, struct sshkey *k, time_t *deathp, { u_char ctype; int r; - u_int seconds, maxsign = 0; + u_int seconds; while (sshbuf_len(m)) { if ((r = sshbuf_get_u8(m, &ctype)) != 0) { @@ -1321,26 +1310,6 @@ parse_key_constraints(struct sshbuf *m, struct sshkey *k, time_t *deathp, } *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, @@ -2208,20 +2177,23 @@ static void usage(void) { fprintf(stderr, - "usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n" + "usage: ssh-agent [-c | -s] [-DdTU] [-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" + " ssh-agent [-TU] [-a bind_address] [-E fingerprint_hash] [-O option]\n" " [-P allowed_providers] [-t life] command [arg ...]\n" - " ssh-agent [-c | -s] -k\n"); + " ssh-agent [-c | -s] -k\n" + " ssh-agent -u\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 c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0; + int s_flag = 0, T_flag = 0, u_flag = 0, U_flag = 0; int sock = -1, ch, result, saved_errno; - char *shell, *format, *fdstr, *pidstr, *agentsocket = NULL; + char *homedir = NULL, *shell, *format, *pidstr, *agentsocket = NULL; + char *fdstr; const char *errstr = NULL; const char *ccp; #ifdef HAVE_SETRLIMIT @@ -2238,6 +2210,7 @@ main(int ac, char **av) size_t npfd = 0; u_int maxfds; sigset_t nsigset, osigset; + int socket_activated = 0; /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ sanitise_stdfd(); @@ -2256,7 +2229,7 @@ main(int ac, char **av) __progname = ssh_get_progname(av[0]); seed_rng(); - while ((ch = getopt(ac, av, "cDdksE:a:O:P:t:")) != -1) { + while ((ch = getopt(ac, av, "cDdksTuUE:a:O:P:t:")) != -1) { switch (ch) { case 'E': fingerprint_hash = ssh_digest_alg_by_name(optarg); @@ -2313,6 +2286,15 @@ main(int ac, char **av) usage(); } break; + case 'T': + T_flag++; + break; + case 'u': + u_flag++; + break; + case 'U': + U_flag++; + break; default: usage(); } @@ -2320,9 +2302,14 @@ main(int ac, char **av) ac -= optind; av += optind; - if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || D_flag)) + if (ac > 0 && + (c_flag || k_flag || s_flag || d_flag || D_flag || u_flag)) usage(); + log_init(__progname, + d_flag ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO, + SYSLOG_FACILITY_AUTH, 1); + if (allowed_providers == NULL) allowed_providers = xstrdup(DEFAULT_ALLOWED_PROVIDERS); if (websafe_allowlist == NULL) @@ -2358,6 +2345,14 @@ main(int ac, char **av) printf("echo Agent pid %ld killed;\n", (long)pid); exit(0); } + if (u_flag) { + if ((homedir = get_homedir()) == NULL) + fatal("Couldn't determine home directory"); + agent_cleanup_stale(homedir, u_flag > 1); + printf("Deleted stale agent sockets in ~/%s\n", + _PATH_SSH_AGENT_SOCKET_DIR); + exit(0); + } /* * Minimum file descriptors: @@ -2389,24 +2384,55 @@ main(int ac, char **av) fatal("bad LISTEN_PID: %d vs pid %d", pid, getpid()); debug("using socket activation on fd=3"); sock = 3; - } - - /* Otherwise, create private directory for agent socket */ - if (sock == -1) { - if (agentsocket == NULL) { + socket_activated = 1; + } + + if (sock == -1 && agentsocket == NULL && !T_flag) { + /* Default case: ~/.ssh/agent/[socket] */ + if ((homedir = get_homedir()) == NULL) + fatal("Couldn't determine home directory"); + if (!U_flag) + agent_cleanup_stale(homedir, 0); + if (agent_listener(homedir, "agent", &sock, &agentsocket) != 0) + fatal_f("Couldn't prepare agent socket"); + if (strlcpy(socket_name, agentsocket, + sizeof(socket_name)) >= sizeof(socket_name)) { + fatal_f("Socket path \"%s\" too long", + agentsocket); + } + free(homedir); + free(agentsocket); + agentsocket = NULL; + } else if (sock == -1) { + if (T_flag) { + /* + * Create private directory for agent socket + * in $TMPDIR. + */ 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); + 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); + if (strlcpy(socket_name, agentsocket, + sizeof(socket_name)) >= sizeof(socket_name)) { + fatal_f("Socket path \"%s\" too long", + agentsocket); + } + } + /* Listen on socket */ + prev_mask = umask(0177); + if ((sock = unix_listener(socket_name, + SSH_LISTEN_BACKLOG, 0)) < 0) { + *socket_name = '\0'; /* Don't unlink existing file */ + cleanup_exit(1); } + umask(prev_mask); } closefrom(sock == -1 ? STDERR_FILENO + 1 : sock + 1); @@ -2522,11 +2548,12 @@ main(int ac, char **av) sigprocmask(SIG_BLOCK, &nsigset, &osigset); if (signalled_exit != 0) { logit("exiting on signal %d", (int)signalled_exit); - cleanup_exit(2); + cleanup_exit((signalled_exit == SIGTERM && + socket_activated) ? 0 : 2); } if (signalled_keydrop) { logit("signal %d received; removing all keys", - signalled_keydrop); + (int)signalled_keydrop); remove_all_identities(); signalled_keydrop = 0; } diff --git a/ssh-dss.c b/ssh-dss.c deleted file mode 100644 index aea661377f5c..000000000000 --- a/ssh-dss.c +++ /dev/null @@ -1,457 +0,0 @@ -/* $OpenBSD: ssh-dss.c,v 1.50 2024/01/11 01:45:36 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" - -#if defined(WITH_OPENSSL) && defined(WITH_DSA) - -#include - -#include -#include -#include - -#include -#include - -#include "sshbuf.h" -#include "ssherr.h" -#include "digest.h" -#define SSHKEY_INTERNAL -#include "sshkey.h" - -#include "openbsd-compat/openssl-compat.h" - -#define INTBLOB_LEN 20 -#define SIGBLOB_LEN (2*INTBLOB_LEN) - -static u_int -ssh_dss_size(const struct sshkey *key) -{ - const BIGNUM *dsa_p; - - if (key->dsa == NULL) - return 0; - DSA_get0_pqg(key->dsa, &dsa_p, NULL, NULL); - return BN_num_bits(dsa_p); -} - -static int -ssh_dss_alloc(struct sshkey *k) -{ - if ((k->dsa = DSA_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - return 0; -} - -static void -ssh_dss_cleanup(struct sshkey *k) -{ - DSA_free(k->dsa); - k->dsa = NULL; -} - -static int -ssh_dss_equal(const struct sshkey *a, const struct sshkey *b) -{ - const BIGNUM *dsa_p_a, *dsa_q_a, *dsa_g_a, *dsa_pub_key_a; - const BIGNUM *dsa_p_b, *dsa_q_b, *dsa_g_b, *dsa_pub_key_b; - - if (a->dsa == NULL || b->dsa == NULL) - return 0; - DSA_get0_pqg(a->dsa, &dsa_p_a, &dsa_q_a, &dsa_g_a); - DSA_get0_pqg(b->dsa, &dsa_p_b, &dsa_q_b, &dsa_g_b); - DSA_get0_key(a->dsa, &dsa_pub_key_a, NULL); - DSA_get0_key(b->dsa, &dsa_pub_key_b, NULL); - if (dsa_p_a == NULL || dsa_p_b == NULL || - dsa_q_a == NULL || dsa_q_b == NULL || - dsa_g_a == NULL || dsa_g_b == NULL || - dsa_pub_key_a == NULL || dsa_pub_key_b == NULL) - return 0; - if (BN_cmp(dsa_p_a, dsa_p_b) != 0) - return 0; - if (BN_cmp(dsa_q_a, dsa_q_b) != 0) - return 0; - if (BN_cmp(dsa_g_a, dsa_g_b) != 0) - return 0; - if (BN_cmp(dsa_pub_key_a, dsa_pub_key_b) != 0) - return 0; - return 1; -} - -static int -ssh_dss_serialize_public(const struct sshkey *key, struct sshbuf *b, - enum sshkey_serialize_rep opts) -{ - int r; - const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; - - if (key->dsa == NULL) - return SSH_ERR_INVALID_ARGUMENT; - DSA_get0_pqg(key->dsa, &dsa_p, &dsa_q, &dsa_g); - DSA_get0_key(key->dsa, &dsa_pub_key, NULL); - if (dsa_p == NULL || dsa_q == NULL || - dsa_g == NULL || dsa_pub_key == NULL) - return SSH_ERR_INTERNAL_ERROR; - if ((r = sshbuf_put_bignum2(b, dsa_p)) != 0 || - (r = sshbuf_put_bignum2(b, dsa_q)) != 0 || - (r = sshbuf_put_bignum2(b, dsa_g)) != 0 || - (r = sshbuf_put_bignum2(b, dsa_pub_key)) != 0) - return r; - - return 0; -} - -static int -ssh_dss_serialize_private(const struct sshkey *key, struct sshbuf *b, - enum sshkey_serialize_rep opts) -{ - int r; - const BIGNUM *dsa_priv_key; - - DSA_get0_key(key->dsa, NULL, &dsa_priv_key); - if (!sshkey_is_cert(key)) { - if ((r = ssh_dss_serialize_public(key, b, opts)) != 0) - return r; - } - if ((r = sshbuf_put_bignum2(b, dsa_priv_key)) != 0) - return r; - - return 0; -} - -static int -ssh_dss_generate(struct sshkey *k, int bits) -{ - DSA *private; - - if (bits != 1024) - return SSH_ERR_KEY_LENGTH; - if ((private = DSA_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL, - NULL, NULL) || !DSA_generate_key(private)) { - DSA_free(private); - return SSH_ERR_LIBCRYPTO_ERROR; - } - k->dsa = private; - return 0; -} - -static int -ssh_dss_copy_public(const struct sshkey *from, struct sshkey *to) -{ - const BIGNUM *dsa_p, *dsa_q, *dsa_g, *dsa_pub_key; - BIGNUM *dsa_p_dup = NULL, *dsa_q_dup = NULL, *dsa_g_dup = NULL; - BIGNUM *dsa_pub_key_dup = NULL; - int r = SSH_ERR_INTERNAL_ERROR; - - DSA_get0_pqg(from->dsa, &dsa_p, &dsa_q, &dsa_g); - DSA_get0_key(from->dsa, &dsa_pub_key, NULL); - if ((dsa_p_dup = BN_dup(dsa_p)) == NULL || - (dsa_q_dup = BN_dup(dsa_q)) == NULL || - (dsa_g_dup = BN_dup(dsa_g)) == NULL || - (dsa_pub_key_dup = BN_dup(dsa_pub_key)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if (!DSA_set0_pqg(to->dsa, dsa_p_dup, dsa_q_dup, dsa_g_dup)) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - dsa_p_dup = dsa_q_dup = dsa_g_dup = NULL; /* transferred */ - if (!DSA_set0_key(to->dsa, dsa_pub_key_dup, NULL)) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - dsa_pub_key_dup = NULL; /* transferred */ - /* success */ - r = 0; - out: - BN_clear_free(dsa_p_dup); - BN_clear_free(dsa_q_dup); - BN_clear_free(dsa_g_dup); - BN_clear_free(dsa_pub_key_dup); - return r; -} - -static int -ssh_dss_deserialize_public(const char *ktype, struct sshbuf *b, - struct sshkey *key) -{ - int ret = SSH_ERR_INTERNAL_ERROR; - BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_pub_key = NULL; - - if (sshbuf_get_bignum2(b, &dsa_p) != 0 || - sshbuf_get_bignum2(b, &dsa_q) != 0 || - sshbuf_get_bignum2(b, &dsa_g) != 0 || - sshbuf_get_bignum2(b, &dsa_pub_key) != 0) { - ret = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - dsa_p = dsa_q = dsa_g = NULL; /* transferred */ - if (!DSA_set0_key(key->dsa, dsa_pub_key, NULL)) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - dsa_pub_key = NULL; /* transferred */ -#ifdef DEBUG_PK - DSA_print_fp(stderr, key->dsa, 8); -#endif - /* success */ - ret = 0; - out: - BN_clear_free(dsa_p); - BN_clear_free(dsa_q); - BN_clear_free(dsa_g); - BN_clear_free(dsa_pub_key); - return ret; -} - -static int -ssh_dss_deserialize_private(const char *ktype, struct sshbuf *b, - struct sshkey *key) -{ - int r; - BIGNUM *dsa_priv_key = NULL; - - if (!sshkey_is_cert(key)) { - if ((r = ssh_dss_deserialize_public(ktype, b, key)) != 0) - return r; - } - - if ((r = sshbuf_get_bignum2(b, &dsa_priv_key)) != 0) - return r; - if (!DSA_set0_key(key->dsa, NULL, dsa_priv_key)) { - BN_clear_free(dsa_priv_key); - return SSH_ERR_LIBCRYPTO_ERROR; - } - return 0; -} - -static int -ssh_dss_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) -{ - DSA_SIG *sig = NULL; - const BIGNUM *sig_r, *sig_s; - u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN]; - size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); - struct sshbuf *b = NULL; - int ret = SSH_ERR_INVALID_ARGUMENT; - - if (lenp != NULL) - *lenp = 0; - if (sigp != NULL) - *sigp = NULL; - - if (key == NULL || key->dsa == NULL || - sshkey_type_plain(key->type) != KEY_DSA) - return SSH_ERR_INVALID_ARGUMENT; - if (dlen == 0) - return SSH_ERR_INTERNAL_ERROR; - - if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, - digest, sizeof(digest))) != 0) - goto out; - - if ((sig = DSA_do_sign(digest, dlen, key->dsa)) == NULL) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - - DSA_SIG_get0(sig, &sig_r, &sig_s); - rlen = BN_num_bytes(sig_r); - slen = BN_num_bytes(sig_s); - if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { - ret = SSH_ERR_INTERNAL_ERROR; - goto out; - } - explicit_bzero(sigblob, SIGBLOB_LEN); - BN_bn2bin(sig_r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen); - BN_bn2bin(sig_s, sigblob + SIGBLOB_LEN - slen); - - if ((b = sshbuf_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((ret = sshbuf_put_cstring(b, "ssh-dss")) != 0 || - (ret = sshbuf_put_string(b, sigblob, SIGBLOB_LEN)) != 0) - goto out; - - len = sshbuf_len(b); - if (sigp != NULL) { - if ((*sigp = malloc(len)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - memcpy(*sigp, sshbuf_ptr(b), len); - } - if (lenp != NULL) - *lenp = len; - ret = 0; - out: - explicit_bzero(digest, sizeof(digest)); - DSA_SIG_free(sig); - sshbuf_free(b); - return ret; -} - -static int -ssh_dss_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) -{ - DSA_SIG *dsig = NULL; - BIGNUM *sig_r = NULL, *sig_s = NULL; - u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL; - size_t len, hlen = ssh_digest_bytes(SSH_DIGEST_SHA1); - int ret = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *b = NULL; - char *ktype = NULL; - - if (key == NULL || key->dsa == NULL || - sshkey_type_plain(key->type) != KEY_DSA || - sig == NULL || siglen == 0) - return SSH_ERR_INVALID_ARGUMENT; - if (hlen == 0) - return SSH_ERR_INTERNAL_ERROR; - - /* fetch signature */ - if ((b = sshbuf_from(sig, siglen)) == NULL) - return SSH_ERR_ALLOC_FAIL; - if (sshbuf_get_cstring(b, &ktype, NULL) != 0 || - sshbuf_get_string(b, &sigblob, &len) != 0) { - ret = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (strcmp("ssh-dss", ktype) != 0) { - ret = SSH_ERR_KEY_TYPE_MISMATCH; - goto out; - } - if (sshbuf_len(b) != 0) { - ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; - goto out; - } - - if (len != SIGBLOB_LEN) { - ret = SSH_ERR_INVALID_FORMAT; - goto out; - } - - /* parse signature */ - if ((dsig = DSA_SIG_new()) == NULL || - (sig_r = BN_new()) == NULL || - (sig_s = BN_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig_r) == NULL) || - (BN_bin2bn(sigblob + INTBLOB_LEN, INTBLOB_LEN, sig_s) == NULL)) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - if (!DSA_SIG_set0(dsig, sig_r, sig_s)) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - sig_r = sig_s = NULL; /* transferred */ - - /* sha1 the data */ - if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, dlen, - digest, sizeof(digest))) != 0) - goto out; - - switch (DSA_do_verify(digest, hlen, dsig, key->dsa)) { - case 1: - ret = 0; - break; - case 0: - ret = SSH_ERR_SIGNATURE_INVALID; - goto out; - default: - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - - out: - explicit_bzero(digest, sizeof(digest)); - DSA_SIG_free(dsig); - BN_clear_free(sig_r); - BN_clear_free(sig_s); - sshbuf_free(b); - free(ktype); - if (sigblob != NULL) - freezero(sigblob, len); - return ret; -} - -static const struct sshkey_impl_funcs sshkey_dss_funcs = { - /* .size = */ ssh_dss_size, - /* .alloc = */ ssh_dss_alloc, - /* .cleanup = */ ssh_dss_cleanup, - /* .equal = */ ssh_dss_equal, - /* .ssh_serialize_public = */ ssh_dss_serialize_public, - /* .ssh_deserialize_public = */ ssh_dss_deserialize_public, - /* .ssh_serialize_private = */ ssh_dss_serialize_private, - /* .ssh_deserialize_private = */ ssh_dss_deserialize_private, - /* .generate = */ ssh_dss_generate, - /* .copy_public = */ ssh_dss_copy_public, - /* .sign = */ ssh_dss_sign, - /* .verify = */ ssh_dss_verify, -}; - -const struct sshkey_impl sshkey_dss_impl = { - /* .name = */ "ssh-dss", - /* .shortname = */ "DSA", - /* .sigalg = */ NULL, - /* .type = */ KEY_DSA, - /* .nid = */ 0, - /* .cert = */ 0, - /* .sigonly = */ 0, - /* .keybits = */ 0, - /* .funcs = */ &sshkey_dss_funcs, -}; - -const struct sshkey_impl sshkey_dsa_cert_impl = { - /* .name = */ "ssh-dss-cert-v01@openssh.com", - /* .shortname = */ "DSA-CERT", - /* .sigalg = */ NULL, - /* .type = */ KEY_DSA_CERT, - /* .nid = */ 0, - /* .cert = */ 1, - /* .sigonly = */ 0, - /* .keybits = */ 0, - /* .funcs = */ &sshkey_dss_funcs, -}; - -#endif /* WITH_OPENSSL && WITH_DSA */ diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c index 695ed451e63d..b423bfb65685 100644 --- a/ssh-ecdsa.c +++ b/ssh-ecdsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-ecdsa.c,v 1.27 2024/08/15 00:51:51 djm Exp $ */ +/* $OpenBSD: ssh-ecdsa.c,v 1.28 2025/07/24 05:44:55 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -328,8 +328,7 @@ ssh_ecdsa_sign(struct sshkey *key, const BIGNUM *sig_r, *sig_s; int hash_alg; size_t slen = 0; - struct sshbuf *b = NULL, *bb = NULL; - int len = 0, ret = SSH_ERR_INTERNAL_ERROR; + int ret = SSH_ERR_INTERNAL_ERROR; if (lenp != NULL) *lenp = 0; @@ -352,11 +351,37 @@ ssh_ecdsa_sign(struct sshkey *key, ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } + ECDSA_SIG_get0(esig, &sig_r, &sig_s); + + if ((ret = ssh_ecdsa_encode_store_sig(key, sig_r, sig_s, + sigp, lenp)) != 0) + goto out; + /* success */ + ret = 0; + out: + freezero(sigb, slen); + ECDSA_SIG_free(esig); + return ret; +} + +int +ssh_ecdsa_encode_store_sig(const struct sshkey *key, + const BIGNUM *sig_r, const BIGNUM *sig_s, + u_char **sigp, size_t *lenp) +{ + struct sshbuf *b = NULL, *bb = NULL; + int ret; + size_t len; + + if (lenp != NULL) + *lenp = 0; + if (sigp != NULL) + *sigp = NULL; + if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } - ECDSA_SIG_get0(esig, &sig_r, &sig_s); if ((ret = sshbuf_put_bignum2(bb, sig_r)) != 0 || (ret = sshbuf_put_bignum2(bb, sig_s)) != 0) goto out; @@ -375,10 +400,8 @@ ssh_ecdsa_sign(struct sshkey *key, *lenp = len; ret = 0; out: - freezero(sigb, slen); sshbuf_free(b); sshbuf_free(bb); - ECDSA_SIG_free(esig); return ret; } diff --git a/ssh-ed25519.c b/ssh-ed25519.c index 22d8db026b4c..c8caa22214b7 100644 --- a/ssh-ed25519.c +++ b/ssh-ed25519.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-ed25519.c,v 1.19 2022/10/28 00:44:44 djm Exp $ */ +/* $OpenBSD: ssh-ed25519.c,v 1.20 2025/07/24 06:12:08 djm Exp $ */ /* * Copyright (c) 2013 Markus Friedl * @@ -149,10 +149,9 @@ ssh_ed25519_sign(struct sshkey *key, const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) { u_char *sig = NULL; - size_t slen = 0, len; + size_t slen = 0; unsigned long long smlen; int r, ret; - struct sshbuf *b = NULL; if (lenp != NULL) *lenp = 0; @@ -173,13 +172,40 @@ ssh_ed25519_sign(struct sshkey *key, r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */ goto out; } + if ((r = ssh_ed25519_encode_store_sig(sig, smlen - datalen, + sigp, lenp)) != 0) + goto out; + + /* success */ + r = 0; + out: + freezero(sig, slen); + return r; +} + +int +ssh_ed25519_encode_store_sig(const u_char *sig, size_t slen, + u_char **sigp, size_t *lenp) +{ + struct sshbuf *b = NULL; + int r = -1; + size_t len; + + if (lenp != NULL) + *lenp = 0; + if (sigp != NULL) + *sigp = NULL; + + if (slen != crypto_sign_ed25519_BYTES) + return SSH_ERR_INVALID_ARGUMENT; + /* encode signature */ if ((b = sshbuf_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshbuf_put_cstring(b, "ssh-ed25519")) != 0 || - (r = sshbuf_put_string(b, sig, smlen - datalen)) != 0) + (r = sshbuf_put_string(b, sig, slen)) != 0) goto out; len = sshbuf_len(b); if (sigp != NULL) { @@ -195,9 +221,6 @@ ssh_ed25519_sign(struct sshkey *key, r = 0; out: sshbuf_free(b); - if (sig != NULL) - freezero(sig, slen); - return r; } diff --git a/ssh-keygen.0 b/ssh-keygen.0 index 799f32365f9c..9ae8d3e3e531 100644 --- a/ssh-keygen.0 +++ b/ssh-keygen.0 @@ -329,7 +329,7 @@ DESCRIPTION RSA keys). -U When used in combination with -s or -Y sign, this option - indicates that a CA key resides in a ssh-agent(1). See the + indicates that a CA key resides in an ssh-agent(1). See the CERTIFICATES section for more information. -u Update a KRL. When specified with -k, keys listed via the @@ -528,10 +528,6 @@ MODULI GENERATION lines in the input file that have already been processed if the job is restarted. - memory=mbytes - Specify the amount of memory to use (in megabytes) when - generating candidate moduli for DH-GEX. - start=hex-value Specify start point (in hex) when generating candidate moduli for DH-GEX. @@ -569,7 +565,7 @@ CERTIFICATES $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id user_key.pub - Similarly, it is possible for the CA key to be hosted in a ssh-agent(1). + Similarly, it is possible for the CA key to be hosted in an ssh-agent(1). This is indicated by the -U flag and, again, the CA key must be identified by its public half. @@ -782,7 +778,7 @@ KEY REVOCATION LISTS OpenSSH versions prior to 7.9. hash: fingerprint - Revokes a key using a fingerprint hash, as obtained from a + Revokes a key using a fingerprint hash, as obtained from an sshd(8) authentication log message or the ssh-keygen -l flag. Only SHA256 fingerprints are supported here and resultant KRLs are not supported by OpenSSH versions prior to 7.9. @@ -905,4 +901,4 @@ AUTHORS created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. -OpenBSD 7.6 November 27, 2024 OpenBSD 7.6 +OpenBSD 7.7 October 4, 2025 OpenBSD 7.7 diff --git a/ssh-keygen.1 b/ssh-keygen.1 index 00246a861ac9..7ceb1db959fb 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.234 2024/11/27 13:00:23 djm Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.236 2025/10/04 21:41:35 naddy Exp $ .\" .\" Author: Tatu Ylonen .\" Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -35,7 +35,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: November 27 2024 $ +.Dd $Mdocdate: October 4 2025 $ .Dt SSH-KEYGEN 1 .Os .Sh NAME @@ -600,7 +600,7 @@ When used in combination with .Fl s or .Fl Y Cm sign , -this option indicates that a CA key resides in a +this option indicates that a CA key resides in an .Xr ssh-agent 1 . See the .Sx CERTIFICATES @@ -878,9 +878,6 @@ Write the last line processed to the specified file while performing DH candidate screening. This will be used to skip lines in the input file that have already been processed if the job is restarted. -.It Ic memory Ns = Ns Ar mbytes -Specify the amount of memory to use (in megabytes) when generating -candidate moduli for DH-GEX. .It Ic start Ns = Ns Ar hex-value Specify start point (in hex) when generating candidate moduli for DH-GEX. .It Ic generator Ns = Ns Ar value @@ -927,7 +924,7 @@ to .Pp .Dl $ ssh-keygen -s ca_key.pub -D libpkcs11.so -I key_id user_key.pub .Pp -Similarly, it is possible for the CA key to be hosted in a +Similarly, it is possible for the CA key to be hosted in an .Xr ssh-agent 1 . This is indicated by the .Fl U @@ -1189,7 +1186,7 @@ Revokes the specified key by including its SHA256 hash in the KRL. KRLs that revoke keys by SHA256 hash are not supported by OpenSSH versions prior to 7.9. .It Cm hash : Ar fingerprint -Revokes a key using a fingerprint hash, as obtained from a +Revokes a key using a fingerprint hash, as obtained from an .Xr sshd 8 authentication log message or the .Nm diff --git a/ssh-keygen.c b/ssh-keygen.c index 533dfe142d0d..d2c3602bfc27 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.477 2024/12/04 14:24:20 djm Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.485 2025/10/03 00:08:02 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -19,19 +19,18 @@ #include #ifdef WITH_OPENSSL +#include "openbsd-compat/openssl-compat.h" +#include #include #include -#include "openbsd-compat/openssl-compat.h" #endif -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include #include #ifdef HAVE_PATHS_H -# include +#include #endif #include #include @@ -56,7 +55,6 @@ #include "ssh.h" #include "ssh2.h" #include "ssherr.h" -#include "ssh-pkcs11.h" #include "atomicio.h" #include "krl.h" #include "digest.h" @@ -67,6 +65,10 @@ #include "sk-api.h" /* XXX for SSH_SK_USER_PRESENCE_REQD; remove */ #include "cipher.h" +#ifdef ENABLE_PKCS11 +#include "ssh-pkcs11.h" +#endif + #ifdef WINDOWS #define DEFAULT_KEY_TYPE_NAME "ecdsa" #else @@ -74,18 +76,14 @@ #endif /* WINDOWS */ /* - * Default number of bits in the RSA, DSA and ECDSA keys. These value can be + * Default number of bits in the RSA and ECDSA keys. These value can be * overridden on the command line. * - * These values, with the exception of DSA, provide security equivalent to at - * least 128 bits of security according to NIST Special Publication 800-57: - * Recommendation for Key Management Part 1 rev 4 section 5.6.1. - * For DSA it (and FIPS-186-4 section 4.2) specifies that the only size for - * which a 160bit hash is acceptable is 1kbit, and since ssh-dss specifies only - * SHA1 we limit the DSA key size 1k bits. + * These values provide security equivalent to at least 128 bits of security + * according to NIST Special Publication 800-57: Recommendation for Key + * Management Part 1 rev 4 section 5.6.1. */ #define DEFAULT_BITS 3072 -#define DEFAULT_BITS_DSA 1024 #ifdef WINDOWS #define DEFAULT_BITS_ECDSA 384 #else @@ -178,7 +176,7 @@ static char hostname[NI_MAXHOST]; #ifdef WITH_OPENSSL /* moduli.c */ -int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); +int gen_candidates(FILE *, u_int32_t, BIGNUM *); int prime_test(FILE *, FILE *, u_int32_t, u_int32_t, char *, unsigned long, unsigned long); #endif @@ -193,9 +191,6 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) int nid; switch(type) { - case KEY_DSA: - *bitsp = DEFAULT_BITS_DSA; - break; case KEY_ECDSA: if (name != NULL && (nid = sshkey_ecdsa_nid_from_name(name)) > 0) @@ -211,10 +206,6 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) } #ifdef WITH_OPENSSL switch (type) { - case KEY_DSA: - if (*bitsp != 1024) - fatal("Invalid DSA key length: must be 1024 bits"); - break; case KEY_RSA: if (*bitsp < SSH_RSA_MINIMUM_MODULUS_SIZE) fatal("Invalid RSA key length: minimum is %d bits", @@ -274,12 +265,6 @@ ask_filename(struct passwd *pw, const char *prompt) #endif /* WINDOWS */ else { switch (sshkey_type_from_shortname(key_type_name)) { -#ifdef WITH_DSA - case KEY_DSA_CERT: - case KEY_DSA: - name = _PATH_SSH_CLIENT_ID_DSA; - break; -#endif #ifdef OPENSSL_HAS_ECC case KEY_ECDSA_CERT: case KEY_ECDSA: @@ -302,10 +287,6 @@ ask_filename(struct passwd *pw, const char *prompt) case KEY_ED25519_SK_CERT: name = _PATH_SSH_CLIENT_ID_ED25519_SK; break; - case KEY_XMSS: - case KEY_XMSS_CERT: - name = _PATH_SSH_CLIENT_ID_XMSS; - break; default: fatal("bad key type"); } @@ -382,7 +363,6 @@ do_convert_to_ssh2(struct passwd *pw, struct sshkey *k) fprintf(stdout, "Comment: \"%s\"\n%s", comment, b64); fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END); free(b64); - exit(0); } static void @@ -394,12 +374,6 @@ do_convert_to_pkcs8(struct sshkey *k) EVP_PKEY_get0_RSA(k->pkey))) fatal("PEM_write_RSA_PUBKEY failed"); break; -#ifdef WITH_DSA - case KEY_DSA: - if (!PEM_write_DSA_PUBKEY(stdout, k->dsa)) - fatal("PEM_write_DSA_PUBKEY failed"); - break; -#endif #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: if (!PEM_write_EC_PUBKEY(stdout, @@ -410,7 +384,6 @@ do_convert_to_pkcs8(struct sshkey *k) default: fatal_f("unsupported key type %s", sshkey_type(k)); } - exit(0); } static void @@ -422,12 +395,6 @@ do_convert_to_pem(struct sshkey *k) EVP_PKEY_get0_RSA(k->pkey))) fatal("PEM_write_RSAPublicKey failed"); break; -#ifdef WITH_DSA - case KEY_DSA: - if (!PEM_write_DSA_PUBKEY(stdout, k->dsa)) - fatal("PEM_write_DSA_PUBKEY failed"); - break; -#endif #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: if (!PEM_write_EC_PUBKEY(stdout, @@ -438,7 +405,6 @@ do_convert_to_pem(struct sshkey *k) default: fatal_f("unsupported key type %s", sshkey_type(k)); } - exit(0); } static void @@ -467,7 +433,6 @@ do_convert_to(struct passwd *pw) default: fatal_f("unknown key format %d", convert_format); } - exit(0); } /* @@ -503,10 +468,6 @@ do_convert_private_ssh2(struct sshbuf *b) u_int magic, i1, i2, i3, i4; size_t slen; u_long e; -#ifdef WITH_DSA - BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL; - BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL; -#endif BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL; BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL; BIGNUM *rsa_dmp1 = NULL, *rsa_dmq1 = NULL; @@ -538,10 +499,6 @@ do_convert_private_ssh2(struct sshbuf *b) if (strstr(type, "rsa")) { ktype = KEY_RSA; -#ifdef WITH_DSA - } else if (strstr(type, "dsa")) { - ktype = KEY_DSA; -#endif } else { free(type); return NULL; @@ -551,27 +508,6 @@ do_convert_private_ssh2(struct sshbuf *b) free(type); switch (key->type) { -#ifdef WITH_DSA - case KEY_DSA: - if ((dsa_p = BN_new()) == NULL || - (dsa_q = BN_new()) == NULL || - (dsa_g = BN_new()) == NULL || - (dsa_pub_key = BN_new()) == NULL || - (dsa_priv_key = BN_new()) == NULL) - fatal_f("BN_new"); - buffer_get_bignum_bits(b, dsa_p); - buffer_get_bignum_bits(b, dsa_g); - buffer_get_bignum_bits(b, dsa_q); - buffer_get_bignum_bits(b, dsa_pub_key); - buffer_get_bignum_bits(b, dsa_priv_key); - if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g)) - fatal_f("DSA_set0_pqg failed"); - dsa_p = dsa_q = dsa_g = NULL; /* transferred */ - if (!DSA_set0_key(key->dsa, dsa_pub_key, dsa_priv_key)) - fatal_f("DSA_set0_key failed"); - dsa_pub_key = dsa_priv_key = NULL; /* transferred */ - break; -#endif case KEY_RSA: if ((r = sshbuf_get_u8(b, &e1)) != 0 || (e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) || @@ -608,6 +544,7 @@ do_convert_private_ssh2(struct sshbuf *b) if ((r = ssh_rsa_complete_crt_parameters(rsa_d, rsa_p, rsa_q, rsa_iqmp, &rsa_dmp1, &rsa_dmq1)) != 0) fatal_fr(r, "generate RSA CRT parameters"); + EVP_PKEY_free(key->pkey); if ((key->pkey = EVP_PKEY_new()) == NULL) fatal_f("EVP_PKEY_new failed"); if ((rsa = RSA_new()) == NULL) @@ -746,14 +683,6 @@ do_convert_from_pkcs8(struct sshkey **k, int *private) (*k)->pkey = pubkey; pubkey = NULL; break; -#ifdef WITH_DSA - case EVP_PKEY_DSA: - if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) - fatal("sshkey_new failed"); - (*k)->type = KEY_DSA; - (*k)->dsa = EVP_PKEY_get1_DSA(pubkey); - break; -#endif #ifdef OPENSSL_HAS_ECC case EVP_PKEY_EC: if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) @@ -770,7 +699,6 @@ do_convert_from_pkcs8(struct sshkey **k, int *private) EVP_PKEY_base_id(pubkey)); } EVP_PKEY_free(pubkey); - return; } static void @@ -829,12 +757,6 @@ do_convert_from(struct passwd *pw) fprintf(stdout, "\n"); } else { switch (k->type) { -#ifdef WITH_DSA - case KEY_DSA: - ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, - NULL, 0, NULL, NULL); - break; -#endif #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: ok = PEM_write_ECPrivateKey(stdout, @@ -855,7 +777,6 @@ do_convert_from(struct passwd *pw) if (!ok) fatal("key write failed"); sshkey_free(k); - exit(0); } #endif @@ -1108,9 +1029,6 @@ do_gen_all_hostkeys(struct passwd *pw) #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ { "ed25519", "ED25519",_PATH_HOST_ED25519_KEY_FILE }, -#ifdef WITH_XMSS - { "xmss", "XMSS",_PATH_HOST_XMSS_KEY_FILE }, -#endif /* WITH_XMSS */ { NULL, NULL, NULL } }; @@ -1539,13 +1457,14 @@ do_print_resource_record(struct passwd *pw, char *fname, char *hname, { struct sshkey *public; char *comment = NULL; + const char *p; struct stat st; int r, hash = -1; size_t i; for (i = 0; i < nopts; i++) { - if (strncasecmp(opts[i], "hashalg=", 8) == 0) { - if ((hash = ssh_digest_alg_by_name(opts[i] + 8)) == -1) + if ((p = strprefix(opts[i], "hashalg=", 1)) != NULL) { + if ((hash = ssh_digest_alg_by_name(p)) == -1) fatal("Unsupported hash algorithm"); } else { error("Invalid option \"%s\"", opts[i]); @@ -1605,7 +1524,7 @@ do_change_comment(struct passwd *pw, const char *identity_comment) } } - if (private->type != KEY_ED25519 && private->type != KEY_XMSS && + if (private->type != KEY_ED25519 && private_key_format != SSHKEY_PRIVATE_OPENSSH) { error("Comments are only supported for keys stored in " "the new format (-o)."); @@ -1975,16 +1894,17 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent, sshkey_free(public); free(out); + free(comment); if (cert_serial_autoinc) cert_serial++; } if (pin != NULL) freezero(pin, strlen(pin)); + sshkey_free(ca); free(ca_fp); #ifdef ENABLE_PKCS11 pkcs11_terminate(); #endif - exit(0); } static u_int64_t @@ -2074,6 +1994,7 @@ static void add_cert_option(char *opt) { char *val, *cp; + const char *p; int iscrit = 0; if (strcasecmp(opt, "clear") == 0) @@ -2106,24 +2027,22 @@ add_cert_option(char *opt) certflags_flags &= ~CERTOPT_REQUIRE_VERIFY; else if (strcasecmp(opt, "verify-required") == 0) certflags_flags |= CERTOPT_REQUIRE_VERIFY; - else if (strncasecmp(opt, "force-command=", 14) == 0) { - val = opt + 14; - if (*val == '\0') + else if ((p = strprefix(opt, "force-command=", 1)) != NULL) { + if (*p == '\0') fatal("Empty force-command option"); if (certflags_command != NULL) fatal("force-command already specified"); - certflags_command = xstrdup(val); - } else if (strncasecmp(opt, "source-address=", 15) == 0) { - val = opt + 15; - if (*val == '\0') + certflags_command = xstrdup(p); + } else if ((p = strprefix(opt, "source-address=", 1)) != NULL) { + if (*p == '\0') fatal("Empty source-address option"); if (certflags_src_addr != NULL) fatal("source-address already specified"); - if (addr_match_cidr_list(NULL, val) != 0) + if (addr_match_cidr_list(NULL, p) != 0) fatal("Invalid source-address list"); - certflags_src_addr = xstrdup(val); - } else if (strncasecmp(opt, "extension:", 10) == 0 || - (iscrit = (strncasecmp(opt, "critical:", 9) == 0))) { + certflags_src_addr = xstrdup(p); + } else if (strprefix(opt, "extension:", 1) != NULL || + (iscrit = (strprefix(opt, "critical:", 1) != NULL))) { val = xstrdup(strchr(opt, ':') + 1); if ((cp = strchr(val, '=')) != NULL) *cp++ = '\0'; @@ -2310,9 +2229,8 @@ hash_to_blob(const char *cp, u_char **blobp, size_t *lenp, struct sshbuf *b; int r; - if (strncmp(cp, "SHA256:", 7) != 0) + if ((cp = strprefix(cp, "SHA256:", 0)) == NULL) fatal("%s:%lu: unsupported hash algorithm", file, lnum); - cp += 7; /* * OpenSSH base64 hashes omit trailing '=' @@ -2434,9 +2352,12 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, cp += 5; cp = cp + strspn(cp, " \t"); hash_to_blob(cp, &blob, &blen, file, lnum); - r = ssh_krl_revoke_key_sha256(krl, blob, blen); - if (r != 0) + if ((r = ssh_krl_revoke_key_sha256(krl, + blob, blen)) != 0) fatal_fr(r, "revoke key failed"); + free(blob); + blob = NULL; + blen = 0; } else { if (strncasecmp(cp, "key:", 4) == 0) { cp += 4; @@ -2743,6 +2664,7 @@ sig_process_opts(char * const *opts, size_t nopts, char **hashalgp, { size_t i; time_t now; + const char *p; if (verify_timep != NULL) *verify_timep = 0; @@ -2752,12 +2674,12 @@ sig_process_opts(char * const *opts, size_t nopts, char **hashalgp, *hashalgp = NULL; for (i = 0; i < nopts; i++) { if (hashalgp != NULL && - strncasecmp(opts[i], "hashalg=", 8) == 0) { - *hashalgp = xstrdup(opts[i] + 8); + (p = strprefix(opts[i], "hashalg=", 1)) != NULL) { + *hashalgp = xstrdup(p); } else if (verify_timep && - strncasecmp(opts[i], "verify-time=", 12) == 0) { - if (parse_absolute_time(opts[i] + 12, - verify_timep) != 0 || *verify_timep == 0) { + (p = strprefix(opts[i], "verify-time=", 1)) != NULL) { + if (parse_absolute_time(p, verify_timep) != 0 || + *verify_timep == 0) { error("Invalid \"verify-time\" option"); return SSH_ERR_INVALID_ARGUMENT; } @@ -3033,32 +2955,22 @@ do_moduli_gen(const char *out_file, char **opts, size_t nopts) { #ifdef WITH_OPENSSL /* Moduli generation/screening */ - u_int32_t memory = 0; BIGNUM *start = NULL; int moduli_bits = 0; FILE *out; size_t i; - const char *errstr; + const char *errstr, *p; /* Parse options */ for (i = 0; i < nopts; i++) { - if (strncmp(opts[i], "memory=", 7) == 0) { - memory = (u_int32_t)strtonum(opts[i]+7, 1, - UINT_MAX, &errstr); - if (errstr) { - fatal("Memory limit is %s: %s", - errstr, opts[i]+7); - } - } else if (strncmp(opts[i], "start=", 6) == 0) { + if ((p = strprefix(opts[i], "start=", 0)) != NULL) { /* XXX - also compare length against bits */ - if (BN_hex2bn(&start, opts[i]+6) == 0) + if (BN_hex2bn(&start, p) == 0) fatal("Invalid start point."); - } else if (strncmp(opts[i], "bits=", 5) == 0) { - moduli_bits = (int)strtonum(opts[i]+5, 1, - INT_MAX, &errstr); + } else if ((p = strprefix(opts[i], "bits=", 0)) != NULL) { + moduli_bits = (int)strtonum(p, 1, INT_MAX, &errstr); if (errstr) { - fatal("Invalid number: %s (%s)", - opts[i]+12, errstr); + fatal("Invalid number: %s (%s)", p, errstr); } } else { fatal("Option \"%s\" is unsupported for moduli " @@ -3076,7 +2988,7 @@ do_moduli_gen(const char *out_file, char **opts, size_t nopts) if (moduli_bits == 0) moduli_bits = DEFAULT_BITS; - if (gen_candidates(out, memory, moduli_bits, start) != 0) + if (gen_candidates(out, moduli_bits, start) != 0) fatal("modulus candidate generation failed"); #else /* WITH_OPENSSL */ fatal("Moduli generation is not supported"); @@ -3094,30 +3006,27 @@ do_moduli_screen(const char *out_file, char **opts, size_t nopts) int prime_tests = 0; FILE *out, *in = stdin; size_t i; - const char *errstr; + const char *errstr, *p; /* Parse options */ for (i = 0; i < nopts; i++) { - if (strncmp(opts[i], "lines=", 6) == 0) { - lines_to_process = strtoul(opts[i]+6, NULL, 10); - } else if (strncmp(opts[i], "start-line=", 11) == 0) { - start_lineno = strtoul(opts[i]+11, NULL, 10); - } else if (strncmp(opts[i], "checkpoint=", 11) == 0) { + if ((p = strprefix(opts[i], "lines=", 0)) != NULL) { + lines_to_process = strtoul(p, NULL, 10); + } else if ((p = strprefix(opts[i], "start-line=", 0)) != NULL) { + start_lineno = strtoul(p, NULL, 10); + } else if ((p = strprefix(opts[i], "checkpoint=", 0)) != NULL) { free(checkpoint); - checkpoint = xstrdup(opts[i]+11); - } else if (strncmp(opts[i], "generator=", 10) == 0) { - generator_wanted = (u_int32_t)strtonum( - opts[i]+10, 1, UINT_MAX, &errstr); + checkpoint = xstrdup(p); + } else if ((p = strprefix(opts[i], "generator=", 0)) != NULL) { + generator_wanted = (u_int32_t)strtonum(p, 1, UINT_MAX, + &errstr); if (errstr != NULL) { - fatal("Generator invalid: %s (%s)", - opts[i]+10, errstr); + fatal("Generator invalid: %s (%s)", p, errstr); } - } else if (strncmp(opts[i], "prime-tests=", 12) == 0) { - prime_tests = (int)strtonum(opts[i]+12, 1, - INT_MAX, &errstr); + } else if ((p = strprefix(opts[i], "prime-tests=", 0)) != NULL) { + prime_tests = (int)strtonum(p, 1, INT_MAX, &errstr); if (errstr) { - fatal("Invalid number: %s (%s)", - opts[i]+12, errstr); + fatal("Invalid number: %s (%s)", p, errstr); } } else { fatal("Option \"%s\" is unsupported for moduli " @@ -3200,13 +3109,14 @@ static char * sk_suffix(const char *application, const uint8_t *user, size_t userlen) { char *ret, *cp; + const char *p; size_t slen, i; /* Trim off URL-like preamble */ - if (strncmp(application, "ssh://", 6) == 0) - ret = xstrdup(application + 6); - else if (strncmp(application, "ssh:", 4) == 0) - ret = xstrdup(application + 4); + if ((p = strprefix(application, "ssh://", 0)) != NULL) + ret = xstrdup(p); + else if ((p = strprefix(application, "ssh:", 0)) != NULL) + ret = xstrdup(p); else ret = xstrdup(application); @@ -3381,7 +3291,7 @@ usage(void) fprintf(stderr, "usage: ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile]\n" " [-m format] [-N new_passphrase] [-O option]\n" - " [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]\n" + " [-t ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]\n" " [-w provider] [-Z cipher]\n" " ssh-keygen -p [-a rounds] [-f keyfile] [-m format] [-N new_passphrase]\n" " [-P old_passphrase] [-Z cipher]\n" @@ -3432,9 +3342,9 @@ main(int argc, char **argv) { char comment[1024], *passphrase = NULL; char *rr_hostname = NULL, *ep, *fp, *ra; - struct sshkey *private, *public; + struct sshkey *private = NULL, *public = NULL; struct passwd *pw; - int r, opt, type; + int ret = 0, r, opt, type; int change_passphrase = 0, change_comment = 0, show_cert = 0; int find_host = 0, delete_host = 0, hash_hosts = 0; int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0; @@ -3449,7 +3359,7 @@ main(int argc, char **argv) size_t i, nopts = 0; u_int32_t bits = 0; uint8_t sk_flags = SSH_SK_USER_PRESENCE_REQD; - const char *errstr; + const char *errstr, *p; int log_level = SYSLOG_LEVEL_INFO; char *sign_op = NULL; @@ -3684,7 +3594,7 @@ main(int argc, char **argv) argc -= optind; if (sign_op != NULL) { - if (strncmp(sign_op, "find-principals", 15) == 0) { + if (strprefix(sign_op, "find-principals", 0) != NULL) { if (ca_key_path == NULL) { error("Too few arguments for find-principals:" "missing signature file"); @@ -3695,9 +3605,10 @@ main(int argc, char **argv) "missing allowed keys file"); exit(1); } - return sig_find_principals(ca_key_path, identity_file, + ret = sig_find_principals(ca_key_path, identity_file, opts, nopts); - } else if (strncmp(sign_op, "match-principals", 16) == 0) { + goto done; + } else if (strprefix(sign_op, "match-principals", 0) != NULL) { if (!have_identity) { error("Too few arguments for match-principals:" "missing allowed keys file"); @@ -3708,9 +3619,10 @@ main(int argc, char **argv) "missing principal ID"); exit(1); } - return sig_match_principals(identity_file, cert_key_id, + ret = sig_match_principals(identity_file, cert_key_id, opts, nopts); - } else if (strncmp(sign_op, "sign", 4) == 0) { + goto done; + } else if (strprefix(sign_op, "sign", 0) != NULL) { /* NB. cert_principals is actually namespace, via -n */ if (cert_principals == NULL || *cert_principals == '\0') { @@ -3723,9 +3635,10 @@ main(int argc, char **argv) "missing key"); exit(1); } - return sig_sign(identity_file, cert_principals, + ret = sig_sign(identity_file, cert_principals, prefer_agent, argc, argv, opts, nopts); - } else if (strncmp(sign_op, "check-novalidate", 16) == 0) { + goto done; + } else if (strprefix(sign_op, "check-novalidate", 0) != NULL) { /* NB. cert_principals is actually namespace, via -n */ if (cert_principals == NULL || *cert_principals == '\0') { @@ -3738,9 +3651,10 @@ main(int argc, char **argv) "missing signature file"); exit(1); } - return sig_verify(ca_key_path, cert_principals, + ret = sig_verify(ca_key_path, cert_principals, NULL, NULL, NULL, opts, nopts); - } else if (strncmp(sign_op, "verify", 6) == 0) { + goto done; + } else if (strprefix(sign_op, "verify", 0) != NULL) { /* NB. cert_principals is actually namespace, via -n */ if (cert_principals == NULL || *cert_principals == '\0') { @@ -3763,9 +3677,10 @@ main(int argc, char **argv) "missing principal identity"); exit(1); } - return sig_verify(ca_key_path, cert_principals, + ret = sig_verify(ca_key_path, cert_principals, cert_key_id, identity_file, rr_hostname, opts, nopts); + goto done; } error("Unsupported operation for -Y: \"%s\"", sign_op); usage(); @@ -3793,11 +3708,11 @@ main(int argc, char **argv) if (gen_krl) { do_gen_krl(pw, update_krl, ca_key_path, cert_serial, identity_comment, argc, argv); - return (0); + goto done; } if (check_krl) { do_check_krl(pw, print_fingerprint, argc, argv); - return (0); + goto done; } if (ca_key_path != NULL) { if (cert_key_id == NULL) @@ -3806,6 +3721,7 @@ main(int argc, char **argv) add_cert_option(opts[i]); do_ca_sign(pw, ca_key_path, prefer_agent, cert_serial, cert_serial_autoinc, argc, argv); + goto done; } if (show_cert) do_show_cert(pw); @@ -3817,14 +3733,15 @@ main(int argc, char **argv) do_download(pw); if (download_sk) { for (i = 0; i < nopts; i++) { - if (strncasecmp(opts[i], "device=", 7) == 0) { - sk_device = xstrdup(opts[i] + 7); + if ((p = strprefix(opts[i], "device=", 1)) != NULL) { + sk_device = xstrdup(p); } else { fatal("Option \"%s\" is unsupported for " "FIDO authenticator download", opts[i]); } } - return do_download_sk(sk_provider, sk_device); + ret = do_download_sk(sk_provider, sk_device); + goto done; } if (print_fingerprint || print_bubblebabble) do_fingerprint(pw); @@ -3833,10 +3750,14 @@ main(int argc, char **argv) if (change_comment) do_change_comment(pw, identity_comment); #ifdef WITH_OPENSSL - if (convert_to) + if (convert_to) { do_convert_to(pw); - if (convert_from) + goto done; + } + if (convert_from) { do_convert_from(pw); + goto done; + } #else /* WITH_OPENSSL */ if (convert_to || convert_from) fatal("key conversion disabled at compile time"); @@ -3857,20 +3778,12 @@ main(int argc, char **argv) n += do_print_resource_record(pw, _PATH_HOST_RSA_KEY_FILE, rr_hostname, print_generic, opts, nopts); -#ifdef WITH_DSA - n += do_print_resource_record(pw, - _PATH_HOST_DSA_KEY_FILE, rr_hostname, - print_generic, opts, nopts); -#endif n += do_print_resource_record(pw, _PATH_HOST_ECDSA_KEY_FILE, rr_hostname, print_generic, opts, nopts); n += do_print_resource_record(pw, _PATH_HOST_ED25519_KEY_FILE, rr_hostname, print_generic, opts, nopts); - n += do_print_resource_record(pw, - _PATH_HOST_XMSS_KEY_FILE, rr_hostname, - print_generic, opts, nopts); if (n == 0) fatal("no keys found."); exit(0); @@ -3885,16 +3798,16 @@ main(int argc, char **argv) } if (do_gen_candidates) { do_moduli_gen(argv[0], opts, nopts); - return 0; + goto done; } if (do_screen_candidates) { do_moduli_screen(argv[0], opts, nopts); - return 0; + goto done; } if (gen_all_hostkeys) { do_gen_all_hostkeys(pw); - return (0); + goto done; } if (key_type_name == NULL) @@ -3916,16 +3829,18 @@ main(int argc, char **argv) sk_flags |= SSH_SK_USER_VERIFICATION_REQD; } else if (strcasecmp(opts[i], "resident") == 0) { sk_flags |= SSH_SK_RESIDENT_KEY; - } else if (strncasecmp(opts[i], "device=", 7) == 0) { - sk_device = xstrdup(opts[i] + 7); - } else if (strncasecmp(opts[i], "user=", 5) == 0) { - sk_user = xstrdup(opts[i] + 5); - } else if (strncasecmp(opts[i], "challenge=", 10) == 0) { - if ((r = sshbuf_load_file(opts[i] + 10, + } else if ((p = strprefix(opts[i], "device=", 1)) + != NULL ) { + sk_device = xstrdup(p); + } else if ((p = strprefix(opts[i], "user=", 1)) + != NULL) { + sk_user = xstrdup(p); + } else if ((p = strprefix(opts[i], "challenge=", 1)) + != NULL) { + if ((r = sshbuf_load_file(p, &challenge)) != 0) { fatal_r(r, "Unable to load FIDO " - "enrollment challenge \"%s\"", - opts[i] + 10); + "enrollment challenge \"%s\"", p); } } else if (strncasecmp(opts[i], "write-attestation=", 18) == 0) { @@ -4060,8 +3975,9 @@ main(int argc, char **argv) if (sk_attestation_path != NULL) save_attestation(attest, sk_attestation_path); + done: sshbuf_free(attest); sshkey_free(public); - - exit(0); + pwfree(pw); + exit(ret); } diff --git a/ssh-keyscan.0 b/ssh-keyscan.0 index 382d1608acb2..76d7388d4c94 100644 --- a/ssh-keyscan.0 +++ b/ssh-keyscan.0 @@ -34,7 +34,7 @@ DESCRIPTION -c Request certificates from target hosts instead of plain keys. -D Print keys found as SSHFP DNS records. The default is to print - keys in a format usable as a ssh(1) known_hosts file. + keys in a format usable as an ssh(1) known_hosts file. -f file Read hosts or M-bM-^@M-^\addrlist namelistM-bM-^@M-^] pairs from file, one per line. @@ -120,4 +120,4 @@ AUTHORS Davison added support for protocol version 2. -OpenBSD 7.6 June 17, 2024 OpenBSD 7.6 +OpenBSD 7.7 October 4, 2025 OpenBSD 7.7 diff --git a/ssh-keyscan.1 b/ssh-keyscan.1 index 79cef300dda9..e17957367367 100644 --- a/ssh-keyscan.1 +++ b/ssh-keyscan.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keyscan.1,v 1.52 2024/06/17 08:30:29 djm Exp $ +.\" $OpenBSD: ssh-keyscan.1,v 1.53 2025/10/04 21:41:35 naddy Exp $ .\" .\" Copyright 1995, 1996 by David Mazieres . .\" @@ -6,7 +6,7 @@ .\" permitted provided that due credit is given to the author and the .\" OpenBSD project by leaving this copyright notice intact. .\" -.Dd $Mdocdate: June 17 2024 $ +.Dd $Mdocdate: October 4 2025 $ .Dt SSH-KEYSCAN 1 .Os .Sh NAME @@ -64,7 +64,7 @@ to use IPv6 addresses only. Request certificates from target hosts instead of plain keys. .It Fl D Print keys found as SSHFP DNS records. -The default is to print keys in a format usable as a +The default is to print keys in a format usable as an .Xr ssh 1 .Pa known_hosts file. diff --git a/ssh-keyscan.c b/ssh-keyscan.c index 3436c0b5c7c6..f9788114df8d 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keyscan.c,v 1.165 2024/12/06 15:17:15 djm Exp $ */ +/* $OpenBSD: ssh-keyscan.c,v 1.167 2025/08/29 03:50:38 djm Exp $ */ /* * Copyright 1995, 1996 by David Mazieres . * @@ -12,9 +12,7 @@ #include #include "openbsd-compat/sys-queue.h" #include -#ifdef HAVE_SYS_TIME_H -# include -#endif +#include #include #include @@ -23,15 +21,13 @@ #include #endif +#include #include #include -#include -#ifdef HAVE_POLL_H -#include -#endif #include #include #include +#include #include #include #include @@ -62,15 +58,13 @@ int IPv4or6 = AF_UNSPEC; int ssh_port = SSH_DEFAULT_PORT; -#define KT_DSA (1) -#define KT_RSA (1<<1) -#define KT_ECDSA (1<<2) -#define KT_ED25519 (1<<3) -#define KT_XMSS (1<<4) -#define KT_ECDSA_SK (1<<5) -#define KT_ED25519_SK (1<<6) +#define KT_RSA (1) +#define KT_ECDSA (1<<1) +#define KT_ED25519 (1<<2) +#define KT_ECDSA_SK (1<<4) +#define KT_ED25519_SK (1<<5) -#define KT_MIN KT_DSA +#define KT_MIN KT_RSA #define KT_MAX KT_ED25519_SK int get_cert = 0; @@ -240,10 +234,6 @@ keygrab_ssh2(con *c) int r; switch (c->c_keytype) { - case KT_DSA: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "ssh-dss-cert-v01@openssh.com" : "ssh-dss"; - break; case KT_RSA: myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? "rsa-sha2-512-cert-v01@openssh.com," @@ -257,10 +247,6 @@ keygrab_ssh2(con *c) myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? "ssh-ed25519-cert-v01@openssh.com" : "ssh-ed25519"; break; - case KT_XMSS: - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? - "ssh-xmss-cert-v01@openssh.com" : "ssh-xmss@openssh.com"; - break; case KT_ECDSA: myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? "ecdsa-sha2-nistp256-cert-v01@openssh.com," @@ -743,11 +729,6 @@ main(int argc, char **argv) int type = sshkey_type_from_shortname(tname); switch (type) { -#ifdef WITH_DSA - case KEY_DSA: - get_keytypes |= KT_DSA; - break; -#endif case KEY_ECDSA: get_keytypes |= KT_ECDSA; break; @@ -757,9 +738,6 @@ main(int argc, char **argv) case KEY_ED25519: get_keytypes |= KT_ED25519; break; - case KEY_XMSS: - get_keytypes |= KT_XMSS; - break; case KEY_ED25519_SK: get_keytypes |= KT_ED25519_SK; break; diff --git a/ssh-keysign.0 b/ssh-keysign.0 index f1e0e096413c..ff330580986f 100644 --- a/ssh-keysign.0 +++ b/ssh-keysign.0 @@ -47,4 +47,4 @@ HISTORY AUTHORS Markus Friedl -OpenBSD 7.6 June 17, 2024 OpenBSD 7.6 +OpenBSD 7.7 June 17, 2024 OpenBSD 7.7 diff --git a/ssh-keysign.c b/ssh-keysign.c index 955f7b0abad9..8d6bcda10919 100644 --- a/ssh-keysign.c +++ b/ssh-keysign.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keysign.c,v 1.75 2025/02/15 01:48:30 djm Exp $ */ +/* $OpenBSD: ssh-keysign.c,v 1.78 2025/09/25 06:25:38 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * @@ -26,9 +26,7 @@ #include "includes.h" #include -#ifdef HAVE_PATHS_H #include -#endif #include #include #include @@ -131,8 +129,10 @@ valid_request(struct passwd *pw, char *host, struct sshkey **ret, char **pkalgp, /* client host name, handle trailing dot */ if ((r = sshbuf_get_cstring(b, &p, &len)) != 0) fatal_fr(r, "parse hostname"); - debug2_f("check expect chost %s got %s", host, p); - if (strlen(host) != len - 1) + debug2_f("check expect chost \"%s\" got \"%s\"", host, p); + if (len == 0) + fail++; + else if (strlen(host) != len - 1) fail++; else if (p[len - 1] != '.') fail++; @@ -200,12 +200,8 @@ main(int argc, char **argv) i = 0; /* XXX This really needs to read sshd_config for the paths */ -#ifdef WITH_DSA - key_fd[i++] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY); -#endif key_fd[i++] = open(_PATH_HOST_ECDSA_KEY_FILE, O_RDONLY); key_fd[i++] = open(_PATH_HOST_ED25519_KEY_FILE, O_RDONLY); - key_fd[i++] = open(_PATH_HOST_XMSS_KEY_FILE, O_RDONLY); key_fd[i++] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY); if ((pw = getpwuid(getuid())) == NULL) diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c index b2f8e0f1e400..4b169d9d5d08 100644 --- a/ssh-pkcs11-client.c +++ b/ssh-pkcs11-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11-client.c,v 1.20 2024/08/15 00:51:51 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11-client.c,v 1.24 2025/07/30 10:17:13 dtucker Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * Copyright (c) 2014 Pedro Martelletto. All rights reserved. @@ -18,23 +18,17 @@ #include "includes.h" -#ifdef ENABLE_PKCS11 - #include -#ifdef HAVE_SYS_TIME_H -# include -#endif +#include #include #include +#include #include #include #include #include -#include -#include - #include "pathnames.h" #include "xmalloc.h" #include "sshbuf.h" @@ -46,36 +40,24 @@ #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 - #ifdef WINDOWS -#include "openbsd-compat/sys-queue.h" -#define CRYPTOKI_COMPAT -#include "pkcs11.h" - -static int fd = -1; -static pid_t pid = -1; -static RSA_METHOD *helper_rsa; -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) -static EC_KEY_METHOD *helper_ecdsa; -#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - -static char module_path[PATH_MAX + 1]; +/* + * On Windows the helper is spawned as the connecting user (via the ssh-agent + * client token) rather than fork()/execlp(), and is located relative to the + * running module instead of $PATH. These globals are provided by the Windows + * ssh-agent (contrib/win32/win32compat/ssh-agent/agent.c). + */ extern char *sshagent_con_username; extern HANDLE sshagent_client_primary_token; +static char module_path[PATH_MAX + 1]; -struct pkcs11_provider { - char *name; - TAILQ_ENTRY(pkcs11_provider) next; -}; - -TAILQ_HEAD(, pkcs11_provider) pkcs11_providers; +#include "openbsd-compat/sys-queue.h" +/* + * In-memory registry of keys held by the Windows ssh-agent. These functions + * are consumed by the Windows agent's keyagent-request.c and are independent + * of the upstream helper-subprocess delegation below. + */ struct pkcs11_keyinfo { struct sshkey *key; char *providername, *label; @@ -84,12 +66,6 @@ struct pkcs11_keyinfo { TAILQ_HEAD(, pkcs11_keyinfo) pkcs11_keylist; -#define MAX_MSG_LENGTH 10240 /*XXX*/ - -/* input and output queue */ -struct sshbuf *iqueue; -struct sshbuf *oqueue; - void add_key(struct sshkey *k, char *name) { @@ -139,12 +115,12 @@ find_helper_in_module_path(void) memset(module_path, 0, sizeof(module_path)); memset(path, 0, sizeof(path)); if ((n = GetModuleFileNameW(NULL, path, PATH_MAX)) == 0 || - n >= PATH_MAX) { + n >= PATH_MAX) { error_f("GetModuleFileNameW failed"); return NULL; } if (wcstombs_s(NULL, module_path, sizeof(module_path), path, - sizeof(module_path) - 1) != 0) { + sizeof(module_path) - 1) != 0) { error_f("wcstombs_s failed"); return NULL; } @@ -162,9 +138,6 @@ static char * find_helper(void) { char *helper = NULL; - char module_path[PATH_MAX + 1]; - char *ep; - DWORD n; size_t len = 0; _dupenv_s(&helper, &len, "SSH_PKCS11_HELPER"); @@ -181,24 +154,20 @@ find_helper(void) return helper; } - -#else +#endif /* WINDOWS */ /* 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. + * by provider path or their unique keyblobs. */ 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 */ + size_t nkeyblobs; + struct sshbuf **keyblobs; /* XXX use a tree or something faster */ }; static struct helper **helpers; static size_t nhelpers; @@ -219,58 +188,75 @@ helper_by_provider(const char *path) } static struct helper * -helper_by_rsa(const RSA *rsa) +helper_by_key(const struct sshkey *key) { - size_t i; - const RSA_METHOD *meth; + size_t i, j; + struct sshbuf *keyblob = NULL; + int r; + + if ((keyblob = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + if ((r = sshkey_putb(key, keyblob)) != 0) + fatal_fr(r, "serialise key"); - 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]; + if (helpers[i] == NULL) + continue; + for (j = 0; j < helpers[i]->nkeyblobs; j++) { + if (sshbuf_equals(keyblob, + helpers[i]->keyblobs[j]) == 0) { + sshbuf_free(keyblob); + return helpers[i]; + } + } } + sshbuf_free(keyblob); return NULL; } -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) -static struct helper * -helper_by_ec(const EC_KEY *ec) +static void +helper_add_key(struct helper *helper, struct sshkey *key) { - 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; + int r; + helper->keyblobs = xrecallocarray(helper->keyblobs, helper->nkeyblobs, + helper->nkeyblobs + 1, sizeof(*helper->keyblobs)); + if ((helper->keyblobs[helper->nkeyblobs] = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + if ((r = sshkey_putb(key, helper->keyblobs[helper->nkeyblobs])) != 0) + fatal_fr(r, "shkey_putb failed"); + helper->nkeyblobs++; + debug3_f("added %s key for provider %s, now has %zu keys", + sshkey_type(key), helper->path, helper->nkeyblobs); } -#endif /* defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) */ static void -helper_free(struct helper *helper) +helper_terminate(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) + if (helper->path == NULL) fatal_f("inconsistent helper"); - debug3_f("free helper for provider %s", helper->path); + + debug3_f("terminating helper for %s; remaining %zu keys", + helper->path, helper->nkeyblobs); + + close(helper->fd); + /* XXX waitpid() */ + helper->fd = -1; + helper->pid = -1; + + /* repack helpers */ for (i = 0; i < nhelpers; i++) { if (helpers[i] == helper) { if (found) fatal_f("helper recorded more than once"); found = 1; - } - else if (found) + } else if (found) helpers[i - 1] = helpers[i]; } if (found) { @@ -278,41 +264,12 @@ helper_free(struct helper *helper) nhelpers - 1, sizeof(*helpers)); nhelpers--; } + for (i = 0; i < helper->nkeyblobs; i++) + sshbuf_free(helper->keyblobs[i]); 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); -} - -#endif /* WINDOWS */ - static void send_msg(int fd, struct sshbuf *m) { @@ -370,7 +327,6 @@ int pkcs11_init(int interactive) { #ifdef WINDOWS - TAILQ_INIT(&pkcs11_providers); TAILQ_INIT(&pkcs11_keylist); #endif /* WINDOWS */ return 0; @@ -379,318 +335,71 @@ pkcs11_init(int interactive) void pkcs11_terminate(void) { -#ifdef WINDOWS - struct pkcs11_provider *p; - - while ((p = TAILQ_FIRST(&pkcs11_providers)) != NULL) { - // Send message to helper to gracefully unload providers - pkcs11_del_provider(p->name); - TAILQ_REMOVE(&pkcs11_providers, p, next); - } - - if (pid != -1) { - kill(pid, SIGTERM); - waitpid(pid, NULL, 0); - pid = -1; - } - - if (fd >= 0) - close(fd); - - fd = -1; -#else size_t i; debug3_f("terminating %zu helpers", nhelpers); for (i = 0; i < nhelpers; i++) helper_terminate(helpers[i]); -#endif /* WINDOWS */ } -static int -rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding) +int +pkcs11_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) { - struct sshkey *key = NULL; struct sshbuf *msg = NULL; - u_char *blob = NULL, *signature = NULL; - size_t blen, slen = 0; - int r, ret = -1; -#ifndef WINDOWS struct helper *helper; + int status, r; + u_char *signature = NULL; + size_t signature_len = 0; + int ret = SSH_ERR_INTERNAL_ERROR; - 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); -#endif /* WINDOWS */ - if (padding != RSA_PKCS1_PADDING) - goto fail; - if ((key = sshkey_new(KEY_UNSPEC)) == NULL) { - error_f("sshkey_new failed"); - goto fail; - } - if ((key->pkey = EVP_PKEY_new()) == NULL || - EVP_PKEY_set1_RSA(key->pkey, rsa) != 1) { - error_f("pkey setup failed"); - goto fail; - } + if (sigp != NULL) + *sigp = NULL; + if (lenp != NULL) + *lenp = 0; + + if ((helper = helper_by_key(key)) == NULL || helper->fd == -1) + fatal_f("no helper for %s key", sshkey_type(key)); - key->type = KEY_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"); + return SSH_ERR_ALLOC_FAIL; 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) + (r = sshkey_puts_plain(key, msg)) != 0 || + (r = sshbuf_put_string(msg, data, datalen)) != 0 || + (r = sshbuf_put_cstring(msg, alg == NULL ? "" : alg)) != 0 || + (r = sshbuf_put_u32(msg, compat)) != 0) fatal_fr(r, "compose"); -#ifndef WINDOWS send_msg(helper->fd, msg); -#else - send_msg(fd, msg); -#endif /* WINDOWS */ sshbuf_reset(msg); -#ifdef WINDOWS - if (recv_msg(fd, msg) == SSH2_AGENT_SIGN_RESPONSE) { -#else - if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) { -#endif /* WINDOWS */ - 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); -} - -#ifndef WINDOWS -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; -} -#endif /* WINDOWS */ - -#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; -#ifndef WINDOWS - 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); -#endif /* WINDOWS */ - if ((key = sshkey_new(KEY_UNSPEC)) == NULL) { - error_f("sshkey_new failed"); + if ((status = recv_msg(helper->fd, msg)) != SSH2_AGENT_SIGN_RESPONSE) { + /* XXX translate status to something useful */ + debug_fr(r, "recv_msg"); + ret = SSH_ERR_AGENT_FAILURE; goto fail; } - if ((key->pkey = EVP_PKEY_new()) == NULL || - EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1) { - error("pkey setup failed"); - goto fail; - } - if ((nid = sshkey_ecdsa_pkey_to_nid(key->pkey)) < 0) { - error("couldn't get curve nid"); - goto fail; - } - key->ecdsa_nid = nid; - key->type = KEY_ECDSA; - 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"); -#ifndef WINDOWS - send_msg(helper->fd, msg); -#else - send_msg(fd, msg); -#endif /* WINDOWS */ - sshbuf_reset(msg); + if ((r = sshbuf_get_string(msg, &signature, &signature_len)) != 0) + fatal_fr(r, "parse"); -#ifdef WINDOWS - if (recv_msg(fd, msg) == SSH2_AGENT_SIGN_RESPONSE) { -#else - if (recv_msg(helper->fd, msg) == SSH2_AGENT_SIGN_RESPONSE) { -#endif /* WINDOWS */ - if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0) - fatal_fr(r, "parse"); - cp = signature; - ret = d2i_ECDSA_SIG(NULL, &cp, slen); - free(signature); + /* success */ + if (sigp != NULL) { + *sigp = signature; + signature = NULL; } + if (lenp != NULL) + *lenp = signature_len; + ret = 0; fail: - free(blob); - sshkey_free(key); + free(signature); sshbuf_free(msg); - return (ret); + return ret; } -#ifndef WINDOWS -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) */ -#endif /* WINDOWS */ - -/* redirect private key crypto operations to the ssh-pkcs11-helper */ -#ifdef WINDOWS - -static void -wrap_key(struct sshkey* k) -{ - RSA* rsa = NULL; - EC_KEY* ecdsa = NULL; - - if (k->type == KEY_RSA) { - if ((rsa = EVP_PKEY_get1_RSA(k->pkey)) == NULL) - fatal_f("no RSA key"); - if (RSA_set_method(rsa, helper_rsa) != 1) - fatal_f("RSA_set_method failed"); - if (EVP_PKEY_set1_RSA(k->pkey, rsa) != 1) - fatal_f("EVP_PKEY_set1_RSA failed"); - RSA_free(rsa); -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) - } - else if (k->type == KEY_ECDSA) { - if ((ecdsa = EVP_PKEY_get1_EC_KEY(k->pkey)) == NULL) - fatal_f("no ECDSA key"); - if (EC_KEY_set_method(ecdsa, helper_ecdsa) != 1) - fatal_f("EC_KEY_set_method failed"); - if (EVP_PKEY_set1_EC_KEY(k->pkey, ecdsa) != 1) - fatal_f("EVP_PKEY_set1_EC_KEY failed"); - EC_KEY_free(ecdsa); -#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - } else - fatal_f("unknown key type"); -} - -#else - -static void -wrap_key(struct helper *helper, struct sshkey *k) -{ - RSA *rsa = NULL; - EC_KEY *ecdsa = NULL; - - debug3_f("wrap %s for provider %s", sshkey_type(k), helper->path); - if (k->type == KEY_RSA) { - if ((rsa = EVP_PKEY_get1_RSA(k->pkey)) == NULL) - fatal_f("no RSA key"); - if (RSA_set_method(rsa, helper->rsa_meth) != 1) - fatal_f("RSA_set_method failed"); - if (helper->nrsa++ >= INT_MAX) - fatal_f("RSA refcount error"); - if (EVP_PKEY_set1_RSA(k->pkey, rsa) != 1) - fatal_f("EVP_PKEY_set1_RSA failed"); - RSA_free(rsa); -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) - } else if (k->type == KEY_ECDSA) { - if ((ecdsa = EVP_PKEY_get1_EC_KEY(k->pkey)) == NULL) - fatal_f("no ECDSA key"); - if (EC_KEY_set_method(ecdsa, helper->ec_meth) != 1) - fatal_f("EC_KEY_set_method failed"); - if (helper->nec++ >= INT_MAX) - fatal_f("EC refcount error"); - if (EVP_PKEY_set1_EC_KEY(k->pkey, ecdsa) != 1) - fatal_f("EVP_PKEY_set1_EC_KEY failed"); - EC_KEY_free(ecdsa); -#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); -} -#endif /* WINDOWS */ - -#ifdef WINDOWS - -static int -pkcs11_start_helper_methods(void) -{ - if (helper_rsa != NULL) - return (0); - -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) - int (*orig_sign)(int, const unsigned char *, int, unsigned char *, - unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL; - if (helper_ecdsa != NULL) - return (0); - helper_ecdsa = EC_KEY_METHOD_new(EC_KEY_OpenSSL()); - if (helper_ecdsa == NULL) - return (-1); - EC_KEY_METHOD_get_sign(helper_ecdsa, &orig_sign, NULL, NULL); - EC_KEY_METHOD_set_sign(helper_ecdsa, orig_sign, NULL, ecdsa_do_sign); -#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - - if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL) - fatal_f("RSA_meth_dup failed"); - if (!RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper") || - !RSA_meth_set_priv_enc(helper_rsa, rsa_encrypt)) - fatal_f("failed to prepare method"); - - return (0); -} - -#else - /* * Make a private PKCS#11-backed certificate by grafting a previously-loaded * PKCS#11 private key and a public certificate key. @@ -702,13 +411,13 @@ pkcs11_make_cert(const struct sshkey *priv, struct helper *helper = NULL; struct sshkey *ret; int r; - RSA *rsa_priv = NULL, *rsa_cert = NULL; -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) - EC_KEY *ec_priv = NULL, *ec_cert = NULL; -#endif - debug3_f("private key type %s cert type %s", sshkey_type(priv), - sshkey_type(certpub)); + if ((helper = helper_by_key(priv)) == NULL || helper->fd == -1) + fatal_f("no helper for %s key", sshkey_type(priv)); + + debug3_f("private key type %s cert type %s on provider %s", + sshkey_type(priv), sshkey_type(certpub), helper->path); + *certprivp = NULL; if (!sshkey_is_cert(certpub) || sshkey_is_cert(priv) || !sshkey_equal_public(priv, certpub)) { @@ -717,178 +426,118 @@ pkcs11_make_cert(const struct sshkey *priv, return SSH_ERR_INVALID_ARGUMENT; } *certprivp = NULL; - if (priv->type == KEY_RSA) { - if ((rsa_priv = EVP_PKEY_get1_RSA(priv->pkey)) == NULL) - fatal_f("no RSA pkey"); - if ((helper = helper_by_rsa(rsa_priv)) == 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"); - if ((rsa_cert = EVP_PKEY_get1_RSA(ret->pkey)) == NULL) - fatal_f("no RSA cert pkey"); - if (RSA_set_method(rsa_cert, helper->rsa_meth) != 1) - fatal_f("RSA_set_method failed"); - if (helper->nrsa++ >= INT_MAX) - fatal_f("RSA refcount error"); - if (EVP_PKEY_set1_RSA(ret->pkey, rsa_cert) != 1) - fatal_f("EVP_PKEY_set1_RSA failed"); - RSA_free(rsa_priv); - RSA_free(rsa_cert); -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) - } else if (priv->type == KEY_ECDSA) { - if ((ec_priv = EVP_PKEY_get1_EC_KEY(priv->pkey)) == NULL) - fatal_f("no EC pkey"); - if ((helper = helper_by_ec(ec_priv)) == 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"); - if ((ec_cert = EVP_PKEY_get1_EC_KEY(ret->pkey)) == NULL) - fatal_f("no EC cert pkey"); - if (EC_KEY_set_method(ec_cert, helper->ec_meth) != 1) - fatal_f("EC_KEY_set_method failed"); - if (helper->nec++ >= INT_MAX) - fatal_f("EC refcount error"); - if (EVP_PKEY_set1_EC_KEY(ret->pkey, ec_cert) != 1) - fatal_f("EVP_PKEY_set1_EC_KEY failed"); - EC_KEY_free(ec_priv); - EC_KEY_free(ec_cert); -#endif - } else - fatal_f("unknown key type %s", sshkey_type(priv)); + if ((r = sshkey_from_private(priv, &ret)) != 0) + fatal_fr(r, "copy key"); 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); + + helper_add_key(helper, ret); + + debug3_f("provider %s: %zu remaining keys", + helper->path, helper->nkeyblobs); + /* success */ *certprivp = ret; return 0; } -static int -pkcs11_start_helper_methods(struct helper *helper) -{ - RSA_METHOD *rsa_meth = NULL; - 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; -} - -#endif /* WINDOWS */ - #ifdef WINDOWS - -static int -pkcs11_start_helper(void) +/* + * Windows spawns the helper as the connecting user using the ssh-agent + * client's primary token (posix_spawnp_as_user) instead of fork()/execlp(), + * and locates the helper relative to the running module. + */ +static struct helper * +pkcs11_start_helper(const char *path) { - int pair[2]; - char *helper, *verbosity = NULL; - int r, actions_inited = 0; - char *av[3]; + int pair[2] = {-1, -1}; + char *prog, *verbosity = NULL; + struct helper *helper; + pid_t pid; posix_spawn_file_actions_t actions; - HANDLE client_token = NULL, client_process_handle = NULL; - - r = SSH_ERR_SYSTEM_ERROR; - pair[0] = pair[1] = -1; - - if ((helper = find_helper()) == NULL) - goto out; - + int actions_inited = 0; + char *av[3]; -#ifdef DEBUG_PKCS11 - verbosity = "-vvv"; -#endif + if (nhelpers >= INT_MAX) + fatal_f("too many helpers"); + debug3_f("start helper for %s", path); + if ((prog = find_helper()) == NULL) + return NULL; if (log_level_get() >= SYSLOG_LEVEL_DEBUG1) verbosity = "-vvv"; - if (pkcs11_start_helper_methods() == -1) { - error("pkcs11_start_helper_methods failed"); - return (-1); - } - if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) { - error("socketpair: %s", strerror(errno)); - return (-1); + error_f("socketpair: %s", strerror(errno)); + return NULL; } + helper = xcalloc(1, sizeof(*helper)); if (posix_spawn_file_actions_init(&actions) != 0) { error_f("posix_spawn_file_actions_init failed"); - goto out; + goto fail; } actions_inited = 1; if (posix_spawn_file_actions_adddup2(&actions, pair[1], - STDIN_FILENO) != 0 || - posix_spawn_file_actions_adddup2(&actions, pair[1], - STDOUT_FILENO) != 0) { + STDIN_FILENO) != 0 || + posix_spawn_file_actions_adddup2(&actions, pair[1], + STDOUT_FILENO) != 0) { error_f("posix_spawn_file_actions_adddup2 failed"); - goto out; + goto fail; } - av[0] = helper; + av[0] = prog; av[1] = verbosity; av[2] = NULL; - - if (!sshagent_con_username) { - error_f("sshagent_con_username is NULL"); - goto out; - } - - if (!sshagent_client_primary_token) { - error_f("sshagent_client_primary_token is NULL for user:%s", sshagent_con_username); - goto out; + debug_f("starting %s %s", prog, verbosity == NULL ? "" : verbosity); + + if (sshagent_con_username != NULL) { + debug_f("spawning helper as user %s", sshagent_con_username); + if (sshagent_client_primary_token == NULL) { + error_f("sshagent_client_primary_token is NULL for " + "user %s", sshagent_con_username); + goto fail; + } + if (posix_spawnp_as_user(&pid, av[0], &actions, NULL, av, NULL, + sshagent_client_primary_token) != 0) { + error_f("failed to spawn process %s", av[0]); + goto fail; + } + } else { + if (posix_spawnp(&pid, av[0], &actions, NULL, av, NULL) != 0) { + error_f("posix_spawnp %s failed", av[0]); + goto fail; + } } - if (posix_spawnp_as_user((pid_t *)&pid, av[0], &actions, NULL, av, NULL, sshagent_client_primary_token) != 0) { - error_f("failed to spwan process %s", av[0]); - goto out; - } + close(pair[1]); + pair[1] = -1; + posix_spawn_file_actions_destroy(&actions); - fd = pair[0]; - r = 0; - /* success */ - debug3_f("started pid=%ld", (long)pid); + 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; -out: - if (client_token) - CloseHandle(client_token); - return r; + fail: + if (actions_inited) + posix_spawn_file_actions_destroy(&actions); + if (pair[0] != -1) + close(pair[0]); + if (pair[1] != -1) + close(pair[1]); + free(helper); + return NULL; } - #else - static struct helper * pkcs11_start_helper(const char *path) { @@ -905,19 +554,10 @@ pkcs11_start_helper(const char *path) 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) { @@ -950,7 +590,6 @@ pkcs11_start_helper(const char *path) helpers[nhelpers++] = helper; return helper; } - #endif /* WINDOWS */ int @@ -959,25 +598,20 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, { struct sshkey *k; int r, type; - u_char *blob; #ifdef WINDOWS char *label = NULL; #else - char* label; -#endif /* WINDOWS*/ - size_t blen; - u_int nkeys, i; + char *label; +#endif /* WINDOWS */ + u_int ret = -1, nkeys, i; struct sshbuf *msg; -#ifndef WINDOWS struct helper *helper; + if ((helper = helper_by_provider(name)) == NULL && (helper = pkcs11_start_helper(name)) == NULL) return -1; -#else - struct pkcs11_provider *p; - if (fd < 0 && pkcs11_start_helper() < 0) - return (-1); -#endif /* WINDOWS */ + + debug3_f("add %s", helper->path); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); @@ -985,90 +619,92 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, (r = sshbuf_put_cstring(msg, name)) != 0 || (r = sshbuf_put_cstring(msg, pin)) != 0) fatal_fr(r, "compose"); -#ifdef WINDOWS - send_msg(fd, msg); -#else send_msg(helper->fd, msg); -#endif /* WINDOWS */ sshbuf_reset(msg); -#ifdef WINDOWS - type = recv_msg(fd, msg); -#else type = recv_msg(helper->fd, msg); -#endif /* WINDOWS */ + debug3_f("response %d", type); if (type == SSH2_AGENT_IDENTITIES_ANSWER) { if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) fatal_fr(r, "parse nkeys"); + debug3_f("helper return %u keys", 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 || + if ((r = sshkey_froms(msg, &k)) != 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"); -#ifdef WINDOWS - wrap_key(k); -#else - wrap_key(helper, k); -#endif /* WINDOWS */ + k->flags |= SSHKEY_FLAG_EXT; + helper_add_key(helper, k); (*keysp)[i] = k; if (labelsp) (*labelsp)[i] = label; else - free(label); // CodeQL [SM03650]: false positive label not previously freed - free(blob); + free(label); } + /* success */ + ret = 0; } else if (type == SSH2_AGENT_FAILURE) { if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) - nkeys = -1; - } else { - nkeys = -1; + error_fr(r, "failed to parse failure response"); + } + if (ret != 0) { + debug_f("no keys; terminate helper"); + helper_terminate(helper); } - -#ifdef WINDOWS - p = xcalloc(1, sizeof(*p)); - p->name = xstrdup(name); - TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); -#endif /* WINDOWS */ sshbuf_free(msg); - return (nkeys); + return ret == 0 ? (int)nkeys : -1; } int pkcs11_del_provider(char *name) { -#ifdef WINDOWS - int r, ret = -1; - struct sshbuf *msg; - - if ((msg = sshbuf_new()) == NULL) - fatal_f("sshbuf_new failed"); - if ((r = sshbuf_put_u8(msg, SSH_AGENTC_REMOVE_SMARTCARD_KEY)) != 0 || - (r = sshbuf_put_cstring(msg, name)) != 0 || - (r = sshbuf_put_cstring(msg, "")) != 0) - fatal_fr(r, "compose"); - send_msg(fd, msg); - sshbuf_reset(msg); - - if (recv_msg(fd, msg) == SSH_AGENT_SUCCESS) - ret = 0; - sshbuf_free(msg); - return (ret); -#else 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); + debug3_f("delete %s", name ? name : "(null)"); if ((helper = helper_by_provider(name)) != NULL) helper_terminate(helper); return 0; -#endif /* WINDOWS */ } -#endif /* ENABLE_PKCS11 */ + +void +pkcs11_key_free(struct sshkey *key) +{ + struct helper *helper; + struct sshbuf *keyblob = NULL; + size_t i; + int r, found = 0; + + debug3_f("free %s key", sshkey_type(key)); + + if ((helper = helper_by_key(key)) == NULL || helper->fd == -1) + fatal_f("no helper for %s key", sshkey_type(key)); + if ((keyblob = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + if ((r = sshkey_putb(key, keyblob)) != 0) + fatal_fr(r, "serialise key"); + + /* repack keys */ + for (i = 0; i < helper->nkeyblobs; i++) { + if (sshbuf_equals(keyblob, helper->keyblobs[i]) == 0) { + if (found) + fatal_f("key recorded more than once"); + found = 1; + } else if (found) + helper->keyblobs[i - 1] = helper->keyblobs[i]; + } + if (found) { + helper->keyblobs = xrecallocarray(helper->keyblobs, + helper->nkeyblobs, helper->nkeyblobs - 1, + sizeof(*helper->keyblobs)); + helper->nkeyblobs--; + } + if (helper->nkeyblobs == 0) + helper_terminate(helper); +} diff --git a/ssh-pkcs11-helper.0 b/ssh-pkcs11-helper.0 index 42a6a208e83a..4b1cb8d7dd12 100644 --- a/ssh-pkcs11-helper.0 +++ b/ssh-pkcs11-helper.0 @@ -32,4 +32,4 @@ HISTORY AUTHORS Markus Friedl -OpenBSD 7.6 April 29, 2022 OpenBSD 7.6 +OpenBSD 7.7 April 29, 2022 OpenBSD 7.7 diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c index a8154f21c058..7ed4bdb76841 100644 --- a/ssh-pkcs11-helper.c +++ b/ssh-pkcs11-helper.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11-helper.c,v 1.27 2024/08/15 00:51:51 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11-helper.c,v 1.29 2025/07/30 04:27:42 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -18,17 +18,11 @@ #include "includes.h" #include -#ifdef HAVE_SYS_TIME_H -# include -#endif - -#include "openbsd-compat/sys-queue.h" +#include #include #include -#ifdef HAVE_POLL_H #include -#endif #include #include #include @@ -44,20 +38,9 @@ #ifdef ENABLE_PKCS11 -#ifdef WITH_OPENSSL -#include -#include -#include - /* borrows code from sftp-server and ssh-agent */ -struct pkcs11_keyinfo { - struct sshkey *key; - char *providername, *label; - TAILQ_ENTRY(pkcs11_keyinfo) next; -}; - -TAILQ_HEAD(, pkcs11_keyinfo) pkcs11_keylist; +static char *providername; /* Provider for this helper */ #define MAX_MSG_LENGTH 10240 /*XXX*/ @@ -65,50 +48,6 @@ TAILQ_HEAD(, pkcs11_keyinfo) pkcs11_keylist; struct sshbuf *iqueue; struct sshbuf *oqueue; -static void -add_key(struct sshkey *k, char *name, char *label) -{ - struct pkcs11_keyinfo *ki; - - ki = xcalloc(1, sizeof(*ki)); - ki->providername = xstrdup(name); - ki->key = k; - ki->label = xstrdup(label); - TAILQ_INSERT_TAIL(&pkcs11_keylist, ki, next); -} - -static void -del_keys_by_name(char *name) -{ - struct pkcs11_keyinfo *ki, *nxt; - - for (ki = TAILQ_FIRST(&pkcs11_keylist); ki; ki = nxt) { - nxt = TAILQ_NEXT(ki, next); - if (!strcmp(ki->providername, name)) { - TAILQ_REMOVE(&pkcs11_keylist, ki, next); - free(ki->providername); - free(ki->label); - sshkey_free(ki->key); - free(ki); - } - } -} - -/* lookup matching 'private' key */ -static struct sshkey * -lookup_key(struct sshkey *k) -{ - struct pkcs11_keyinfo *ki; - - TAILQ_FOREACH(ki, &pkcs11_keylist, next) { - debug("check %s %s %s", sshkey_type(ki->key), - ki->providername, ki->label); - if (sshkey_equal(k, ki->key)) - return (ki->key); - } - return (NULL); -} - static void send_msg(struct sshbuf *m) { @@ -121,34 +60,32 @@ send_msg(struct sshbuf *m) static void process_add(void) { - char *name, *pin; + char *pin; struct sshkey **keys = NULL; int r, i, nkeys; - u_char *blob; - size_t blen; struct sshbuf *msg; char **labels = NULL; + if (providername != NULL) + fatal_f("provider already set"); if ((msg = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); - if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || + if ((r = sshbuf_get_cstring(iqueue, &providername, NULL)) != 0 || (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0) fatal_fr(r, "parse"); - if ((nkeys = pkcs11_add_provider(name, pin, &keys, &labels)) > 0) { + debug3_f("add %s", providername); + if ((nkeys = pkcs11_add_provider(providername, pin, + &keys, &labels)) > 0) { if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || (r = sshbuf_put_u32(msg, nkeys)) != 0) fatal_fr(r, "compose"); for (i = 0; i < nkeys; i++) { - if ((r = sshkey_to_blob(keys[i], &blob, &blen)) != 0) { - debug_fr(r, "encode key"); - continue; - } - if ((r = sshbuf_put_string(msg, blob, blen)) != 0 || + if ((r = sshkey_puts(keys[i], msg)) != 0 || (r = sshbuf_put_cstring(msg, labels[i])) != 0) fatal_fr(r, "compose key"); - free(blob); - add_key(keys[i], name, labels[i]); + debug3_f("%s: %s \"%s\"", providername, + sshkey_type(keys[i]), labels[i]); free(labels[i]); } } else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0 || @@ -157,95 +94,39 @@ process_add(void) free(labels); free(keys); /* keys themselves are transferred to pkcs11_keylist */ free(pin); - free(name); send_msg(msg); sshbuf_free(msg); } static void -process_del(void) +process_sign(void) { - char *name, *pin; + const u_char *data; + u_char *signature = NULL; + size_t dlen, slen = 0; + u_int compat; + int r, ok = -1; + struct sshkey *key = NULL; struct sshbuf *msg; - int r; + char *alg = NULL; - if ((msg = sshbuf_new()) == NULL) - fatal_f("sshbuf_new failed"); - if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || - (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0) + if ((r = sshkey_froms(iqueue, &key)) != 0 || + (r = sshbuf_get_string_direct(iqueue, &data, &dlen)) != 0 || + (r = sshbuf_get_cstring(iqueue, &alg, NULL)) != 0 || + (r = sshbuf_get_u32(iqueue, &compat)) != 0) fatal_fr(r, "parse"); - del_keys_by_name(name); - if ((r = sshbuf_put_u8(msg, pkcs11_del_provider(name) == 0 ? - SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0) - fatal_fr(r, "compose"); - free(pin); - free(name); - send_msg(msg); - sshbuf_free(msg); -} -static void -process_sign(void) -{ - u_char *blob, *data, *signature = NULL; - size_t blen, dlen; - u_int slen = 0; - int len, r, ok = -1; - struct sshkey *key = NULL, *found; - struct sshbuf *msg; -#ifdef WITH_OPENSSL - RSA *rsa = NULL; -#ifdef OPENSSL_HAS_ECC - EC_KEY *ecdsa = NULL; -#endif /* OPENSSL_HAS_ECC */ -#endif /* WITH_OPENSSL */ - - /* XXX support SHA2 signature flags */ - if ((r = sshbuf_get_string(iqueue, &blob, &blen)) != 0 || - (r = sshbuf_get_string(iqueue, &data, &dlen)) != 0 || - (r = sshbuf_get_u32(iqueue, NULL)) != 0) - fatal_fr(r, "parse"); + if (*alg == '\0') { + free(alg); + alg = NULL; + } - if ((r = sshkey_from_blob(blob, blen, &key)) != 0) - fatal_fr(r, "decode key"); - if ((found = lookup_key(key)) == NULL) + if ((r = pkcs11_sign(key, &signature, &slen, data, dlen, + alg, NULL, NULL, compat)) != 0) { + error_fr(r, "sign %s", sshkey_type(key)); goto reply; - - /* XXX use pkey API properly for signing */ - switch (key->type) { -#ifdef WITH_OPENSSL - case KEY_RSA: - if ((rsa = EVP_PKEY_get1_RSA(found->pkey)) == NULL) - fatal_f("no RSA in pkey"); - if ((len = RSA_size(rsa)) < 0) - fatal_f("bad RSA length"); - signature = xmalloc(len); - if ((len = RSA_private_encrypt(dlen, data, signature, - rsa, RSA_PKCS1_PADDING)) < 0) { - error_f("RSA_private_encrypt failed"); - goto reply; - } - slen = (u_int)len; - break; -#ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - if ((ecdsa = EVP_PKEY_get1_EC_KEY(found->pkey)) == NULL) - fatal_f("no ECDSA in pkey"); - if ((len = ECDSA_size(ecdsa)) < 0) - fatal_f("bad ECDSA length"); - slen = (u_int)len; - signature = xmalloc(slen); - /* "The parameter type is ignored." */ - if (!ECDSA_sign(-1, data, dlen, signature, &slen, ecdsa)) { - error_f("ECDSA_sign failed"); - goto reply; - } - break; -#endif /* OPENSSL_HAS_ECC */ -#endif /* WITH_OPENSSL */ - default: - fatal_f("unsupported key type %d", key->type); } + /* success */ ok = 0; reply: @@ -260,12 +141,7 @@ process_sign(void) fatal_fr(r, "compose failure response"); } sshkey_free(key); - RSA_free(rsa); -#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) - EC_KEY_free(ecdsa); -#endif - free(data); - free(blob); + free(alg); free(signature); send_msg(msg); sshbuf_free(msg); @@ -301,10 +177,6 @@ process(void) debug("process_add"); process_add(); break; - case SSH_AGENTC_REMOVE_SMARTCARD_KEY: - debug("process_del"); - process_del(); - break; case SSH2_AGENTC_SIGN_REQUEST: debug("process_sign"); process_sign(); @@ -336,7 +208,6 @@ cleanup_exit(int i) _exit(i); } - int main(int argc, char **argv) { @@ -350,7 +221,6 @@ main(int argc, char **argv) __progname = ssh_get_progname(argv[0]); seed_rng(); - TAILQ_INIT(&pkcs11_keylist); log_init(__progname, log_level, log_facility, log_stderr); @@ -439,22 +309,23 @@ main(int argc, char **argv) fatal_fr(r, "reserve"); } } - -#else /* WITH_OPENSSL */ -void -cleanup_exit(int i) +#else /* ENABLE_PKCS11 */ +/* stubs */ +int +pkcs11_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) { - _exit(i); + return SSH_ERR_INTERNAL_ERROR; } -int -main(int argc, char **argv) +void +pkcs11_key_free(struct sshkey *key) { - fprintf(stderr, "PKCS#11 code is not enabled\n"); - return 1; } -#endif /* WITH_OPENSSL */ -#else /* ENABLE_PKCS11 */ + int main(int argc, char **argv) { diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c index 31b9360f0adb..0a94fcd97adb 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11.c,v 1.64 2024/09/20 02:00:46 jsg Exp $ */ +/* $OpenBSD: ssh-pkcs11.c,v 1.72 2025/10/03 00:08:02 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * Copyright (c) 2014 Pedro Martelletto. All rights reserved. @@ -20,9 +20,7 @@ #ifdef ENABLE_PKCS11 -#ifdef HAVE_SYS_TIME_H -# include -#endif +#include #include #include @@ -35,19 +33,27 @@ #include "openbsd-compat/sys-queue.h" #include "openbsd-compat/openssl-compat.h" +#ifdef WITH_OPENSSL +#include "openbsd-compat/openssl-compat.h" +#include #include #include #include +#endif #define CRYPTOKI_COMPAT #include "pkcs11.h" +#define SSHKEY_INTERNAL +#include "sshkey.h" + #include "log.h" #include "misc.h" -#include "sshkey.h" +#include "sshbuf.h" #include "ssh-pkcs11.h" #include "digest.h" #include "xmalloc.h" +#include "crypto_api.h" struct pkcs11_slotinfo { CK_TOKEN_INFO token; @@ -71,15 +77,19 @@ struct pkcs11_provider { TAILQ_HEAD(, pkcs11_provider) pkcs11_providers; struct pkcs11_key { + struct sshbuf *keyblob; struct pkcs11_provider *provider; CK_ULONG slotidx; char *keyid; int keyid_len; + TAILQ_ENTRY(pkcs11_key) next; }; +TAILQ_HEAD(, pkcs11_key) pkcs11_keys; /* XXX a tree would be better */ + int pkcs11_interactive = 0; -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) +#if defined(OPENSSL_HAS_ECC) || defined(OPENSSL_HAS_ED25519) static void ossl_error(const char *msg) { @@ -89,15 +99,7 @@ ossl_error(const char *msg) while ((e = ERR_get_error()) != 0) error_f("libcrypto error: %s", ERR_error_string(e, NULL)); } -#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - -int -pkcs11_init(int interactive) -{ - pkcs11_interactive = interactive; - TAILQ_INIT(&pkcs11_providers); - return (0); -} +#endif /* * finalize a provider shared library, it's no longer usable. @@ -146,19 +148,6 @@ pkcs11_provider_unref(struct pkcs11_provider *p) } } -/* unregister all providers, keys might still point to the providers */ -void -pkcs11_terminate(void) -{ - struct pkcs11_provider *p; - - while ((p = TAILQ_FIRST(&pkcs11_providers)) != NULL) { - TAILQ_REMOVE(&pkcs11_providers, p, next); - pkcs11_provider_finalize(p); - pkcs11_provider_unref(p); - } -} - /* lookup provider by name */ static struct pkcs11_provider * pkcs11_provider_lookup(char *provider_id) @@ -188,26 +177,16 @@ pkcs11_del_provider(char *provider_id) return (-1); } -static RSA_METHOD *rsa_method; -static int rsa_idx = 0; -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) -static EC_KEY_METHOD *ec_key_method; -static int ec_key_idx = 0; -#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - /* release a wrapped object */ static void -pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, - long argl, void *argp) +pkcs11_k11_free(struct pkcs11_key *k11) { - struct pkcs11_key *k11 = ptr; - - debug_f("parent %p ptr %p idx %d", parent, ptr, idx); if (k11 == NULL) return; if (k11->provider) pkcs11_provider_unref(k11->provider); free(k11->keyid); + sshbuf_free(k11->keyblob); free(k11); } @@ -417,214 +396,384 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) return (0); } -/* openssl callback doing the actual signing operation */ +/* record the key information later use lookup by keyblob */ static int -pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, - int padding) +pkcs11_record_key(struct pkcs11_provider *provider, CK_ULONG slotidx, + CK_ATTRIBUTE *keyid_attrib, struct sshkey *key) { - struct pkcs11_key *k11; - struct pkcs11_slotinfo *si; - CK_FUNCTION_LIST *f; - CK_ULONG tlen = 0; - CK_RV rv; - int rval = -1; - - if ((k11 = RSA_get_ex_data(rsa, rsa_idx)) == NULL) { - error("RSA_get_ex_data failed"); - return (-1); + struct sshbuf *keyblob; + struct pkcs11_key *k11; + int r; + char *hex; + + hex = tohex(keyid_attrib->pValue, keyid_attrib->ulValueLen); + debug_f("%s key: provider %s slot %lu keyid %s", + sshkey_type(key), provider->name, (u_long)slotidx, hex); + free(hex); + + if ((keyblob = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + if ((r = sshkey_putb(key, keyblob)) != 0) + fatal_fr(r, "sshkey_putb"); + + /* Check if we've already recorded this key in a different slot */ + TAILQ_FOREACH(k11, &pkcs11_keys, next) { + if (sshbuf_equals(k11->keyblob, keyblob) == 0) { + hex = tohex(k11->keyid, k11->keyid_len); + debug_f("Already seen this key at " + "provider %s slot %lu keyid %s", + k11->provider->name, k11->slotidx, hex); + free(hex); + sshbuf_free(keyblob); + return -1; + } } - if (pkcs11_get_key(k11, CKM_RSA_PKCS) == -1) { - error("pkcs11_get_key failed"); - return (-1); + k11 = xcalloc(1, sizeof(*k11)); + k11->provider = provider; + k11->keyblob = keyblob; + provider->refcount++; /* provider referenced by RSA key */ + k11->slotidx = slotidx; + /* identify key object on smartcard */ + k11->keyid_len = keyid_attrib->ulValueLen; + if (k11->keyid_len > 0) { + k11->keyid = xmalloc(k11->keyid_len); + memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); } + TAILQ_INSERT_TAIL(&pkcs11_keys, k11, next); - f = k11->provider->function_list; - si = &k11->provider->slotinfo[k11->slotidx]; - tlen = RSA_size(rsa); - - /* XXX handle CKR_BUFFER_TOO_SMALL */ - rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen); - if (rv == CKR_OK) - rval = tlen; - else - error("C_Sign failed: %lu", rv); - - return (rval); + return 0; } -static int -pkcs11_rsa_private_decrypt(int flen, const u_char *from, u_char *to, RSA *rsa, - int padding) +/* retrieve the key information by keyblob */ +static struct pkcs11_key * +pkcs11_lookup_key(struct sshkey *key) { - return (-1); + struct pkcs11_key *k11, *found = NULL; + struct sshbuf *keyblob; + int r; + + if ((keyblob = sshbuf_new()) == NULL) + fatal_f("sshbuf_new failed"); + if ((r = sshkey_putb(key, keyblob)) != 0) + fatal_fr(r, "sshkey_putb"); + TAILQ_FOREACH(k11, &pkcs11_keys, next) { + if (sshbuf_equals(k11->keyblob, keyblob) == 0) { + found = k11; + break; + } + } + sshbuf_free(keyblob); + return found; } +#ifdef WITH_OPENSSL +/* + * See: + * https://datatracker.ietf.org/doc/html/rfc8017#section-9.2 + */ + +/* + * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) + * oiw(14) secsig(3) algorithms(2) 26 } + */ +static const u_char id_sha1[] = { + 0x30, 0x21, /* type Sequence, length 0x21 (33) */ + 0x30, 0x09, /* type Sequence, length 0x09 */ + 0x06, 0x05, /* type OID, length 0x05 */ + 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */ + 0x05, 0x00, /* NULL */ + 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ +}; + +/* + * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) + * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) + * id-sha256(1) } + */ +static const u_char id_sha256[] = { + 0x30, 0x31, /* type Sequence, length 0x31 (49) */ + 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ + 0x06, 0x09, /* type OID, length 0x09 */ + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */ + 0x05, 0x00, /* NULL */ + 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */ +}; + +/* + * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) + * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) + * id-sha256(3) } + */ +static const u_char id_sha512[] = { + 0x30, 0x51, /* type Sequence, length 0x51 (81) */ + 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ + 0x06, 0x09, /* type OID, length 0x09 */ + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */ + 0x05, 0x00, /* NULL */ + 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */ +}; + static int -pkcs11_rsa_start_wrapper(void) +rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp) { - if (rsa_method != NULL) - return (0); - rsa_method = RSA_meth_dup(RSA_get_default_method()); - if (rsa_method == NULL) - return (-1); - rsa_idx = RSA_get_ex_new_index(0, "ssh-pkcs11-rsa", - NULL, NULL, pkcs11_k11_free); - if (rsa_idx == -1) - return (-1); - if (!RSA_meth_set1_name(rsa_method, "pkcs11") || - !RSA_meth_set_priv_enc(rsa_method, pkcs11_rsa_private_encrypt) || - !RSA_meth_set_priv_dec(rsa_method, pkcs11_rsa_private_decrypt)) { - error_f("setup pkcs11 method failed"); - return (-1); + switch (hash_alg) { + case SSH_DIGEST_SHA1: + *oidp = id_sha1; + *oidlenp = sizeof(id_sha1); + break; + case SSH_DIGEST_SHA256: + *oidp = id_sha256; + *oidlenp = sizeof(id_sha256); + break; + case SSH_DIGEST_SHA512: + *oidp = id_sha512; + *oidlenp = sizeof(id_sha512); + break; + default: + return SSH_ERR_INVALID_ARGUMENT; } - return (0); + return 0; } -/* redirect private key operations for rsa key to pkcs11 token */ static int -pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, - CK_ATTRIBUTE *keyid_attrib, RSA *rsa) +pkcs11_sign_rsa(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) { struct pkcs11_key *k11; + struct pkcs11_slotinfo *si; + CK_FUNCTION_LIST *f; + CK_ULONG slen = 0; + CK_RV rv; + int hashalg, r, diff, siglen, ret = -1; + u_char *oid_dgst = NULL, *sig = NULL; + size_t dgst_len, oid_len, oid_dgst_len = 0; + const u_char *oid; - if (pkcs11_rsa_start_wrapper() == -1) - return (-1); + if (sigp != NULL) + *sigp = NULL; + if (lenp != NULL) + *lenp = 0; - k11 = xcalloc(1, sizeof(*k11)); - k11->provider = provider; - provider->refcount++; /* provider referenced by RSA key */ - k11->slotidx = slotidx; - /* identify key object on smartcard */ - k11->keyid_len = keyid_attrib->ulValueLen; - if (k11->keyid_len > 0) { - k11->keyid = xmalloc(k11->keyid_len); - memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); + if ((k11 = pkcs11_lookup_key(key)) == NULL) { + error_f("no key found"); + return SSH_ERR_KEY_NOT_FOUND; } - if (RSA_set_method(rsa, rsa_method) != 1) - fatal_f("RSA_set_method failed"); - if (RSA_set_ex_data(rsa, rsa_idx, k11) != 1) - fatal_f("RSA_set_ex_data failed"); - return (0); + debug3_f("sign with alg \"%s\" using provider %s slotidx %lu", + alg == NULL ? "" : alg, k11->provider->name, (u_long)k11->slotidx); + + if (pkcs11_get_key(k11, CKM_RSA_PKCS) == -1) { + error("pkcs11_get_key failed"); + return SSH_ERR_AGENT_FAILURE; + } + + f = k11->provider->function_list; + si = &k11->provider->slotinfo[k11->slotidx]; + + if ((siglen = EVP_PKEY_size(key->pkey)) <= 0) + return SSH_ERR_INVALID_ARGUMENT; + sig = xmalloc(siglen); + slen = (CK_ULONG)siglen; + + /* Determine hash algorithm and OID for signature */ + if (alg == NULL || *alg == '\0') + hashalg = SSH_DIGEST_SHA1; + else if ((hashalg = ssh_rsa_hash_id_from_keyname(alg)) == -1) + fatal_f("couldn't determine RSA hash alg \"%s\"", alg); + if ((r = rsa_hash_alg_oid(hashalg, &oid, &oid_len)) != 0) + fatal_fr(r, "rsa_hash_alg_oid failed"); + if ((dgst_len = ssh_digest_bytes(hashalg)) == 0) + fatal_f("bad hash alg %d", hashalg); + + /* Prepare { oid || digest } */ + oid_dgst_len = oid_len + dgst_len; + oid_dgst = xcalloc(1, oid_dgst_len); + memcpy(oid_dgst, oid, oid_len); + if ((r = ssh_digest_memory(hashalg, data, datalen, + oid_dgst + oid_len, dgst_len)) == -1) + fatal_fr(r, "hash failed"); + + /* XXX handle CKR_BUFFER_TOO_SMALL */ + if ((rv = f->C_Sign(si->session, (CK_BYTE *)oid_dgst, + oid_dgst_len, sig, &slen)) != CKR_OK) { + error("C_Sign failed: %lu", rv); + goto done; + } + + if (slen < (CK_ULONG)siglen) { + diff = siglen - slen; + debug3_f("repack %lu < %d (diff %d)", + (u_long)slen, siglen, diff); + memmove(sig + diff, sig, slen); + explicit_bzero(sig, diff); + } else if (slen > (size_t)siglen) + fatal_f("bad C_Sign length"); + + if ((ret = ssh_rsa_encode_store_sig(hashalg, sig, siglen, + sigp, lenp)) != 0) + fatal_fr(ret, "couldn't store signature"); + + /* success */ + ret = 0; + done: + freezero(oid_dgst, oid_dgst_len); + free(sig); + return ret; } -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) -/* openssl callback doing the actual signing operation */ -static ECDSA_SIG * -ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, - const BIGNUM *rp, EC_KEY *ec) +#ifdef OPENSSL_HAS_ECC +static int +pkcs11_sign_ecdsa(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) { struct pkcs11_key *k11; struct pkcs11_slotinfo *si; CK_FUNCTION_LIST *f; - CK_ULONG siglen = 0, bnlen; + CK_ULONG slen = 0, bnlen; CK_RV rv; - ECDSA_SIG *ret = NULL; - u_char *sig; - BIGNUM *r = NULL, *s = NULL; + BIGNUM *sig_r = NULL, *sig_s = NULL; + u_char *sig = NULL, *dgst = NULL; + size_t dgst_len = 0; + int hashalg, ret = -1, r, siglen; - if ((k11 = EC_KEY_get_ex_data(ec, ec_key_idx)) == NULL) { - ossl_error("EC_KEY_get_ex_data failed for ec"); - return (NULL); + if (sigp != NULL) + *sigp = NULL; + if (lenp != NULL) + *lenp = 0; + + if ((k11 = pkcs11_lookup_key(key)) == NULL) { + error_f("no key found"); + return SSH_ERR_KEY_NOT_FOUND; } if (pkcs11_get_key(k11, CKM_ECDSA) == -1) { error("pkcs11_get_key failed"); - return (NULL); + return SSH_ERR_AGENT_FAILURE; } + debug3_f("sign using provider %s slotidx %lu", + k11->provider->name, (u_long)k11->slotidx); + f = k11->provider->function_list; si = &k11->provider->slotinfo[k11->slotidx]; - siglen = ECDSA_size(ec); + /* Prepare digest to be signed */ + if ((hashalg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) + fatal_f("couldn't determine ECDSA hash alg"); + if ((dgst_len = ssh_digest_bytes(hashalg)) == 0) + fatal_f("bad hash alg %d", hashalg); + dgst = xcalloc(1, dgst_len); + if ((r = ssh_digest_memory(hashalg, data, datalen, + dgst, dgst_len)) == -1) + fatal_fr(r, "hash failed"); + + if ((siglen = EVP_PKEY_size(key->pkey)) <= 0) + return SSH_ERR_INVALID_ARGUMENT; sig = xmalloc(siglen); + slen = (CK_ULONG)siglen; /* XXX handle CKR_BUFFER_TOO_SMALL */ - rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, sig, &siglen); + rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, sig, &slen); if (rv != CKR_OK) { error("C_Sign failed: %lu", rv); goto done; } - if (siglen < 64 || siglen > 132 || siglen % 2) { - error_f("bad signature length: %lu", (u_long)siglen); - goto done; - } - bnlen = siglen/2; - if ((ret = ECDSA_SIG_new()) == NULL) { - error("ECDSA_SIG_new failed"); + if (slen < 64 || slen > 132 || slen % 2) { + error_f("bad signature length: %lu", (u_long)slen); goto done; } - if ((r = BN_bin2bn(sig, bnlen, NULL)) == NULL || - (s = BN_bin2bn(sig+bnlen, bnlen, NULL)) == NULL) { + bnlen = slen/2; + if ((sig_r = BN_bin2bn(sig, bnlen, NULL)) == NULL || + (sig_s = BN_bin2bn(sig+bnlen, bnlen, NULL)) == NULL) { ossl_error("BN_bin2bn failed"); - ECDSA_SIG_free(ret); - ret = NULL; goto done; } - if (!ECDSA_SIG_set0(ret, r, s)) { - error_f("ECDSA_SIG_set0 failed"); - ECDSA_SIG_free(ret); - ret = NULL; - goto done; - } - r = s = NULL; /* now owned by ret */ + + if ((ret = ssh_ecdsa_encode_store_sig(key, sig_r, sig_s, + sigp, lenp)) != 0) + fatal_fr(ret, "couldn't store signature"); + /* success */ + ret = 0; done: - BN_free(r); - BN_free(s); + freezero(dgst, dgst_len); + BN_free(sig_r); + BN_free(sig_s); free(sig); - - return (ret); + return ret; } +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ static int -pkcs11_ecdsa_start_wrapper(void) +pkcs11_sign_ed25519(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 (*orig_sign)(int, const unsigned char *, int, unsigned char *, - unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL; + struct pkcs11_key *k11; + struct pkcs11_slotinfo *si; + CK_FUNCTION_LIST *f; + CK_ULONG slen = 0; + CK_RV rv; + u_char *sig = NULL; + CK_BYTE *xdata = NULL; + int ret = -1; - if (ec_key_method != NULL) - return (0); - ec_key_idx = EC_KEY_get_ex_new_index(0, "ssh-pkcs11-ecdsa", - NULL, NULL, pkcs11_k11_free); - if (ec_key_idx == -1) - return (-1); - ec_key_method = EC_KEY_METHOD_new(EC_KEY_OpenSSL()); - if (ec_key_method == NULL) - return (-1); - EC_KEY_METHOD_get_sign(ec_key_method, &orig_sign, NULL, NULL); - EC_KEY_METHOD_set_sign(ec_key_method, orig_sign, NULL, ecdsa_do_sign); - return (0); -} + if (sigp != NULL) + *sigp = NULL; + if (lenp != NULL) + *lenp = 0; -static int -pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, - CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec) -{ - struct pkcs11_key *k11; + if ((k11 = pkcs11_lookup_key(key)) == NULL) { + error_f("no key found"); + return SSH_ERR_KEY_NOT_FOUND; + } - if (pkcs11_ecdsa_start_wrapper() == -1) - return (-1); + if (pkcs11_get_key(k11, CKM_EDDSA) == -1) { + error("pkcs11_get_key failed"); + return SSH_ERR_AGENT_FAILURE; + } - k11 = xcalloc(1, sizeof(*k11)); - k11->provider = provider; - provider->refcount++; /* provider referenced by ECDSA key */ - k11->slotidx = slotidx; - /* identify key object on smartcard */ - k11->keyid_len = keyid_attrib->ulValueLen; - if (k11->keyid_len > 0) { - k11->keyid = xmalloc(k11->keyid_len); - memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); + debug3_f("sign using provider %s slotidx %lu", + k11->provider->name, (u_long)k11->slotidx); + + f = k11->provider->function_list; + si = &k11->provider->slotinfo[k11->slotidx]; + + xdata = xmalloc(datalen); + memcpy(xdata, data, datalen); + sig = xmalloc(crypto_sign_ed25519_BYTES); + slen = crypto_sign_ed25519_BYTES; + + rv = f->C_Sign(si->session, xdata, datalen, sig, &slen); + if (rv != CKR_OK) { + error("C_Sign failed: %lu", rv); + goto done; } - if (EC_KEY_set_method(ec, ec_key_method) != 1) - fatal_f("EC_KEY_set_method failed"); - if (EC_KEY_set_ex_data(ec, ec_key_idx, k11) != 1) - fatal_f("EC_KEY_set_ex_data failed"); + if (slen != crypto_sign_ed25519_BYTES) { + error_f("bad signature length: %lu", (u_long)slen); + goto done; + } + if ((ret = ssh_ed25519_encode_store_sig(sig, slen, sigp, lenp)) != 0) + fatal_fr(ret, "couldn't store signature"); - return (0); + /* success */ + ret = 0; + done: + if (xdata != NULL) + freezero(xdata, datalen); + free(sig); + return ret; } -#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ /* remove trailing spaces */ static char * @@ -702,7 +851,8 @@ pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key) return (0); } -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) +#ifdef WITH_OPENSSL +#ifdef OPENSSL_HAS_ECC static struct sshkey * pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj) @@ -716,8 +866,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, EC_GROUP *group = NULL; struct sshkey *key = NULL; const unsigned char *attrp = NULL; - int i; - int nid; + int success = -1, r, i, nid; memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -791,6 +940,11 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, ossl_error("o2i_ECPublicKey failed"); goto fail; } + if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(ec), + EC_KEY_get0_public_key(ec))) != 0) { + error_fr(r, "invalid EC key"); + goto fail; + } nid = sshkey_ecdsa_key_to_nid(ec); if (nid < 0) { @@ -798,9 +952,6 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, goto fail; } - if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec)) - goto fail; - key = sshkey_new(KEY_UNSPEC); if (key == NULL) { error("sshkey_new failed"); @@ -815,8 +966,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, key->ecdsa_nid = nid; key->type = KEY_ECDSA; key->flags |= SSHKEY_FLAG_EXT; - + if (pkcs11_record_key(p, slotidx, &key_attr[0], key)) + goto fail; + /* success */ + success = 0; fail: + if (success != 0) { + sshkey_free(key); + key = NULL; + } for (i = 0; i < 3; i++) free(key_attr[i].pValue); if (ec) @@ -828,7 +986,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, return (key); } -#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ +#endif /* OPENSSL_HAS_ECC */ static struct sshkey * pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, @@ -841,7 +999,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, RSA *rsa = NULL; BIGNUM *rsa_n, *rsa_e; struct sshkey *key = NULL; - int i; + int i, success = -1; memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -897,9 +1055,6 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, fatal_f("set key"); rsa_n = rsa_e = NULL; /* transferred */ - if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa)) - goto fail; - key = sshkey_new(KEY_UNSPEC); if (key == NULL) { error("sshkey_new failed"); @@ -913,15 +1068,137 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, fatal("EVP_PKEY_set1_RSA failed"); key->type = KEY_RSA; key->flags |= SSHKEY_FLAG_EXT; - + if (EVP_PKEY_bits(key->pkey) < SSH_RSA_MINIMUM_MODULUS_SIZE) { + error_f("RSA key too small %d < minimum %d", + EVP_PKEY_bits(key->pkey), SSH_RSA_MINIMUM_MODULUS_SIZE); + goto fail; + } + if (pkcs11_record_key(p, slotidx, &key_attr[0], key)) + goto fail; + /* success */ + success = 0; fail: for (i = 0; i < 3; i++) free(key_attr[i].pValue); RSA_free(rsa); + if (success != 0) { + sshkey_free(key); + key = NULL; + } + return key; +} +#endif /* WITH_OPENSSL */ - return (key); +static struct sshkey * +pkcs11_fetch_ed25519_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE *obj) +{ + CK_ATTRIBUTE key_attr[3]; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; + struct sshkey *key = NULL; + const unsigned char *d = NULL; + size_t len; + char *hex = NULL; + int success = -1, i; + /* https://docs.oasis-open.org/pkcs11/pkcs11-curr/v3.0/os/pkcs11-curr-v3.0-os.html#_Toc30061180 */ + const u_char id1[14] = { + 0x13, 0x0c, 0x65, 0x64, 0x77, 0x61, 0x72, 0x64, + 0x73, 0x32, 0x35, 0x35, 0x31, 0x39, + }; /* PrintableString { "edwards25519" } */ + const u_char id2[5] = { + 0x06, 0x03, 0x2b, 0x65, 0x70, + }; /* OBJECT_IDENTIFIER { 1.3.101.112 } */ + + memset(&key_attr, 0, sizeof(key_attr)); + key_attr[0].type = CKA_ID; + key_attr[1].type = CKA_EC_POINT; /* XXX or CKA_VALUE ? */ + key_attr[2].type = CKA_EC_PARAMS; + + session = p->slotinfo[slotidx].session; + f = p->function_list; + + /* figure out size of the attributes */ + rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + return (NULL); + } + + /* + * Allow CKA_ID (always first attribute) to be empty, but + * ensure that none of the others are zero length. + * XXX assumes CKA_ID is always first. + */ + if (key_attr[1].ulValueLen == 0 || + key_attr[2].ulValueLen == 0) { + error("invalid attribute length"); + return (NULL); + } + + /* allocate buffers for attributes */ + for (i = 0; i < 3; i++) { + if (key_attr[i].ulValueLen > 0) + key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); + } + + /* retrieve ID, public point and curve parameters of EC key */ + rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + goto fail; + } + + /* Expect one of the supported identifiers in CKA_EC_PARAMS */ + d = (u_char *)key_attr[2].pValue; + len = key_attr[2].ulValueLen; + if ((len != sizeof(id1) || memcmp(d, id1, sizeof(id1)) != 0) && + (len != sizeof(id2) || memcmp(d, id2, sizeof(id2)) != 0)) { + hex = tohex(d, len); + logit_f("unsupported CKA_EC_PARAMS: %s (len %zu)", hex, len); + goto fail; + } + + /* + * Expect either a raw 32 byte pubkey or an OCTET STRING with + * a 32 byte pubkey in CKA_VALUE + */ + d = (u_char *)key_attr[1].pValue; + len = key_attr[1].ulValueLen; + if (len == ED25519_PK_SZ + 2 && d[0] == 0x04 && d[1] == ED25519_PK_SZ) { + d += 2; + len -= 2; + } + if (len != ED25519_PK_SZ) { + hex = tohex(key_attr[1].pValue, key_attr[1].ulValueLen); + logit_f("CKA_EC_POINT invalid octet str: %s (len %lu)", + hex, (u_long)key_attr[1].ulValueLen); + goto fail; + } + + if ((key = sshkey_new(KEY_UNSPEC)) == NULL) + fatal_f("sshkey_new failed"); + key->ed25519_pk = xmalloc(ED25519_PK_SZ); + memcpy(key->ed25519_pk, d, ED25519_PK_SZ); + key->type = KEY_ED25519; + key->flags |= SSHKEY_FLAG_EXT; + if (pkcs11_record_key(p, slotidx, &key_attr[0], key)) + goto fail; + /* success */ + success = 0; + fail: + if (success != 0) { + sshkey_free(key); + key = NULL; + } + free(hex); + for (i = 0; i < 3; i++) + free(key_attr[i].pValue); + return key; } +#ifdef WITH_OPENSSL static int pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp) @@ -934,16 +1211,18 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, X509_NAME *x509_name = NULL; EVP_PKEY *evp; RSA *rsa = NULL; -#ifdef OPENSSL_HAS_ECC - EC_KEY *ec = NULL; -#endif + struct sshkey *key = NULL; - int i; -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) - int nid; -#endif + int i, success = -1; const u_char *cp; char *subject = NULL; +#ifdef OPENSSL_HAS_ED25519 + size_t len; +#endif /* OPENSSL_HAS_ED25519 */ +#ifdef OPENSSL_HAS_ECC + EC_KEY *ec = NULL; + int r, nid; +#endif *keyp = NULL; *labelp = NULL; @@ -1015,9 +1294,6 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, goto out; } - if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa)) - goto out; - key = sshkey_new(KEY_UNSPEC); if (key == NULL) { error("sshkey_new failed"); @@ -1031,7 +1307,17 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, fatal("EVP_PKEY_set1_RSA failed"); key->type = KEY_RSA; key->flags |= SSHKEY_FLAG_EXT; -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) + if (EVP_PKEY_bits(key->pkey) < SSH_RSA_MINIMUM_MODULUS_SIZE) { + error_f("RSA key too small %d < minimum %d", + EVP_PKEY_bits(key->pkey), + SSH_RSA_MINIMUM_MODULUS_SIZE); + goto out; + } + if (pkcs11_record_key(p, slotidx, &cert_attr[0], key)) + goto out; + /* success */ + success = 0; +#ifdef OPENSSL_HAS_ECC } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) { if (EVP_PKEY_get0_EC_KEY(evp) == NULL) { error("invalid x509; no ec key"); @@ -1041,16 +1327,17 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, error("EC_KEY_dup failed"); goto out; } - + if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(ec), + EC_KEY_get0_public_key(ec))) != 0) { + error_fr(r, "invalid EC key"); + goto out; + } nid = sshkey_ecdsa_key_to_nid(ec); if (nid < 0) { error("couldn't get curve nid"); goto out; } - if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec)) - goto out; - key = sshkey_new(KEY_UNSPEC); if (key == NULL) { error("sshkey_new failed"); @@ -1065,7 +1352,33 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, key->ecdsa_nid = nid; key->type = KEY_ECDSA; key->flags |= SSHKEY_FLAG_EXT; -#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ + if (pkcs11_record_key(p, slotidx, &cert_attr[0], key)) + goto out; + /* success */ + success = 0; +#endif /* OPENSSL_HAS_ECC */ +#ifdef OPENSSL_HAS_ED25519 + } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_ED25519) { + if ((key = sshkey_new(KEY_UNSPEC)) == NULL || + (key->ed25519_pk = calloc(1, ED25519_PK_SZ)) == NULL) + fatal_f("allocation failed"); + len = ED25519_PK_SZ; + if (!EVP_PKEY_get_raw_public_key(evp, key->ed25519_pk, &len)) { + ossl_error("EVP_PKEY_get_raw_public_key failed"); + goto out; + } + if (len != ED25519_PK_SZ) { + error_f("incorrect returned public key " + "length for ed25519"); + goto out; + } + key->type = KEY_ED25519; + key->flags |= SSHKEY_FLAG_EXT; + if (pkcs11_record_key(p, slotidx, &cert_attr[0], key)) + goto out; + /* success */ + success = 0; +#endif /* OPENSSL_HAS_ED25519 */ } else { error("unknown certificate key type"); goto out; @@ -1077,8 +1390,9 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, RSA_free(rsa); #ifdef OPENSSL_HAS_ECC EC_KEY_free(ec); -#endif - if (key == NULL) { +#endif /* OPENSSL_HAS_ECC */ + if (success != 0 || key == NULL) { + sshkey_free(key); free(subject); return -1; } @@ -1087,17 +1401,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, *labelp = subject; return 0; } - -#if 0 -static int -have_rsa_key(const RSA *rsa) -{ - const BIGNUM *rsa_n, *rsa_e; - - RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL); - return rsa_n != NULL && rsa_e != NULL; -} -#endif +#endif /* WITH_OPENSSL */ static void note_key(struct pkcs11_provider *p, CK_ULONG slotidx, const char *context, @@ -1115,6 +1419,7 @@ note_key(struct pkcs11_provider *p, CK_ULONG slotidx, const char *context, free(fp); } +#ifdef WITH_OPENSSL /* libcrypto needed for certificate parsing */ /* * lookup certificates for token in slot identified by slotidx, * add 'wrapped' public keys to the 'keysp' array and increment nkeys. @@ -1219,6 +1524,7 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, return (ret); } +#endif /* WITH_OPENSSL */ /* * lookup public keys for token in slot identified by slotidx, @@ -1286,18 +1592,24 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, label[key_attr[1].ulValueLen] = '\0'; switch (ck_key_type) { +#ifdef WITH_OPENSSL case CKK_RSA: key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj); break; -#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) +#ifdef OPENSSL_HAS_ECC case CKK_ECDSA: key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj); break; -#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + case CKK_EC_EDWARDS: + key = pkcs11_fetch_ed25519_pubkey(p, slotidx, &obj); + break; default: /* XXX print key type? */ key = NULL; - error("skipping unsupported key type"); + error("skipping unsupported key type 0x%lx", + (u_long)ck_key_type); } if (key == NULL) { @@ -1431,7 +1743,7 @@ pkcs11_decode_hex(const char *hex, unsigned char **dest, size_t *rlen) *dest = xmalloc(len); for (i = 0; i < len; i++) { - int hi, low; + int hi, lo; hi = h2i(hex[2 * i]); lo = h2i(hex[(2 * i) + 1]); @@ -1652,7 +1964,9 @@ pkcs11_register_provider(char *provider_id, char *pin, keyp == NULL) continue; pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); +#ifdef WITH_OPENSSL pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); +#endif if (nkeys == 0 && !p->slotinfo[i].logged_in && pkcs11_interactive) { /* @@ -1665,7 +1979,9 @@ pkcs11_register_provider(char *provider_id, char *pin, continue; } pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); +#ifdef WITH_OPENSSL pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); +#endif } } @@ -1693,6 +2009,35 @@ pkcs11_register_provider(char *provider_id, char *pin, return (ret); } +int +pkcs11_init(int interactive) +{ + debug3_f("called, interactive = %d", interactive); + + pkcs11_interactive = interactive; + TAILQ_INIT(&pkcs11_providers); + TAILQ_INIT(&pkcs11_keys); + return (0); +} + +/* unregister all providers, keys might still point to the providers */ +void +pkcs11_terminate(void) +{ + struct pkcs11_provider *p; + struct pkcs11_key *k11; + + debug3_f("called"); + + while ((k11 = TAILQ_FIRST(&pkcs11_keys)) != NULL) + pkcs11_k11_free(k11); + while ((p = TAILQ_FIRST(&pkcs11_providers)) != NULL) { + TAILQ_REMOVE(&pkcs11_providers, p, next); + pkcs11_provider_finalize(p); + pkcs11_provider_unref(p); + } +} + /* * register a new provider and get number of keys hold by the token, * fails if provider already exists @@ -1719,6 +2064,41 @@ pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp, return (nkeys); } +int +pkcs11_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) +{ + switch (key->type) { + case KEY_RSA: + case KEY_RSA_CERT: +#ifdef WITH_OPENSSL + return pkcs11_sign_rsa(key, sigp, lenp, data, datalen, + alg, sk_provider, sk_pin, compat); +#ifdef OPENSSL_HAS_ECC + case KEY_ECDSA: + case KEY_ECDSA_CERT: + return pkcs11_sign_ecdsa(key, sigp, lenp, data, datalen, + alg, sk_provider, sk_pin, compat); +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + case KEY_ED25519: + case KEY_ED25519_CERT: + return pkcs11_sign_ed25519(key, sigp, lenp, data, datalen, + alg, sk_provider, sk_pin, compat); + default: + return SSH_ERR_KEY_TYPE_UNKNOWN; + } +} + +void +pkcs11_key_free(struct sshkey *key) +{ + /* never called */ +} + #ifdef WITH_PKCS11_KEYGEN struct sshkey * pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label, @@ -1862,10 +2242,24 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx, *err = rv; key_type = -1; } - if (key_type == CKK_RSA) + switch (key_type) { +#ifdef WITH_OPENSSL + case CKK_RSA: k = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj); - else if (key_type == CKK_ECDSA) + break; +#ifdef OPENSSL_HAS_ECC + case CKK_ECDSA: k = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj); + break; +#endif /* OPENSSL_HAS_ECC */ +#endif /* WITH_OPENSSL */ + case CKK_EC_EDWARDS: + k = pkcs11_fetch_ed25519_pubkey(p, slotidx, &obj); + break; + default: + debug_f("unsupported key type %lu", (u_long)key_type); + break; + } if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) { debug_f("could not destroy public key 0x%hhx", keyid); @@ -1897,7 +2291,7 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx, int pkcs11_init(int interactive) { - error("%s: dlopen() not supported", __func__); + error_f("dlopen() not supported"); return (-1); } @@ -1905,13 +2299,13 @@ int pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp, char ***labelsp) { - error("%s: dlopen() not supported", __func__); + error_f("dlopen() not supported"); return (-1); } void pkcs11_terminate(void) { - error("%s: dlopen() not supported", __func__); + error_f("dlopen() not supported"); } #endif /* ENABLE_PKCS11 */ diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h index 526689f41a14..d86c506c1c57 100644 --- a/ssh-pkcs11.h +++ b/ssh-pkcs11.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11.h,v 1.7 2023/12/18 14:46:56 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11.h,v 1.9 2025/07/30 04:27:42 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -22,10 +22,17 @@ #define SSH_PKCS11_ERR_PIN_REQUIRED 4 #define SSH_PKCS11_ERR_PIN_LOCKED 5 +struct sshkey; + int pkcs11_init(int); void pkcs11_terminate(void); -int pkcs11_add_provider(char*, char*, struct sshkey***, char***); -int pkcs11_del_provider(char*); +int pkcs11_add_provider(char *, char *, struct sshkey ***, char ***); +int pkcs11_del_provider(char *); +int pkcs11_sign(struct sshkey *, u_char **, size_t *, + const u_char *, size_t, const char *, const char *, + const char *, u_int); +void pkcs11_key_free(struct sshkey *); + #ifdef WITH_PKCS11_KEYGEN struct sshkey * pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int, @@ -35,9 +42,6 @@ struct sshkey * u_int32_t *); #endif -/* Only available in ssh-pkcs11-client.c so far */ +/* Only available in ssh-pkcs11-client.c */ 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/ssh-rsa.c b/ssh-rsa.c index 3ad1fddc4e16..fe1518984849 100644 --- a/ssh-rsa.c +++ b/ssh-rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-rsa.c,v 1.80 2024/08/15 00:51:51 djm Exp $ */ +/* $OpenBSD: ssh-rsa.c,v 1.82 2025/10/03 00:08:02 djm Exp $ */ /* * Copyright (c) 2000, 2003 Markus Friedl * @@ -21,6 +21,8 @@ #include +#include "openbsd-compat/openssl-compat.h" +#include #include #include @@ -34,8 +36,6 @@ #include "digest.h" #include "log.h" -#include "openbsd-compat/openssl-compat.h" - static u_int ssh_rsa_size(const struct sshkey *k) { @@ -309,8 +309,8 @@ ssh_rsa_deserialize_private(const char *ktype, struct sshbuf *b, return r; } -static const char * -rsa_hash_alg_ident(int hash_alg) +const char * +ssh_rsa_hash_alg_ident(int hash_alg) { switch (hash_alg) { case SSH_DIGEST_SHA1: @@ -344,8 +344,8 @@ rsa_hash_id_from_ident(const char *ident) * all the cases of rsa_hash_id_from_ident() but also the certificate key * types. */ -static int -rsa_hash_id_from_keyname(const char *alg) +int +ssh_rsa_hash_id_from_keyname(const char *alg) { int r; @@ -410,7 +410,6 @@ ssh_rsa_sign(struct sshkey *key, size_t diff, len = 0; int slen = 0; int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *b = NULL; if (lenp != NULL) *lenp = 0; @@ -420,7 +419,7 @@ ssh_rsa_sign(struct sshkey *key, if (alg == NULL || strlen(alg) == 0) hash_alg = SSH_DIGEST_SHA1; else - hash_alg = rsa_hash_id_from_keyname(alg); + hash_alg = ssh_rsa_hash_id_from_keyname(alg); if (key == NULL || key->pkey == NULL || hash_alg == -1 || sshkey_type_plain(key->type) != KEY_RSA) @@ -442,16 +441,42 @@ ssh_rsa_sign(struct sshkey *key, ret = SSH_ERR_INTERNAL_ERROR; goto out; } + if ((ret = ssh_rsa_encode_store_sig(hash_alg, sig, slen, + sigp, lenp)) != 0) + goto out; + + /* success */ + ret = 0; + out: + freezero(sig, slen); + return ret; +} - /* encode signature */ +int +ssh_rsa_encode_store_sig(int hash_alg, const u_char *sig, size_t slen, + u_char **sigp, size_t *lenp) +{ + struct sshbuf *b = NULL; + int ret = SSH_ERR_INTERNAL_ERROR; + size_t len; + + if (lenp != NULL) + *lenp = 0; + if (sigp != NULL) + *sigp = NULL; + + /* Encode signature */ if ((b = sshbuf_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; } - if ((ret = sshbuf_put_cstring(b, rsa_hash_alg_ident(hash_alg))) != 0 || + if ((ret = sshbuf_put_cstring(b, + ssh_rsa_hash_alg_ident(hash_alg))) != 0 || (ret = sshbuf_put_string(b, sig, slen)) != 0) goto out; len = sshbuf_len(b); + + /* Store signature */ if (sigp != NULL) { if ((*sigp = malloc(len)) == NULL) { ret = SSH_ERR_ALLOC_FAIL; @@ -463,7 +488,6 @@ ssh_rsa_sign(struct sshkey *key, *lenp = len; ret = 0; out: - freezero(sig, slen); sshbuf_free(b); return ret; } @@ -502,7 +526,7 @@ ssh_rsa_verify(const struct sshkey *key, * legacy reasons, but otherwise the signature type should match. */ if (alg != NULL && strcmp(alg, "ssh-rsa-cert-v01@openssh.com") != 0) { - if ((want_alg = rsa_hash_id_from_keyname(alg)) == -1) { + if ((want_alg = ssh_rsa_hash_id_from_keyname(alg)) == -1) { ret = SSH_ERR_INVALID_ARGUMENT; goto out; } diff --git a/ssh-sk-helper.0 b/ssh-sk-helper.0 index 9dc341c35b6d..4abc5e8a03c9 100644 --- a/ssh-sk-helper.0 +++ b/ssh-sk-helper.0 @@ -31,4 +31,4 @@ HISTORY AUTHORS Damien Miller -OpenBSD 7.6 April 29, 2022 OpenBSD 7.6 +OpenBSD 7.7 April 29, 2022 OpenBSD 7.7 diff --git a/ssh-sk-helper.c b/ssh-sk-helper.c index 2e1cb4351419..6b2bd8dd4abd 100644 --- a/ssh-sk-helper.c +++ b/ssh-sk-helper.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-sk-helper.c,v 1.14 2022/12/04 11:03:11 dtucker Exp $ */ +/* $OpenBSD: ssh-sk-helper.c,v 1.15 2025/07/24 05:44:55 djm Exp $ */ /* * Copyright (c) 2019 Google LLC * @@ -45,6 +45,7 @@ #include "uidswap.h" #include "ssherr.h" #include "ssh-sk.h" +#include "ssh-pkcs11.h" #ifdef ENABLE_SK extern char *__progname; @@ -87,6 +88,22 @@ null_empty(char **s) *s = NULL; } +/* stubs */ +int +pkcs11_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) +{ + return SSH_ERR_INTERNAL_ERROR; +} + +void +pkcs11_key_free(struct sshkey *key) +{ +} + static struct sshbuf * process_sign(struct sshbuf *req) { diff --git a/ssh-sk.c b/ssh-sk.c index c1739c876963..f6d8c5be956b 100644 --- a/ssh-sk.c +++ b/ssh-sk.c @@ -23,9 +23,7 @@ #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include diff --git a/ssh-xmss.c b/ssh-xmss.c deleted file mode 100644 index b6d0561b1411..000000000000 --- a/ssh-xmss.c +++ /dev/null @@ -1,389 +0,0 @@ -/* $OpenBSD: ssh-xmss.c,v 1.14 2022/10/28 00:44:44 djm Exp $*/ -/* - * Copyright (c) 2017 Stefan-Lukas Gazdag. - * Copyright (c) 2017 Markus Friedl. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include "includes.h" -#ifdef WITH_XMSS - -#define SSHKEY_INTERNAL -#include -#include - -#include -#include -#include -#ifdef HAVE_STDINT_H -# include -#endif -#include - -#include "log.h" -#include "sshbuf.h" -#include "sshkey.h" -#include "sshkey-xmss.h" -#include "ssherr.h" -#include "ssh.h" - -#include "xmss_fast.h" - -static void -ssh_xmss_cleanup(struct sshkey *k) -{ - freezero(k->xmss_pk, sshkey_xmss_pklen(k)); - freezero(k->xmss_sk, sshkey_xmss_sklen(k)); - sshkey_xmss_free_state(k); - free(k->xmss_name); - free(k->xmss_filename); - k->xmss_pk = NULL; - k->xmss_sk = NULL; - k->xmss_name = NULL; - k->xmss_filename = NULL; -} - -static int -ssh_xmss_equal(const struct sshkey *a, const struct sshkey *b) -{ - if (a->xmss_pk == NULL || b->xmss_pk == NULL) - return 0; - if (sshkey_xmss_pklen(a) != sshkey_xmss_pklen(b)) - return 0; - if (memcmp(a->xmss_pk, b->xmss_pk, sshkey_xmss_pklen(a)) != 0) - return 0; - return 1; -} - -static int -ssh_xmss_serialize_public(const struct sshkey *key, struct sshbuf *b, - enum sshkey_serialize_rep opts) -{ - int r; - - if (key->xmss_name == NULL || key->xmss_pk == NULL || - sshkey_xmss_pklen(key) == 0) - return SSH_ERR_INVALID_ARGUMENT; - if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 || - (r = sshbuf_put_string(b, key->xmss_pk, - sshkey_xmss_pklen(key))) != 0 || - (r = sshkey_xmss_serialize_pk_info(key, b, opts)) != 0) - return r; - - return 0; -} - -static int -ssh_xmss_serialize_private(const struct sshkey *key, struct sshbuf *b, - enum sshkey_serialize_rep opts) -{ - int r; - - if (key->xmss_name == NULL) - return SSH_ERR_INVALID_ARGUMENT; - /* Note: can't reuse ssh_xmss_serialize_public because of sk order */ - if ((r = sshbuf_put_cstring(b, key->xmss_name)) != 0 || - (r = sshbuf_put_string(b, key->xmss_pk, - sshkey_xmss_pklen(key))) != 0 || - (r = sshbuf_put_string(b, key->xmss_sk, - sshkey_xmss_sklen(key))) != 0 || - (r = sshkey_xmss_serialize_state_opt(key, b, opts)) != 0) - return r; - - return 0; -} - -static int -ssh_xmss_copy_public(const struct sshkey *from, struct sshkey *to) -{ - int r = SSH_ERR_INTERNAL_ERROR; - u_int32_t left; - size_t pklen; - - if ((r = sshkey_xmss_init(to, from->xmss_name)) != 0) - return r; - if (from->xmss_pk == NULL) - return 0; /* XXX SSH_ERR_INTERNAL_ERROR ? */ - - if ((pklen = sshkey_xmss_pklen(from)) == 0 || - sshkey_xmss_pklen(to) != pklen) - return SSH_ERR_INTERNAL_ERROR; - if ((to->xmss_pk = malloc(pklen)) == NULL) - return SSH_ERR_ALLOC_FAIL; - memcpy(to->xmss_pk, from->xmss_pk, pklen); - /* simulate number of signatures left on pubkey */ - left = sshkey_xmss_signatures_left(from); - if (left) - sshkey_xmss_enable_maxsign(to, left); - return 0; -} - -static int -ssh_xmss_deserialize_public(const char *ktype, struct sshbuf *b, - struct sshkey *key) -{ - size_t len = 0; - char *xmss_name = NULL; - u_char *pk = NULL; - int ret = SSH_ERR_INTERNAL_ERROR; - - if ((ret = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0) - goto out; - if ((ret = sshkey_xmss_init(key, xmss_name)) != 0) - goto out; - if ((ret = sshbuf_get_string(b, &pk, &len)) != 0) - goto out; - if (len == 0 || len != sshkey_xmss_pklen(key)) { - ret = SSH_ERR_INVALID_FORMAT; - goto out; - } - key->xmss_pk = pk; - pk = NULL; - if (!sshkey_is_cert(key) && - (ret = sshkey_xmss_deserialize_pk_info(key, b)) != 0) - goto out; - /* success */ - ret = 0; - out: - free(xmss_name); - freezero(pk, len); - return ret; -} - -static int -ssh_xmss_deserialize_private(const char *ktype, struct sshbuf *b, - struct sshkey *key) -{ - int r; - char *xmss_name = NULL; - size_t pklen = 0, sklen = 0; - u_char *xmss_pk = NULL, *xmss_sk = NULL; - - /* Note: can't reuse ssh_xmss_deserialize_public because of sk order */ - if ((r = sshbuf_get_cstring(b, &xmss_name, NULL)) != 0 || - (r = sshbuf_get_string(b, &xmss_pk, &pklen)) != 0 || - (r = sshbuf_get_string(b, &xmss_sk, &sklen)) != 0) - goto out; - if (!sshkey_is_cert(key) && - (r = sshkey_xmss_init(key, xmss_name)) != 0) - goto out; - if (pklen != sshkey_xmss_pklen(key) || - sklen != sshkey_xmss_sklen(key)) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - key->xmss_pk = xmss_pk; - key->xmss_sk = xmss_sk; - xmss_pk = xmss_sk = NULL; - /* optional internal state */ - if ((r = sshkey_xmss_deserialize_state_opt(key, b)) != 0) - goto out; - /* success */ - r = 0; - out: - free(xmss_name); - freezero(xmss_pk, pklen); - freezero(xmss_sk, sklen); - return r; -} - -static int -ssh_xmss_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) -{ - u_char *sig = NULL; - size_t slen = 0, len = 0, required_siglen; - unsigned long long smlen; - int r, ret; - struct sshbuf *b = NULL; - - if (lenp != NULL) - *lenp = 0; - if (sigp != NULL) - *sigp = NULL; - - if (key == NULL || - sshkey_type_plain(key->type) != KEY_XMSS || - key->xmss_sk == NULL || - sshkey_xmss_params(key) == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if ((r = sshkey_xmss_siglen(key, &required_siglen)) != 0) - return r; - if (datalen >= INT_MAX - required_siglen) - return SSH_ERR_INVALID_ARGUMENT; - smlen = slen = datalen + required_siglen; - if ((sig = malloc(slen)) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshkey_xmss_get_state(key, 1)) != 0) - goto out; - if ((ret = xmss_sign(key->xmss_sk, sshkey_xmss_bds_state(key), sig, &smlen, - data, datalen, sshkey_xmss_params(key))) != 0 || smlen <= datalen) { - r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */ - goto out; - } - /* encode signature */ - if ((b = sshbuf_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((r = sshbuf_put_cstring(b, "ssh-xmss@openssh.com")) != 0 || - (r = sshbuf_put_string(b, sig, smlen - datalen)) != 0) - goto out; - len = sshbuf_len(b); - if (sigp != NULL) { - if ((*sigp = malloc(len)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - memcpy(*sigp, sshbuf_ptr(b), len); - } - if (lenp != NULL) - *lenp = len; - /* success */ - r = 0; - out: - if ((ret = sshkey_xmss_update_state(key, 1)) != 0) { - /* discard signature since we cannot update the state */ - if (r == 0 && sigp != NULL && *sigp != NULL) { - explicit_bzero(*sigp, len); - free(*sigp); - } - if (sigp != NULL) - *sigp = NULL; - if (lenp != NULL) - *lenp = 0; - r = ret; - } - sshbuf_free(b); - if (sig != NULL) - freezero(sig, slen); - - return r; -} - -static int -ssh_xmss_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) -{ - struct sshbuf *b = NULL; - char *ktype = NULL; - const u_char *sigblob; - u_char *sm = NULL, *m = NULL; - size_t len, required_siglen; - unsigned long long smlen = 0, mlen = 0; - int r, ret; - - if (key == NULL || - sshkey_type_plain(key->type) != KEY_XMSS || - key->xmss_pk == NULL || - sshkey_xmss_params(key) == NULL || - sig == NULL || siglen == 0) - return SSH_ERR_INVALID_ARGUMENT; - if ((r = sshkey_xmss_siglen(key, &required_siglen)) != 0) - return r; - if (dlen >= INT_MAX - required_siglen) - return SSH_ERR_INVALID_ARGUMENT; - - if ((b = sshbuf_from(sig, siglen)) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 || - (r = sshbuf_get_string_direct(b, &sigblob, &len)) != 0) - goto out; - if (strcmp("ssh-xmss@openssh.com", ktype) != 0) { - r = SSH_ERR_KEY_TYPE_MISMATCH; - goto out; - } - if (sshbuf_len(b) != 0) { - r = SSH_ERR_UNEXPECTED_TRAILING_DATA; - goto out; - } - if (len != required_siglen) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if (dlen >= SIZE_MAX - len) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - smlen = len + dlen; - mlen = smlen; - if ((sm = malloc(smlen)) == NULL || (m = malloc(mlen)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - memcpy(sm, sigblob, len); - memcpy(sm+len, data, dlen); - if ((ret = xmss_sign_open(m, &mlen, sm, smlen, - key->xmss_pk, sshkey_xmss_params(key))) != 0) { - debug2_f("xmss_sign_open failed: %d", ret); - } - if (ret != 0 || mlen != dlen) { - r = SSH_ERR_SIGNATURE_INVALID; - goto out; - } - /* XXX compare 'm' and 'data' ? */ - /* success */ - r = 0; - out: - if (sm != NULL) - freezero(sm, smlen); - if (m != NULL) - freezero(m, smlen); - sshbuf_free(b); - free(ktype); - return r; -} - -static const struct sshkey_impl_funcs sshkey_xmss_funcs = { - /* .size = */ NULL, - /* .alloc = */ NULL, - /* .cleanup = */ ssh_xmss_cleanup, - /* .equal = */ ssh_xmss_equal, - /* .ssh_serialize_public = */ ssh_xmss_serialize_public, - /* .ssh_deserialize_public = */ ssh_xmss_deserialize_public, - /* .ssh_serialize_private = */ ssh_xmss_serialize_private, - /* .ssh_deserialize_private = */ ssh_xmss_deserialize_private, - /* .generate = */ sshkey_xmss_generate_private_key, - /* .copy_public = */ ssh_xmss_copy_public, - /* .sign = */ ssh_xmss_sign, - /* .verify = */ ssh_xmss_verify, -}; - -const struct sshkey_impl sshkey_xmss_impl = { - /* .name = */ "ssh-xmss@openssh.com", - /* .shortname = */ "XMSS", - /* .sigalg = */ NULL, - /* .type = */ KEY_XMSS, - /* .nid = */ 0, - /* .cert = */ 0, - /* .sigonly = */ 0, - /* .keybits = */ 256, - /* .funcs = */ &sshkey_xmss_funcs, -}; - -const struct sshkey_impl sshkey_xmss_cert_impl = { - /* .name = */ "ssh-xmss-cert-v01@openssh.com", - /* .shortname = */ "XMSS-CERT", - /* .sigalg = */ NULL, - /* .type = */ KEY_XMSS_CERT, - /* .nid = */ 0, - /* .cert = */ 1, - /* .sigonly = */ 0, - /* .keybits = */ 256, - /* .funcs = */ &sshkey_xmss_funcs, -}; -#endif /* WITH_XMSS */ diff --git a/ssh.0 b/ssh.0 index 7c8cf82e2d09..5cc410b1a8cd 100644 --- a/ssh.0 +++ b/ssh.0 @@ -1027,4 +1027,4 @@ AUTHORS created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. -OpenBSD 7.6 December 4, 2024 OpenBSD 7.6 +OpenBSD 7.7 December 4, 2024 OpenBSD 7.7 diff --git a/ssh.c b/ssh.c index ea94d25106cf..2fb69e63fc2d 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.612 2025/04/09 01:24:40 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.619 2025/09/25 07:05:11 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -43,9 +43,7 @@ #include "includes.h" #include -#ifdef HAVE_SYS_STAT_H -# include -#endif +#include #include #include #include @@ -531,16 +529,28 @@ resolve_canonicalize(char **hostp, int port) static void check_load(int r, struct sshkey **k, const char *path, const char *message) { + char *fp; + switch (r) { case 0: + if (k == NULL || *k == NULL) + return; /* Check RSA keys size and discard if undersized */ - if (k != NULL && *k != NULL && - (r = sshkey_check_rsa_length(*k, + if ((r = sshkey_check_rsa_length(*k, options.required_rsa_size)) != 0) { error_r(r, "load %s \"%s\"", message, path); free(*k); *k = NULL; + break; + } + if ((fp = sshkey_fingerprint(*k, + options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) { + fatal_f("failed to fingerprint %s %s key from %s", + sshkey_type(*k), message, path); } + debug("loaded %s from %s: %s %s", message, path, + sshkey_type(*k), fp); + free(fp); break; case SSH_ERR_INTERNAL_ERROR: case SSH_ERR_ALLOC_FAIL: @@ -554,6 +564,8 @@ check_load(int r, struct sshkey **k, const char *path, const char *message) error_r(r, "load %s \"%s\"", message, path); break; } + if (k != NULL && *k == NULL) + debug("no %s loaded from %s", message, path); } /* @@ -667,6 +679,8 @@ valid_ruser(const char *s) if (*s == '-') return 0; for (i = 0; s[i] != 0; i++) { + if (iscntrl((u_char)s[i])) + return 0; if (strchr("'`\";&<>|(){}", s[i]) != NULL) return 0; /* Disallow '-' after whitespace */ @@ -688,6 +702,7 @@ 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; + int user_on_commandline = 0, user_was_default = 0, user_expanded = 0; char *p, *cp, *line, *argv0, *logfile, *args; char cname[NI_MAXHOST], thishost[NI_MAXHOST]; struct stat st; @@ -759,7 +774,6 @@ main(int ac, char **av) fatal("Couldn't allocate session state"); channel_init_channels(ssh); - /* Parse command-line arguments. */ args = argv_assemble(ac, av); /* logged later */ host = NULL; @@ -1039,8 +1053,10 @@ main(int ac, char **av) } break; case 'l': - if (options.user == NULL) + if (options.user == NULL) { options.user = xstrdup(optarg); + user_on_commandline = 1; + } break; case 'L': @@ -1143,6 +1159,7 @@ main(int ac, char **av) if (options.user == NULL) { options.user = tuser; tuser = NULL; + user_on_commandline = 1; } free(tuser); if (options.port == -1 && tport != -1) @@ -1157,6 +1174,7 @@ main(int ac, char **av) if (options.user == NULL) { options.user = p; p = NULL; + user_on_commandline = 1; } *cp++ = '\0'; host = xstrdup(cp); @@ -1318,8 +1336,10 @@ main(int ac, char **av) if (fill_default_options(&options) != 0) cleanup_exit(255); - if (options.user == NULL) + if (options.user == NULL) { + user_was_default = 1; options.user = xstrdup(pw->pw_name); + } /* * If ProxyJump option specified, then construct a ProxyCommand now. @@ -1385,6 +1405,8 @@ main(int ac, char **av) if (options.port == 0) options.port = default_ssh_port(); channel_set_af(ssh, options.address_family); + ssh_packet_set_qos(ssh, options.ip_qos_interactive, + options.ip_qos_bulk); /* Tidy and check options */ if (options.host_key_alias != NULL) @@ -1472,20 +1494,30 @@ main(int ac, char **av) "" : options.jump_host); /* - * Expand User. It cannot contain %r (itself) or %C since User is + * If the user was specified via a configuration directive then attempt + * to expand it. It cannot contain %r (itself) or %C since User is * a component of the hash. */ - if (options.user != NULL) { + if (!user_on_commandline && !user_was_default) { if ((p = percent_dollar_expand(options.user, DEFAULT_CLIENT_PERCENT_EXPAND_ARGS_NOUSER(cinfo), (char *)NULL)) == NULL) fatal("invalid environment variable expansion"); + user_expanded = strcmp(p, options.user) != 0; free(options.user); options.user = p; - if (!valid_ruser(options.user)) - fatal("remote username contains invalid characters"); } + /* + * Usernames specified on the commandline or expanded from the + * configuration file must be validated. + * Conversely, usernames from getpwnam(3) or specified as literals + * via configuration (i.e. not expanded) are not subject to validation. + */ + if ((user_on_commandline || user_expanded) && + !valid_ruser(options.user)) + fatal("remote username contains invalid characters"); + /* Now User is expanded, store it and calculate hash. */ cinfo->remuser = xstrdup(options.user); cinfo->conn_hash_hex = ssh_connection_hash(cinfo->thishost, @@ -1718,8 +1750,6 @@ main(int ac, char **av) &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); @@ -1746,10 +1776,9 @@ main(int ac, char **av) 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"); \ + &(sensitive_data.keys[o]), p, "hostbased pubkey"); \ if (sensitive_data.keys[o] != NULL) { \ - debug2("hostbased key %d: %s key from \"%s\"", o, \ - sshkey_ssh_name(sensitive_data.keys[o]), p); \ + debug2("hostbased pubkey \"%s\" in slot %d", p, o); \ loaded++; \ } \ } while (0) @@ -1757,10 +1786,9 @@ main(int ac, char **av) 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"); \ + &(sensitive_data.keys[o]), p, "hostbased cert"); \ if (sensitive_data.keys[o] != NULL) { \ - debug2("hostbased key %d: %s cert from \"%s\"", o, \ - sshkey_ssh_name(sensitive_data.keys[o]), p); \ + debug2("hostbased cert \"%s\" in slot %d", p, o); \ loaded++; \ } \ } while (0) @@ -1769,17 +1797,9 @@ main(int ac, char **av) L_CERT(_PATH_HOST_ECDSA_KEY_FILE, 0); L_CERT(_PATH_HOST_ED25519_KEY_FILE, 1); L_CERT(_PATH_HOST_RSA_KEY_FILE, 2); -#ifdef WITH_DSA - L_CERT(_PATH_HOST_DSA_KEY_FILE, 3); -#endif L_PUBKEY(_PATH_HOST_ECDSA_KEY_FILE, 4); L_PUBKEY(_PATH_HOST_ED25519_KEY_FILE, 5); L_PUBKEY(_PATH_HOST_RSA_KEY_FILE, 6); -#ifdef WITH_DSA - L_PUBKEY(_PATH_HOST_DSA_KEY_FILE, 7); -#endif - 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."); @@ -1870,9 +1890,13 @@ main(int ac, char **av) #endif skip_connect: + if (addrs != NULL) + freeaddrinfo(addrs); exit_status = ssh_session2(ssh, cinfo); ssh_conn_info_free(cinfo); - ssh_packet_close(ssh); + channel_free_channels(ssh); + ssh_packet_free(ssh); + pwfree(pw); if (options.control_path != NULL && muxserver_sock != -1) unlink(options.control_path); @@ -2199,7 +2223,7 @@ ssh_session2_setup(struct ssh *ssh, int id, int success, void *arg) { extern char **environ; const char *display, *term; - int r, interactive = tty_flag; + int r; char *proto = NULL, *data = NULL; if (!success) @@ -2218,7 +2242,6 @@ ssh_session2_setup(struct ssh *ssh, int id, int success, void *arg) data, 1); client_expect_confirm(ssh, id, "X11 forwarding", CONFIRM_WARN); /* XXX exit_on_forward_failure */ - interactive = 1; } check_agent_present(); @@ -2229,10 +2252,6 @@ ssh_session2_setup(struct ssh *ssh, int id, int success, void *arg) 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"); @@ -2269,8 +2288,9 @@ ssh_session2_open(struct ssh *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); + if (tty_flag) + channel_set_tty(ssh, c); + debug3_f("channel_new: %d%s", c->self, tty_flag ? " (tty)" : ""); channel_send_open(ssh, c->self); if (options.session_type != SESSION_TYPE_NONE) @@ -2283,7 +2303,7 @@ ssh_session2_open(struct ssh *ssh) static int ssh_session2(struct ssh *ssh, const struct ssh_conn_info *cinfo) { - int r, interactive, id = -1; + int r, id = -1; char *cp, *tun_fwd_ifname = NULL; /* XXX should be pre-session */ @@ -2339,14 +2359,6 @@ ssh_session2(struct ssh *ssh, const struct ssh_conn_info *cinfo) 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 && @@ -2471,9 +2483,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo) 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); + &public, filename, "identity pubkey"); if (public == NULL) { free(cp); continue; @@ -2485,6 +2495,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo) free(cp); continue; } + free(cp); /* NB. leave filename pointing to private key */ identity_files[n_ids] = xstrdup(filename); identity_keys[n_ids] = public; @@ -2502,9 +2513,7 @@ load_public_identity_files(const struct ssh_conn_info *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); + &public, filename, "identity cert"); free(options.certificate_files[i]); options.certificate_files[i] = NULL; if (public == NULL) { diff --git a/ssh_config b/ssh_config index cc5663562e95..238a0c5e371b 100644 --- a/ssh_config +++ b/ssh_config @@ -1,4 +1,4 @@ -# $OpenBSD: ssh_config,v 1.36 2023/08/02 23:04:38 djm Exp $ +# $OpenBSD: ssh_config,v 1.37 2025/05/06 05:40:56 djm Exp $ # This is the ssh client system-wide configuration file. See # ssh_config(5) for more information. This file provides defaults for @@ -30,7 +30,6 @@ # ConnectTimeout 0 # StrictHostKeyChecking ask # IdentityFile ~/.ssh/id_rsa -# IdentityFile ~/.ssh/id_dsa # IdentityFile ~/.ssh/id_ecdsa # IdentityFile ~/.ssh/id_ed25519 # Port 22 diff --git a/ssh_config.0 b/ssh_config.0 index 5e692480316a..1c236cf05844 100644 --- a/ssh_config.0 +++ b/ssh_config.0 @@ -266,13 +266,13 @@ DESCRIPTION direct-tcpip, direct-streamlocal@openssh.com Open TCP or Unix socket (respectively) connections that - have been established from a ssh(1) local forwarding, + have been established from an ssh(1) local forwarding, i.e. LocalForward or DynamicForward. forwarded-tcpip, forwarded-streamlocal@openssh.com Open TCP or Unix socket (respectively) connections that - have been established to a sshd(8) listening on behalf of - a ssh(1) remote forwarding, i.e. RemoteForward. + have been established to an sshd(8) listening on behalf + of an ssh(1) remote forwarding, i.e. RemoteForward. session The interactive main session, including shell session, @@ -729,18 +729,18 @@ DESCRIPTION from the system configuration file. Include directive may appear inside a Match or Host block to perform conditional inclusion. - IPQoS Specifies the IPv4 type-of-service or DSCP class for connections. - Accepted values are af11, af12, af13, af21, af22, af23, af31, - af32, af33, af41, af42, af43, cs0, cs1, cs2, cs3, cs4, cs5, cs6, - cs7, ef, le, lowdelay, throughput, reliability, a numeric value, - or none to use the operating system default. This option may - take one or two arguments, separated by whitespace. If one - argument is specified, it is used as the packet class - unconditionally. If two values are specified, the first is - automatically selected for interactive sessions and the second - for non-interactive sessions. The default is af21 (Low-Latency - Data) for interactive sessions and cs1 (Lower Effort) for non- - interactive sessions. + IPQoS Specifies the Differentiated Services Field Codepoint (DSCP) + value for connections. Accepted values are af11, af12, af13, + af21, af22, af23, af31, af32, af33, af41, af42, af43, cs0, cs1, + cs2, cs3, cs4, cs5, cs6, cs7, ef, le, a numeric value, or none to + use the operating system default. This option may take one or + two arguments, separated by whitespace. If one argument is + specified, it is used as the packet class unconditionally. If + two values are specified, the first is automatically selected for + interactive sessions and the second for non-interactive sessions. + The default is ef (Expedited Forwarding) for interactive sessions + and none (the operating system default) for non-interactive + sessions. KbdInteractiveAuthentication Specifies whether to use keyboard-interactive authentication. @@ -979,8 +979,8 @@ DESCRIPTION Specifies one or more jump proxies as either [user@]host[:port] or an ssh URI. Multiple proxies may be separated by comma characters and will be visited sequentially. Setting this option - will cause ssh(1) to connect to the target host by first making a - ssh(1) connection to the specified ProxyJump host and then + will cause ssh(1) to connect to the target host by first making + an ssh(1) connection to the specified ProxyJump host and then establishing a TCP forwarding to the ultimate target from there. Setting the host to none disables this option entirely. @@ -1035,6 +1035,14 @@ DESCRIPTION OpenSSH host-bound authentication protocol extension required for restricted ssh-agent(1) forwarding. + RefuseConnection + Allows a connection to be refused by the configuration file. If + this option is specified, then ssh(1) will terminate immediately + before attempting to connect to the remote host, display an error + message that contains the argument to this keyword and return a + non-zero exit status. This option may be useful to express + reminders or warnings to the user via ssh_config. + RekeyLimit Specifies the maximum amount of data that may be transmitted or received before the session key is renegotiated, optionally @@ -1348,6 +1356,15 @@ DESCRIPTION printed at login and only the fingerprint string will be printed for unknown host keys. + WarnWeakCrypto + controls whether the user is warned when the cryptographic + algorithms negotiated for the connection are weak or otherwise + recommended against. Warnings may be disabled by turning off a + specific warning or by disabling all warnings. Warnings about + connections that don't use a post-quantum key exchange may be + disabled using the no-pq-kex flag. no will disable all warnings. + The default, equivalent to yes, is to enable all warnings. + XAuthLocation Specifies the full pathname of the xauth(1) program. The default is /usr/X11R6/bin/xauth. @@ -1472,4 +1489,4 @@ AUTHORS created OpenSSH. Markus Friedl contributed the support for SSH protocol versions 1.5 and 2.0. -OpenBSD 7.6 March 3, 2025 OpenBSD 7.6 +OpenBSD 7.7 October 4, 2025 OpenBSD 7.7 diff --git a/ssh_config.5 b/ssh_config.5 index 894d738310c8..f7066cbaab78 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -33,8 +33,8 @@ .\" (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.413 2025/03/03 06:53:09 dtucker Exp $ -.Dd $Mdocdate: March 3 2025 $ +.\" $OpenBSD: ssh_config.5,v 1.420 2025/10/04 21:41:35 naddy Exp $ +.Dd $Mdocdate: October 4 2025 $ .Dt SSH_CONFIG 5 .Os .Sh NAME @@ -532,7 +532,7 @@ 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 +been established from an .Xr ssh 1 local forwarding, i.e.\& .Cm LocalForward @@ -540,9 +540,9 @@ 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 +established to an .Xr sshd 8 -listening on behalf of a +listening on behalf of an .Xr ssh 1 remote forwarding, i.e.\& .Cm RemoteForward . @@ -1242,7 +1242,9 @@ or block to perform conditional inclusion. .It Cm IPQoS -Specifies the IPv4 type-of-service or DSCP class for connections. +Specifies the +.Em Differentiated Services Field Codepoint Pq DSCP +value for connections. Accepted values are .Cm af11 , .Cm af12 , @@ -1266,9 +1268,6 @@ Accepted values are .Cm cs7 , .Cm ef , .Cm le , -.Cm lowdelay , -.Cm throughput , -.Cm reliability , a numeric value, or .Cm none to use the operating system default. @@ -1277,11 +1276,11 @@ 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) +.Cm ef +(Expedited Forwarding) for interactive sessions and -.Cm cs1 -(Lower Effort) +.Cm none +(the operating system default) for non-interactive sessions. .It Cm KbdInteractiveAuthentication Specifies whether to use keyboard-interactive authentication. @@ -1639,7 +1638,7 @@ 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 +to connect to the target host by first making an .Xr ssh 1 connection to the specified .Cm ProxyJump @@ -1715,6 +1714,15 @@ disabling or enabling the OpenSSH host-bound authentication protocol extension required for restricted .Xr ssh-agent 1 forwarding. +.It Cm RefuseConnection +Allows a connection to be refused by the configuration file. +If this option is specified, then +.Xr ssh 1 +will terminate immediately before attempting to connect to the remote +host, display an error message that contains the argument to this keyword +and return a non-zero exit status. +This option may be useful to express reminders or warnings to the user via +.Nm . .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 @@ -2221,6 +2229,20 @@ If this flag is set to (the default), no fingerprint strings are printed at login and only the fingerprint string will be printed for unknown host keys. +.It Cm WarnWeakCrypto +controls whether the user is warned when the cryptographic algorithms +negotiated for the connection are weak or otherwise recommended against. +Warnings may be disabled by turning off a specific warning or by disabling +all warnings. +Warnings about connections that don't use a post-quantum key exchange +may be disabled using the +.Cm no-pq-kex +flag. +.Cm no +will disable all warnings. +The default, equivalent to +.Cm yes , +is to enable all warnings. .It Cm XAuthLocation Specifies the full pathname of the .Xr xauth 1 diff --git a/sshbuf-getput-basic.c b/sshbuf-getput-basic.c index 78db4b7008f5..c1813e0e1287 100644 --- a/sshbuf-getput-basic.c +++ b/sshbuf-getput-basic.c @@ -24,9 +24,7 @@ #include #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include "ssherr.h" #include "sshbuf.h" diff --git a/sshbuf-misc.c b/sshbuf-misc.c index 501dfb7fbe4a..83b472c6b9a9 100644 --- a/sshbuf-misc.c +++ b/sshbuf-misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshbuf-misc.c,v 1.18 2022/01/22 00:43:43 djm Exp $ */ +/* $OpenBSD: sshbuf-misc.c,v 1.22 2025/09/04 00:32:31 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -22,9 +22,7 @@ #include #include #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include #include @@ -71,7 +69,7 @@ sshbuf_dump(const struct sshbuf *buf, FILE *f) } char * -sshbuf_dtob16(struct sshbuf *buf) +sshbuf_dtob16(const struct sshbuf *buf) { size_t i, j, len = sshbuf_len(buf); const u_char *p = sshbuf_ptr(buf); @@ -90,6 +88,42 @@ sshbuf_dtob16(struct sshbuf *buf) return ret; } +static int +b16tod(const char v) +{ + if (v >= '0' && v <= '9') + return v - '0'; + if (v >= 'a' && v <= 'f') + return 10 + v - 'a'; + if (v >= 'A' && v <= 'A') + return 10 + v - 'A'; + return -1; +} + +struct sshbuf * +sshbuf_b16tod(const char *b16) +{ + struct sshbuf *ret; + size_t o; + int r, v1, v2; + + if ((ret = sshbuf_new()) == NULL) + return NULL; + for (o = 0; b16[o] != '\0'; o += 2) { + if ((v1 = b16tod(b16[o])) == -1 || + (v2 = b16tod(b16[o + 1])) == -1) { + sshbuf_free(ret); + return NULL; + } + if ((r = sshbuf_put_u8(ret, (u_char)((v1 << 4) | v2))) != 0) { + sshbuf_free(ret); + return NULL; + } + } + /* success */ + return ret; +} + int sshbuf_dtob64(const struct sshbuf *d, struct sshbuf *b64, int wrap) { @@ -176,6 +210,9 @@ sshbuf_dtourlb64(const struct sshbuf *d, struct sshbuf *b64, int wrap) struct sshbuf *b = NULL; size_t i, l; + if (sshbuf_len(d) == 0) + return 0; + if ((b = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; /* Encode using regular base64; we'll transform it once done */ @@ -218,7 +255,7 @@ sshbuf_dup_string(struct sshbuf *buf) size_t l = sshbuf_len(buf); char *r; - if (s == NULL || l > SIZE_MAX) + if (s == NULL || l >= SIZE_MAX) return NULL; /* accept a nul only as the last character in the buffer */ if (l > 0 && (p = memchr(s, '\0', l)) != NULL) { @@ -249,6 +286,20 @@ sshbuf_cmp(const struct sshbuf *b, size_t offset, return 0; } +int +sshbuf_equals(const struct sshbuf *a, const struct sshbuf *b) +{ + if (sshbuf_ptr(a) == NULL || sshbuf_ptr(b) == NULL) + return SSH_ERR_INTERNAL_ERROR; + if (sshbuf_len(a) != sshbuf_len(b)) + return SSH_ERR_MESSAGE_INCOMPLETE; + if (sshbuf_len(a) == 0) + return 0; + if (memcmp(sshbuf_ptr(a), sshbuf_ptr(b), sshbuf_len(a)) != 0) + return SSH_ERR_INVALID_FORMAT; + return 0; +} + int sshbuf_find(const struct sshbuf *b, size_t start_offset, const void *s, size_t len, size_t *offsetp) diff --git a/sshbuf.h b/sshbuf.h index 6ba2c9ba223c..a362a78a136f 100644 --- a/sshbuf.h +++ b/sshbuf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshbuf.h,v 1.29 2024/08/15 00:51:51 djm Exp $ */ +/* $OpenBSD: sshbuf.h,v 1.32 2025/09/02 09:41:23 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -61,7 +61,8 @@ struct sshbuf *sshbuf_fromb(struct sshbuf *buf); * an existing buffer (the string is consumed in the process). * The contents of "buf" must not change in the lifetime of the resultant * buffer. - * Returns pointer to buffer on success, or NULL on allocation failure. + * On success, a pointer to the newly allocated buffer is placed in *bufp. + * Returns 0 on success, or a negative SSH_ERR_* error code on failure. */ int sshbuf_froms(struct sshbuf *buf, struct sshbuf **bufp); @@ -235,7 +236,9 @@ void sshbuf_dump(const struct sshbuf *buf, FILE *f); void sshbuf_dump_data(const void *s, size_t len, FILE *f); /* Return the hexadecimal representation of the contents of the buffer */ -char *sshbuf_dtob16(struct sshbuf *buf); +char *sshbuf_dtob16(const struct sshbuf *buf); +/* Make a sshbuf from a hex string */ +struct sshbuf *sshbuf_b16tod(const char *b16); /* Encode the contents of the buffer as base64 */ char *sshbuf_dtob64_string(const struct sshbuf *buf, int wrap); @@ -261,6 +264,15 @@ int sshbuf_b64tod(struct sshbuf *buf, const char *b64); int sshbuf_cmp(const struct sshbuf *b, size_t offset, const void *s, size_t len); +/* + * Test whether two buffers have identical contents. + * SSH_ERR_MESSAGE_INCOMPLETE indicates the buffers had differing size. + * SSH_ERR_INVALID_FORMAT indicates the buffers were the same size but + * had differing contents. + * Returns 0 on successful compare (comparing two empty buffers returns 0). + */ +int sshbuf_equals(const struct sshbuf *a, const struct sshbuf *b); + /* * Searches the buffer for the specified string. Returns 0 on success * and updates *offsetp with the offset of the first match, relative to diff --git a/sshconnect.c b/sshconnect.c index dc28a5e4a9af..36c5c31add52 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.369 2024/12/06 16:21:48 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.376 2025/09/25 06:23:19 jsg Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -19,9 +19,7 @@ #include #include #include -#ifdef HAVE_SYS_TIME_H -# include -#endif +#include #include #include @@ -36,9 +34,7 @@ #include #endif #include -#ifdef HAVE_POLL_H #include -#endif #include #include #include @@ -46,7 +42,7 @@ #include #include #ifdef HAVE_IFADDRS_H -# include +#include #endif #ifdef WINDOWS @@ -834,7 +830,7 @@ hostkeys_find_by_key(const char *host, const char *ip, const struct sshkey *key, char **system_hostfiles, u_int num_system_hostfiles, char ***names, u_int *nnames) { - struct find_by_key_ctx ctx = {0, 0, 0, 0, 0}; + struct find_by_key_ctx ctx = {NULL, NULL, NULL, NULL, 0}; u_int i; *names = NULL; @@ -1182,7 +1178,7 @@ check_host_key(char *hostname, const struct ssh_conn_info *cinfo, 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); // CodeQL [SM02311]: false positive NULL check for ra in earlier line + logit("Host key fingerprint is: %s\n%s", fp, ra); // CodeQL [SM02311]: false positive NULL check for ra in earlier line free(ra); free(fp); } @@ -1233,7 +1229,7 @@ check_host_key(char *hostname, const struct ssh_conn_info *cinfo, options.fingerprint_hash, SSH_FP_RANDOMART); if (fp == NULL || ra == NULL) fatal_f("sshkey_fingerprint failed"); - xextendf(&msg1, "\n", "%s key fingerprint is %s.", + xextendf(&msg1, "\n", "%s key fingerprint is: %s", type, fp); if (options.visual_host_key) xextendf(&msg1, "\n", "%s", ra); // CodeQL [SM02311]: false positive NULL check for ra in earlier line @@ -1471,6 +1467,7 @@ check_host_key(char *hostname, const struct ssh_conn_info *cinfo, options.update_hostkeys = 0; } + sshkey_free(raw_key); free(ip); free(host); if (host_hostkeys != NULL) @@ -1617,6 +1614,14 @@ verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key, return r; } +static void +warn_nonpq_kex(void) +{ + logit("** WARNING: connection is not using a post-quantum key exchange algorithm."); + logit("** This session may be vulnerable to \"store now, decrypt later\" attacks."); + logit("** The server may need to be upgraded. See https://openssh.com/pq.html"); +} + /* * Starts a dialog with the server, and authenticates the current user on the * server. This does not need any extra privileges. The basic connection @@ -1652,6 +1657,10 @@ ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost, /* authenticate user */ debug("Authenticating to %s:%d as '%s'", host, port, server_user); ssh_kex2(ssh, host, hostaddr, port, cinfo); + if (!options.kex_algorithms_set && ssh->kex != NULL && + ssh->kex->name != NULL && options.warn_weak_crypto && + !kex_is_pq_from_name(ssh->kex->name)) + warn_nonpq_kex(); ssh_userauth2(ssh, local_user, server_user, host, sensitive); free(local_user); free(host); @@ -1663,12 +1672,8 @@ show_other_keys(struct hostkeys *hostkeys, struct sshkey *key) { int type[] = { KEY_RSA, -#ifdef WITH_DSA - KEY_DSA, -#endif KEY_ECDSA, KEY_ED25519, - KEY_XMSS, -1 }; int i, ret = 0; @@ -1795,7 +1800,7 @@ maybe_add_key_to_agent(const char *authfile, struct sshkey *private, 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) + (options.add_keys_to_agent == 3), skprovider, NULL, 0)) == 0) debug("identity added to agent: %s", authfile); else debug("could not add identity to agent: %s (%d)", authfile, r); diff --git a/sshconnect2.c b/sshconnect2.c index d7d8ef8e01bc..becbc01fed85 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.377 2025/02/18 08:02:48 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.378 2025/09/15 04:51:35 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -1857,7 +1857,7 @@ pubkey_prepare(struct ssh *ssh, Authctxt *authctxt) TAILQ_REMOVE(preferred, id, next); sshkey_free(id->key); free(id->filename); - memset(id, 0, sizeof(*id)); + freezero(id, sizeof(*id)); } /* List the keys we plan on using */ TAILQ_FOREACH_SAFE(id, preferred, next, id2) { diff --git a/sshd-auth.c b/sshd-auth.c index ad22dc338ee3..833e42d8fe38 100644 --- a/sshd-auth.c +++ b/sshd-auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd-auth.c,v 1.3 2025/01/16 06:37:10 dtucker Exp $ */ +/* $OpenBSD: sshd-auth.c,v 1.9 2025/09/15 04:52:12 djm Exp $ */ /* * SSH2 implementation: * Privilege Separation: @@ -43,7 +43,7 @@ #include #include #ifdef HAVE_PATHS_H -# include +#include #endif #include #include @@ -250,12 +250,10 @@ list_hostkey_types(void) 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; } @@ -271,12 +269,10 @@ list_hostkey_types(void) 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; } @@ -297,12 +293,10 @@ get_hostkey_public_by_type(int type, int nid, struct ssh *ssh) 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 = host_certificates[i]; break; default: @@ -448,7 +442,7 @@ main(int ac, char **av) extern int optind; int r, opt, have_key = 0; int sock_in = -1, sock_out = -1, rexeced_flag = 0; - char *line, *logfile = NULL; + char *line; u_int i; mode_t new_umask; Authctxt *authctxt; @@ -511,11 +505,7 @@ main(int ac, char **av) options.log_level++; break; case 'D': - /* ignore */ - break; case 'E': - logfile = optarg; - /* FALLTHROUGH */ case 'e': /* ignore */ break; @@ -604,23 +594,6 @@ main(int ac, char **av) OpenSSL_add_all_algorithms(); #endif -// Windows logging handled by sending debug messages to the parent sshd process -// because an unprivileged sshd-auth process cannot open a log file owned by system -#ifndef WINDOWS - /* If requested, redirect the logs to the specified logfile. */ - if (logfile != NULL) { - char *cp, pid_s[32]; - - snprintf(pid_s, sizeof(pid_s), "%ld", (unsigned long)getpid()); - cp = percent_expand(logfile, - "p", pid_s, - "P", "sshd-auth", - (char *)NULL); - log_redirect_stderr_to(cp); - free(cp); - } -#endif /* !WINDOWS */ - log_init(__progname, options.log_level == SYSLOG_LEVEL_NOT_SET ? SYSLOG_LEVEL_INFO : options.log_level, @@ -680,9 +653,12 @@ main(int ac, char **av) /* Fill in default values for those options not explicitly set. */ fill_default_server_options(&options); options.timing_secret = timing_secret; /* XXX eliminate from unpriv */ + ssh_packet_set_qos(ssh, options.ip_qos_interactive, + options.ip_qos_bulk); /* Reinit logging in case config set Level, Facility or Verbose. */ log_init(__progname, options.log_level, options.log_facility, 1); + set_log_handler(mm_log_handler, pmonitor); debug("sshd-auth version %s, %s", SSH_VERSION, SSH_OPENSSL_VERSION); @@ -803,6 +779,7 @@ main(int ac, char **av) * The unprivileged child now transfers the current keystate and exits. */ mm_send_keystate(ssh, pmonitor); + sshauthopt_free(auth_opts); ssh_packet_clear_keys(ssh); exit(0); } diff --git a/sshd-session.c b/sshd-session.c index 623c20eba2df..cabf3dc3b2ce 100644 --- a/sshd-session.c +++ b/sshd-session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd-session.c,v 1.12 2025/03/12 22:43:44 djm Exp $ */ +/* $OpenBSD: sshd-session.c,v 1.16 2025/09/25 06:45:50 djm Exp $ */ /* * SSH2 implementation: * Privilege Separation: @@ -32,12 +32,8 @@ #include #include #include -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef HAVE_SYS_TIME_H -# include -#endif +#include +#include #include "openbsd-compat/sys-tree.h" #include "openbsd-compat/sys-queue.h" #include @@ -46,7 +42,7 @@ #include #include #ifdef HAVE_PATHS_H -# include +#include #endif #include #include @@ -626,7 +622,7 @@ reseed_prngs(void) 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__); + fatal_f("RAND_bytes failed"); #endif explicit_bzero(rnd, sizeof(rnd)); @@ -672,7 +668,7 @@ pack_hostkeys(void) static int privsep_preauth(struct ssh *ssh) { - int status, r; + int r; pid_t pid; /* Set up unprivileged child process to deal with network data */ @@ -717,15 +713,13 @@ privsep_preauth(struct ssh *ssh) close(pmonitor->m_recvfd); close(pmonitor->m_log_sendfd); + /* + * monitor_child_preauth() now waits for the unprivileged + * sshd-auth child to exit (see monitor.c) and resets + * pmonitor->m_pid, so no explicit waitpid() is needed here. + */ monitor_child_preauth(ssh, pmonitor); - while (waitpid(pid, &status, 0) < 0) { - if (errno == EINTR) - continue; - pmonitor->m_pid = -1; - fatal("%s: waitpid: %s", __func__, strerror(errno)); - } privsep_is_preauth = 0; - pmonitor->m_pid = -1; return 1; } #else @@ -743,23 +737,7 @@ privsep_preauth(struct ssh *ssh) } } 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)); return 1; } else { /* child */ @@ -934,12 +912,10 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) 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: @@ -1702,6 +1678,8 @@ main(int ac, char **av) fatal("Unable to create connection"); the_active_state = ssh; ssh_packet_set_server(ssh); + ssh_packet_set_qos(ssh, options.ip_qos_interactive, + options.ip_qos_bulk); check_ip_options(ssh); diff --git a/sshd.0 b/sshd.0 index 23e28bee2dfb..eddbeec0bd9c 100644 --- a/sshd.0 +++ b/sshd.0 @@ -306,7 +306,7 @@ AUTHORIZED_KEYS FILE FORMAT The command originally supplied by the client is available in the SSH_ORIGINAL_COMMAND environment variable. Note that this option applies to shell, command or subsystem execution. Also note that - this command may be superseded by a sshd_config(5) ForceCommand + this command may be superseded by an sshd_config(5) ForceCommand directive. If a command is specified and a forced-command is embedded in a @@ -684,4 +684,4 @@ AUTHORS versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support for privilege separation. -OpenBSD 7.6 September 15, 2024 OpenBSD 7.6 +OpenBSD 7.7 October 4, 2025 OpenBSD 7.7 diff --git a/sshd.8 b/sshd.8 index 08ebf53a1281..7fbca776aa22 100644 --- a/sshd.8 +++ b/sshd.8 @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd.8,v 1.327 2024/09/15 01:19:56 djm Exp $ -.Dd $Mdocdate: September 15 2024 $ +.\" $OpenBSD: sshd.8,v 1.328 2025/10/04 21:41:35 naddy Exp $ +.Dd $Mdocdate: October 4 2025 $ .Dt SSHD 8 .Os .Sh NAME @@ -530,7 +530,7 @@ The command originally supplied by the client is available in the .Ev SSH_ORIGINAL_COMMAND environment variable. Note that this option applies to shell, command or subsystem execution. -Also note that this command may be superseded by a +Also note that this command may be superseded by an .Xr sshd_config 5 .Cm ForceCommand directive. diff --git a/sshd.c b/sshd.c index 3e6c34276543..8de9516c8903 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.617 2025/04/07 08:12:22 dtucker Exp $ */ +/* $OpenBSD: sshd.c,v 1.622 2025/08/29 03:50:38 djm Exp $ */ /* * Copyright (c) 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 2002 Niels Provos. All rights reserved. @@ -29,12 +29,8 @@ #include #include #include -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef HAVE_SYS_TIME_H -# include -#endif +#include +#include #include "openbsd-compat/sys-tree.h" #include "openbsd-compat/sys-queue.h" #include @@ -49,9 +45,7 @@ #include #endif #include -#ifdef HAVE_POLL_H #include -#endif #include #include #include @@ -100,6 +94,10 @@ #include "addr.h" #include "srclimit.h" #include "atomicio.h" +#ifdef GSSAPI +#include "ssh-gss.h" +#endif +#include "monitor_wrap.h" /* Re-exec fds */ #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) @@ -304,8 +302,10 @@ child_finish(struct early_child *child) { if (children_active == 0) fatal_f("internal error: children_active underflow"); - if (child->pipefd != -1) + if (child->pipefd != -1) { + srclimit_done(child->pipefd); close(child->pipefd); + } sshbuf_free(child->config); sshbuf_free(child->keys); free(child->id); @@ -326,6 +326,7 @@ child_close(struct early_child *child, int force_final, int quiet) if (!quiet) debug_f("enter%s", force_final ? " (forcing)" : ""); if (child->pipefd != -1) { + srclimit_done(child->pipefd); close(child->pipefd); child->pipefd = -1; } @@ -1059,7 +1060,6 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s, if (ret <= 0) { if (children[i].early) listening--; - srclimit_done(children[i].pipefd); child_close(&(children[i]), 0, 0); continue; } @@ -1098,23 +1098,19 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s, } /* FALLTHROUGH */ case 0: - /* child exited preauth */ + /* child closed pipe */ if (children[i].early) listening--; - srclimit_done(children[i].pipefd); + debug3_f("child %lu for %s closed pipe", + (long)children[i].pid, children[i].id); child_close(&(children[i]), 0, 0); break; case 1: if (children[i].config) { error_f("startup pipe %d (fd=%d)" - " early read", i, children[i].pipefd); - if (children[i].early) - listening--; - if (children[i].pid > 0) - kill(children[i].pid, SIGTERM); - srclimit_done(children[i].pipefd); - child_close(&(children[i]), 0, 0); - break; + " early read", + i, children[i].pipefd); + goto problem_child; } if (children[i].early && c == '\0') { /* child has finished preliminaries */ @@ -1134,6 +1130,12 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s, "child %ld for %s in state %d", (int)c, (long)children[i].pid, children[i].id, children[i].early); + problem_child: + if (children[i].early) + listening--; + if (children[i].pid > 0) + kill(children[i].pid, SIGTERM); + child_close(&(children[i]), 0, 0); } break; } @@ -1192,6 +1194,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s, close(config_s[0]); #endif /* !WINDOWS */ free(pfd); + free(startup_pollfd); return; } @@ -1245,6 +1248,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s, log_stderr); close(config_s[0]); free(pfd); + free(startup_pollfd); return; } @@ -1268,7 +1272,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s, #ifdef WITH_OPENSSL RAND_seed(rnd, sizeof(rnd)); if ((RAND_bytes((u_char *)rnd, 1)) != 1) - fatal("%s: RAND_bytes failed", __func__); + fatal_f("RAND_bytes failed"); #endif explicit_bzero(rnd, sizeof(rnd)); } @@ -1712,12 +1716,10 @@ main(int ac, char **av) 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; @@ -1806,6 +1808,12 @@ main(int ac, char **av) if (test_flag > 1) print_config(&connection_info); + config = pack_config(cfg); + if (sshbuf_len(config) > MONITOR_MAX_CFGLEN) { + fatal("Configuration file is too large (have %zu, max %d)", + sshbuf_len(config), MONITOR_MAX_CFGLEN); + } + /* Configuration looks good, so exit if in test mode. */ if (test_flag) exit(0); @@ -1883,8 +1891,6 @@ main(int ac, char **av) /* ignore SIGPIPE */ ssh_signal(SIGPIPE, SIG_IGN); - config = pack_config(cfg); - /* Get a connection, either from inetd or a listening TCP socket */ if (inetd_flag) { /* Send configuration to ancestor sshd-session process */ diff --git a/sshd_config.0 b/sshd_config.0 index 2f77b4f4c0b6..c63d729a98a4 100644 --- a/sshd_config.0 +++ b/sshd_config.0 @@ -254,13 +254,13 @@ DESCRIPTION direct-tcpip, direct-streamlocal@openssh.com Open TCP or Unix socket (respectively) connections that - have been established from a ssh(1) local forwarding, + have been established from an ssh(1) local forwarding, i.e. LocalForward or DynamicForward. forwarded-tcpip, forwarded-streamlocal@openssh.com Open TCP or Unix socket (respectively) connections that - have been established to a sshd(8) listening on behalf of - a ssh(1) remote forwarding, i.e. RemoteForward. + have been established to an sshd(8) listening on behalf + of an ssh(1) remote forwarding, i.e. RemoteForward. session The interactive main session, including shell session, @@ -577,18 +577,18 @@ DESCRIPTION directive may appear inside a Match block to perform conditional inclusion. - IPQoS Specifies the IPv4 type-of-service or DSCP class for the - connection. Accepted values are af11, af12, af13, af21, af22, - af23, af31, af32, af33, af41, af42, af43, cs0, cs1, cs2, cs3, - cs4, cs5, cs6, cs7, ef, le, lowdelay, throughput, reliability, a - numeric value, or none to use the operating system default. This - option may take one or two arguments, separated by whitespace. - If one argument is specified, it is used as the packet class - unconditionally. If two values are specified, the first is - automatically selected for interactive sessions and the second - for non-interactive sessions. The default is af21 (Low-Latency - Data) for interactive sessions and cs1 (Lower Effort) for non- - interactive sessions. + IPQoS Specifies the Differentiated Services Field Codepoint (DSCP) + value for the connection. Accepted values are af11, af12, af13, + af21, af22, af23, af31, af32, af33, af41, af42, af43, cs0, cs1, + cs2, cs3, cs4, cs5, cs6, cs7, ef, le, a numeric value, or none to + use the operating system default. This option may take one or + two arguments, separated by whitespace. If one argument is + specified, it is used as the packet class unconditionally. If + two values are specified, the first is automatically selected for + interactive sessions and the second for non-interactive sessions. + The default is ef (Expedited Forwarding) for interactive sessions + and none (the operating system default) for non-interactive + sessions. KbdInteractiveAuthentication Specifies whether to allow keyboard-interactive authentication. @@ -1416,4 +1416,4 @@ AUTHORS versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support for privilege separation. -OpenBSD 7.6 February 15, 2025 OpenBSD 7.6 +OpenBSD 7.7 October 4, 2025 OpenBSD 7.7 diff --git a/sshd_config.5 b/sshd_config.5 index c07717375d90..6ae606f1e04f 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -33,8 +33,8 @@ .\" (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.381 2025/02/15 01:52:07 djm Exp $ -.Dd $Mdocdate: February 15 2025 $ +.\" $OpenBSD: sshd_config.5,v 1.385 2025/10/04 21:41:35 naddy Exp $ +.Dd $Mdocdate: October 4 2025 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -440,7 +440,7 @@ 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 +been established from an .Xr ssh 1 local forwarding, i.e.\& .Cm LocalForward @@ -448,9 +448,9 @@ 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 +established to an .Xr sshd 8 -listening on behalf of a +listening on behalf of an .Xr ssh 1 remote forwarding, i.e.\& .Cm RemoteForward . @@ -923,7 +923,9 @@ directive may appear inside a block to perform conditional inclusion. .It Cm IPQoS -Specifies the IPv4 type-of-service or DSCP class for the connection. +Specifies the +.Em Differentiated Services Field Codepoint Pq DSCP +value for the connection. Accepted values are .Cm af11 , .Cm af12 , @@ -947,9 +949,6 @@ Accepted values are .Cm cs7 , .Cm ef , .Cm le , -.Cm lowdelay , -.Cm throughput , -.Cm reliability , a numeric value, or .Cm none to use the operating system default. @@ -958,11 +957,11 @@ 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) +.Cm ef +(Expedited Forwarding) for interactive sessions and -.Cm cs1 -(Lower Effort) +.Cm none +(the operating system default) for non-interactive sessions. .It Cm KbdInteractiveAuthentication Specifies whether to allow keyboard-interactive authentication. diff --git a/sshkey-xmss.c b/sshkey-xmss.c deleted file mode 100644 index 818aba9059df..000000000000 --- a/sshkey-xmss.c +++ /dev/null @@ -1,1113 +0,0 @@ -/* $OpenBSD: sshkey-xmss.c,v 1.12 2022/10/28 00:39:29 djm Exp $ */ -/* - * Copyright (c) 2017 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "includes.h" -#ifdef WITH_XMSS - -#include -#include - -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_FILE_H -# include -#endif - -#include "ssh2.h" -#include "ssherr.h" -#include "sshbuf.h" -#include "cipher.h" -#include "sshkey.h" -#include "sshkey-xmss.h" -#include "atomicio.h" -#include "log.h" - -#include "xmss_fast.h" - -/* opaque internal XMSS state */ -#define XMSS_MAGIC "xmss-state-v1" -#define XMSS_CIPHERNAME "aes256-gcm@openssh.com" -struct ssh_xmss_state { - xmss_params params; - u_int32_t n, w, h, k; - - bds_state bds; - u_char *stack; - u_int32_t stackoffset; - u_char *stacklevels; - u_char *auth; - u_char *keep; - u_char *th_nodes; - u_char *retain; - treehash_inst *treehash; - - u_int32_t idx; /* state read from file */ - u_int32_t maxidx; /* restricted # of signatures */ - int have_state; /* .state file exists */ - int lockfd; /* locked in sshkey_xmss_get_state() */ - u_char allow_update; /* allow sshkey_xmss_update_state() */ - char *enc_ciphername;/* encrypt state with cipher */ - u_char *enc_keyiv; /* encrypt state with key */ - u_int32_t enc_keyiv_len; /* length of enc_keyiv */ -}; - -int sshkey_xmss_init_bds_state(struct sshkey *); -int sshkey_xmss_init_enc_key(struct sshkey *, const char *); -void sshkey_xmss_free_bds(struct sshkey *); -int sshkey_xmss_get_state_from_file(struct sshkey *, const char *, - int *, int); -int sshkey_xmss_encrypt_state(const struct sshkey *, struct sshbuf *, - struct sshbuf **); -int sshkey_xmss_decrypt_state(const struct sshkey *, struct sshbuf *, - struct sshbuf **); -int sshkey_xmss_serialize_enc_key(const struct sshkey *, struct sshbuf *); -int sshkey_xmss_deserialize_enc_key(struct sshkey *, struct sshbuf *); - -#define PRINT(...) do { if (printerror) sshlog(__FILE__, __func__, __LINE__, \ - 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__); } while (0) - -int -sshkey_xmss_init(struct sshkey *key, const char *name) -{ - struct ssh_xmss_state *state; - - if (key->xmss_state != NULL) - return SSH_ERR_INVALID_FORMAT; - if (name == NULL) - return SSH_ERR_INVALID_FORMAT; - state = calloc(sizeof(struct ssh_xmss_state), 1); - if (state == NULL) - return SSH_ERR_ALLOC_FAIL; - if (strcmp(name, XMSS_SHA2_256_W16_H10_NAME) == 0) { - state->n = 32; - state->w = 16; - state->h = 10; - } else if (strcmp(name, XMSS_SHA2_256_W16_H16_NAME) == 0) { - state->n = 32; - state->w = 16; - state->h = 16; - } else if (strcmp(name, XMSS_SHA2_256_W16_H20_NAME) == 0) { - state->n = 32; - state->w = 16; - state->h = 20; - } else { - free(state); - return SSH_ERR_KEY_TYPE_UNKNOWN; - } - if ((key->xmss_name = strdup(name)) == NULL) { - free(state); - return SSH_ERR_ALLOC_FAIL; - } - state->k = 2; /* XXX hardcoded */ - state->lockfd = -1; - if (xmss_set_params(&state->params, state->n, state->h, state->w, - state->k) != 0) { - free(state); - return SSH_ERR_INVALID_FORMAT; - } - key->xmss_state = state; - return 0; -} - -void -sshkey_xmss_free_state(struct sshkey *key) -{ - struct ssh_xmss_state *state = key->xmss_state; - - sshkey_xmss_free_bds(key); - if (state) { - if (state->enc_keyiv) { - explicit_bzero(state->enc_keyiv, state->enc_keyiv_len); - free(state->enc_keyiv); - } - free(state->enc_ciphername); - free(state); - } - key->xmss_state = NULL; -} - -#define SSH_XMSS_K2_MAGIC "k=2" -#define num_stack(x) ((x->h+1)*(x->n)) -#define num_stacklevels(x) (x->h+1) -#define num_auth(x) ((x->h)*(x->n)) -#define num_keep(x) ((x->h >> 1)*(x->n)) -#define num_th_nodes(x) ((x->h - x->k)*(x->n)) -#define num_retain(x) (((1ULL << x->k) - x->k - 1) * (x->n)) -#define num_treehash(x) ((x->h) - (x->k)) - -int -sshkey_xmss_init_bds_state(struct sshkey *key) -{ - struct ssh_xmss_state *state = key->xmss_state; - u_int32_t i; - - state->stackoffset = 0; - if ((state->stack = calloc(num_stack(state), 1)) == NULL || - (state->stacklevels = calloc(num_stacklevels(state), 1))== NULL || - (state->auth = calloc(num_auth(state), 1)) == NULL || - (state->keep = calloc(num_keep(state), 1)) == NULL || - (state->th_nodes = calloc(num_th_nodes(state), 1)) == NULL || - (state->retain = calloc(num_retain(state), 1)) == NULL || - (state->treehash = calloc(num_treehash(state), - sizeof(treehash_inst))) == NULL) { - sshkey_xmss_free_bds(key); - return SSH_ERR_ALLOC_FAIL; - } - for (i = 0; i < state->h - state->k; i++) - state->treehash[i].node = &state->th_nodes[state->n*i]; - xmss_set_bds_state(&state->bds, state->stack, state->stackoffset, - state->stacklevels, state->auth, state->keep, state->treehash, - state->retain, 0); - return 0; -} - -void -sshkey_xmss_free_bds(struct sshkey *key) -{ - struct ssh_xmss_state *state = key->xmss_state; - - if (state == NULL) - return; - free(state->stack); - free(state->stacklevels); - free(state->auth); - free(state->keep); - free(state->th_nodes); - free(state->retain); - free(state->treehash); - state->stack = NULL; - state->stacklevels = NULL; - state->auth = NULL; - state->keep = NULL; - state->th_nodes = NULL; - state->retain = NULL; - state->treehash = NULL; -} - -void * -sshkey_xmss_params(const struct sshkey *key) -{ - struct ssh_xmss_state *state = key->xmss_state; - - if (state == NULL) - return NULL; - return &state->params; -} - -void * -sshkey_xmss_bds_state(const struct sshkey *key) -{ - struct ssh_xmss_state *state = key->xmss_state; - - if (state == NULL) - return NULL; - return &state->bds; -} - -int -sshkey_xmss_siglen(const struct sshkey *key, size_t *lenp) -{ - struct ssh_xmss_state *state = key->xmss_state; - - if (lenp == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if (state == NULL) - return SSH_ERR_INVALID_FORMAT; - *lenp = 4 + state->n + - state->params.wots_par.keysize + - state->h * state->n; - return 0; -} - -size_t -sshkey_xmss_pklen(const struct sshkey *key) -{ - struct ssh_xmss_state *state = key->xmss_state; - - if (state == NULL) - return 0; - return state->n * 2; -} - -size_t -sshkey_xmss_sklen(const struct sshkey *key) -{ - struct ssh_xmss_state *state = key->xmss_state; - - if (state == NULL) - return 0; - return state->n * 4 + 4; -} - -int -sshkey_xmss_init_enc_key(struct sshkey *k, const char *ciphername) -{ - struct ssh_xmss_state *state = k->xmss_state; - const struct sshcipher *cipher; - size_t keylen = 0, ivlen = 0; - - if (state == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if ((cipher = cipher_by_name(ciphername)) == NULL) - return SSH_ERR_INTERNAL_ERROR; - if ((state->enc_ciphername = strdup(ciphername)) == NULL) - return SSH_ERR_ALLOC_FAIL; - keylen = cipher_keylen(cipher); - ivlen = cipher_ivlen(cipher); - state->enc_keyiv_len = keylen + ivlen; - if ((state->enc_keyiv = calloc(state->enc_keyiv_len, 1)) == NULL) { - free(state->enc_ciphername); - state->enc_ciphername = NULL; - return SSH_ERR_ALLOC_FAIL; - } - arc4random_buf(state->enc_keyiv, state->enc_keyiv_len); - return 0; -} - -int -sshkey_xmss_serialize_enc_key(const struct sshkey *k, struct sshbuf *b) -{ - struct ssh_xmss_state *state = k->xmss_state; - int r; - - if (state == NULL || state->enc_keyiv == NULL || - state->enc_ciphername == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if ((r = sshbuf_put_cstring(b, state->enc_ciphername)) != 0 || - (r = sshbuf_put_string(b, state->enc_keyiv, - state->enc_keyiv_len)) != 0) - return r; - return 0; -} - -int -sshkey_xmss_deserialize_enc_key(struct sshkey *k, struct sshbuf *b) -{ - struct ssh_xmss_state *state = k->xmss_state; - size_t len; - int r; - - if (state == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if ((r = sshbuf_get_cstring(b, &state->enc_ciphername, NULL)) != 0 || - (r = sshbuf_get_string(b, &state->enc_keyiv, &len)) != 0) - return r; - state->enc_keyiv_len = len; - return 0; -} - -int -sshkey_xmss_serialize_pk_info(const struct sshkey *k, struct sshbuf *b, - enum sshkey_serialize_rep opts) -{ - struct ssh_xmss_state *state = k->xmss_state; - u_char have_info = 1; - u_int32_t idx; - int r; - - if (state == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if (opts != SSHKEY_SERIALIZE_INFO) - return 0; - idx = k->xmss_sk ? PEEK_U32(k->xmss_sk) : state->idx; - if ((r = sshbuf_put_u8(b, have_info)) != 0 || - (r = sshbuf_put_u32(b, idx)) != 0 || - (r = sshbuf_put_u32(b, state->maxidx)) != 0) - return r; - return 0; -} - -int -sshkey_xmss_deserialize_pk_info(struct sshkey *k, struct sshbuf *b) -{ - struct ssh_xmss_state *state = k->xmss_state; - u_char have_info; - int r; - - if (state == NULL) - return SSH_ERR_INVALID_ARGUMENT; - /* optional */ - if (sshbuf_len(b) == 0) - return 0; - if ((r = sshbuf_get_u8(b, &have_info)) != 0) - return r; - if (have_info != 1) - return SSH_ERR_INVALID_ARGUMENT; - if ((r = sshbuf_get_u32(b, &state->idx)) != 0 || - (r = sshbuf_get_u32(b, &state->maxidx)) != 0) - return r; - return 0; -} - -int -sshkey_xmss_generate_private_key(struct sshkey *k, int bits) -{ - int r; - const char *name; - - if (bits == 10) { - name = XMSS_SHA2_256_W16_H10_NAME; - } else if (bits == 16) { - name = XMSS_SHA2_256_W16_H16_NAME; - } else if (bits == 20) { - name = XMSS_SHA2_256_W16_H20_NAME; - } else { - name = XMSS_DEFAULT_NAME; - } - if ((r = sshkey_xmss_init(k, name)) != 0 || - (r = sshkey_xmss_init_bds_state(k)) != 0 || - (r = sshkey_xmss_init_enc_key(k, XMSS_CIPHERNAME)) != 0) - return r; - if ((k->xmss_pk = malloc(sshkey_xmss_pklen(k))) == NULL || - (k->xmss_sk = malloc(sshkey_xmss_sklen(k))) == NULL) { - return SSH_ERR_ALLOC_FAIL; - } - xmss_keypair(k->xmss_pk, k->xmss_sk, sshkey_xmss_bds_state(k), - sshkey_xmss_params(k)); - return 0; -} - -int -sshkey_xmss_get_state_from_file(struct sshkey *k, const char *filename, - int *have_file, int printerror) -{ - struct sshbuf *b = NULL, *enc = NULL; - int ret = SSH_ERR_SYSTEM_ERROR, r, fd = -1; - u_int32_t len; - unsigned char buf[4], *data = NULL; - - *have_file = 0; - if ((fd = open(filename, O_RDONLY)) >= 0) { - *have_file = 1; - if (atomicio(read, fd, buf, sizeof(buf)) != sizeof(buf)) { - PRINT("corrupt state file: %s", filename); - goto done; - } - len = PEEK_U32(buf); - if ((data = calloc(len, 1)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto done; - } - if (atomicio(read, fd, data, len) != len) { - PRINT("cannot read blob: %s", filename); - goto done; - } - if ((enc = sshbuf_from(data, len)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto done; - } - sshkey_xmss_free_bds(k); - if ((r = sshkey_xmss_decrypt_state(k, enc, &b)) != 0) { - ret = r; - goto done; - } - if ((r = sshkey_xmss_deserialize_state(k, b)) != 0) { - ret = r; - goto done; - } - ret = 0; - } -done: - if (fd != -1) - close(fd); - free(data); - sshbuf_free(enc); - sshbuf_free(b); - return ret; -} - -int -sshkey_xmss_get_state(const struct sshkey *k, int printerror) -{ - struct ssh_xmss_state *state = k->xmss_state; - u_int32_t idx = 0; - char *filename = NULL; - char *statefile = NULL, *ostatefile = NULL, *lockfile = NULL; - int lockfd = -1, have_state = 0, have_ostate, tries = 0; - int ret = SSH_ERR_INVALID_ARGUMENT, r; - - if (state == NULL) - goto done; - /* - * If maxidx is set, then we are allowed a limited number - * of signatures, but don't need to access the disk. - * Otherwise we need to deal with the on-disk state. - */ - if (state->maxidx) { - /* xmss_sk always contains the current state */ - idx = PEEK_U32(k->xmss_sk); - if (idx < state->maxidx) { - state->allow_update = 1; - return 0; - } - return SSH_ERR_INVALID_ARGUMENT; - } - if ((filename = k->xmss_filename) == NULL) - goto done; - if (asprintf(&lockfile, "%s.lock", filename) == -1 || - asprintf(&statefile, "%s.state", filename) == -1 || - asprintf(&ostatefile, "%s.ostate", filename) == -1) { - ret = SSH_ERR_ALLOC_FAIL; - goto done; - } - if ((lockfd = open(lockfile, O_CREAT|O_RDONLY, 0600)) == -1) { - ret = SSH_ERR_SYSTEM_ERROR; - PRINT("cannot open/create: %s", lockfile); - goto done; - } - while (flock(lockfd, LOCK_EX|LOCK_NB) == -1) { - if (errno != EWOULDBLOCK) { - ret = SSH_ERR_SYSTEM_ERROR; - PRINT("cannot lock: %s", lockfile); - goto done; - } - if (++tries > 10) { - ret = SSH_ERR_SYSTEM_ERROR; - PRINT("giving up on: %s", lockfile); - goto done; - } - usleep(1000*100*tries); - } - /* XXX no longer const */ - if ((r = sshkey_xmss_get_state_from_file((struct sshkey *)k, - statefile, &have_state, printerror)) != 0) { - if ((r = sshkey_xmss_get_state_from_file((struct sshkey *)k, - ostatefile, &have_ostate, printerror)) == 0) { - state->allow_update = 1; - r = sshkey_xmss_forward_state(k, 1); - state->idx = PEEK_U32(k->xmss_sk); - state->allow_update = 0; - } - } - if (!have_state && !have_ostate) { - /* check that bds state is initialized */ - if (state->bds.auth == NULL) - goto done; - PRINT("start from scratch idx 0: %u", state->idx); - } else if (r != 0) { - ret = r; - goto done; - } - if (state->idx + 1 < state->idx) { - PRINT("state wrap: %u", state->idx); - goto done; - } - state->have_state = have_state; - state->lockfd = lockfd; - state->allow_update = 1; - lockfd = -1; - ret = 0; -done: - if (lockfd != -1) - close(lockfd); - free(lockfile); - free(statefile); - free(ostatefile); - return ret; -} - -int -sshkey_xmss_forward_state(const struct sshkey *k, u_int32_t reserve) -{ - struct ssh_xmss_state *state = k->xmss_state; - u_char *sig = NULL; - size_t required_siglen; - unsigned long long smlen; - u_char data; - int ret, r; - - if (state == NULL || !state->allow_update) - return SSH_ERR_INVALID_ARGUMENT; - if (reserve == 0) - return SSH_ERR_INVALID_ARGUMENT; - if (state->idx + reserve <= state->idx) - return SSH_ERR_INVALID_ARGUMENT; - if ((r = sshkey_xmss_siglen(k, &required_siglen)) != 0) - return r; - if ((sig = malloc(required_siglen)) == NULL) - return SSH_ERR_ALLOC_FAIL; - while (reserve-- > 0) { - state->idx = PEEK_U32(k->xmss_sk); - smlen = required_siglen; - if ((ret = xmss_sign(k->xmss_sk, sshkey_xmss_bds_state(k), - sig, &smlen, &data, 0, sshkey_xmss_params(k))) != 0) { - r = SSH_ERR_INVALID_ARGUMENT; - break; - } - } - free(sig); - return r; -} - -int -sshkey_xmss_update_state(const struct sshkey *k, int printerror) -{ - struct ssh_xmss_state *state = k->xmss_state; - struct sshbuf *b = NULL, *enc = NULL; - u_int32_t idx = 0; - unsigned char buf[4]; - char *filename = NULL; - char *statefile = NULL, *ostatefile = NULL, *nstatefile = NULL; - int fd = -1; - int ret = SSH_ERR_INVALID_ARGUMENT; - - if (state == NULL || !state->allow_update) - return ret; - if (state->maxidx) { - /* no update since the number of signatures is limited */ - ret = 0; - goto done; - } - idx = PEEK_U32(k->xmss_sk); - if (idx == state->idx) { - /* no signature happened, no need to update */ - ret = 0; - goto done; - } else if (idx != state->idx + 1) { - PRINT("more than one signature happened: idx %u state %u", - idx, state->idx); - goto done; - } - state->idx = idx; - if ((filename = k->xmss_filename) == NULL) - goto done; - if (asprintf(&statefile, "%s.state", filename) == -1 || - asprintf(&ostatefile, "%s.ostate", filename) == -1 || - asprintf(&nstatefile, "%s.nstate", filename) == -1) { - ret = SSH_ERR_ALLOC_FAIL; - goto done; - } - unlink(nstatefile); - if ((b = sshbuf_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto done; - } - if ((ret = sshkey_xmss_serialize_state(k, b)) != 0) { - PRINT("SERLIALIZE FAILED: %d", ret); - goto done; - } - if ((ret = sshkey_xmss_encrypt_state(k, b, &enc)) != 0) { - PRINT("ENCRYPT FAILED: %d", ret); - goto done; - } - if ((fd = open(nstatefile, O_CREAT|O_WRONLY|O_EXCL, 0600)) == -1) { - ret = SSH_ERR_SYSTEM_ERROR; - PRINT("open new state file: %s", nstatefile); - goto done; - } - POKE_U32(buf, sshbuf_len(enc)); - if (atomicio(vwrite, fd, buf, sizeof(buf)) != sizeof(buf)) { - ret = SSH_ERR_SYSTEM_ERROR; - PRINT("write new state file hdr: %s", nstatefile); - close(fd); - goto done; - } - if (atomicio(vwrite, fd, sshbuf_mutable_ptr(enc), sshbuf_len(enc)) != - sshbuf_len(enc)) { - ret = SSH_ERR_SYSTEM_ERROR; - PRINT("write new state file data: %s", nstatefile); - close(fd); - goto done; - } - if (fsync(fd) == -1) { - ret = SSH_ERR_SYSTEM_ERROR; - PRINT("sync new state file: %s", nstatefile); - close(fd); - goto done; - } - if (close(fd) == -1) { - ret = SSH_ERR_SYSTEM_ERROR; - PRINT("close new state file: %s", nstatefile); - goto done; - } - if (state->have_state) { - unlink(ostatefile); - if (link(statefile, ostatefile)) { - ret = SSH_ERR_SYSTEM_ERROR; - PRINT("backup state %s to %s", statefile, ostatefile); - goto done; - } - } - if (rename(nstatefile, statefile) == -1) { - ret = SSH_ERR_SYSTEM_ERROR; - PRINT("rename %s to %s", nstatefile, statefile); - goto done; - } - ret = 0; -done: - if (state->lockfd != -1) { - close(state->lockfd); - state->lockfd = -1; - } - if (nstatefile) - unlink(nstatefile); - free(statefile); - free(ostatefile); - free(nstatefile); - sshbuf_free(b); - sshbuf_free(enc); - return ret; -} - -int -sshkey_xmss_serialize_state(const struct sshkey *k, struct sshbuf *b) -{ - struct ssh_xmss_state *state = k->xmss_state; - treehash_inst *th; - u_int32_t i, node; - int r; - - if (state == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if (state->stack == NULL) - return SSH_ERR_INVALID_ARGUMENT; - state->stackoffset = state->bds.stackoffset; /* copy back */ - if ((r = sshbuf_put_cstring(b, SSH_XMSS_K2_MAGIC)) != 0 || - (r = sshbuf_put_u32(b, state->idx)) != 0 || - (r = sshbuf_put_string(b, state->stack, num_stack(state))) != 0 || - (r = sshbuf_put_u32(b, state->stackoffset)) != 0 || - (r = sshbuf_put_string(b, state->stacklevels, num_stacklevels(state))) != 0 || - (r = sshbuf_put_string(b, state->auth, num_auth(state))) != 0 || - (r = sshbuf_put_string(b, state->keep, num_keep(state))) != 0 || - (r = sshbuf_put_string(b, state->th_nodes, num_th_nodes(state))) != 0 || - (r = sshbuf_put_string(b, state->retain, num_retain(state))) != 0 || - (r = sshbuf_put_u32(b, num_treehash(state))) != 0) - return r; - for (i = 0; i < num_treehash(state); i++) { - th = &state->treehash[i]; - node = th->node - state->th_nodes; - if ((r = sshbuf_put_u32(b, th->h)) != 0 || - (r = sshbuf_put_u32(b, th->next_idx)) != 0 || - (r = sshbuf_put_u32(b, th->stackusage)) != 0 || - (r = sshbuf_put_u8(b, th->completed)) != 0 || - (r = sshbuf_put_u32(b, node)) != 0) - return r; - } - return 0; -} - -int -sshkey_xmss_serialize_state_opt(const struct sshkey *k, struct sshbuf *b, - enum sshkey_serialize_rep opts) -{ - struct ssh_xmss_state *state = k->xmss_state; - int r = SSH_ERR_INVALID_ARGUMENT; - u_char have_stack, have_filename, have_enc; - - if (state == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if ((r = sshbuf_put_u8(b, opts)) != 0) - return r; - switch (opts) { - case SSHKEY_SERIALIZE_STATE: - r = sshkey_xmss_serialize_state(k, b); - break; - case SSHKEY_SERIALIZE_FULL: - if ((r = sshkey_xmss_serialize_enc_key(k, b)) != 0) - return r; - r = sshkey_xmss_serialize_state(k, b); - break; - case SSHKEY_SERIALIZE_SHIELD: - /* all of stack/filename/enc are optional */ - have_stack = state->stack != NULL; - if ((r = sshbuf_put_u8(b, have_stack)) != 0) - return r; - if (have_stack) { - state->idx = PEEK_U32(k->xmss_sk); /* update */ - if ((r = sshkey_xmss_serialize_state(k, b)) != 0) - return r; - } - have_filename = k->xmss_filename != NULL; - if ((r = sshbuf_put_u8(b, have_filename)) != 0) - return r; - if (have_filename && - (r = sshbuf_put_cstring(b, k->xmss_filename)) != 0) - return r; - have_enc = state->enc_keyiv != NULL; - if ((r = sshbuf_put_u8(b, have_enc)) != 0) - return r; - if (have_enc && - (r = sshkey_xmss_serialize_enc_key(k, b)) != 0) - return r; - if ((r = sshbuf_put_u32(b, state->maxidx)) != 0 || - (r = sshbuf_put_u8(b, state->allow_update)) != 0) - return r; - break; - case SSHKEY_SERIALIZE_DEFAULT: - r = 0; - break; - default: - r = SSH_ERR_INVALID_ARGUMENT; - break; - } - return r; -} - -int -sshkey_xmss_deserialize_state(struct sshkey *k, struct sshbuf *b) -{ - struct ssh_xmss_state *state = k->xmss_state; - treehash_inst *th; - u_int32_t i, lh, node; - size_t ls, lsl, la, lk, ln, lr; - char *magic; - int r = SSH_ERR_INTERNAL_ERROR; - - if (state == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if (k->xmss_sk == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if ((state->treehash = calloc(num_treehash(state), - sizeof(treehash_inst))) == NULL) - return SSH_ERR_ALLOC_FAIL; - if ((r = sshbuf_get_cstring(b, &magic, NULL)) != 0 || - (r = sshbuf_get_u32(b, &state->idx)) != 0 || - (r = sshbuf_get_string(b, &state->stack, &ls)) != 0 || - (r = sshbuf_get_u32(b, &state->stackoffset)) != 0 || - (r = sshbuf_get_string(b, &state->stacklevels, &lsl)) != 0 || - (r = sshbuf_get_string(b, &state->auth, &la)) != 0 || - (r = sshbuf_get_string(b, &state->keep, &lk)) != 0 || - (r = sshbuf_get_string(b, &state->th_nodes, &ln)) != 0 || - (r = sshbuf_get_string(b, &state->retain, &lr)) != 0 || - (r = sshbuf_get_u32(b, &lh)) != 0) - goto out; - if (strcmp(magic, SSH_XMSS_K2_MAGIC) != 0) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - /* XXX check stackoffset */ - if (ls != num_stack(state) || - lsl != num_stacklevels(state) || - la != num_auth(state) || - lk != num_keep(state) || - ln != num_th_nodes(state) || - lr != num_retain(state) || - lh != num_treehash(state)) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - for (i = 0; i < num_treehash(state); i++) { - th = &state->treehash[i]; - if ((r = sshbuf_get_u32(b, &th->h)) != 0 || - (r = sshbuf_get_u32(b, &th->next_idx)) != 0 || - (r = sshbuf_get_u32(b, &th->stackusage)) != 0 || - (r = sshbuf_get_u8(b, &th->completed)) != 0 || - (r = sshbuf_get_u32(b, &node)) != 0) - goto out; - if (node < num_th_nodes(state)) - th->node = &state->th_nodes[node]; - } - POKE_U32(k->xmss_sk, state->idx); - xmss_set_bds_state(&state->bds, state->stack, state->stackoffset, - state->stacklevels, state->auth, state->keep, state->treehash, - state->retain, 0); - /* success */ - r = 0; - out: - free(magic); - return r; -} - -int -sshkey_xmss_deserialize_state_opt(struct sshkey *k, struct sshbuf *b) -{ - struct ssh_xmss_state *state = k->xmss_state; - enum sshkey_serialize_rep opts; - u_char have_state, have_stack, have_filename, have_enc; - int r; - - if ((r = sshbuf_get_u8(b, &have_state)) != 0) - return r; - - opts = have_state; - switch (opts) { - case SSHKEY_SERIALIZE_DEFAULT: - r = 0; - break; - case SSHKEY_SERIALIZE_SHIELD: - if ((r = sshbuf_get_u8(b, &have_stack)) != 0) - return r; - if (have_stack && - (r = sshkey_xmss_deserialize_state(k, b)) != 0) - return r; - if ((r = sshbuf_get_u8(b, &have_filename)) != 0) - return r; - if (have_filename && - (r = sshbuf_get_cstring(b, &k->xmss_filename, NULL)) != 0) - return r; - if ((r = sshbuf_get_u8(b, &have_enc)) != 0) - return r; - if (have_enc && - (r = sshkey_xmss_deserialize_enc_key(k, b)) != 0) - return r; - if ((r = sshbuf_get_u32(b, &state->maxidx)) != 0 || - (r = sshbuf_get_u8(b, &state->allow_update)) != 0) - return r; - break; - case SSHKEY_SERIALIZE_STATE: - if ((r = sshkey_xmss_deserialize_state(k, b)) != 0) - return r; - break; - case SSHKEY_SERIALIZE_FULL: - if ((r = sshkey_xmss_deserialize_enc_key(k, b)) != 0 || - (r = sshkey_xmss_deserialize_state(k, b)) != 0) - return r; - break; - default: - r = SSH_ERR_INVALID_FORMAT; - break; - } - return r; -} - -int -sshkey_xmss_encrypt_state(const struct sshkey *k, struct sshbuf *b, - struct sshbuf **retp) -{ - struct ssh_xmss_state *state = k->xmss_state; - struct sshbuf *encrypted = NULL, *encoded = NULL, *padded = NULL; - struct sshcipher_ctx *ciphercontext = NULL; - const struct sshcipher *cipher; - u_char *cp, *key, *iv = NULL; - size_t i, keylen, ivlen, blocksize, authlen, encrypted_len, aadlen; - int r = SSH_ERR_INTERNAL_ERROR; - - if (retp != NULL) - *retp = NULL; - if (state == NULL || - state->enc_keyiv == NULL || - state->enc_ciphername == NULL) - return SSH_ERR_INTERNAL_ERROR; - if ((cipher = cipher_by_name(state->enc_ciphername)) == NULL) { - r = SSH_ERR_INTERNAL_ERROR; - goto out; - } - blocksize = cipher_blocksize(cipher); - keylen = cipher_keylen(cipher); - ivlen = cipher_ivlen(cipher); - authlen = cipher_authlen(cipher); - if (state->enc_keyiv_len != keylen + ivlen) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - key = state->enc_keyiv; - if ((encrypted = sshbuf_new()) == NULL || - (encoded = sshbuf_new()) == NULL || - (padded = sshbuf_new()) == NULL || - (iv = malloc(ivlen)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - - /* replace first 4 bytes of IV with index to ensure uniqueness */ - memcpy(iv, key + keylen, ivlen); - POKE_U32(iv, state->idx); - - if ((r = sshbuf_put(encoded, XMSS_MAGIC, sizeof(XMSS_MAGIC))) != 0 || - (r = sshbuf_put_u32(encoded, state->idx)) != 0) - goto out; - - /* padded state will be encrypted */ - if ((r = sshbuf_putb(padded, b)) != 0) - goto out; - i = 0; - while (sshbuf_len(padded) % blocksize) { - if ((r = sshbuf_put_u8(padded, ++i & 0xff)) != 0) - goto out; - } - encrypted_len = sshbuf_len(padded); - - /* header including the length of state is used as AAD */ - if ((r = sshbuf_put_u32(encoded, encrypted_len)) != 0) - goto out; - aadlen = sshbuf_len(encoded); - - /* concat header and state */ - if ((r = sshbuf_putb(encoded, padded)) != 0) - goto out; - - /* reserve space for encryption of encoded data plus auth tag */ - /* encrypt at offset addlen */ - if ((r = sshbuf_reserve(encrypted, - encrypted_len + aadlen + authlen, &cp)) != 0 || - (r = cipher_init(&ciphercontext, cipher, key, keylen, - iv, ivlen, 1)) != 0 || - (r = cipher_crypt(ciphercontext, 0, cp, sshbuf_ptr(encoded), - encrypted_len, aadlen, authlen)) != 0) - goto out; - - /* success */ - r = 0; - out: - if (retp != NULL) { - *retp = encrypted; - encrypted = NULL; - } - sshbuf_free(padded); - sshbuf_free(encoded); - sshbuf_free(encrypted); - cipher_free(ciphercontext); - free(iv); - return r; -} - -int -sshkey_xmss_decrypt_state(const struct sshkey *k, struct sshbuf *encoded, - struct sshbuf **retp) -{ - struct ssh_xmss_state *state = k->xmss_state; - struct sshbuf *copy = NULL, *decrypted = NULL; - struct sshcipher_ctx *ciphercontext = NULL; - const struct sshcipher *cipher = NULL; - u_char *key, *iv = NULL, *dp; - size_t keylen, ivlen, authlen, aadlen; - u_int blocksize, encrypted_len, index; - int r = SSH_ERR_INTERNAL_ERROR; - - if (retp != NULL) - *retp = NULL; - if (state == NULL || - state->enc_keyiv == NULL || - state->enc_ciphername == NULL) - return SSH_ERR_INTERNAL_ERROR; - if ((cipher = cipher_by_name(state->enc_ciphername)) == NULL) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - blocksize = cipher_blocksize(cipher); - keylen = cipher_keylen(cipher); - ivlen = cipher_ivlen(cipher); - authlen = cipher_authlen(cipher); - if (state->enc_keyiv_len != keylen + ivlen) { - r = SSH_ERR_INTERNAL_ERROR; - goto out; - } - key = state->enc_keyiv; - - if ((copy = sshbuf_fromb(encoded)) == NULL || - (decrypted = sshbuf_new()) == NULL || - (iv = malloc(ivlen)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - - /* check magic */ - if (sshbuf_len(encoded) < sizeof(XMSS_MAGIC) || - memcmp(sshbuf_ptr(encoded), XMSS_MAGIC, sizeof(XMSS_MAGIC))) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - /* parse public portion */ - if ((r = sshbuf_consume(encoded, sizeof(XMSS_MAGIC))) != 0 || - (r = sshbuf_get_u32(encoded, &index)) != 0 || - (r = sshbuf_get_u32(encoded, &encrypted_len)) != 0) - goto out; - - /* check size of encrypted key blob */ - if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - /* check that an appropriate amount of auth data is present */ - if (sshbuf_len(encoded) < authlen || - sshbuf_len(encoded) - authlen < encrypted_len) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - - aadlen = sshbuf_len(copy) - sshbuf_len(encoded); - - /* replace first 4 bytes of IV with index to ensure uniqueness */ - memcpy(iv, key + keylen, ivlen); - POKE_U32(iv, index); - - /* decrypt private state of key */ - if ((r = sshbuf_reserve(decrypted, aadlen + encrypted_len, &dp)) != 0 || - (r = cipher_init(&ciphercontext, cipher, key, keylen, - iv, ivlen, 0)) != 0 || - (r = cipher_crypt(ciphercontext, 0, dp, sshbuf_ptr(copy), - encrypted_len, aadlen, authlen)) != 0) - goto out; - - /* there should be no trailing data */ - if ((r = sshbuf_consume(encoded, encrypted_len + authlen)) != 0) - goto out; - if (sshbuf_len(encoded) != 0) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - - /* remove AAD */ - if ((r = sshbuf_consume(decrypted, aadlen)) != 0) - goto out; - /* XXX encrypted includes unchecked padding */ - - /* success */ - r = 0; - if (retp != NULL) { - *retp = decrypted; - decrypted = NULL; - } - out: - cipher_free(ciphercontext); - sshbuf_free(copy); - sshbuf_free(decrypted); - free(iv); - return r; -} - -u_int32_t -sshkey_xmss_signatures_left(const struct sshkey *k) -{ - struct ssh_xmss_state *state = k->xmss_state; - u_int32_t idx; - - if (sshkey_type_plain(k->type) == KEY_XMSS && state && - state->maxidx) { - idx = k->xmss_sk ? PEEK_U32(k->xmss_sk) : state->idx; - if (idx < state->maxidx) - return state->maxidx - idx; - } - return 0; -} - -int -sshkey_xmss_enable_maxsign(struct sshkey *k, u_int32_t maxsign) -{ - struct ssh_xmss_state *state = k->xmss_state; - - if (sshkey_type_plain(k->type) != KEY_XMSS) - return SSH_ERR_INVALID_ARGUMENT; - if (maxsign == 0) - return 0; - if (state->idx + maxsign < state->idx) - return SSH_ERR_INVALID_ARGUMENT; - state->maxidx = state->idx + maxsign; - return 0; -} -#endif /* WITH_XMSS */ diff --git a/sshkey-xmss.h b/sshkey-xmss.h deleted file mode 100644 index ab8b9c905a96..000000000000 --- a/sshkey-xmss.h +++ /dev/null @@ -1,56 +0,0 @@ -/* $OpenBSD: sshkey-xmss.h,v 1.4 2022/10/28 00:39:29 djm Exp $ */ -/* - * Copyright (c) 2017 Markus Friedl. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef SSHKEY_XMSS_H -#define SSHKEY_XMSS_H - -#define XMSS_SHA2_256_W16_H10_NAME "XMSS_SHA2-256_W16_H10" -#define XMSS_SHA2_256_W16_H16_NAME "XMSS_SHA2-256_W16_H16" -#define XMSS_SHA2_256_W16_H20_NAME "XMSS_SHA2-256_W16_H20" -#define XMSS_DEFAULT_NAME XMSS_SHA2_256_W16_H10_NAME - -size_t sshkey_xmss_pklen(const struct sshkey *); -size_t sshkey_xmss_sklen(const struct sshkey *); -int sshkey_xmss_init(struct sshkey *, const char *); -void sshkey_xmss_free_state(struct sshkey *); -int sshkey_xmss_generate_private_key(struct sshkey *, int); -int sshkey_xmss_serialize_state(const struct sshkey *, struct sshbuf *); -int sshkey_xmss_serialize_state_opt(const struct sshkey *, struct sshbuf *, - enum sshkey_serialize_rep); -int sshkey_xmss_serialize_pk_info(const struct sshkey *, struct sshbuf *, - enum sshkey_serialize_rep); -int sshkey_xmss_deserialize_state(struct sshkey *, struct sshbuf *); -int sshkey_xmss_deserialize_state_opt(struct sshkey *, struct sshbuf *); -int sshkey_xmss_deserialize_pk_info(struct sshkey *, struct sshbuf *); - -int sshkey_xmss_siglen(const struct sshkey *, size_t *); -void *sshkey_xmss_params(const struct sshkey *); -void *sshkey_xmss_bds_state(const struct sshkey *); -int sshkey_xmss_get_state(const struct sshkey *, int); -int sshkey_xmss_enable_maxsign(struct sshkey *, u_int32_t); -int sshkey_xmss_forward_state(const struct sshkey *, u_int32_t); -int sshkey_xmss_update_state(const struct sshkey *, int); -u_int32_t sshkey_xmss_signatures_left(const struct sshkey *); - -#endif /* SSHKEY_XMSS_H */ diff --git a/sshkey.c b/sshkey.c index a33fc0724873..5d87d4c91d53 100644 --- a/sshkey.c +++ b/sshkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.c,v 1.148 2024/12/03 15:53:51 tb Exp $ */ +/* $OpenBSD: sshkey.c,v 1.155 2025/10/03 00:08:02 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. @@ -34,6 +34,7 @@ #include #ifdef WITH_OPENSSL +#include #include #include #include @@ -62,11 +63,8 @@ #include "sshkey.h" #include "match.h" #include "ssh-sk.h" +#include "ssh-pkcs11.h" -#ifdef WITH_XMSS -#include "sshkey-xmss.h" -#include "xmss_fast.h" -#endif #ifdef WINDOWS #include #include @@ -99,8 +97,6 @@ #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); @@ -131,15 +127,7 @@ 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; -# ifdef WITH_DSA -extern const struct sshkey_impl sshkey_dss_impl; -extern const struct sshkey_impl sshkey_dsa_cert_impl; -# endif #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, @@ -164,10 +152,6 @@ const struct sshkey_impl * const keyimpls[] = { &sshkey_ecdsa_sk_webauthn_impl, # endif /* ENABLE_SK */ # endif /* OPENSSL_HAS_ECC */ -# ifdef WITH_DSA - &sshkey_dss_impl, - &sshkey_dsa_cert_impl, -# endif &sshkey_rsa_impl, &sshkey_rsa_cert_impl, &sshkey_rsa_sha256_impl, @@ -175,10 +159,6 @@ const struct sshkey_impl * const keyimpls[] = { &sshkey_rsa_sha512_impl, &sshkey_rsa_sha512_cert_impl, #endif /* WITH_OPENSSL */ -#ifdef WITH_XMSS - &sshkey_xmss_impl, - &sshkey_xmss_cert_impl, -#endif NULL }; @@ -342,9 +322,10 @@ sshkey_match_keyname_to_sigalgs(const char *keyname, const char *sigalgs) 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; + char *ret = NULL; + size_t i; const struct sshkey_impl *impl; + char sep_str[2] = {sep, '\0'}; for (i = 0; keyimpls[i] != NULL; i++) { impl = keyimpls[i]; @@ -354,16 +335,7 @@ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) 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; + xextendf(&ret, sep_str, "%s", impl->name); } return ret; } @@ -463,8 +435,6 @@ 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: @@ -473,8 +443,6 @@ sshkey_type_plain(int type) return KEY_ED25519; case KEY_ED25519_SK_CERT: return KEY_ED25519_SK; - case KEY_XMSS_CERT: - return KEY_XMSS; default: return type; } @@ -487,8 +455,6 @@ 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: @@ -497,8 +463,6 @@ sshkey_type_certified(int type) return KEY_ED25519_CERT; case KEY_ED25519_SK: return KEY_ED25519_SK_CERT; - case KEY_XMSS: - return KEY_XMSS_CERT; default: return -1; } @@ -816,6 +780,8 @@ sshkey_free_contents(struct sshkey *k) if (k == NULL) return; + if ((k->flags & SSHKEY_FLAG_EXT) != 0) + pkcs11_key_free(k); if ((impl = sshkey_impl_from_type(k->type)) != NULL && impl->funcs->cleanup != NULL) impl->funcs->cleanup(k); @@ -938,16 +904,16 @@ 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) +static int +sshkey_puts_opts_internal(const struct sshkey *key, struct sshbuf *b, + enum sshkey_serialize_rep opts, int force_plain) { struct sshbuf *tmp; int r; if ((tmp = sshbuf_new()) == NULL) return SSH_ERR_ALLOC_FAIL; - r = to_blob_buf(key, tmp, 0, opts); + r = to_blob_buf(key, tmp, force_plain, opts); if (r == 0) r = sshbuf_put_stringb(b, tmp); sshbuf_free(tmp); @@ -957,7 +923,7 @@ sshkey_puts_opts(const struct sshkey *key, struct sshbuf *b, int sshkey_puts(const struct sshkey *key, struct sshbuf *b) { - return sshkey_puts_opts(key, b, SSHKEY_SERIALIZE_DEFAULT); + return sshkey_puts_opts_internal(key, b, SSHKEY_SERIALIZE_DEFAULT, 0); } int @@ -966,6 +932,12 @@ sshkey_putb_plain(const struct sshkey *key, struct sshbuf *b) return to_blob_buf(key, b, 1, SSHKEY_SERIALIZE_DEFAULT); } +int +sshkey_puts_plain(const struct sshkey *key, struct sshbuf *b) +{ + return sshkey_puts_opts_internal(key, b, SSHKEY_SERIALIZE_DEFAULT, 1); +} + static int to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain, enum sshkey_serialize_rep opts) @@ -1713,8 +1685,7 @@ sshkey_shield_private(struct sshkey *k) } if (sshkey_is_shielded(k) && (r = sshkey_unshield_private(k)) != 0) goto out; - if ((r = sshkey_private_serialize_opt(k, prvbuf, - SSHKEY_SERIALIZE_SHIELD)) != 0) + if ((r = sshkey_private_serialize(k, prvbuf)) != 0) goto out; /* pad to cipher blocksize */ i = 0; @@ -2238,6 +2209,9 @@ sshkey_sign(struct sshkey *key, if (sshkey_is_sk(key)) { r = sshsk_sign(sk_provider, key, sigp, lenp, data, datalen, compat, sk_pin); + } else if ((key->flags & SSHKEY_FLAG_EXT) != 0) { + r = pkcs11_sign(key, sigp, lenp, data, datalen, + alg, sk_provider, sk_pin, compat); } else { if (impl->funcs->sign == NULL) r = SSH_ERR_SIGN_ALG_UNSUPPORTED; @@ -2598,7 +2572,7 @@ sshkey_serialize_private_sk(const struct sshkey *key, struct sshbuf *b) return 0; } -int +static int sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, enum sshkey_serialize_rep opts) { @@ -2649,6 +2623,7 @@ sshkey_private_serialize(struct sshkey *key, struct sshbuf *b) SSHKEY_SERIALIZE_DEFAULT); } + /* Shared deserialization of FIDO private key components */ int sshkey_private_deserialize_sk(struct sshbuf *buf, struct sshkey *k) @@ -2708,7 +2683,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) 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; @@ -2722,7 +2696,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) 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 || @@ -2774,8 +2747,7 @@ sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) /* 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) { + EC_POINT_get_affine_coordinates(group, public, x, y, NULL) != 1) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } @@ -2859,9 +2831,8 @@ sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point) fprintf(stderr, "%s: BN_new failed\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", + if (EC_POINT_get_affine_coordinates(group, point, x, y, NULL) != 1) { + fprintf(stderr, "%s: EC_POINT_get_affine_coordinates\n", __func__); goto out; } @@ -2969,8 +2940,7 @@ sshkey_private_to_blob2(struct sshkey *prv, struct sshbuf *blob, goto out; /* append private key and comment*/ - if ((r = sshkey_private_serialize_opt(prv, encrypted, - SSHKEY_SERIALIZE_FULL)) != 0 || + if ((r = sshkey_private_serialize(prv, encrypted)) != 0 || (r = sshbuf_put_cstring(encrypted, comment)) != 0) goto out; @@ -3396,20 +3366,6 @@ sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf, goto out; switch (key->type) { -#ifdef WITH_DSA - case KEY_DSA: - if (format == SSHKEY_PRIVATE_PEM) { - success = PEM_write_bio_DSAPrivateKey(bio, key->dsa, - cipher, passphrase, len, NULL, NULL); - } else { - if ((pkey = EVP_PKEY_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - success = EVP_PKEY_set1_DSA(pkey, key->dsa); - } - break; -#endif #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: if (format == SSHKEY_PRIVATE_PEM) { @@ -3477,16 +3433,12 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, { 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 */ @@ -3652,19 +3604,6 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, prv->pkey = pk; if ((r = sshkey_check_rsa_length(prv, 0)) != 0) goto out; -#ifdef WITH_DSA - } 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 -#endif #ifdef OPENSSL_HAS_ECC } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_EC && (type == KEY_UNSPEC || type == KEY_ECDSA)) { @@ -3761,24 +3700,16 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, if (commentp != NULL) *commentp = NULL; - switch (type) { - 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; + 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); + return sshkey_parse_private_pem_fileblob(blob, type, + passphrase, keyp); #else - return SSH_ERR_INVALID_FORMAT; + return SSH_ERR_INVALID_FORMAT; #endif /* WITH_OPENSSL */ - } } int @@ -3813,90 +3744,3 @@ sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, int type, 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/sshkey.h b/sshkey.h index 19bbbac7dc0f..c3262b896f06 100644 --- a/sshkey.h +++ b/sshkey.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.h,v 1.66 2025/04/02 04:28:03 tb Exp $ */ +/* $OpenBSD: sshkey.h,v 1.70 2025/08/29 03:50:38 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -30,9 +30,6 @@ #ifdef WITH_OPENSSL #include -#ifdef WITH_DSA -#include -#endif #include # ifdef OPENSSL_HAS_ECC # include @@ -46,7 +43,6 @@ #else /* WITH_OPENSSL */ # define BIGNUM void # define RSA void -# define DSA void # define EC_KEY void # define EC_GROUP void # define EC_POINT void @@ -62,15 +58,11 @@ struct sshbuf; /* Key types */ enum sshkey_types { KEY_RSA, - KEY_DSA, KEY_ECDSA, KEY_ED25519, KEY_RSA_CERT, - KEY_DSA_CERT, KEY_ECDSA_CERT, KEY_ED25519_CERT, - KEY_XMSS, - KEY_XMSS_CERT, KEY_ECDSA_SK, KEY_ECDSA_SK_CERT, KEY_ED25519_SK, @@ -93,10 +85,6 @@ enum sshkey_fp_rep { /* Private key serialisation formats, used on the wire */ enum sshkey_serialize_rep { SSHKEY_SERIALIZE_DEFAULT = 0, - SSHKEY_SERIALIZE_STATE = 1, /* only state is serialized */ - SSHKEY_SERIALIZE_FULL = 2, /* include keys for saving to disk */ - SSHKEY_SERIALIZE_SHIELD = 3, /* everything, for encrypting in ram */ - SSHKEY_SERIALIZE_INFO = 254, /* minimal information */ }; /* Private key disk formats */ @@ -129,8 +117,6 @@ struct sshkey_cert { struct sshkey { int type; int flags; - /* KEY_DSA */ - DSA *dsa; /* KEY_ECDSA and KEY_ECDSA_SK */ int ecdsa_nid; /* NID of curve */ /* libcrypto-backed keys */ @@ -138,12 +124,6 @@ struct sshkey { /* KEY_ED25519 and KEY_ED25519_SK */ u_char *ed25519_sk; u_char *ed25519_pk; - /* KEY_XMSS */ - char *xmss_name; - char *xmss_filename; /* for state file updates */ - void *xmss_state; /* depends on xmss_name, opaque */ - u_char *xmss_sk; - u_char *xmss_pk; /* KEY_ECDSA_SK and KEY_ED25519_SK */ char *sk_application; uint8_t sk_flags; @@ -279,10 +259,9 @@ int sshkey_to_blob(const struct sshkey *, u_char **, size_t *); int sshkey_to_base64(const struct sshkey *, char **); int sshkey_putb(const struct sshkey *, struct sshbuf *); int sshkey_puts(const struct sshkey *, struct sshbuf *); -int sshkey_puts_opts(const struct sshkey *, struct sshbuf *, - enum sshkey_serialize_rep); int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *); int sshkey_putb_plain(const struct sshkey *, struct sshbuf *); +int sshkey_puts_plain(const struct sshkey *, struct sshbuf *); int sshkey_sign(struct sshkey *, u_char **, size_t *, const u_char *, size_t, const char *, const char *, const char *, u_int); @@ -304,8 +283,6 @@ void sshkey_dump_ec_key(const EC_KEY *); /* private key parsing and serialisation */ int sshkey_private_serialize(struct sshkey *key, struct sshbuf *buf); -int sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, - enum sshkey_serialize_rep); int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **keyp); /* private key file format parsing and serialisation */ @@ -320,17 +297,18 @@ int sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, int type, struct sshkey **pubkeyp); int sshkey_check_rsa_length(const struct sshkey *, int); +int ssh_rsa_hash_id_from_keyname(const char *); +const char *ssh_rsa_hash_alg_ident(int); +int ssh_rsa_encode_store_sig(int, const u_char *, size_t, + u_char **, size_t *); +int ssh_ecdsa_encode_store_sig(const struct sshkey *, + const BIGNUM *, const BIGNUM *, u_char **, size_t *); +int ssh_ed25519_encode_store_sig(const u_char *, size_t, + u_char **, size_t *); /* XXX should be internal, but used by ssh-keygen */ int ssh_rsa_complete_crt_parameters(const BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *, BIGNUM **, BIGNUM **); -/* stateful keys (e.g. XMSS) */ -int sshkey_set_filename(struct sshkey *, const char *); -int sshkey_enable_maxsign(struct sshkey *, u_int32_t); -u_int32_t sshkey_signatures_left(const struct sshkey *); -int sshkey_private_serialize_maxsign(struct sshkey *key, - struct sshbuf *buf, u_int32_t maxsign, int); - void sshkey_sig_details_free(struct sshkey_sig_details *); #ifdef WITH_OPENSSL @@ -353,7 +331,6 @@ int check_rsa_length(const RSA *rsa); /* XXX remove */ #if !defined(WITH_OPENSSL) # undef RSA -# undef DSA # undef EC_KEY # undef EC_GROUP # undef EC_POINT diff --git a/sshlogin.c b/sshlogin.c index 06a7b381ade7..fb55cadd677b 100644 --- a/sshlogin.c +++ b/sshlogin.c @@ -106,7 +106,7 @@ store_lastlog_message(const char *user, uid_t uid) if (time_string != NULL) { if ((r = sshbuf_put(loginmsg, time_string, strlen(time_string))) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); free(time_string); } # else diff --git a/sshpty.c b/sshpty.c index cae0b977a585..0a82b7d3bea9 100644 --- a/sshpty.c +++ b/sshpty.c @@ -22,18 +22,14 @@ #include #include #include -#ifdef HAVE_PATHS_H -# include -#endif +#include #include #include #include #include #include -#ifdef HAVE_UTIL_H -# include -#endif #include +#include #include "sshpty.h" #include "log.h" @@ -173,7 +169,7 @@ pty_setowner(struct passwd *pw, const char *tty) /* Determine the group to make the owner of the tty. */ grp = getgrnam("tty"); if (grp == NULL) - debug("%s: no tty group", __func__); + debug_f("no tty group"); gid = (grp != NULL) ? grp->gr_gid : pw->pw_gid; mode = (grp != NULL) ? 0620 : 0600; diff --git a/sshsig.c b/sshsig.c index ed22e15d5710..edf5e5d27606 100644 --- a/sshsig.c +++ b/sshsig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshsig.c,v 1.38 2025/02/18 08:02:48 djm Exp $ */ +/* $OpenBSD: sshsig.c,v 1.40 2025/09/25 06:23:19 jsg Exp $ */ /* * Copyright (c) 2019 Google LLC * @@ -1156,11 +1156,12 @@ sshsig_match_principals(const char *path, const char *principal, linesize = 0; } fclose(f); + free(line); if (ret == 0) { if (nprincipals == 0) ret = SSH_ERR_KEY_NOT_FOUND; - if (nprincipalsp != 0) + if (nprincipalsp != NULL) *nprincipalsp = nprincipals; if (principalsp != NULL) { *principalsp = principals; diff --git a/uidswap.c b/uidswap.c index 6ed3024d0180..793688eb5817 100644 --- a/uidswap.c +++ b/uidswap.c @@ -163,9 +163,9 @@ restore_uid(void) * as well. */ if (setuid(getuid()) == -1) - fatal("%s: setuid failed: %s", __func__, strerror(errno)); + fatal_f("setuid failed: %s", strerror(errno)); if (setgid(getgid()) == -1) - fatal("%s: setgid failed: %s", __func__, strerror(errno)); + fatal_f("setgid failed: %s", strerror(errno)); #endif /* SAVED_IDS_WORK_WITH_SETEUID */ if (setgroups(saved_egroupslen, saved_egroups) == -1) @@ -212,7 +212,7 @@ permanently_set_uid(struct passwd *pw) /* Try restoration of GID if changed (test clearing of saved gid) */ if (old_gid != pw->pw_gid && pw->pw_uid != 0 && (setgid(old_gid) != -1 || setegid(old_gid) != -1)) - fatal("%s: was able to restore old [e]gid", __func__); + fatal_f("was able to restore old [e]gid"); #endif /* Verify GID drop was successful */ @@ -226,7 +226,7 @@ permanently_set_uid(struct passwd *pw) /* Try restoration of UID if changed (test clearing of saved uid) */ if (old_uid != pw->pw_uid && (setuid(old_uid) != -1 || seteuid(old_uid) != -1)) - fatal("%s: was able to restore old [e]uid", __func__); + fatal_f("was able to restore old [e]uid"); #endif /* Verify UID drop was successful */ diff --git a/umac.c b/umac.c index d5958babfd34..bc2dcdc26d59 100644 --- a/umac.c +++ b/umac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: umac.c,v 1.23 2023/03/07 01:30:52 djm Exp $ */ +/* $OpenBSD: umac.c,v 1.27 2025/09/05 10:34:35 dtucker Exp $ */ /* ----------------------------------------------------------------------- * * umac.c -- C Implementation UMAC Message Authentication @@ -6,7 +6,7 @@ * Version 0.93b of rfc4418.txt -- 2006 July 18 * * For a full description of UMAC message authentication see the UMAC - * world-wide-web page at http://www.cs.ucdavis.edu/~rogaway/umac + * world-wide-web page at https://fastcrypto.org/umac/ * Please report bugs and suggestions to the UMAC webpage. * * Copyright (c) 1999-2006 Ted Krovetz @@ -72,10 +72,15 @@ /* ---------------------------------------------------------------------- */ #include "includes.h" + #include +#ifdef HAVE_ENDIAN_H +# include +#endif #include #include #include +#include #include #include @@ -1089,7 +1094,7 @@ static int uhash_update(uhash_ctx_t ctx, const u_char *input, long len) } /* pass remaining < L1_KEY_LEN bytes of input data to NH */ - if (len) { + if (len > 0 && (unsigned long)len <= UINT32_MAX) { nh_update(&ctx->hash, (const UINT8 *)input, len); ctx->msg_len += len; } diff --git a/version.h b/version.h index 46da6bd38ce5..40335b4b6610 100644 --- a/version.h +++ b/version.h @@ -1,8 +1,8 @@ -/* $OpenBSD: version.h,v 1.105 2025/04/09 07:00:21 djm Exp $ */ +/* $OpenBSD: version.h,v 1.106 2025/10/06 01:45:22 djm Exp $ */ -#define SSH_WINDOWS_VERSION "OpenSSH_for_Windows_10.0" +#define SSH_WINDOWS_VERSION "OpenSSH_for_Windows_10.1" #define SSH_WINDOWS_BANNER " Win32-OpenSSH-GitHub" #define SSH_VERSION SSH_WINDOWS_VERSION SSH_WINDOWS_BANNER -#define SSH_PORTABLE "p2" +#define SSH_PORTABLE "p1" #define SSH_RELEASE SSH_WINDOWS_VERSION SSH_PORTABLE SSH_WINDOWS_BANNER diff --git a/xmalloc.c b/xmalloc.c index 67191e3f214d..a058f085c148 100644 --- a/xmalloc.c +++ b/xmalloc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: xmalloc.c,v 1.37 2022/03/13 23:27:54 cheloha Exp $ */ +/* $OpenBSD: xmalloc.c,v 1.38 2025/05/23 00:40:45 deraadt Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -16,9 +16,7 @@ #include "includes.h" #include -#ifdef HAVE_STDINT_H -# include -#endif +#include #include #include #include @@ -27,7 +25,7 @@ #include "log.h" #if defined(__OpenBSD__) -char *malloc_options = "S"; +const char * const malloc_options = "S"; #endif /* __OpenBSD__ */ void * diff --git a/xmss_commons.c b/xmss_commons.c deleted file mode 100644 index 8d6b80b6eb79..000000000000 --- a/xmss_commons.c +++ /dev/null @@ -1,36 +0,0 @@ -/* $OpenBSD: xmss_commons.c,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */ -/* -xmss_commons.c 20160722 -Andreas Hülsing -Joost Rijneveld -Public domain. -*/ - -#include "includes.h" -#ifdef WITH_XMSS - -#include "xmss_commons.h" -#include -#include -#ifdef HAVE_STDINT_H -# include -#endif - -void to_byte(unsigned char *out, unsigned long long in, uint32_t bytes) -{ - int32_t i; - for (i = bytes-1; i >= 0; i--) { - out[i] = in & 0xff; - in = in >> 8; - } -} - -#if 0 -void hexdump(const unsigned char *a, size_t len) -{ - size_t i; - for (i = 0; i < len; i++) - printf("%02x", a[i]); -} -#endif -#endif /* WITH_XMSS */ diff --git a/xmss_commons.h b/xmss_commons.h deleted file mode 100644 index a98e4799c425..000000000000 --- a/xmss_commons.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifdef WITH_XMSS -/* $OpenBSD: xmss_commons.h,v 1.3 2018/02/26 03:56:44 dtucker Exp $ */ -/* -xmss_commons.h 20160722 -Andreas Hülsing -Joost Rijneveld -Public domain. -*/ -#ifndef XMSS_COMMONS_H -#define XMSS_COMMONS_H - -#include -#ifdef HAVE_STDINT_H -#include -#endif -#endif -void to_byte(unsigned char *output, unsigned long long in, uint32_t bytes); -#if 0 -void hexdump(const unsigned char *a, size_t len); -#endif -#endif /* WITH_XMSS */ diff --git a/xmss_fast.c b/xmss_fast.c deleted file mode 100644 index 421b39a37a9e..000000000000 --- a/xmss_fast.c +++ /dev/null @@ -1,1106 +0,0 @@ -/* $OpenBSD: xmss_fast.c,v 1.3 2018/03/22 07:06:11 markus Exp $ */ -/* -xmss_fast.c version 20160722 -Andreas Hülsing -Joost Rijneveld -Public domain. -*/ - -#include "includes.h" -#ifdef WITH_XMSS - -#include -#include -#ifdef HAVE_STDINT_H -# include -#endif - -#include "xmss_fast.h" -#include "crypto_api.h" -#include "xmss_wots.h" -#include "xmss_hash.h" - -#include "xmss_commons.h" -#include "xmss_hash_address.h" -// For testing -#include "stdio.h" - - - -/** - * Used for pseudorandom keygeneration, - * generates the seed for the WOTS keypair at address addr - * - * takes n byte sk_seed and returns n byte seed using 32 byte address addr. - */ -static void get_seed(unsigned char *seed, const unsigned char *sk_seed, int n, uint32_t addr[8]) -{ - unsigned char bytes[32]; - // Make sure that chain addr, hash addr, and key bit are 0! - setChainADRS(addr,0); - setHashADRS(addr,0); - setKeyAndMask(addr,0); - // Generate pseudorandom value - addr_to_byte(bytes, addr); - prf(seed, bytes, sk_seed, n); -} - -/** - * Initialize xmss params struct - * parameter names are the same as in the draft - * parameter k is K as used in the BDS algorithm - */ -int xmss_set_params(xmss_params *params, int n, int h, int w, int k) -{ - if (k >= h || k < 2 || (h - k) % 2) { - fprintf(stderr, "For BDS traversal, H - K must be even, with H > K >= 2!\n"); - return 1; - } - params->h = h; - params->n = n; - params->k = k; - wots_params wots_par; - wots_set_params(&wots_par, n, w); - params->wots_par = wots_par; - return 0; -} - -/** - * Initialize BDS state struct - * parameter names are the same as used in the description of the BDS traversal - */ -void xmss_set_bds_state(bds_state *state, unsigned char *stack, int stackoffset, unsigned char *stacklevels, unsigned char *auth, unsigned char *keep, treehash_inst *treehash, unsigned char *retain, int next_leaf) -{ - state->stack = stack; - state->stackoffset = stackoffset; - state->stacklevels = stacklevels; - state->auth = auth; - state->keep = keep; - state->treehash = treehash; - state->retain = retain; - state->next_leaf = next_leaf; -} - -/** - * Initialize xmssmt_params struct - * parameter names are the same as in the draft - * - * Especially h is the total tree height, i.e. the XMSS trees have height h/d - */ -int xmssmt_set_params(xmssmt_params *params, int n, int h, int d, int w, int k) -{ - if (h % d) { - fprintf(stderr, "d must divide h without remainder!\n"); - return 1; - } - params->h = h; - params->d = d; - params->n = n; - params->index_len = (h + 7) / 8; - xmss_params xmss_par; - if (xmss_set_params(&xmss_par, n, (h/d), w, k)) { - return 1; - } - params->xmss_par = xmss_par; - return 0; -} - -/** - * Computes a leaf from a WOTS public key using an L-tree. - */ -static void l_tree(unsigned char *leaf, unsigned char *wots_pk, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8]) -{ - unsigned int l = params->wots_par.len; - unsigned int n = params->n; - uint32_t i = 0; - uint32_t height = 0; - uint32_t bound; - - //ADRS.setTreeHeight(0); - setTreeHeight(addr, height); - - while (l > 1) { - bound = l >> 1; //floor(l / 2); - for (i = 0; i < bound; i++) { - //ADRS.setTreeIndex(i); - setTreeIndex(addr, i); - //wots_pk[i] = RAND_HASH(pk[2i], pk[2i + 1], SEED, ADRS); - hash_h(wots_pk+i*n, wots_pk+i*2*n, pub_seed, addr, n); - } - //if ( l % 2 == 1 ) { - if (l & 1) { - //pk[floor(l / 2) + 1] = pk[l]; - memcpy(wots_pk+(l>>1)*n, wots_pk+(l-1)*n, n); - //l = ceil(l / 2); - l=(l>>1)+1; - } - else { - //l = ceil(l / 2); - l=(l>>1); - } - //ADRS.setTreeHeight(ADRS.getTreeHeight() + 1); - height++; - setTreeHeight(addr, height); - } - //return pk[0]; - memcpy(leaf, wots_pk, n); -} - -/** - * Computes the leaf at a given address. First generates the WOTS key pair, then computes leaf using l_tree. As this happens position independent, we only require that addr encodes the right ltree-address. - */ -static void gen_leaf_wots(unsigned char *leaf, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, uint32_t ltree_addr[8], uint32_t ots_addr[8]) -{ - unsigned char seed[params->n]; - unsigned char pk[params->wots_par.keysize]; - - get_seed(seed, sk_seed, params->n, ots_addr); - wots_pkgen(pk, seed, &(params->wots_par), pub_seed, ots_addr); - - l_tree(leaf, pk, params, pub_seed, ltree_addr); -} - -static int treehash_minheight_on_stack(bds_state* state, const xmss_params *params, const treehash_inst *treehash) { - unsigned int r = params->h, i; - for (i = 0; i < treehash->stackusage; i++) { - if (state->stacklevels[state->stackoffset - i - 1] < r) { - r = state->stacklevels[state->stackoffset - i - 1]; - } - } - return r; -} - -/** - * Merkle's TreeHash algorithm. The address only needs to initialize the first 78 bits of addr. Everything else will be set by treehash. - * Currently only used for key generation. - * - */ -static void treehash_setup(unsigned char *node, int height, int index, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8]) -{ - unsigned int idx = index; - unsigned int n = params->n; - unsigned int h = params->h; - unsigned int k = params->k; - // use three different addresses because at this point we use all three formats in parallel - uint32_t ots_addr[8]; - uint32_t ltree_addr[8]; - uint32_t node_addr[8]; - // only copy layer and tree address parts - memcpy(ots_addr, addr, 12); - // type = ots - setType(ots_addr, 0); - memcpy(ltree_addr, addr, 12); - setType(ltree_addr, 1); - memcpy(node_addr, addr, 12); - setType(node_addr, 2); - - uint32_t lastnode, i; - unsigned char stack[(height+1)*n]; - unsigned int stacklevels[height+1]; - unsigned int stackoffset=0; - unsigned int nodeh; - - lastnode = idx+(1<treehash[i].h = i; - state->treehash[i].completed = 1; - state->treehash[i].stackusage = 0; - } - - i = 0; - for (; idx < lastnode; idx++) { - setLtreeADRS(ltree_addr, idx); - setOTSADRS(ots_addr, idx); - gen_leaf_wots(stack+stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr); - stacklevels[stackoffset] = 0; - stackoffset++; - if (h - k > 0 && i == 3) { - memcpy(state->treehash[0].node, stack+stackoffset*n, n); - } - while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) - { - nodeh = stacklevels[stackoffset-1]; - if (i >> nodeh == 1) { - memcpy(state->auth + nodeh*n, stack+(stackoffset-1)*n, n); - } - else { - if (nodeh < h - k && i >> nodeh == 3) { - memcpy(state->treehash[nodeh].node, stack+(stackoffset-1)*n, n); - } - else if (nodeh >= h - k) { - memcpy(state->retain + ((1 << (h - 1 - nodeh)) + nodeh - h + (((i >> nodeh) - 3) >> 1)) * n, stack+(stackoffset-1)*n, n); - } - } - setTreeHeight(node_addr, stacklevels[stackoffset-1]); - setTreeIndex(node_addr, (idx >> (stacklevels[stackoffset-1]+1))); - hash_h(stack+(stackoffset-2)*n, stack+(stackoffset-2)*n, pub_seed, - node_addr, n); - stacklevels[stackoffset-2]++; - stackoffset--; - } - i++; - } - - for (i = 0; i < n; i++) - node[i] = stack[i]; -} - -static void treehash_update(treehash_inst *treehash, bds_state *state, const unsigned char *sk_seed, const xmss_params *params, const unsigned char *pub_seed, const uint32_t addr[8]) { - int n = params->n; - - uint32_t ots_addr[8]; - uint32_t ltree_addr[8]; - uint32_t node_addr[8]; - // only copy layer and tree address parts - memcpy(ots_addr, addr, 12); - // type = ots - setType(ots_addr, 0); - memcpy(ltree_addr, addr, 12); - setType(ltree_addr, 1); - memcpy(node_addr, addr, 12); - setType(node_addr, 2); - - setLtreeADRS(ltree_addr, treehash->next_idx); - setOTSADRS(ots_addr, treehash->next_idx); - - unsigned char nodebuffer[2 * n]; - unsigned int nodeheight = 0; - gen_leaf_wots(nodebuffer, sk_seed, params, pub_seed, ltree_addr, ots_addr); - while (treehash->stackusage > 0 && state->stacklevels[state->stackoffset-1] == nodeheight) { - memcpy(nodebuffer + n, nodebuffer, n); - memcpy(nodebuffer, state->stack + (state->stackoffset-1)*n, n); - setTreeHeight(node_addr, nodeheight); - setTreeIndex(node_addr, (treehash->next_idx >> (nodeheight+1))); - hash_h(nodebuffer, nodebuffer, pub_seed, node_addr, n); - nodeheight++; - treehash->stackusage--; - state->stackoffset--; - } - if (nodeheight == treehash->h) { // this also implies stackusage == 0 - memcpy(treehash->node, nodebuffer, n); - treehash->completed = 1; - } - else { - memcpy(state->stack + state->stackoffset*n, nodebuffer, n); - treehash->stackusage++; - state->stacklevels[state->stackoffset] = nodeheight; - state->stackoffset++; - treehash->next_idx++; - } -} - -/** - * Computes a root node given a leaf and an authapth - */ -static void validate_authpath(unsigned char *root, const unsigned char *leaf, unsigned long leafidx, const unsigned char *authpath, const xmss_params *params, const unsigned char *pub_seed, uint32_t addr[8]) -{ - unsigned int n = params->n; - - uint32_t i, j; - unsigned char buffer[2*n]; - - // If leafidx is odd (last bit = 1), current path element is a right child and authpath has to go to the left. - // Otherwise, it is the other way around - if (leafidx & 1) { - for (j = 0; j < n; j++) - buffer[n+j] = leaf[j]; - for (j = 0; j < n; j++) - buffer[j] = authpath[j]; - } - else { - for (j = 0; j < n; j++) - buffer[j] = leaf[j]; - for (j = 0; j < n; j++) - buffer[n+j] = authpath[j]; - } - authpath += n; - - for (i=0; i < params->h-1; i++) { - setTreeHeight(addr, i); - leafidx >>= 1; - setTreeIndex(addr, leafidx); - if (leafidx&1) { - hash_h(buffer+n, buffer, pub_seed, addr, n); - for (j = 0; j < n; j++) - buffer[j] = authpath[j]; - } - else { - hash_h(buffer, buffer, pub_seed, addr, n); - for (j = 0; j < n; j++) - buffer[j+n] = authpath[j]; - } - authpath += n; - } - setTreeHeight(addr, (params->h-1)); - leafidx >>= 1; - setTreeIndex(addr, leafidx); - hash_h(root, buffer, pub_seed, addr, n); -} - -/** - * Performs one treehash update on the instance that needs it the most. - * Returns 1 if such an instance was not found - **/ -static char bds_treehash_update(bds_state *state, unsigned int updates, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const uint32_t addr[8]) { - uint32_t i, j; - unsigned int level, l_min, low; - unsigned int h = params->h; - unsigned int k = params->k; - unsigned int used = 0; - - for (j = 0; j < updates; j++) { - l_min = h; - level = h - k; - for (i = 0; i < h - k; i++) { - if (state->treehash[i].completed) { - low = h; - } - else if (state->treehash[i].stackusage == 0) { - low = i; - } - else { - low = treehash_minheight_on_stack(state, params, &(state->treehash[i])); - } - if (low < l_min) { - level = i; - l_min = low; - } - } - if (level == h - k) { - break; - } - treehash_update(&(state->treehash[level]), state, sk_seed, params, pub_seed, addr); - used++; - } - return updates - used; -} - -/** - * Updates the state (typically NEXT_i) by adding a leaf and updating the stack - * Returns 1 if all leaf nodes have already been processed - **/ -static char bds_state_update(bds_state *state, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, const uint32_t addr[8]) { - uint32_t ltree_addr[8]; - uint32_t node_addr[8]; - uint32_t ots_addr[8]; - - int n = params->n; - int h = params->h; - int k = params->k; - - int nodeh; - int idx = state->next_leaf; - if (idx == 1 << h) { - return 1; - } - - // only copy layer and tree address parts - memcpy(ots_addr, addr, 12); - // type = ots - setType(ots_addr, 0); - memcpy(ltree_addr, addr, 12); - setType(ltree_addr, 1); - memcpy(node_addr, addr, 12); - setType(node_addr, 2); - - setOTSADRS(ots_addr, idx); - setLtreeADRS(ltree_addr, idx); - - gen_leaf_wots(state->stack+state->stackoffset*n, sk_seed, params, pub_seed, ltree_addr, ots_addr); - - state->stacklevels[state->stackoffset] = 0; - state->stackoffset++; - if (h - k > 0 && idx == 3) { - memcpy(state->treehash[0].node, state->stack+state->stackoffset*n, n); - } - while (state->stackoffset>1 && state->stacklevels[state->stackoffset-1] == state->stacklevels[state->stackoffset-2]) { - nodeh = state->stacklevels[state->stackoffset-1]; - if (idx >> nodeh == 1) { - memcpy(state->auth + nodeh*n, state->stack+(state->stackoffset-1)*n, n); - } - else { - if (nodeh < h - k && idx >> nodeh == 3) { - memcpy(state->treehash[nodeh].node, state->stack+(state->stackoffset-1)*n, n); - } - else if (nodeh >= h - k) { - memcpy(state->retain + ((1 << (h - 1 - nodeh)) + nodeh - h + (((idx >> nodeh) - 3) >> 1)) * n, state->stack+(state->stackoffset-1)*n, n); - } - } - setTreeHeight(node_addr, state->stacklevels[state->stackoffset-1]); - setTreeIndex(node_addr, (idx >> (state->stacklevels[state->stackoffset-1]+1))); - hash_h(state->stack+(state->stackoffset-2)*n, state->stack+(state->stackoffset-2)*n, pub_seed, node_addr, n); - - state->stacklevels[state->stackoffset-2]++; - state->stackoffset--; - } - state->next_leaf++; - return 0; -} - -/** - * Returns the auth path for node leaf_idx and computes the auth path for the - * next leaf node, using the algorithm described by Buchmann, Dahmen and Szydlo - * in "Post Quantum Cryptography", Springer 2009. - */ -static void bds_round(bds_state *state, const unsigned long leaf_idx, const unsigned char *sk_seed, const xmss_params *params, unsigned char *pub_seed, uint32_t addr[8]) -{ - unsigned int i; - unsigned int n = params->n; - unsigned int h = params->h; - unsigned int k = params->k; - - unsigned int tau = h; - unsigned int startidx; - unsigned int offset, rowidx; - unsigned char buf[2 * n]; - - uint32_t ots_addr[8]; - uint32_t ltree_addr[8]; - uint32_t node_addr[8]; - // only copy layer and tree address parts - memcpy(ots_addr, addr, 12); - // type = ots - setType(ots_addr, 0); - memcpy(ltree_addr, addr, 12); - setType(ltree_addr, 1); - memcpy(node_addr, addr, 12); - setType(node_addr, 2); - - for (i = 0; i < h; i++) { - if (! ((leaf_idx >> i) & 1)) { - tau = i; - break; - } - } - - if (tau > 0) { - memcpy(buf, state->auth + (tau-1) * n, n); - // we need to do this before refreshing state->keep to prevent overwriting - memcpy(buf + n, state->keep + ((tau-1) >> 1) * n, n); - } - if (!((leaf_idx >> (tau + 1)) & 1) && (tau < h - 1)) { - memcpy(state->keep + (tau >> 1)*n, state->auth + tau*n, n); - } - if (tau == 0) { - setLtreeADRS(ltree_addr, leaf_idx); - setOTSADRS(ots_addr, leaf_idx); - gen_leaf_wots(state->auth, sk_seed, params, pub_seed, ltree_addr, ots_addr); - } - else { - setTreeHeight(node_addr, (tau-1)); - setTreeIndex(node_addr, leaf_idx >> tau); - hash_h(state->auth + tau * n, buf, pub_seed, node_addr, n); - for (i = 0; i < tau; i++) { - if (i < h - k) { - memcpy(state->auth + i * n, state->treehash[i].node, n); - } - else { - offset = (1 << (h - 1 - i)) + i - h; - rowidx = ((leaf_idx >> i) - 1) >> 1; - memcpy(state->auth + i * n, state->retain + (offset + rowidx) * n, n); - } - } - - for (i = 0; i < ((tau < h - k) ? tau : (h - k)); i++) { - startidx = leaf_idx + 1 + 3 * (1 << i); - if (startidx < 1U << h) { - state->treehash[i].h = i; - state->treehash[i].next_idx = startidx; - state->treehash[i].completed = 0; - state->treehash[i].stackusage = 0; - } - } - } -} - -/* - * Generates a XMSS key pair for a given parameter set. - * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] omitting algo oid. - */ -int xmss_keypair(unsigned char *pk, unsigned char *sk, bds_state *state, xmss_params *params) -{ - unsigned int n = params->n; - // Set idx = 0 - sk[0] = 0; - sk[1] = 0; - sk[2] = 0; - sk[3] = 0; - // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte) - randombytes(sk+4, 3*n); - // Copy PUB_SEED to public key - memcpy(pk+n, sk+4+2*n, n); - - uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - - // Compute root - treehash_setup(pk, params->h, 0, state, sk+4, params, sk+4+2*n, addr); - // copy root to sk - memcpy(sk+4+3*n, pk, n); - return 0; -} - -/** - * Signs a message. - * Returns - * 1. an array containing the signature followed by the message AND - * 2. an updated secret key! - * - */ -int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmss_params *params) -{ - unsigned int h = params->h; - unsigned int n = params->n; - unsigned int k = params->k; - uint16_t i = 0; - - // Extract SK - unsigned long idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3]; - unsigned char sk_seed[n]; - memcpy(sk_seed, sk+4, n); - unsigned char sk_prf[n]; - memcpy(sk_prf, sk+4+n, n); - unsigned char pub_seed[n]; - memcpy(pub_seed, sk+4+2*n, n); - - // index as 32 bytes string - unsigned char idx_bytes_32[32]; - to_byte(idx_bytes_32, idx, 32); - - unsigned char hash_key[3*n]; - - // Update SK - sk[0] = ((idx + 1) >> 24) & 255; - sk[1] = ((idx + 1) >> 16) & 255; - sk[2] = ((idx + 1) >> 8) & 255; - sk[3] = (idx + 1) & 255; - // -- Secret key for this non-forward-secure version is now updated. - // -- A productive implementation should use a file handle instead and write the updated secret key at this point! - - // Init working params - unsigned char R[n]; - unsigned char msg_h[n]; - unsigned char ots_seed[n]; - uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - - // --------------------------------- - // Message Hashing - // --------------------------------- - - // Message Hash: - // First compute pseudorandom value - prf(R, idx_bytes_32, sk_prf, n); - // Generate hash key (R || root || idx) - memcpy(hash_key, R, n); - memcpy(hash_key+n, sk+4+3*n, n); - to_byte(hash_key+2*n, idx, n); - // Then use it for message digest - h_msg(msg_h, msg, msglen, hash_key, 3*n, n); - - // Start collecting signature - *sig_msg_len = 0; - - // Copy index to signature - sig_msg[0] = (idx >> 24) & 255; - sig_msg[1] = (idx >> 16) & 255; - sig_msg[2] = (idx >> 8) & 255; - sig_msg[3] = idx & 255; - - sig_msg += 4; - *sig_msg_len += 4; - - // Copy R to signature - for (i = 0; i < n; i++) - sig_msg[i] = R[i]; - - sig_msg += n; - *sig_msg_len += n; - - // ---------------------------------- - // Now we start to "really sign" - // ---------------------------------- - - // Prepare Address - setType(ots_addr, 0); - setOTSADRS(ots_addr, idx); - - // Compute seed for OTS key pair - get_seed(ots_seed, sk_seed, n, ots_addr); - - // Compute WOTS signature - wots_sign(sig_msg, msg_h, ots_seed, &(params->wots_par), pub_seed, ots_addr); - - sig_msg += params->wots_par.keysize; - *sig_msg_len += params->wots_par.keysize; - - // the auth path was already computed during the previous round - memcpy(sig_msg, state->auth, h*n); - - if (idx < (1U << h) - 1) { - bds_round(state, idx, sk_seed, params, pub_seed, ots_addr); - bds_treehash_update(state, (h - k) >> 1, sk_seed, params, pub_seed, ots_addr); - } - -/* TODO: save key/bds state here! */ - - sig_msg += params->h*n; - *sig_msg_len += params->h*n; - - //Whipe secret elements? - //zerobytes(tsk, CRYPTO_SECRETKEYBYTES); - - - memcpy(sig_msg, msg, msglen); - *sig_msg_len += msglen; - - return 0; -} - -/** - * Verifies a given message signature pair under a given public key. - */ -int xmss_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmss_params *params) -{ - unsigned int n = params->n; - - unsigned long long i, m_len; - unsigned long idx=0; - unsigned char wots_pk[params->wots_par.keysize]; - unsigned char pkhash[n]; - unsigned char root[n]; - unsigned char msg_h[n]; - unsigned char hash_key[3*n]; - - unsigned char pub_seed[n]; - memcpy(pub_seed, pk+n, n); - - // Init addresses - uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - - setType(ots_addr, 0); - setType(ltree_addr, 1); - setType(node_addr, 2); - - // Extract index - idx = ((unsigned long)sig_msg[0] << 24) | ((unsigned long)sig_msg[1] << 16) | ((unsigned long)sig_msg[2] << 8) | sig_msg[3]; - printf("verify:: idx = %lu\n", idx); - - // Generate hash key (R || root || idx) - memcpy(hash_key, sig_msg+4,n); - memcpy(hash_key+n, pk, n); - to_byte(hash_key+2*n, idx, n); - - sig_msg += (n+4); - sig_msg_len -= (n+4); - - // hash message - unsigned long long tmp_sig_len = params->wots_par.keysize+params->h*n; - m_len = sig_msg_len - tmp_sig_len; - h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n); - - //----------------------- - // Verify signature - //----------------------- - - // Prepare Address - setOTSADRS(ots_addr, idx); - // Check WOTS signature - wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->wots_par), pub_seed, ots_addr); - - sig_msg += params->wots_par.keysize; - sig_msg_len -= params->wots_par.keysize; - - // Compute Ltree - setLtreeADRS(ltree_addr, idx); - l_tree(pkhash, wots_pk, params, pub_seed, ltree_addr); - - // Compute root - validate_authpath(root, pkhash, idx, sig_msg, params, pub_seed, node_addr); - - sig_msg += params->h*n; - sig_msg_len -= params->h*n; - - for (i = 0; i < n; i++) - if (root[i] != pk[i]) - goto fail; - - *msglen = sig_msg_len; - for (i = 0; i < *msglen; i++) - msg[i] = sig_msg[i]; - - return 0; - - -fail: - *msglen = sig_msg_len; - for (i = 0; i < *msglen; i++) - msg[i] = 0; - *msglen = -1; - return -1; -} - -/* - * Generates a XMSSMT key pair for a given parameter set. - * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] omitting algo oid. - */ -int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsigned char *wots_sigs, xmssmt_params *params) -{ - unsigned int n = params->n; - unsigned int i; - unsigned char ots_seed[params->n]; - // Set idx = 0 - for (i = 0; i < params->index_len; i++) { - sk[i] = 0; - } - // Init SK_SEED (n byte), SK_PRF (n byte), and PUB_SEED (n byte) - randombytes(sk+params->index_len, 3*n); - // Copy PUB_SEED to public key - memcpy(pk+n, sk+params->index_len+2*n, n); - - // Set address to point on the single tree on layer d-1 - uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - setLayerADRS(addr, (params->d-1)); - // Set up state and compute wots signatures for all but topmost tree root - for (i = 0; i < params->d - 1; i++) { - // Compute seed for OTS key pair - treehash_setup(pk, params->xmss_par.h, 0, states + i, sk+params->index_len, &(params->xmss_par), pk+n, addr); - setLayerADRS(addr, (i+1)); - get_seed(ots_seed, sk+params->index_len, n, addr); - wots_sign(wots_sigs + i*params->xmss_par.wots_par.keysize, pk, ots_seed, &(params->xmss_par.wots_par), pk+n, addr); - } - treehash_setup(pk, params->xmss_par.h, 0, states + i, sk+params->index_len, &(params->xmss_par), pk+n, addr); - memcpy(sk+params->index_len+3*n, pk, n); - return 0; -} - -/** - * Signs a message. - * Returns - * 1. an array containing the signature followed by the message AND - * 2. an updated secret key! - * - */ -int xmssmt_sign(unsigned char *sk, bds_state *states, unsigned char *wots_sigs, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmssmt_params *params) -{ - unsigned int n = params->n; - - unsigned int tree_h = params->xmss_par.h; - unsigned int h = params->h; - unsigned int k = params->xmss_par.k; - unsigned int idx_len = params->index_len; - uint64_t idx_tree; - uint32_t idx_leaf; - uint64_t i, j; - int needswap_upto = -1; - unsigned int updates; - - unsigned char sk_seed[n]; - unsigned char sk_prf[n]; - unsigned char pub_seed[n]; - // Init working params - unsigned char R[n]; - unsigned char msg_h[n]; - unsigned char hash_key[3*n]; - unsigned char ots_seed[n]; - uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - unsigned char idx_bytes_32[32]; - bds_state tmp; - - // Extract SK - unsigned long long idx = 0; - for (i = 0; i < idx_len; i++) { - idx |= ((unsigned long long)sk[i]) << 8*(idx_len - 1 - i); - } - - memcpy(sk_seed, sk+idx_len, n); - memcpy(sk_prf, sk+idx_len+n, n); - memcpy(pub_seed, sk+idx_len+2*n, n); - - // Update SK - for (i = 0; i < idx_len; i++) { - sk[i] = ((idx + 1) >> 8*(idx_len - 1 - i)) & 255; - } - // -- Secret key for this non-forward-secure version is now updated. - // -- A productive implementation should use a file handle instead and write the updated secret key at this point! - - - // --------------------------------- - // Message Hashing - // --------------------------------- - - // Message Hash: - // First compute pseudorandom value - to_byte(idx_bytes_32, idx, 32); - prf(R, idx_bytes_32, sk_prf, n); - // Generate hash key (R || root || idx) - memcpy(hash_key, R, n); - memcpy(hash_key+n, sk+idx_len+3*n, n); - to_byte(hash_key+2*n, idx, n); - - // Then use it for message digest - h_msg(msg_h, msg, msglen, hash_key, 3*n, n); - - // Start collecting signature - *sig_msg_len = 0; - - // Copy index to signature - for (i = 0; i < idx_len; i++) { - sig_msg[i] = (idx >> 8*(idx_len - 1 - i)) & 255; - } - - sig_msg += idx_len; - *sig_msg_len += idx_len; - - // Copy R to signature - for (i = 0; i < n; i++) - sig_msg[i] = R[i]; - - sig_msg += n; - *sig_msg_len += n; - - // ---------------------------------- - // Now we start to "really sign" - // ---------------------------------- - - // Handle lowest layer separately as it is slightly different... - - // Prepare Address - setType(ots_addr, 0); - idx_tree = idx >> tree_h; - idx_leaf = (idx & ((1 << tree_h)-1)); - setLayerADRS(ots_addr, 0); - setTreeADRS(ots_addr, idx_tree); - setOTSADRS(ots_addr, idx_leaf); - - // Compute seed for OTS key pair - get_seed(ots_seed, sk_seed, n, ots_addr); - - // Compute WOTS signature - wots_sign(sig_msg, msg_h, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr); - - sig_msg += params->xmss_par.wots_par.keysize; - *sig_msg_len += params->xmss_par.wots_par.keysize; - - memcpy(sig_msg, states[0].auth, tree_h*n); - sig_msg += tree_h*n; - *sig_msg_len += tree_h*n; - - // prepare signature of remaining layers - for (i = 1; i < params->d; i++) { - // put WOTS signature in place - memcpy(sig_msg, wots_sigs + (i-1)*params->xmss_par.wots_par.keysize, params->xmss_par.wots_par.keysize); - - sig_msg += params->xmss_par.wots_par.keysize; - *sig_msg_len += params->xmss_par.wots_par.keysize; - - // put AUTH nodes in place - memcpy(sig_msg, states[i].auth, tree_h*n); - sig_msg += tree_h*n; - *sig_msg_len += tree_h*n; - } - - updates = (tree_h - k) >> 1; - - setTreeADRS(addr, (idx_tree + 1)); - // mandatory update for NEXT_0 (does not count towards h-k/2) if NEXT_0 exists - if ((1 + idx_tree) * (1 << tree_h) + idx_leaf < (1ULL << h)) { - bds_state_update(&states[params->d], sk_seed, &(params->xmss_par), pub_seed, addr); - } - - for (i = 0; i < params->d; i++) { - // check if we're not at the end of a tree - if (! (((idx + 1) & ((1ULL << ((i+1)*tree_h)) - 1)) == 0)) { - idx_leaf = (idx >> (tree_h * i)) & ((1 << tree_h)-1); - idx_tree = (idx >> (tree_h * (i+1))); - setLayerADRS(addr, i); - setTreeADRS(addr, idx_tree); - if (i == (unsigned int) (needswap_upto + 1)) { - bds_round(&states[i], idx_leaf, sk_seed, &(params->xmss_par), pub_seed, addr); - } - updates = bds_treehash_update(&states[i], updates, sk_seed, &(params->xmss_par), pub_seed, addr); - setTreeADRS(addr, (idx_tree + 1)); - // if a NEXT-tree exists for this level; - if ((1 + idx_tree) * (1 << tree_h) + idx_leaf < (1ULL << (h - tree_h * i))) { - if (i > 0 && updates > 0 && states[params->d + i].next_leaf < (1ULL << h)) { - bds_state_update(&states[params->d + i], sk_seed, &(params->xmss_par), pub_seed, addr); - updates--; - } - } - } - else if (idx < (1ULL << h) - 1) { - memcpy(&tmp, states+params->d + i, sizeof(bds_state)); - memcpy(states+params->d + i, states + i, sizeof(bds_state)); - memcpy(states + i, &tmp, sizeof(bds_state)); - - setLayerADRS(ots_addr, (i+1)); - setTreeADRS(ots_addr, ((idx + 1) >> ((i+2) * tree_h))); - setOTSADRS(ots_addr, (((idx >> ((i+1) * tree_h)) + 1) & ((1 << tree_h)-1))); - - get_seed(ots_seed, sk+params->index_len, n, ots_addr); - wots_sign(wots_sigs + i*params->xmss_par.wots_par.keysize, states[i].stack, ots_seed, &(params->xmss_par.wots_par), pub_seed, ots_addr); - - states[params->d + i].stackoffset = 0; - states[params->d + i].next_leaf = 0; - - updates--; // WOTS-signing counts as one update - needswap_upto = i; - for (j = 0; j < tree_h-k; j++) { - states[i].treehash[j].completed = 1; - } - } - } - - //Whipe secret elements? - //zerobytes(tsk, CRYPTO_SECRETKEYBYTES); - - memcpy(sig_msg, msg, msglen); - *sig_msg_len += msglen; - - return 0; -} - -/** - * Verifies a given message signature pair under a given public key. - */ -int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmssmt_params *params) -{ - unsigned int n = params->n; - - unsigned int tree_h = params->xmss_par.h; - unsigned int idx_len = params->index_len; - uint64_t idx_tree; - uint32_t idx_leaf; - - unsigned long long i, m_len; - unsigned long long idx=0; - unsigned char wots_pk[params->xmss_par.wots_par.keysize]; - unsigned char pkhash[n]; - unsigned char root[n]; - unsigned char msg_h[n]; - unsigned char hash_key[3*n]; - - unsigned char pub_seed[n]; - memcpy(pub_seed, pk+n, n); - - // Init addresses - uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - uint32_t ltree_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - uint32_t node_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - - // Extract index - for (i = 0; i < idx_len; i++) { - idx |= ((unsigned long long)sig_msg[i]) << (8*(idx_len - 1 - i)); - } - printf("verify:: idx = %llu\n", idx); - sig_msg += idx_len; - sig_msg_len -= idx_len; - - // Generate hash key (R || root || idx) - memcpy(hash_key, sig_msg,n); - memcpy(hash_key+n, pk, n); - to_byte(hash_key+2*n, idx, n); - - sig_msg += n; - sig_msg_len -= n; - - - // hash message (recall, R is now on pole position at sig_msg - unsigned long long tmp_sig_len = (params->d * params->xmss_par.wots_par.keysize) + (params->h * n); - m_len = sig_msg_len - tmp_sig_len; - h_msg(msg_h, sig_msg + tmp_sig_len, m_len, hash_key, 3*n, n); - - - //----------------------- - // Verify signature - //----------------------- - - // Prepare Address - idx_tree = idx >> tree_h; - idx_leaf = (idx & ((1 << tree_h)-1)); - setLayerADRS(ots_addr, 0); - setTreeADRS(ots_addr, idx_tree); - setType(ots_addr, 0); - - memcpy(ltree_addr, ots_addr, 12); - setType(ltree_addr, 1); - - memcpy(node_addr, ltree_addr, 12); - setType(node_addr, 2); - - setOTSADRS(ots_addr, idx_leaf); - - // Check WOTS signature - wots_pkFromSig(wots_pk, sig_msg, msg_h, &(params->xmss_par.wots_par), pub_seed, ots_addr); - - sig_msg += params->xmss_par.wots_par.keysize; - sig_msg_len -= params->xmss_par.wots_par.keysize; - - // Compute Ltree - setLtreeADRS(ltree_addr, idx_leaf); - l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr); - - // Compute root - validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr); - - sig_msg += tree_h*n; - sig_msg_len -= tree_h*n; - - for (i = 1; i < params->d; i++) { - // Prepare Address - idx_leaf = (idx_tree & ((1 << tree_h)-1)); - idx_tree = idx_tree >> tree_h; - - setLayerADRS(ots_addr, i); - setTreeADRS(ots_addr, idx_tree); - setType(ots_addr, 0); - - memcpy(ltree_addr, ots_addr, 12); - setType(ltree_addr, 1); - - memcpy(node_addr, ltree_addr, 12); - setType(node_addr, 2); - - setOTSADRS(ots_addr, idx_leaf); - - // Check WOTS signature - wots_pkFromSig(wots_pk, sig_msg, root, &(params->xmss_par.wots_par), pub_seed, ots_addr); - - sig_msg += params->xmss_par.wots_par.keysize; - sig_msg_len -= params->xmss_par.wots_par.keysize; - - // Compute Ltree - setLtreeADRS(ltree_addr, idx_leaf); - l_tree(pkhash, wots_pk, &(params->xmss_par), pub_seed, ltree_addr); - - // Compute root - validate_authpath(root, pkhash, idx_leaf, sig_msg, &(params->xmss_par), pub_seed, node_addr); - - sig_msg += tree_h*n; - sig_msg_len -= tree_h*n; - - } - - for (i = 0; i < n; i++) - if (root[i] != pk[i]) - goto fail; - - *msglen = sig_msg_len; - for (i = 0; i < *msglen; i++) - msg[i] = sig_msg[i]; - - return 0; - - -fail: - *msglen = sig_msg_len; - for (i = 0; i < *msglen; i++) - msg[i] = 0; - *msglen = -1; - return -1; -} -#endif /* WITH_XMSS */ diff --git a/xmss_fast.h b/xmss_fast.h deleted file mode 100644 index 2ffba7057baf..000000000000 --- a/xmss_fast.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifdef WITH_XMSS -/* $OpenBSD: xmss_fast.h,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */ -/* -xmss_fast.h version 20160722 -Andreas Hülsing -Joost Rijneveld -Public domain. -*/ - -#include "xmss_wots.h" - -#ifndef XMSS_H -#define XMSS_H -typedef struct{ - unsigned int level; - unsigned long long subtree; - unsigned int subleaf; -} leafaddr; - -typedef struct{ - wots_params wots_par; - unsigned int n; - unsigned int h; - unsigned int k; -} xmss_params; - -typedef struct{ - xmss_params xmss_par; - unsigned int n; - unsigned int h; - unsigned int d; - unsigned int index_len; -} xmssmt_params; - -typedef struct{ - unsigned int h; - unsigned int next_idx; - unsigned int stackusage; - unsigned char completed; - unsigned char *node; -} treehash_inst; - -typedef struct { - unsigned char *stack; - unsigned int stackoffset; - unsigned char *stacklevels; - unsigned char *auth; - unsigned char *keep; - treehash_inst *treehash; - unsigned char *retain; - unsigned int next_leaf; -} bds_state; - -/** - * Initialize BDS state struct - * parameter names are the same as used in the description of the BDS traversal - */ -void xmss_set_bds_state(bds_state *state, unsigned char *stack, int stackoffset, unsigned char *stacklevels, unsigned char *auth, unsigned char *keep, treehash_inst *treehash, unsigned char *retain, int next_leaf); -/** - * Initializes parameter set. - * Needed, for any of the other methods. - */ -int xmss_set_params(xmss_params *params, int n, int h, int w, int k); -/** - * Initialize xmssmt_params struct - * parameter names are the same as in the draft - * - * Especially h is the total tree height, i.e. the XMSS trees have height h/d - */ -int xmssmt_set_params(xmssmt_params *params, int n, int h, int d, int w, int k); -/** - * Generates a XMSS key pair for a given parameter set. - * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] omitting algo oid. - */ -int xmss_keypair(unsigned char *pk, unsigned char *sk, bds_state *state, xmss_params *params); -/** - * Signs a message. - * Returns - * 1. an array containing the signature followed by the message AND - * 2. an updated secret key! - * - */ -int xmss_sign(unsigned char *sk, bds_state *state, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg,unsigned long long msglen, const xmss_params *params); -/** - * Verifies a given message signature pair under a given public key. - * - * Note: msg and msglen are pure outputs which carry the message in case verification succeeds. The (input) message is assumed to be within sig_msg which has the form (sig||msg). - */ -int xmss_sign_open(unsigned char *msg,unsigned long long *msglen, const unsigned char *sig_msg,unsigned long long sig_msg_len, const unsigned char *pk, const xmss_params *params); - -/* - * Generates a XMSSMT key pair for a given parameter set. - * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED || root] - * Format pk: [root || PUB_SEED] omitting algo oid. - */ -int xmssmt_keypair(unsigned char *pk, unsigned char *sk, bds_state *states, unsigned char *wots_sigs, xmssmt_params *params); -/** - * Signs a message. - * Returns - * 1. an array containing the signature followed by the message AND - * 2. an updated secret key! - * - */ -int xmssmt_sign(unsigned char *sk, bds_state *state, unsigned char *wots_sigs, unsigned char *sig_msg, unsigned long long *sig_msg_len, const unsigned char *msg, unsigned long long msglen, const xmssmt_params *params); -/** - * Verifies a given message signature pair under a given public key. - */ -int xmssmt_sign_open(unsigned char *msg, unsigned long long *msglen, const unsigned char *sig_msg, unsigned long long sig_msg_len, const unsigned char *pk, const xmssmt_params *params); -#endif -#endif /* WITH_XMSS */ diff --git a/xmss_hash.c b/xmss_hash.c deleted file mode 100644 index 70c126ae25a3..000000000000 --- a/xmss_hash.c +++ /dev/null @@ -1,137 +0,0 @@ -/* $OpenBSD: xmss_hash.c,v 1.4 2023/12/20 00:06:25 jsg Exp $ */ -/* -hash.c version 20160722 -Andreas Hülsing -Joost Rijneveld -Public domain. -*/ - -#include "includes.h" -#ifdef WITH_XMSS - -#include "xmss_hash_address.h" -#include "xmss_commons.h" -#include "xmss_hash.h" - -#include -#ifdef HAVE_STDINT_H -# include -#endif -#include -#include - -int core_hash_SHA2(unsigned char *, const unsigned int, const unsigned char *, - unsigned int, const unsigned char *, unsigned long long, unsigned int); - -unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8]){ -#if IS_LITTLE_ENDIAN==1 - int i = 0; - for(i=0;i<8;i++) - to_byte(bytes+i*4, addr[i],4); - return bytes; -#else - memcpy(bytes, addr, 32); - return bytes; -#endif -} - -int core_hash_SHA2(unsigned char *out, const unsigned int type, const unsigned char *key, unsigned int keylen, const unsigned char *in, unsigned long long inlen, unsigned int n){ - unsigned long long i = 0; - unsigned char buf[inlen + n + keylen]; - - // Input is (toByte(X, 32) || KEY || M) - - // set toByte - to_byte(buf, type, n); - - for (i=0; i < keylen; i++) { - buf[i+n] = key[i]; - } - - for (i=0; i < inlen; i++) { - buf[keylen + n + i] = in[i]; - } - - if (n == 32) { - SHA256(buf, inlen + keylen + n, out); - return 0; - } - else { - if (n == 64) { - SHA512(buf, inlen + keylen + n, out); - return 0; - } - } - return 1; -} - -/** - * Implements PRF - */ -int prf(unsigned char *out, const unsigned char *in, const unsigned char *key, unsigned int keylen) -{ - return core_hash_SHA2(out, 3, key, keylen, in, 32, keylen); -} - -/* - * Implements H_msg - */ -int h_msg(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *key, const unsigned int keylen, const unsigned int n) -{ - if (keylen != 3*n){ - // H_msg takes 3n-bit keys, but n does not match the keylength of keylen - return -1; - } - return core_hash_SHA2(out, 2, key, keylen, in, inlen, n); -} - -/** - * We assume the left half is in in[0]...in[n-1] - */ -int hash_h(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n) -{ - - unsigned char buf[2*n]; - unsigned char key[n]; - unsigned char bitmask[2*n]; - unsigned char byte_addr[32]; - unsigned int i; - - setKeyAndMask(addr, 0); - addr_to_byte(byte_addr, addr); - prf(key, byte_addr, pub_seed, n); - // Use MSB order - setKeyAndMask(addr, 1); - addr_to_byte(byte_addr, addr); - prf(bitmask, byte_addr, pub_seed, n); - setKeyAndMask(addr, 2); - addr_to_byte(byte_addr, addr); - prf(bitmask+n, byte_addr, pub_seed, n); - for (i = 0; i < 2*n; i++) { - buf[i] = in[i] ^ bitmask[i]; - } - return core_hash_SHA2(out, 1, key, n, buf, 2*n, n); -} - -int hash_f(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n) -{ - unsigned char buf[n]; - unsigned char key[n]; - unsigned char bitmask[n]; - unsigned char byte_addr[32]; - unsigned int i; - - setKeyAndMask(addr, 0); - addr_to_byte(byte_addr, addr); - prf(key, byte_addr, pub_seed, n); - - setKeyAndMask(addr, 1); - addr_to_byte(byte_addr, addr); - prf(bitmask, byte_addr, pub_seed, n); - - for (i = 0; i < n; i++) { - buf[i] = in[i] ^ bitmask[i]; - } - return core_hash_SHA2(out, 0, key, n, buf, n, n); -} -#endif /* WITH_XMSS */ diff --git a/xmss_hash.h b/xmss_hash.h deleted file mode 100644 index d19c62152add..000000000000 --- a/xmss_hash.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifdef WITH_XMSS -/* $OpenBSD: xmss_hash.h,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */ -/* -hash.h version 20160722 -Andreas Hülsing -Joost Rijneveld -Public domain. -*/ - -#ifndef HASH_H -#define HASH_H - -#define IS_LITTLE_ENDIAN 1 - -unsigned char* addr_to_byte(unsigned char *bytes, const uint32_t addr[8]); -int prf(unsigned char *out, const unsigned char *in, const unsigned char *key, unsigned int keylen); -int h_msg(unsigned char *out,const unsigned char *in,unsigned long long inlen, const unsigned char *key, const unsigned int keylen, const unsigned int n); -int hash_h(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n); -int hash_f(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, uint32_t addr[8], const unsigned int n); - -#endif -#endif /* WITH_XMSS */ diff --git a/xmss_hash_address.c b/xmss_hash_address.c deleted file mode 100644 index 2702c4562bfc..000000000000 --- a/xmss_hash_address.c +++ /dev/null @@ -1,66 +0,0 @@ -/* $OpenBSD: xmss_hash_address.c,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */ -/* -hash_address.c version 20160722 -Andreas Hülsing -Joost Rijneveld -Public domain. -*/ -#include "includes.h" -#ifdef WITH_XMSS - -#ifdef HAVE_STDINT_H -# include -#endif -#include "xmss_hash_address.h" /* prototypes */ - -void setLayerADRS(uint32_t adrs[8], uint32_t layer){ - adrs[0] = layer; -} - -void setTreeADRS(uint32_t adrs[8], uint64_t tree){ - adrs[1] = (uint32_t) (tree >> 32); - adrs[2] = (uint32_t) tree; -} - -void setType(uint32_t adrs[8], uint32_t type){ - adrs[3] = type; - int i; - for(i = 4; i < 8; i++){ - adrs[i] = 0; - } -} - -void setKeyAndMask(uint32_t adrs[8], uint32_t keyAndMask){ - adrs[7] = keyAndMask; -} - -// OTS - -void setOTSADRS(uint32_t adrs[8], uint32_t ots){ - adrs[4] = ots; -} - -void setChainADRS(uint32_t adrs[8], uint32_t chain){ - adrs[5] = chain; -} - -void setHashADRS(uint32_t adrs[8], uint32_t hash){ - adrs[6] = hash; -} - -// L-tree - -void setLtreeADRS(uint32_t adrs[8], uint32_t ltree){ - adrs[4] = ltree; -} - -// Hash Tree & L-tree - -void setTreeHeight(uint32_t adrs[8], uint32_t treeHeight){ - adrs[5] = treeHeight; -} - -void setTreeIndex(uint32_t adrs[8], uint32_t treeIndex){ - adrs[6] = treeIndex; -} -#endif /* WITH_XMSS */ diff --git a/xmss_hash_address.h b/xmss_hash_address.h deleted file mode 100644 index 66bb4cc4d5fa..000000000000 --- a/xmss_hash_address.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifdef WITH_XMSS -/* $OpenBSD: xmss_hash_address.h,v 1.2 2018/02/26 03:56:44 dtucker Exp $ */ -/* -hash_address.h version 20160722 -Andreas Hülsing -Joost Rijneveld -Public domain. -*/ - -#ifdef HAVE_STDINT_H -#include -#endif - -void setLayerADRS(uint32_t adrs[8], uint32_t layer); - -void setTreeADRS(uint32_t adrs[8], uint64_t tree); - -void setType(uint32_t adrs[8], uint32_t type); - -void setKeyAndMask(uint32_t adrs[8], uint32_t keyAndMask); - -// OTS - -void setOTSADRS(uint32_t adrs[8], uint32_t ots); - -void setChainADRS(uint32_t adrs[8], uint32_t chain); - -void setHashADRS(uint32_t adrs[8], uint32_t hash); - -// L-tree - -void setLtreeADRS(uint32_t adrs[8], uint32_t ltree); - -// Hash Tree & L-tree - -void setTreeHeight(uint32_t adrs[8], uint32_t treeHeight); - -void setTreeIndex(uint32_t adrs[8], uint32_t treeIndex); - -#endif /* WITH_XMSS */ diff --git a/xmss_wots.c b/xmss_wots.c deleted file mode 100644 index 993e661f6707..000000000000 --- a/xmss_wots.c +++ /dev/null @@ -1,192 +0,0 @@ -/* $OpenBSD: xmss_wots.c,v 1.3 2018/04/10 00:10:49 djm Exp $ */ -/* -wots.c version 20160722 -Andreas Hülsing -Joost Rijneveld -Public domain. -*/ - -#include "includes.h" -#ifdef WITH_XMSS - -#include -#ifdef HAVE_STDINT_H -# include -#endif -#include -#include "xmss_commons.h" -#include "xmss_hash.h" -#include "xmss_wots.h" -#include "xmss_hash_address.h" - - -/* libm-free version of log2() for wots */ -static inline int -wots_log2(uint32_t v) -{ - int b; - - for (b = sizeof (v) * CHAR_BIT - 1; b >= 0; b--) { - if ((1U << b) & v) { - return b; - } - } - return 0; -} - -void -wots_set_params(wots_params *params, int n, int w) -{ - params->n = n; - params->w = w; - params->log_w = wots_log2(params->w); - params->len_1 = (CHAR_BIT * n) / params->log_w; - params->len_2 = (wots_log2(params->len_1 * (w - 1)) / params->log_w) + 1; - params->len = params->len_1 + params->len_2; - params->keysize = params->len * params->n; -} - -/** - * Helper method for pseudorandom key generation - * Expands an n-byte array into a len*n byte array - * this is done using PRF - */ -static void expand_seed(unsigned char *outseeds, const unsigned char *inseed, const wots_params *params) -{ - uint32_t i = 0; - unsigned char ctr[32]; - for(i = 0; i < params->len; i++){ - to_byte(ctr, i, 32); - prf((outseeds + (i*params->n)), ctr, inseed, params->n); - } -} - -/** - * Computes the chaining function. - * out and in have to be n-byte arrays - * - * interprets in as start-th value of the chain - * addr has to contain the address of the chain - */ -static void gen_chain(unsigned char *out, const unsigned char *in, unsigned int start, unsigned int steps, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) -{ - uint32_t i, j; - for (j = 0; j < params->n; j++) - out[j] = in[j]; - - for (i = start; i < (start+steps) && i < params->w; i++) { - setHashADRS(addr, i); - hash_f(out, out, pub_seed, addr, params->n); - } -} - -/** - * base_w algorithm as described in draft. - * - * - */ -static void base_w(int *output, const int out_len, const unsigned char *input, const wots_params *params) -{ - int in = 0; - int out = 0; - uint32_t total = 0; - int bits = 0; - int consumed = 0; - - for (consumed = 0; consumed < out_len; consumed++) { - if (bits == 0) { - total = input[in]; - in++; - bits += 8; - } - bits -= params->log_w; - output[out] = (total >> bits) & (params->w - 1); - out++; - } -} - -void wots_pkgen(unsigned char *pk, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) -{ - uint32_t i; - expand_seed(pk, sk, params); - for (i=0; i < params->len; i++) { - setChainADRS(addr, i); - gen_chain(pk+i*params->n, pk+i*params->n, 0, params->w-1, params, pub_seed, addr); - } -} - - -int wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) -{ - //int basew[params->len]; - int csum = 0; - uint32_t i = 0; - int *basew = calloc(params->len, sizeof(int)); - if (basew == NULL) - return -1; - - base_w(basew, params->len_1, msg, params); - - for (i=0; i < params->len_1; i++) { - csum += params->w - 1 - basew[i]; - } - - csum = csum << (8 - ((params->len_2 * params->log_w) % 8)); - - int len_2_bytes = ((params->len_2 * params->log_w) + 7) / 8; - - unsigned char csum_bytes[len_2_bytes]; - to_byte(csum_bytes, csum, len_2_bytes); - - int csum_basew[params->len_2]; - base_w(csum_basew, params->len_2, csum_bytes, params); - - for (i = 0; i < params->len_2; i++) { - basew[params->len_1 + i] = csum_basew[i]; - } - - expand_seed(sig, sk, params); - - for (i = 0; i < params->len; i++) { - setChainADRS(addr, i); - gen_chain(sig+i*params->n, sig+i*params->n, 0, basew[i], params, pub_seed, addr); - } - free(basew); - return 0; -} - -int wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]) -{ - int csum = 0; - uint32_t i = 0; - int *basew = calloc(params->len, sizeof(int)); - if (basew == NULL) - return -1; - - base_w(basew, params->len_1, msg, params); - - for (i=0; i < params->len_1; i++) { - csum += params->w - 1 - basew[i]; - } - - csum = csum << (8 - ((params->len_2 * params->log_w) % 8)); - - int len_2_bytes = ((params->len_2 * params->log_w) + 7) / 8; - - unsigned char csum_bytes[len_2_bytes]; - to_byte(csum_bytes, csum, len_2_bytes); - - int csum_basew[params->len_2]; - base_w(csum_basew, params->len_2, csum_bytes, params); - - for (i = 0; i < params->len_2; i++) { - basew[params->len_1 + i] = csum_basew[i]; - } - for (i=0; i < params->len; i++) { - setChainADRS(addr, i); - gen_chain(pk+i*params->n, sig+i*params->n, basew[i], params->w-1-basew[i], params, pub_seed, addr); - } - free(basew); - return 0; -} -#endif /* WITH_XMSS */ diff --git a/xmss_wots.h b/xmss_wots.h deleted file mode 100644 index 1eebf3b215df..000000000000 --- a/xmss_wots.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifdef WITH_XMSS -/* $OpenBSD: xmss_wots.h,v 1.3 2018/02/26 12:14:53 dtucker Exp $ */ -/* -wots.h version 20160722 -Andreas Hülsing -Joost Rijneveld -Public domain. -*/ - -#ifndef WOTS_H -#define WOTS_H - -#ifdef HAVE_STDINT_H -#include "stdint.h" -#endif - -/** - * WOTS parameter set - * - * Meaning as defined in draft-irtf-cfrg-xmss-hash-based-signatures-02 - */ -typedef struct { - uint32_t len_1; - uint32_t len_2; - uint32_t len; - uint32_t n; - uint32_t w; - uint32_t log_w; - uint32_t keysize; -} wots_params; - -/** - * Set the WOTS parameters, - * only m, n, w are required as inputs, - * len, len_1, and len_2 are computed from those. - * - * Assumes w is a power of 2 - */ -void wots_set_params(wots_params *params, int n, int w); - -/** - * WOTS key generation. Takes a 32byte seed for the secret key, expands it to a full WOTS secret key and computes the corresponding public key. - * For this it takes the seed pub_seed which is used to generate bitmasks and hash keys and the address of this WOTS key pair addr - * - * params, must have been initialized before using wots_set params for params ! This is not done in this function - * - * Places the computed public key at address pk. - */ -void wots_pkgen(unsigned char *pk, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]); - -/** - * Takes a m-byte message and the 32-byte seed for the secret key to compute a signature that is placed at "sig". - * - */ -int wots_sign(unsigned char *sig, const unsigned char *msg, const unsigned char *sk, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]); - -/** - * Takes a WOTS signature, a m-byte message and computes a WOTS public key that it places at pk. - * - */ -int wots_pkFromSig(unsigned char *pk, const unsigned char *sig, const unsigned char *msg, const wots_params *params, const unsigned char *pub_seed, uint32_t addr[8]); - -#endif -#endif /* WITH_XMSS */